CI/CD with GitHub Actions: Automating Your Development Workflow
Introduction
Continuous Integration and Continuous Deployment (CI/CD) have become essential practices in modern software development. GitHub Actions provides a powerful, integrated CI/CD platform that automates your development workflow directly in your GitHub repository.
This comprehensive guide covers CI/CD with GitHub Actions, from basic workflows to advanced automation. You'll learn how to automate testing, building, and deployment processes, improving code quality and deployment speed.
What is CI/CD?
CI/CD stands for Continuous Integration and Continuous Deployment:
Continuous Integration (CI):
- Automatically test code on every commit
- Catch bugs early in development
- Ensure code quality
- Run automated tests
- Perform code analysis
Continuous Deployment (CD):
- Automatically deploy code to production
- Reduce manual deployment errors
- Faster time to market
- Consistent deployment process
Benefits:
- Faster Development: Automated processes save time
- Higher Quality: Catch issues early
- Reduced Risk: Automated testing and deployment
- Better Collaboration: Team sees results immediately
- Consistent Deployments: Same process every time
Getting Started with GitHub Actions
GitHub Actions workflows are defined in YAML files:
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
on:
# Push to branches
push:
branches: [ main, develop ]
# Pull requests
pull_request:
branches: [ main ]
# Scheduled (cron)
schedule:
- cron: '0 0 * * *' # Daily at midnight
# Manual trigger
workflow_dispatch:
# Release
release:
types: [ published ]
Common CI/CD Workflows
Here are common CI/CD workflow patterns:
name: Node.js CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage/lcov.info
name: Python CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-cov
- name: Run tests
run: pytest --cov=src --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v3
name: Docker Build
on:
push:
branches: [ main ]
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: user/app:latest
Deployment Workflows
Automate deployment with GitHub Actions:
name: Deploy to AWS
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- 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 Elastic Beanstalk
run: |
eb init -p python-3.9 myapp
eb deploy
name: Deploy to Vercel
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to Vercel
uses: amondnet/vercel-action@v20
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.ORG_ID }}
vercel-project-id: ${{ secrets.PROJECT_ID }}
name: Deploy to Kubernetes
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up kubectl
uses: azure/setup-kubectl@v2
- name: Configure kubectl
run: |
echo "${{ secrets.KUBECONFIG }}" > $HOME/.kube/config
- name: Deploy
run: |
kubectl set image deployment/myapp myapp=myapp:${{ github.sha }}
kubectl rollout status deployment/myapp
Advanced Workflow Features
GitHub Actions provides advanced features for complex workflows:
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
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
steps:
- name: Run tests
run: npm test
- name: Deploy
if: github.ref == 'refs/heads/main'
run: npm run deploy
env:
NODE_ENV: production
API_URL: ${{ secrets.API_URL }}
jobs:
deploy:
runs-on: ubuntu-latest
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
steps:
- name: Deploy
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
run: ./deploy.sh
steps:
- name: Build
run: npm run build
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: dist
path: dist/
- name: Download artifacts
uses: actions/download-artifact@v3
with:
name: dist
Best Practices
Follow these best practices for effective CI/CD:
1. Fast Feedback:
- Run quick tests first
- Parallelize jobs when possible
- Cache dependencies
2. Security:
- Use secrets for sensitive data
- Never commit secrets
- Use least privilege
- Scan for vulnerabilities
3. Reliability:
- Use specific action versions
- Test workflows locally
- Handle failures gracefully
- Use retry logic
4. Maintainability:
- Reusable workflows
- Clear workflow names
- Document complex steps
- Keep workflows simple
Example Reusable Workflow:
# .github/workflows/reusable-test.yml
name: Reusable Test
on:
workflow_call:
inputs:
node-version:
required: true
type: string
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ inputs.node-version }}
- run: npm ci
- run: npm test
Conclusion
GitHub Actions provides a powerful, integrated CI/CD platform that automates your development workflow. By implementing CI/CD practices, you can improve code quality, reduce deployment time, and catch issues early.
Start with simple workflows and gradually add more automation. Focus on fast feedback, security, and reliability to build effective CI/CD pipelines. Remember that CI/CD is not just about automationβit's about improving your development process and delivering better software faster.
With the right approach, GitHub Actions can transform your development workflow, making it more efficient, reliable, and enjoyable.