DevOps

Building Modern CI/CD Pipelines with GitHub Actions

📅 December 12, 2025 ⏱️ 2 min read 👁️ 12 views 🏷️ DevOps

GitHub Actions provides powerful automation for CI/CD pipelines directly in your repository. This guide covers practical workflows for modern development.

Basic CI Workflow


# .github/workflows/ci.yml
name: CI Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        python-version: ['3.9', '3.10', '3.11']
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      
      - name: Cache pip packages
        uses: actions/cache@v3
        with:
          path: ~/.cache/pip
          key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
      
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install pytest pytest-cov
      
      - name: Run tests with coverage
        run: |
          pytest --cov=src --cov-report=xml --cov-report=html
      
      - name: Upload coverage report
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage.xml

Docker Build and Push


# .github/workflows/docker.yml
name: Docker Build

on:
  push:
    tags: ['v*']

jobs:
  build-push:
    runs-on: ubuntu-latest
    
    steps:
      - 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_PASSWORD }}
      
      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: username/my-app
          tags: |
            type=semver,pattern={{version}}
            type=sha
      
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

Complete CD Pipeline with Kubernetes


# .github/workflows/cd.yml
name: Deploy to Production

on:
  release:
    types: [published]

env:
  CLUSTER_NAME: production-cluster
  NAMESPACE: my-app

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        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: Update kubeconfig
        run: |
          aws eks update-kubeconfig --name $CLUSTER_NAME
      
      - name: Deploy to Kubernetes
        run: |
          kubectl set image deployment/my-app             my-app=username/my-app:${{ github.event.release.tag_name }}             -n $NAMESPACE
          
          kubectl rollout status deployment/my-app -n $NAMESPACE
      
      - name: Run smoke tests
        run: |
          ./scripts/smoke-tests.sh
      
      - name: Notify on Slack
        if: always()
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          channel: '#deployments'
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

Reusable Workflows


# .github/workflows/reusable-test.yml
name: Reusable Test Workflow

on:
  workflow_call:
    inputs:
      python-version:
        required: true
        type: string
    secrets:
      api-key:
        required: true

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ inputs.python-version }}
      - run: pytest
        env:
          API_KEY: ${{ secrets.api-key }}

# Usage in another workflow:
# jobs:
#   call-tests:
#     uses: ./.github/workflows/reusable-test.yml
#     with:
#       python-version: '3.11'
#     secrets:
#       api-key: ${{ secrets.API_KEY }}

Security Scanning


# .github/workflows/security.yml
name: Security Scan

on:
  push:
    branches: [main]
  schedule:
    - cron: '0 0 * * 0'

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          severity: 'CRITICAL,HIGH'
      
      - name: Run CodeQL analysis
        uses: github/codeql-action/analyze@v2

Well-designed CI/CD pipelines save time and improve code quality. Start simple and iterate!

🏷️ Tags:
cicd github actions devops automation deployment kubernetes

📚 Related Articles

DevOps

CI/CD Pipeline with GitHub Actions

Build automated CI/CD pipelines using GitHub Actions. Learn workflow syntax, jobs, deployment strategies, and best practices.

⏱️ 3 min 👁️ 2 views
DevOps

Git Commands Every Developer Needs

Master essential Git commands for version control. Learn branching, merging, rebasing, and team collaboration workflows.

⏱️ 3 min 👁️ 0 views