Pendahuluan
Halo teman-teman! 👋
Pernah nggak sih kalian merasa capek harus manual deploy setiap kali ada perubahan kode? Push code ke repository, lalu harus login ke server, pull code baru, jalankan migration, clear cache, restart service... dan seterusnya. Kalau hanya satu kali sih nggak masalah, tapi kalau harus dilakukan berulang-ulang setiap hari? Pasti melelahkan, kan?
Nah, di sinilah konsep CI/CD hadir sebagai solusi. Dan salah satu tools yang paling populer untuk mengimplementasikannya adalah GitHub Actions. Di tutorial kali ini, kita akan belajar bareng tentang apa itu CI/CD, kenapa kita butuh GitHub Actions, dan bagaimana cara membuat pipeline lengkap untuk proyek Laravel kita.
Siap? Let's go! 🚀
Apa Itu CI/CD?
Sebelum kita masuk ke implementasi, yuk pahami dulu konsep dasarnya.
Continuous Integration (CI)
Continuous Integration adalah praktik di mana setiap developer mengintegrasikan kode mereka ke dalam branch utama secara berkala (biasanya beberapa kali sehari). Setiap integrasi ini kemudian diverifikasi secara otomatis — mulai dari build, test, sampai linting.
Intinya, CI memastikan bahwa kode yang kita tulis selalu dalam kondisi sehat dan tidak merusak kode lain. Bayangkan kalau 5 orang developer bekerja di proyek yang sama tanpa CI — bisa berantakan banget, kan? 😅
Continuous Delivery / Continuous Deployment (CD)
Continuous Delivery memastikan bahwa kode yang sudah lolos CI selalu siap untuk dideploy ke production kapan pun. Artinya, ada pipeline otomatis yang mempersiapkan segalanya — tinggal kita klik tombol "deploy" saja.
Sedangkan Continuous Deployment adalah langkah lebih lanjut: setiap perubahan yang lolos CI akan langsung dideploy ke production secara otomatis, tanpa intervensi manusia.
Dalam praktiknya, banyak tim yang menerapkan Continuous Delivery (ada approval manual sebelum deploy) karena lebih aman. Tapi untuk project kecil atau side project, Continuous Deployment juga bisa jadi pilihan yang menarik.
Kenapa GitHub Actions?
Sebenarnya ada banyak tools CI/CD di luar sana seperti Jenkins, GitLab CI, CircleCI, Travis CI, dan lain-lain. Tapi GitHub Actions punya kelebihan tersendiri:
- Terintegrasi langsung dengan GitHub — Nggak perlu setup integrasi terpisah. Kalau repo kalian sudah di GitHub, tinggal pakai.
- Gratis untuk public repos — Untuk open source, GitHub Actions sangat generous dengan limitasi gratisnya.
- Marketplace yang kaya — Ada ribuan action siap pakai yang bisa kita gunakan, mulai dari deploy ke AWS sampai kirim notifikasi ke Slack.
- Mudah dipelajari — Syntax-nya berbasis YAML yang relatif mudah dipahami.
- Multi-platform — Bisa dijalankan di Ubuntu, Windows, dan macOS.
Perbandingan dengan Tools Lain
| Feature | GitHub Actions | GitLab CI | Jenkins | CircleCI |
|---|---|---|---|---|
| Hosted Runner | ✅ | ✅ | ❌ (self-hosted) | ✅ |
| Free Tier | Generous | Moderate | Unlimited (self-hosted) | Limited |
| Marketplace | 20k+ actions | Fewer | 1800+ plugins | Orbs |
| Setup Complexity | Low | Low | High | Medium |
Konsep Dasar GitHub Actions
Sebelum kita membuat workflow, penting untuk memahami konsep-konsep dasar dalam GitHub Actions:
Repository
Workflow files disimpan di folder .github/workflows/ di dalam repository kita. Setiap file workflow ditulis dalam format YAML.
Workflow
Workflow adalah proses otomatis yang kita definisikan. Satu repository bisa memiliki banyak workflow, dan masing-masing workflow bisa dijalankan oleh trigger yang berbeda.
Event
Event adalah sesuatu yang memicu workflow untuk berjalan. Contohnya:
push— Ketika ada code yang di-push ke branch tertentupull_request— Ketika ada pull request yang dibuat atau di-updateschedule— Berdasarkan cron scheduleworkflow_dispatch— Trigger manual dari UI GitHub
Job
Job adalah sekumpulan steps yang berjalan di runner yang sama. Multiple jobs bisa berjalan secara paralel atau berurutan (bergantung pada dependency).
Step
Step adalah instruksi individual dalam sebuah job. Step bisa menjalankan command, menggunakan action, atau menjalankan script.
Action
Action adalah unit reusable yang bisa kita gunakan untuk mempersingkat workflow. Contohnya, actions/checkout@v4 untuk checkout kode, atau actions/setup-php@v2 untuk setup PHP.
Runner
Runner adalah server yang menjalankan workflow. GitHub menyediakan hosted runners (Ubuntu, Windows, macOS) atau kita bisa menggunakan self-hosted runner.
Struktur Workflow Dasar
Oke, sekarang kita sudah paham konsep-konsep dasarnya. Yuk kita lihat struktur workflow GitHub Actions yang paling sederhana:
name: CI Pipeline
# Trigger: kapan workflow ini berjalan
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
# Jobs yang akan berjalan
jobs:
# Nama job
build:
# Runner yang digunakan
runs-on: ubuntu-latest
# Steps dalam job ini
steps:
# Step 1: Checkout kode
- name: Checkout code
uses: actions/checkout@v4
# Step 2: Jalankan command
- name: Run a one-line script
run: echo "Hello, GitHub Actions!"Coba perhatikan strukturnya:
name— Nama workflow yang akan tampil di tab Actions di GitHubon— Trigger yang memicu workflowjobs— Sekumpulan job yang akan dieksekusisteps— Langkah-langkah dalam setiap job
Setup Environment PHP untuk Laravel
Sebelum kita masuk ke contoh workflow Laravel yang lengkap, mari kita pahami cara setup environment PHP di GitHub Actions.
Menggunakan actions/setup-php
Action shivammathur/setup-php adalah action paling populer untuk setup PHP di GitHub Actions. Berikut cara menggunakannya:
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: mbstring, xml, ctype, json, bcmath, pdo, sqlite3
tools: composer:v2
coverage: xdebugParameter extensions memungkinkan kita menginstal PHP extension yang dibutuhkan, dan tools memungkinkan kita menginstal tools tambahan seperti Composer.
Menggunakan Service Containers
Untuk Laravel, kita biasanya butuh database saat testing. GitHub Actions menyediakan service containers yang bisa kita gunakan:
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: testing
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping"
--health-interval=10s
--health-timeout=5s
--health-retries=3Service container akan berjalan bersama job kita dan otomatis dihentikan setelah job selesai.
Contoh Workflow Lengkap untuk Laravel
Sekarang kita akan membuat workflow CI/CD lengkap untuk proyek Laravel. Workflow ini akan melakukan:
- Test — Menjalankan PHPUnit test
- Lint — Menjalankan PHP CodeSniffer
- Build — Build assets dengan Vite
- Deploy — Deploy ke production
File: .github/workflows/ci.yml
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
PHP_VERSION: '8.2'
NODE_VERSION: '20'
jobs:
# ============================================
# Job 1: Code Quality & Testing
# ============================================
test:
name: Test
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: testing
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping"
--health-interval=10s
--health-timeout=5s
--health-retries=3
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ env.PHP_VERSION }}
extensions: mbstring, xml, ctype, json, bcmath, pdo, sqlite3
tools: composer:v2
coverage: xdebug
- name: Get Composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache Composer dependencies
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Copy environment file
run: cp .env.example .env
- name: Generate application key
run: php artisan key:generate
- name: Configure environment
run: |
sed -i 's/DB_DATABASE=laravel/DB_DATABASE=testing/' .env
sed -i 's/DB_USERNAME=root/DB_USERNAME=root/' .env
sed -i 's/DB_PASSWORD=/DB_PASSWORD=password/' .env
- name: Run migrations
run: php artisan migrate --force
env:
DB_CONNECTION: mysql
- name: Run tests
run: php artisan test --coverage --min=80
env:
DB_CONNECTION: mysql
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: ./coverage.xml
fail_ci_if_error: false
# ============================================
# Job 2: Code Linting
# ============================================
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ env.PHP_VERSION }}
tools: composer:v2, phpcs
- name: Get Composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache Composer dependencies
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Run PHP CodeSniffer
run: vendor/bin/phpcs --standard=PSR12 --report=checkstyle app/ || true
- name: Run PHPStan (static analysis)
vendor/bin/phpstan analyse --memory-limit=2G
# ============================================
# Job 3: Build Assets
# ============================================
build:
name: Build Assets
runs-on: ubuntu-latest
needs: [test, lint]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install npm dependencies
run: npm ci
- name: Build production assets
run: npm run build
env:
VITE_APP_URL: ${{ secrets.APP_URL }}
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-assets
path: public/build/
retention-days: 7
# ============================================
# Job 4: Deploy to Production
# ============================================
deploy:
name: Deploy to Production
runs-on: ubuntu-latest
needs: [build]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
environment: production
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: build-assets
path: public/build/
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ env.PHP_VERSION }}
tools: composer:v2
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
cd /var/www/myapp
git pull origin main
composer install --prefer-dist --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan queue:restart
- name: Deploy artifacts to server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
source: "public/build/"
target: "/var/www/myapp/public/build/"Menjelaskan Workflow di Atas
Mari kita bedah satu per satu bagian dari workflow di atas:
Job: Test
Job ini berfokus pada menjalankan PHPUnit test. Perhatikan beberapa hal penting:
- Service MySQL — Kita menggunakan service container MySQL untuk testing, karena Laravel biasanya membutuhkan database saat menjalankan test.
- Composer Cache — Kita caching Composer dependencies untuk mempercepat build time di run berikutnya.
- Environment Setup — Kita copy
.env.exampleke.env, generate application key, dan konfigurasi database. - Coverage Report — Kita menggunakan
--coverage --min=80untuk memastikan minimal 80% kode ter-cover oleh test.
Job: Lint
Job ini menjalankan code quality checks:
- PHP CodeSniffer — Memastikan kode mengikuti coding standard PSR-12.
- PHPStan — Melakukan static analysis untuk menemukan potensi bug sebelum code dijalankan.
Job: Build
Job ini build assets frontend (CSS, JS) menggunakan Vite:
- Node.js Setup — Kita setup Node.js untuk menjalankan build command.
- npm ci — Menginstal dependencies berdasarkan
package-lock.jsonuntuk reproducibility. - Upload Artifacts — Build artifacts disimpan agar bisa digunakan oleh job deploy.
Job: Deploy
Job ini hanya berjalan di branch main dan hanya saat event push:
- Conditional Execution —
if: github.ref == 'refs/heads/main'memastikan deploy hanya terjadi di branch main. - Environment Protection —
environment: productionmemungkinkan kita mengatur approval rules di GitHub. - SSH Deploy — Kita menggunakan
appleboy/ssh-actionuntuk menjalankan deploy command di server.
Secrets Management
Salah satu hal penting dalam CI/CD adalah bagaimana kita mengelola secrets (kata sandi, API keys, SSH keys, dll). GitHub Actions menyediakan fitur Repository Secrets yang aman.
Menambahkan Secrets
- Buka repository di GitHub
- Masuk ke Settings → Secrets and variables → Actions
- Klik New repository secret
- Masukkan nama dan nilai secret
Menggunakan Secrets dalam Workflow
steps:
- name: Deploy
env:
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
API_KEY: ${{ secrets.API_KEY }}
APP_URL: ${{ secrets.APP_URL }}
run: |
echo "Deploying to $APP_URL"
# Jalankan deploy scriptTips Keamanan
- Jangan pernah hardcode secrets di dalam file workflow. Selalu gunakan repository secrets.
- Gunakan Environment Secrets untuk secrets yang berbeda per environment (staging vs production).
- Rotate secrets secara berkala — ubah password atau API key secara berkala untuk keamanan.
- Gunakan OpenID Connect untuk authenticasi ke cloud providers (AWS, GCP, Azure) tanpa menyimpan credentials.
OpenID Connect untuk AWS
permissions:
id-token: write
contents: read
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
aws-region: ap-southeast-1
- name: Deploy to S3
run: aws s3 sync ./public/build/ s3://my-bucket/build/Caching untuk Mempercepat Build
Build time yang lama bisa sangat mengganggu produktivitas. GitHub Actions menyediakan beberapa cara untuk caching:
Cache Composer Dependencies
- name: Get Composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache Composer dependencies
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-restore-keys digunakan sebagai fallback jika exact match cache tidak ditemukan. Ini memastikan kita selalu mendapat cache terdekat yang tersedia.
Cache Node.js Dependencies
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'Action setup-node sudah built-in support untuk caching npm dependencies. Cukup tambahkan cache: 'npm' dan otomatis semua dependencies akan di-cache.
Cache Docker Layers
- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myapp:latest
cache-from: type=gha
cache-to: type=gha,mode=maxDengan caching Docker layers, build time bisa berkurang drastis dari beberapa menit menjadi puluhan detik.
Matrix Builds
Matrix builds memungkinkan kita menjalankan workflow dengan berbagai kombinasi versi PHP, Node.js, atau database secara paralel. Ini sangat berguna untuk memastikan kompatibilitas lintas versi.
Contoh: Test di Berbagai Versi PHP
jobs:
test:
name: PHP ${{ matrix.php-version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php-version: ['8.1', '8.2', '8.3']
database: ['mysql', 'sqlite']
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: testing
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping"
--health-interval=10s
--health-timeout=5s
--health-retries=3
# Hanya jalankan MySQL jika matrix database = mysql
if: ${{ matrix.database == 'mysql' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: mbstring, xml, ctype, json, bcmath, pdo
tools: composer:v2
- name: Install dependencies
run: composer install --prefer-dist --no-progress
- name: Setup SQLite for testing
if: ${{ matrix.database == 'sqlite' }}
run: |
touch database/database.sqlite
cp .env.example .env
sed -i 's/DB_CONNECTION=mysql/DB_CONNECTION=sqlite/' .env
sed -i 's/DB_DATABASE=laravel/DB_DATABASE=database\/database.sqlite/' .env
- name: Setup MySQL for testing
if: ${{ matrix.database == 'mysql' }}
run: |
cp .env.example .env
sed -i 's/DB_DATABASE=laravel/DB_DATABASE=testing/' .env
sed -i 's/DB_USERNAME=root/DB_USERNAME=root/' .env
sed -i 's/DB_PASSWORD=/DB_PASSWORD=password/' .env
- name: Generate application key
run: php artisan key:generate
- name: Run migrations
run: php artisan migrate --force
- name: Run tests
run: php artisan testDengan konfigurasi di atas, kita akan menjalankan test di 6 kombinasi:
- PHP 8.1 + MySQL
- PHP 8.1 + SQLite
- PHP 8.2 + MySQL
- PHP 8.2 + SQLite
- PHP 8.3 + MySQL
- PHP 8.3 + SQLite
Contoh: Matrix Build untuk Multi-Platform
jobs:
build:
name: Build (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18, 20, 22]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run buildWorkflow untuk Deploy ke Berbagai Platform
Deploy ke Vercel
name: Deploy to Vercel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
working-directory: ./Deploy ke Docker Hub
name: Build and Push Docker Image
on:
push:
tags:
- 'v*'
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: myusername/myapp
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=maxDeploy ke AWS ECS
name: Deploy to AWS ECS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ap-southeast-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build, tag, and push image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: myapp
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:latest .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
- name: Deploy to ECS
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ecs-task-definition.json
service: myapp-service
cluster: myapp-cluster
wait-for-service-stability: trueReusable Workflows
Ketika kita memiliki banyak proyek dengan workflow yang mirip, reusable workflows bisa menghemat waktu dan menjaga konsistensi.
Membuat Reusable Workflow
# .github/workflows/reusable-laravel-ci.yml
name: Reusable Laravel CI
on:
workflow_call:
inputs:
php-version:
description: 'PHP version'
required: false
default: '8.2'
type: string
node-version:
description: 'Node.js version'
required: false
default: '20'
type: string
secrets:
SERVER_HOST:
required: true
SERVER_USER:
required: true
SERVER_SSH_KEY:
required: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ inputs.php-version }}
- run: composer install --prefer-dist --no-progress
- run: php artisan test
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ inputs.php-version }}
tools: phpcs
- run: composer install --prefer-dist --no-progress
- run: vendor/bin/phpcs --standard=PSR12 app/Menggunakan Reusable Workflow
# .github/workflows/ci.yml (di proyek utama)
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
ci:
uses: ./.github/workflows/reusable-laravel-ci.yml
with:
php-version: '8.2'
secrets: inheritTips dan Best Practices
1. Gunakan concurrency untuk menghemat resources
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: trueIni akan membatalkan workflow yang sedang berjalan di branch yang sama ketika ada push baru.
2. Gunakan environments untuk approval gates
jobs:
deploy:
environment:
name: production
url: https://myapp.comAnda bisa mengatur approval rules di Settings → Environments → production.
3. Gunakan dependabot untuk update actions
Buat file .github/dependabot.yml:
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"4. Pantau workflow runs
GitHub Actions menyediakan dashboard untuk memantau semua workflow runs. Perhatikan:
- Duration — Jika workflow mulai melambati, mungkin ada masalah dengan caching.
- Failure rate — Jika banyak gagal, periksa apakah ada flaky tests.
- Cost — Pantau penggunaan minutes, terutama untuk private repos.
5. Jangan lupa untuk test workflow Anda
Sebelum push ke main, test workflow di branch feature terlebih dahulu. Buat branch baru, buat perubahan di workflow file, dan push. Pastikan workflow berjalan dengan benar sebelum merge ke main.
Troubleshooting Umum
Workflow gagal di step "composer install"
Pastikan versi PHP yang digunakan kompatibel dengan dependencies di composer.json. Gunakan matrix builds untuk test di berbagai versi PHP.
Test gagal karena database
Pastikan service container MySQL sudah berjalan sebelum migrasi dijalankan. Gunakan health check untuk memastikan MySQL siap menerima koneksi.
Deploy gagal dengan SSH error
Pastikan SSH key yang digunakan sudah benar dan terdaftar di server. Juga, pastikan server IP sudah ditambahkan ke allowlist di firewall.
Workflow lambat
- Gunakan caching untuk Composer dan npm dependencies
- Gunakan
npm cialih-alihnpm install - Pertimbangkan untuk menggunakan self-hosted runner untuk build yang berat
Kesimpulan
CI/CD dengan GitHub Actions adalah cara yang powerful untuk mengotomasi pipeline development kita. Dengan memahami konsep dasar workflow, job, steps, dan action, kita bisa membuat pipeline yang robust dan reliable.
Beberapa poin penting yang perlu diingat:
- CI/CD bukan sekedar tools — ini adalah mindset dan praktik kerja yang membantu tim bekerja lebih efisient.
- GitHub Actions sangat fleksibel — bisa digunakan untuk hampir semua kebutuhan otomasi, bukan hanya CI/CD.
- Mulai dari yang sederhana — tidak perlu langsung membuat workflow yang kompleks. Mulai dari test saja, lalu tambah step satu per satu.
- Manfaatkan marketplace — banyak action yang sudah tersedia dan bisa langsung digunakan.
- Jaga keamanan — selalu gunakan secrets management dan hindari hardcode credentials.
Sekarang giliran kalian untuk mencoba! Buat workflow pertama kalian, dan rasakan bagaimana rasanya push code dan lihat semuanya berjalan otomatis. Happy coding! 🎉
Artikel ini ditulis sebagai bagian dari seri tutorial DevOps. Jika kalian punya pertanyaan atau ingin request topik lain, jangan ragu untuk meninggalkan komentar di bawah!
Tulisan lain
Docker untuk Developer PHP/Laravel: Panduan Lengkap
· 2 menit baca
Database Design Patterns yang Wajib Diketahui Developer
· 7 menit baca
Microservices vs Monolith: Pilih yang Mana?
· 10 menit baca