Kuasai GitHub Actions dari konsep inti hingga produksi. Pelajari workflows, jobs, actions, dan build complete CI/CD pipelines. Pahami repository structure, best practices, dan implement automated testing, linting, building, dan deployment workflows untuk modern development teams.

Manual deployments adalah slow, error-prone, dan tidak scale. Setiap kali code dipush, developers manually run tests, build artifacts, dan deploy ke production. Process ini adalah tedious, inconsistent, dan prone ke human error.
GitHub Actions adalah continuous integration dan continuous deployment (CI/CD) platform yang automate software workflows directly dalam repository Anda. Digunakan oleh millions dari developers dan organizations, GitHub Actions enable Anda untuk build, test, dan deploy code automatically whenever Anda push changes.
Dalam artikel ini, kita akan mengeksplorasi arsitektur GitHub Actions, memahami CI/CD fundamentals, dan build production-ready pipelines yang automate testing, linting, building, dan deployment untuk modern development teams.
Traditional CI/CD approaches memiliki significant limitations:
Separate Tools: Memerlukan external services seperti Jenkins, CircleCI, atau Travis CI.
Complex Setup: Difficult untuk configure dan maintain separate infrastructure.
Context Switching: Developers harus leave GitHub untuk manage CI/CD.
Limited Integration: Poor integration dengan GitHub features dan workflows.
Cost: Expensive infrastructure dan licensing fees.
Vendor Lock-in: Difficult untuk migrate between CI/CD platforms.
Slow Feedback: Delays antara code push dan test results.
GitHub Actions dibangun untuk solve problems ini:
Native Integration: Built directly ke GitHub, no external tools needed.
Easy Setup: Simple YAML configuration dalam repository Anda.
Powerful Automation: Automate any workflow, bukan hanya CI/CD.
Community Actions: Thousands dari pre-built actions available.
Free untuk Public Repos: No cost untuk open-source projects.
Fast Feedback: Immediate test results dan notifications.
Flexible: Works dengan any language, framework, atau platform.
Workflow: Automated process defined dalam YAML, triggered oleh events.
Event: Trigger yang start workflow (push, pull_request, schedule, etc.).
Job: Set dari steps yang execute pada same runner.
Step: Individual task dalam job (run command, use action, etc.).
Action: Reusable unit dari code yang perform specific task.
Runner: Machine yang execute jobs (GitHub-hosted atau self-hosted).
Artifact: Files produced oleh job yang bisa digunakan oleh other jobs.
Secret: Encrypted environment variable untuk sensitive data.
Event Triggered → Workflow Loaded → Jobs Queued → Runner Assigned → Steps Executed → Results Reported.github/workflows/GitHub Repository
↓
Event Triggered (push, PR, schedule)
↓
Workflow File Loaded (.github/workflows/*.yml)
↓
Jobs Created
↓
Runner Assigned (GitHub-hosted atau self-hosted)
↓
Steps Executed
↓
Artifacts & Logs Stored
↓
Status Reported (Checks, Notifications)Workflows triggered oleh events dan define automation.
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 0 * * *' # Daily di midnight
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run tests
run: npm testCommon Events:
on:
push: # Code pushed ke repository
pull_request: # Pull request opened/updated
schedule: # Scheduled time
workflow_dispatch: # Manual trigger
release: # Release published
issues: # Issue opened/closed
pull_request_review: # PR review submitted
repository_dispatch: # External trigger via APIUse Cases:
Jobs contain steps yang execute sequentially atau dalam parallel.
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm install
- run: npm run lint
- run: npm test
build:
runs-on: ubuntu-latest
needs: test # Wait untuk test job complete
steps:
- uses: actions/checkout@v3
- run: npm run build
- uses: actions/upload-artifact@v3
with:
name: build
path: dist/Use Cases:
Actions adalah reusable units dari code.
steps:
# Official GitHub actions
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- uses: actions/upload-artifact@v3
with:
name: build
path: dist/
# Community actions
- uses: codecov/codecov-action@v3
- uses: aquasecurity/trivy-action@master
- uses: docker/build-push-action@v4
# Local actions
- uses: ./.github/actions/custom-actionPopular Actions:
Use Cases:
Runners execute jobs pada specified operating systems.
jobs:
test-linux:
runs-on: ubuntu-latest
steps:
- run: echo "Running pada Linux"
test-windows:
runs-on: windows-latest
steps:
- run: echo "Running pada Windows"
test-macos:
runs-on: macos-latest
steps:
- run: echo "Running pada macOS"
test-matrix:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [16, 18, 20]
steps:
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm testAvailable Runners:
Use Cases:
Manage sensitive data securely.
env:
NODE_ENV: production
LOG_LEVEL: info
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v3
- name: Deploy
run: |
echo "Deploying ke ${{ secrets.DEPLOY_HOST }}"
curl -X POST ${{ secrets.WEBHOOK_URL }} \
-H "Authorization: Bearer ${{ secrets.API_TOKEN }}"
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
API_KEY: ${{ secrets.API_KEY }}Secret Types:
Use Cases:
Store dan retrieve files antara jobs.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
# Cache dependencies
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
- run: npm install
- run: npm run build
# Upload artifacts
- uses: actions/upload-artifact@v3
with:
name: build-output
path: dist/
retention-days: 5
deploy:
needs: build
runs-on: ubuntu-latest
steps:
# Download artifacts
- uses: actions/download-artifact@v3
with:
name: build-output
path: dist/
- name: Deploy
run: |
echo "Deploying files dari dist/"
ls -la dist/Use Cases:
Run steps atau jobs based pada conditions.
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# Run hanya pada main branch
- name: Deploy ke production
if: github.ref == 'refs/heads/main'
run: npm run deploy:prod
# Run hanya pada pull requests
- name: Comment pada PR
if: github.event_name == 'pull_request'
run: echo "Ini adalah pull request"
# Run hanya pada failure
- name: Notify pada failure
if: failure()
run: echo "Build failed!"
# Run hanya pada success
- name: Notify pada success
if: success()
run: echo "Build succeeded!"
# Run always
- name: Cleanup
if: always()
run: rm -rf temp/Condition Functions:
Use Cases:
Control access dan deployment environments.
permissions:
contents: read
pull-requests: write
checks: write
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v3
- name: Deploy ke staging
run: npm run deploy:staging
deploy-production:
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
needs: deploy-staging
steps:
- uses: actions/checkout@v3
- name: Deploy ke production
run: npm run deploy:prodPermission Scopes:
Use Cases:
Report workflow status dan results.
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm test
# Create check run
- uses: actions/github-script@v6
if: always()
with:
script: |
github.rest.checks.create({
owner: context.repo.owner,
repo: context.repo.repo,
name: 'Test Results',
head_sha: context.sha,
status: 'completed',
conclusion: 'success',
output: {
title: 'All tests passed',
summary: 'No failures detected'
}
})Use Cases:
Share workflows across repositories.
# .github/workflows/test.yml
name: Test
on:
workflow_call:
inputs:
node-version:
required: false
type: string
default: '18'
secrets:
npm-token:
required: false
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ inputs.node-version }}
registry-url: 'https://registry.npmjs.org'
- run: npm install
- run: npm test
env:
NODE_AUTH_TOKEN: ${{ secrets.npm-token }}
# .github/workflows/ci.yml (calling reusable workflow)
name: CI
on: [push, pull_request]
jobs:
test:
uses: ./.github/workflows/test.yml
with:
node-version: '18'
secrets:
npm-token: ${{ secrets.NPM_TOKEN }}Use Cases:
Well-organized repository include GitHub-specific configuration files dan workflows.
.
├── .github/
│ ├── CODEOWNERS # Code ownership rules
│ ├── FUNDING.yml # Sponsorship information
│ ├── SECURITY.md # Security policy
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml # Bug report template
│ │ ├── feature_request.yml # Feature request template
│ │ ├── config.yml # Issue template config
│ │ └── blank.md # Blank issue template
│ ├── PULL_REQUEST_TEMPLATE.md # PR template
│ ├── dependabot.yml # Dependabot configuration
│ ├── labeler.yml # Label automation
│ └── workflows/
│ ├── lint.yml # Linting workflow
│ ├── test.yml # Testing workflow
│ ├── build.yml # Build workflow
│ ├── pr-checks.yml # PR validation
│ ├── release.yml # Release workflow
│ ├── deploy.yml # Deployment workflow
│ └── security.yml # Security scanning
├── CONTRIBUTING.md # Contribution guidelines
├── LICENSE # License file
├── README.md # Project documentation
├── package.json
├── src/
└── tests/Define code ownership dan require reviews.
# Global owners
* @maintainer1 @maintainer2
# Frontend code
/src/components/ @frontend-team
/src/pages/ @frontend-team
# Backend code
/src/api/ @backend-team
/src/services/ @backend-team
# DevOps
/docker/ @devops-team
/.github/workflows/ @devops-team
# Documentation
/docs/ @documentation-team
*.md @documentation-team
# Tests
/tests/ @qa-teamUse Cases:
Display sponsorship options.
github: [maintainer1, maintainer2]
patreon: username
ko_fi: username
custom: ['https://example.com/donate']Define security policy dan reporting.
# Security Policy
## Reporting a Vulnerability
Please email security@example.com dengan:
- Description dari vulnerability
- Steps untuk reproduce
- Potential impact
- Suggested fix (jika ada)
## Supported Versions
| Version | Supported |
|---------|-----------|
| 2.x | ✅ |
| 1.x | ❌ |
## Security Updates
Security updates dirilis sebagai patch versions.Standardize issue reporting.
name: Bug Report
description: Report bug
title: "[BUG] "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks untuk reporting bug!
- type: textarea
id: description
attributes:
label: Description
description: Describe bug
placeholder: Apa yang terjadi?
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps untuk Reproduce
description: Bagaimana untuk reproduce bug
placeholder: |
1. Go ke...
2. Click...
3. See error...
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Behavior
description: Apa yang seharusnya terjadi
validations:
required: true
- type: textarea
id: environment
attributes:
label: Environment
description: |
- OS: [e.g. macOS, Windows, Linux]
- Browser: [e.g. Chrome, Firefox]
- Version: [e.g. 1.0.0]
validations:
required: trueStandardize PR descriptions.
## Description
Brief description dari changes
## Type dari Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Related Issues
Closes #(issue number)
## Testing
- [ ] Unit tests added
- [ ] Integration tests added
- [ ] Manual testing completed
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Comments added untuk complex logic
- [ ] Documentation updated
- [ ] No new warnings generated
- [ ] Tests pass locally
## Screenshots (jika applicable)
Add screenshots untuk UI changes
## Additional Context
Any additional informationAutomate dependency updates.
version: 2
updates:
# npm dependencies
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "03:00"
open-pull-requests-limit: 5
reviewers:
- "maintainer1"
labels:
- "dependencies"
commit-message:
prefix: "chore(deps):"
# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependencies"
- "github-actions"
# Docker
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependencies"
- "docker"Automate label assignment.
# Label based pada file changes
frontend:
- changed-files:
- any-glob-to-any-file: 'src/components/**'
backend:
- changed-files:
- any-glob-to-any-file: 'src/api/**'
devops:
- changed-files:
- any-glob-to-any-file: '.github/**'
- any-glob-to-any-file: 'docker/**'
documentation:
- changed-files:
- any-glob-to-any-file: '**/*.md'
tests:
- changed-files:
- any-glob-to-any-file: 'tests/**'name: Lint
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- name: Run ESLint
run: npm run lint
- name: Run Prettier
run: npm run format:check
- name: Run TypeScript
run: npm run type-checkname: Test
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- name: Run unit tests
run: npm run test:unit
- name: Run integration tests
run: npm run test:integration
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage/coverage-final.json
flags: unittests
name: codecov-umbrellaname: Build
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- name: Build application
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build
path: dist/
retention-days: 5
- name: Check bundle size
run: npm run build:analyzename: PR Checks
on:
pull_request:
branches: [main, develop]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- name: Lint
run: npm run lint
- name: Type check
run: npm run type-check
- name: Test
run: npm run test
- name: Build
run: npm run build
- name: Check untuk breaking changes
run: npm run check:breaking-changes
- name: Generate coverage report
run: npm run test:coverage
- name: Comment PR dengan results
if: always()
uses: actions/github-script@v6
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '✅ All checks passed!'
})name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- name: Build
run: npm run build
- name: Publish ke npm
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Create GitHub Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
body: |
Changes dalam Release ini
- Feature 1
- Feature 2
draft: false
prerelease: false
- name: Upload artifacts
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./dist/app.zip
asset_name: app.zip
asset_content_type: application/zipname: Deploy
on:
push:
branches: [main]
workflow_dispatch:
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Deploy ke staging
run: |
npm run deploy:staging
env:
DEPLOY_KEY: ${{ secrets.STAGING_DEPLOY_KEY }}
DEPLOY_HOST: ${{ secrets.STAGING_HOST }}
deploy-production:
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
needs: deploy-staging
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Deploy ke production
run: |
npm run deploy:prod
env:
DEPLOY_KEY: ${{ secrets.PROD_DEPLOY_KEY }}
DEPLOY_HOST: ${{ secrets.PROD_HOST }}
- name: Notify deployment
if: success()
run: |
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-H 'Content-Type: application/json' \
-d '{"text":"Deployment successful!"}'name: Security
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
schedule:
- cron: '0 0 * * 0' # Weekly
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
- name: Run npm audit
run: npm audit --audit-level=moderate
- name: SAST dengan CodeQL
uses: github/codeql-action/init@v2
with:
languages: 'javascript'
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2name: Labeler
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
label:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/labeler@v4
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
configuration-path: .github/labeler.yml# ❌ Wrong - secrets dalam workflow
- name: Deploy
run: |
curl -H "Authorization: Bearer abc123xyz" https://api.example.com
# ✅ Correct - use secrets
- name: Deploy
run: |
curl -H "Authorization: Bearer ${{ secrets.API_TOKEN }}" https://api.example.com# ❌ Wrong - reinstalls dependencies setiap time
- run: npm install
- run: npm test
# ✅ Correct - cache dependencies
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
- run: npm ci
- run: npm test# ❌ Wrong - runs semua combinations
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [14, 16, 18, 20]
# Results dalam 12 jobs
# ✅ Correct - hanya necessary combinations
strategy:
matrix:
include:
- os: ubuntu-latest
node-version: 18
- os: windows-latest
node-version: 18
- os: macos-latest
node-version: 18# ❌ Wrong - no error handling
- name: Deploy
run: npm run deploy
# ✅ Correct - handle errors
- name: Deploy
run: npm run deploy
continue-on-error: true
- name: Notify pada failure
if: failure()
run: echo "Deployment failed"# ❌ Wrong - sequential jobs
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: npm test
lint:
needs: test
runs-on: ubuntu-latest
steps:
- run: npm run lint
# ✅ Correct - parallel jobs
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: npm test
lint:
runs-on: ubuntu-latest
steps:
- run: npm run lint# ❌ Wrong - uses latest
- uses: actions/checkout@latest
# ✅ Correct - uses specific version
- uses: actions/checkout@v3.github/workflows/
├── lint.yml # Code quality
├── test.yml # Testing
├── build.yml # Building
├── security.yml # Security scanning
├── deploy.yml # Deployment
└── release.yml # Release process# Share common logic across workflows
jobs:
test:
uses: ./.github/workflows/test.yml
with:
node-version: '18'# Require workflows untuk pass sebelum merge
# Settings → Branches → Branch protection rules
# → Require status checks untuk pass sebelum merging# Track execution time
- name: Report timing
run: |
echo "Workflow completed dalam ${{ job.duration }} seconds"environment:
name: production
url: https://example.com# Add comments explaining complex logic
# Use descriptive job dan step names
- name: Run security scan dengan Trivy
run: trivy scan .# Use act untuk test workflows locally
act -j testGitHub Actions transform CI/CD dari complex infrastructure menjadi simple, integrated automation. Memahami workflows, jobs, actions, dan best practices enable Anda untuk build reliable, efficient pipelines.
Key takeaways:
Next steps:
GitHub Actions makes CI/CD accessible dan powerful. Master it, dan Anda akan build systems yang reliable, fast, dan maintainable.