CI/CD Pipeline with GitHub Actions: Complete Guide
Build a robust CI/CD pipeline using GitHub Actions for automated testing, building, and deployment
Continuous Integration and Continuous Deployment (CI/CD) are essential practices in modern software development. GitHub Actions provides a powerful, integrated way to automate your workflows directly from your repository.
Why GitHub Actions?
GitHub Actions offers several advantages:
- Integrated with GitHub: No need for external CI/CD tools
- Matrix builds: Test across multiple OS and language versions
- Marketplace: Thousands of pre-built actions
- Free tier: 2,000 minutes/month for private repositories
- Flexible: YAML-based configuration
Basic Workflow Structure
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "18"
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
Advanced Features
Matrix Strategy
Test across multiple versions and platforms:
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [16, 18, 20]
steps:
- uses: actions/checkout@v3
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
Caching Dependencies
Speed up workflows by caching dependencies:
- name: Cache node modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
Docker Integration
Build and push Docker images:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: user/app:latest
cache-from: type=gha
cache-to: type=gha,mode=max
Deployment Workflows
Deploy to AWS
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Deploy to ECS
run: |
aws ecs update-service --cluster my-cluster \
--service my-service --force-new-deployment
Deploy to Kubernetes
- name: Setup kubectl
uses: azure/setup-kubectl@v3
- name: Deploy to Kubernetes
run: |
kubectl config set-context --current --namespace=production
kubectl apply -f k8s/
kubectl rollout status deployment/myapp
Security Best Practices
Use Secrets
Never hardcode sensitive information:
- name: Run deployment
env:
API_KEY: ${{ secrets.API_KEY }}
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
run: ./deploy.sh
Dependency Scanning
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
Code Scanning
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: javascript
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
Complete Production Pipeline
name: Production Pipeline
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "18"
- run: npm ci
- run: npm test
- run: npm run lint
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
myregistry/app:latest
myregistry/app:${{ github.sha }}
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy to production
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.PROD_HOST }}
username: ${{ secrets.PROD_USER }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /app
docker-compose pull
docker-compose up -d
Monitoring and Notifications
Slack Notifications
- name: Notify Slack
if: always()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: "Deployment to production completed"
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
Best Practices Checklist
- ✅ Use specific action versions (e.g.,
@v3 not @latest)
- ✅ Cache dependencies to speed up builds
- ✅ Use matrix builds for comprehensive testing
- ✅ Implement proper secret management
- ✅ Add status checks for pull requests
- ✅ Use environments for deployment approvals
- ✅ Monitor workflow execution times
- ✅ Set up notifications for failures
Conclusion
GitHub Actions provides a powerful, flexible platform for building CI/CD pipelines. Start with simple workflows and gradually add complexity as your needs grow.
The integration with GitHub's ecosystem makes it an excellent choice for teams already using GitHub for version control.
Resources