iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

GitHub Actions

GitHub Actions runs workflows in .github/workflows/*.yml. Triggered by pushes / PRs / schedules / manual dispatch; jobs run on runners (Linux, Windows, macOS, or self-hosted).

Workflow for test + build + deploy

EXAMPLE
# .github/workflows/ci.yml
name: CI
on:
    push:         { branches: [main] }
    pull_request: { branches: [main] }

concurrency:
    group: ${{ github.workflow }}-${{ github.ref }}
    cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

permissions:
    contents: read
    id-token: write          # OIDC for cloud / signing

jobs:
    test:
        runs-on: ubuntu-latest
        strategy:
            matrix:
                node: [20, 22]
        steps:
            - uses: actions/checkout@v4
            - uses: actions/setup-node@v4
              with:
                  node-version: ${{ matrix.node }}
                  cache: npm
            - run: npm ci
            - run: npm run lint
            - run: npm test -- --coverage
            - uses: codecov/codecov-action@v4
              with: { token: ${{ secrets.CODECOV_TOKEN }} }

    e2e:
        runs-on: ubuntu-latest
        needs: test
        steps:
            - uses: actions/checkout@v4
            - uses: actions/setup-node@v4
              with: { node-version: 22, cache: npm }
            - run: npm ci
            - run: npx playwright install --with-deps
            - run: npm run test:e2e
            - uses: actions/upload-artifact@v4
              if: failure()
              with:
                  name: playwright-trace
                  path: test-results/

    build-and-push:
        runs-on: ubuntu-latest
        needs: [test, e2e]
        if: github.ref == 'refs/heads/main'
        steps:
            - uses: actions/checkout@v4
            - uses: docker/setup-buildx-action@v3
            - uses: docker/login-action@v3
              with:
                  registry: ghcr.io
                  username: ${{ github.actor }}
                  password: ${{ secrets.GITHUB_TOKEN }}
            - id: meta
              uses: docker/metadata-action@v5
              with:
                  images: ghcr.io/${{ github.repository }}
                  tags: |
                      type=sha,format=long
                      type=raw,value=latest
            - uses: docker/build-push-action@v6
              with:
                  push: true
                  tags:        ${{ steps.meta.outputs.tags }}
                  labels:      ${{ steps.meta.outputs.labels }}
                  cache-from:  type=gha
                  cache-to:    type=gha,mode=max

    deploy:
        runs-on: ubuntu-latest
        needs: build-and-push
        environment:
            name: production
            url:  https://example.com
        steps:
            - uses: aws-actions/configure-aws-credentials@v4
              with:
                  role-to-assume: arn:aws:iam::123456789012:role/gh-deploy-role
                  aws-region:     us-east-1
            - run: ./scripts/deploy.sh

# Reusable workflow example
# .github/workflows/_node-ci.yml
name: node-ci
on:
    workflow_call:
        inputs:
            node-version: { type: string, default: '22' }
jobs:
    test:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4
            - uses: actions/setup-node@v4
              with: { node-version: ${{ inputs.node-version }}, cache: npm }
            - run: npm ci && npm test

# Use it:
# jobs:
#   ci:
#     uses: ./.github/workflows/_node-ci.yml
#     with: { node-version: '22' }

Why it matters

Pair concurrency: with cancel-in-progress: true on PR branches — a new push cancels the running build, saving minutes and money. Don’t do it on main: production deploys shouldn’t race.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
name: deploy
on: push
jobs:
    deploy:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4
            - uses: actions/setup-node@v4
              with: { node-version: 20 }
            - run: npm ci
            - run: npm run build
            - run: rsync -av dist/ deploy@host:/var/www/
Try it Yourself »

Exercise

Reuse a published action.

: actions/checkout@v4

Test yourself

Q1. A workflow file lives at…
Q2. A job runs on a…
Q3. Reuse an action with…

Discussion

Loading…