name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
env:
NODE_VERSION: '20'
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
lint:
name: Lint & Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
- run: npm ci
- run: npm run lint
- run: npm run format:check
test:
name: Test
runs-on: ubuntu-latest
needs: lint
strategy:
matrix:
node-version: [18, 20, 22]
services:
postgres:
image: postgres:16
env:
POSTGRES_DB: test
POSTGRES_PASSWORD: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- run: npm test -- --coverage
env:
DATABASE_URL: postgres://postgres:test@localhost:5432/test
- uses: actions/upload-artifact@v4
if: matrix.node-version == 20
with:
name: coverage
path: coverage/
build:
name: Build & Push Image
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'
permissions:
contents: read
packages: write
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha
type=semver,pattern={{version}}
- 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=max
deploy:
name: Deploy to Production
runs-on: ubuntu-latest
needs: build
environment:
name: production
url: https://app.example.com
steps:
- uses: actions/checkout@v4
- uses: azure/setup-kubectl@v3
- uses: azure/k8s-set-context@v3
with:
kubeconfig: ${{ secrets.KUBE_CONFIG }}
- run: |
kubectl set image deployment/web-app web-app=${{ needs.build.outputs.image-tag }} -n production
kubectl rollout status deployment/web-app -n production
GitHub Actions automates build, test, and deploy workflows. Workflows are defined in .github/workflows/ YAML files. The on key specifies triggers—push, pull_request, schedule, or workflow_dispatch. Jobs run on runners with configurable OS. steps execute sequentially within a job. The uses keyword references reusable actions. env and secrets inject configuration securely. Matrix strategies test across multiple versions simultaneously. Caching with actions/cache speeds up dependency installation. Artifacts persist build outputs between jobs. Concurrency groups prevent duplicate runs. Environment protection rules gate deployments. Status checks enforce quality before merging.