Github Actions

by bobmatnyc718070a7d622No license77 starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated 2 months ago

GitHub Actions CI/CD workflows for automating build, test, and deployment

Instructions onlyDevOps & Cloud
AI-generated overview

Reference guide for writing GitHub Actions CI/CD workflows in YAML for build, test, and deployment automation.

What it does
This skill provides instructional documentation on GitHub Actions, GitHub's native CI/CD platform. It explains workflow YAML structure, triggers, jobs, steps, actions, contexts, runners, matrix strategies, environment variables, and secrets, with many example workflow snippets. It also covers framework-specific pipelines, deployment patterns, testing workflows, and release automation.
When to use it
Use it when you need to author or understand GitHub Actions workflow files, such as automating tests on pull requests, building and deploying on merge, publishing packages, or scheduling recurring jobs. It is a reference for CI/CD configuration rather than an executable tool.
Requirements
No scripts are shipped; it is instructions only. Applying the guidance assumes a GitHub repository with Actions enabled, and workflows may reference repository secrets, third-party actions, and hosted or self-hosted runners.

GitHub Actions CI/CD

Summary

GitHub Actions is GitHub's native CI/CD platform for automating software workflows. Define workflows in YAML files to build, test, and deploy code directly from your repository with event-driven automation.

When to Use

  • Automate testing on every pull request
  • Build and deploy applications on merge to main
  • Schedule regular tasks (nightly builds, backups)
  • Publish packages to registries (npm, PyPI, Docker Hub)
  • Run security scans and code quality checks
  • Automate release processes and changelog generation

Quick Start

Basic Test Workflow

Create .github/workflows/test.yml:

yaml
name: Test
on:  push:    branches: [main]  pull_request:    branches: [main]
jobs:  test:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4      - uses: actions/setup-node@v4        with:          node-version: '20'      - run: npm ci      - run: npm test

Complete GitHub Actions Guide

Core Concepts

Workflows

YAML files in .github/workflows/ that define automation pipelines.

Structure:

  • Name: Workflow identifier
  • Triggers: Events that start the workflow
  • Jobs: One or more jobs to execute
  • Steps: Commands/actions within each job
yaml
name: CI Pipelineon: [push, pull_request]jobs:  build:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4      - run: echo "Building project"

Jobs

Independent execution units that run in parallel by default.

yaml
jobs:  lint:    runs-on: ubuntu-latest    steps:      - run: npm run lint
  test:    runs-on: ubuntu-latest    needs: lint  # Wait for lint to complete    steps:      - run: npm test
  deploy:    runs-on: ubuntu-latest    needs: [lint, test]  # Wait for both    steps:      - run: ./deploy.sh

Steps

Sequential commands or actions within a job.

yaml
steps:  # Use pre-built action  - uses: actions/checkout@v4
  # Run shell command  - run: npm install
  # Named step with environment  - name: Run tests    run: npm test    env:      NODE_ENV: test

Actions

Reusable units of code (from marketplace or custom).

yaml
# Official action- uses: actions/checkout@v4
# Third-party action- uses: docker/build-push-action@v5  with:    context: .    push: true    tags: user/app:latest
# Local action- uses: ./.github/actions/custom-action

Workflow Syntax

Triggers (on)

Push Events
yaml
on:  push:    branches:      - main      - 'releases/**'  # Wildcard pattern    tags:      - 'v*'  # All version tags    paths:      - 'src/**'      - '!src/docs/**'  # Exclude docs
Pull Request Events
yaml
on:  pull_request:    types: [opened, synchronize, reopened]    branches: [main, develop]    paths-ignore:      - '**.md'      - 'docs/**'
Schedule (Cron)
yaml
on:  schedule:    # Every day at 2:30 AM UTC    - cron: '30 2 * * *'    # Every Monday at 9:00 AM UTC    - cron: '0 9 * * 1'
Manual Trigger
yaml
on:  workflow_dispatch:    inputs:      environment:        description: 'Deployment environment'        required: true        type: choice        options:          - staging          - production      version:        description: 'Version to deploy'        required: false        default: 'latest'
Multiple Triggers
yaml
on:  push:    branches: [main]  pull_request:    branches: [main]  schedule:    - cron: '0 0 * * 0'  # Weekly  workflow_dispatch:  # Manual

Environment Variables

Workflow-level
yaml
env:  NODE_ENV: production  API_URL: https://api.example.com
jobs:  build:    runs-on: ubuntu-latest    steps:      - run: echo $NODE_ENV
Job-level
yaml
jobs:  test:    runs-on: ubuntu-latest    env:      TEST_DATABASE: test_db    steps:      - run: pytest
Step-level
yaml
steps:  - name: Build    run: npm run build    env:      BUILD_TARGET: production

Secrets

Store sensitive data in repository settings.

yaml
steps:  - name: Deploy    run: ./deploy.sh    env:      API_KEY: ${{ secrets.API_KEY }}      DATABASE_URL: ${{ secrets.DATABASE_URL }}

Best Practices:

  • Never commit secrets to code
  • Use GitHub encrypted secrets
  • Limit secret access to specific environments
  • Rotate secrets regularly

Contexts

github Context

Repository and workflow information.

yaml
steps:  - name: Print context    run: |      echo "Repository: ${{ github.repository }}"      echo "Ref: ${{ github.ref }}"      echo "SHA: ${{ github.sha }}"      echo "Actor: ${{ github.actor }}"      echo "Event: ${{ github.event_name }}"      echo "Branch: ${{ github.ref_name }}"

env Context

Access environment variables.

yaml
env:  BUILD_ID: 12345
steps:  - run: echo "Build ${{ env.BUILD_ID }}"

secrets Context

Access repository secrets.

yaml
- run: echo "Token exists"  env:    TOKEN: ${{ secrets.GITHUB_TOKEN }}

matrix Context

Access matrix values.

yaml
strategy:  matrix:    node: [18, 20, 22]steps:  - run: echo "Testing Node ${{ matrix.node }}"

needs Context

Access outputs from dependent jobs.

yaml
jobs:  build:    outputs:      version: ${{ steps.get_version.outputs.version }}    steps:      - id: get_version        run: echo "version=1.2.3" >> $GITHUB_OUTPUT
  deploy:    needs: build    steps:      - run: echo "Deploying ${{ needs.build.outputs.version }}"

Runners

GitHub-hosted Runners

yaml
jobs:  ubuntu:    runs-on: ubuntu-latest  # ubuntu-22.04
  macos:    runs-on: macos-latest  # macOS 14
  windows:    runs-on: windows-latest  # Windows 2022
  specific:    runs-on: ubuntu-20.04  # Specific version

Available Runners:

  • ubuntu-latest, ubuntu-22.04, ubuntu-20.04
  • macos-latest, macos-14, macos-13
  • windows-latest, windows-2022, windows-2019

Self-hosted Runners

yaml
runs-on: self-hosted
# With labelsruns-on: [self-hosted, linux, x64, gpu]

Setup:

  1. Go to Settings → Actions → Runners
  2. Click "New self-hosted runner"
  3. Follow platform-specific instructions
  4. Add custom labels for targeting

Matrix Strategies

Basic Matrix

Test across multiple versions.

yaml
strategy:  matrix:    node: [18, 20, 22]    os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}steps:  - uses: actions/setup-node@v4    with:      node-version: ${{ matrix.node }}

Include/Exclude

yaml
strategy:  matrix:    node: [18, 20, 22]    os: [ubuntu-latest, windows-latest]    include:      # Add specific combination      - node: 22        os: macos-latest        experimental: true    exclude:      # Remove specific combination      - node: 18        os: windows-latest

Fail-fast

yaml
strategy:  fail-fast: false  # Continue other jobs if one fails  matrix:    node: [18, 20, 22]

Max Parallel

yaml
strategy:  max-parallel: 2  # Run only 2 jobs concurrently  matrix:    node: [18, 20, 22]

Common Actions

Checkout Code

yaml
- uses: actions/checkout@v4  with:    fetch-depth: 0  # Full history for changelog    submodules: true  # Include submodules

Setup Node.js

yaml
- uses: actions/setup-node@v4  with:    node-version: '20'    cache: 'npm'  # or 'yarn', 'pnpm'    registry-url: 'https://registry.npmjs.org'

Setup Python

yaml
- uses: actions/setup-python@v5  with:    python-version: '3.11'    cache: 'pip'

Setup Java

yaml
- uses: actions/setup-java@v4  with:    distribution: 'temurin'    java-version: '17'    cache: 'maven'

Setup Go

yaml
- uses: actions/setup-go@v5  with:    go-version: '1.21'    cache: true

Cache Dependencies

yaml
- uses: actions/cache@v4  with:    path: |      ~/.npm      node_modules    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}    restore-keys: |      ${{ runner.os }}-node-

Upload Artifacts

yaml
- uses: actions/upload-artifact@v4  with:    name: build-output    path: dist/    retention-days: 7

Download Artifacts

yaml
- uses: actions/download-artifact@v4  with:    name: build-output    path: dist/

Conditional Execution

if Conditions

yaml
steps:  - name: Deploy to production    if: github.ref == 'refs/heads/main'    run: ./deploy.sh
  - name: Deploy to staging    if: github.ref == 'refs/heads/develop'    run: ./deploy-staging.sh
  - name: Only on PR    if: github.event_name == 'pull_request'    run: echo "This is a PR"
  - name: On success    if: success()    run: echo "Previous steps succeeded"
  - name: On failure    if: failure()    run: echo "A step failed"
  - name: Always run    if: always()    run: echo "Cleanup tasks"

Job Conditions

yaml
jobs:  deploy:    if: github.ref == 'refs/heads/main'    runs-on: ubuntu-latest    steps:      - run: ./deploy.sh

Framework-Specific Workflows

Node.js/TypeScript

yaml
name: Node.js CI
on: [push, pull_request]
jobs:  test:    runs-on: ubuntu-latest    strategy:      matrix:        node-version: [18, 20, 22]    steps:      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4        with:          node-version: ${{ matrix.node-version }}          cache: 'npm'
      - run: npm ci
      - run: npm run lint
      - run: npm run type-check
      - run: npm test        env:          CI: true
      - run: npm run build
      - uses: codecov/codecov-action@v4        if: matrix.node-version == 20        with:          token: ${{ secrets.CODECOV_TOKEN }}

Python

yaml
name: Python CI
on: [push, pull_request]
jobs:  test:    runs-on: ubuntu-latest    strategy:      matrix:        python-version: ['3.10', '3.11', '3.12']    steps:      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5        with:          python-version: ${{ matrix.python-version }}          cache: 'pip'
      - run: pip install -r requirements.txt
      - run: pip install pytest pytest-cov mypy ruff
      - run: ruff check .
      - run: mypy .
      - run: pytest --cov=. --cov-report=xml
      - uses: codecov/codecov-action@v4        if: matrix.python-version == '3.11'

Docker

yaml
name: Docker Build
on:  push:    branches: [main]    tags: ['v*']
jobs:  build:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3        with:          username: ${{ secrets.DOCKERHUB_USERNAME }}          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - uses: docker/metadata-action@v5        id: meta        with:          images: user/app          tags: |            type=ref,event=branch            type=semver,pattern={{version}}            type=semver,pattern={{major}}.{{minor}}
      - 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

Next.js with Vercel

yaml
name: Next.js CI
on:  push:    branches: [main]  pull_request:    branches: [main]
jobs:  build:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4        with:          node-version: '20'          cache: 'npm'
      - run: npm ci
      - run: npm run lint
      - run: npm run build
      - run: npm test
  deploy-preview:    if: github.event_name == 'pull_request'    runs-on: ubuntu-latest    needs: build    steps:      - uses: actions/checkout@v4
      - uses: amondnet/vercel-action@v25        with:          vercel-token: ${{ secrets.VERCEL_TOKEN }}          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
  deploy-production:    if: github.ref == 'refs/heads/main'    runs-on: ubuntu-latest    needs: build    steps:      - uses: actions/checkout@v4
      - uses: amondnet/vercel-action@v25        with:          vercel-token: ${{ secrets.VERCEL_TOKEN }}          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}          vercel-args: '--prod'

Deployment Patterns

Vercel Deployment

yaml
name: Deploy to Vercel
on:  push:    branches: [main]
jobs:  deploy:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4
      - uses: amondnet/vercel-action@v25        with:          vercel-token: ${{ secrets.VERCEL_TOKEN }}          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}          vercel-args: '--prod'

Netlify Deployment

yaml
name: Deploy to Netlify
on:  push:    branches: [main]
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
      - uses: netlify/actions/cli@master        with:          args: deploy --prod --dir=dist        env:          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}

AWS S3 + CloudFront

yaml
name: Deploy to AWS
on:  push:    branches: [main]
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
      - 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
      - run: aws s3 sync dist/ s3://${{ secrets.S3_BUCKET }} --delete
      - run: |          aws cloudfront create-invalidation \            --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \            --paths "/*"

Docker Registry Push

yaml
name: Publish Docker Image
on:  release:    types: [published]
jobs:  push:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4
      - uses: docker/login-action@v3        with:          registry: ghcr.io          username: ${{ github.actor }}          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/build-push-action@v5        with:          context: .          push: true          tags: |            ghcr.io/${{ github.repository }}:latest            ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }}

Testing Workflows

Unit Tests with Coverage

yaml
name: Test Coverage
on: [push, pull_request]
jobs:  test:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4        with:          node-version: '20'          cache: 'npm'
      - run: npm ci
      - run: npm test -- --coverage
      - uses: codecov/codecov-action@v4        with:          token: ${{ secrets.CODECOV_TOKEN }}          files: ./coverage/coverage-final.json          fail_ci_if_error: true

Integration Tests

yaml
name: Integration Tests
on: [push, pull_request]
jobs:  integration:    runs-on: ubuntu-latest    services:      postgres:        image: postgres:15        env:          POSTGRES_PASSWORD: postgres        options: >-          --health-cmd pg_isready          --health-interval 10s          --health-timeout 5s          --health-retries 5        ports:          - 5432:5432
      redis:        image: redis:7        options: >-          --health-cmd "redis-cli ping"          --health-interval 10s          --health-timeout 5s          --health-retries 5        ports:          - 6379:6379
    steps:      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4        with:          node-version: '20'
      - run: npm ci
      - run: npm run test:integration        env:          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test          REDIS_URL: redis://localhost:6379

E2E Tests with Playwright

yaml
name: E2E Tests
on: [push, pull_request]
jobs:  e2e:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4        with:          node-version: '20'          cache: 'npm'
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npm run build
      - run: npm run test:e2e
      - uses: actions/upload-artifact@v4        if: always()        with:          name: playwright-report          path: playwright-report/          retention-days: 30

Release Automation

Semantic Release

yaml
name: Release
on:  push:    branches: [main]
jobs:  release:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4        with:          fetch-depth: 0  # Full history for changelog
      - uses: actions/setup-node@v4        with:          node-version: '20'
      - run: npm ci
      - run: npx semantic-release        env:          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

Create Release with Changelog

yaml
name: Create Release
on:  push:    tags:      - 'v*'
jobs:  release:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4        with:          fetch-depth: 0
      - name: Generate changelog        id: changelog        run: |          # Generate changelog from commits          CHANGELOG=$(git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:"- %s (%h)" --no-merges)          echo "changelog<<EOF" >> $GITHUB_OUTPUT          echo "$CHANGELOG" >> $GITHUB_OUTPUT          echo "EOF" >> $GITHUB_OUTPUT
      - uses: actions/create-release@v1        env:          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}        with:          tag_name: ${{ github.ref_name }}          release_name: Release ${{ github.ref_name }}          body: |            ## Changes            ${{ steps.changelog.outputs.changelog }}          draft: false          prerelease: false

Publish npm Package

yaml
name: Publish to npm
on:  release:    types: [published]
jobs:  publish:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4        with:          node-version: '20'          registry-url: 'https://registry.npmjs.org'
      - run: npm ci
      - run: npm test
      - run: npm publish        env:          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Security Scanning

CodeQL Analysis

yaml
name: CodeQL
on:  push:    branches: [main]  pull_request:    branches: [main]  schedule:    - cron: '0 0 * * 1'  # Weekly
jobs:  analyze:    runs-on: ubuntu-latest    permissions:      actions: read      contents: read      security-events: write
    strategy:      fail-fast: false      matrix:        language: ['javascript', 'python']
    steps:      - uses: actions/checkout@v4
      - uses: github/codeql-action/init@v3        with:          languages: ${{ matrix.language }}
      - uses: github/codeql-action/autobuild@v3
      - uses: github/codeql-action/analyze@v3

Dependency Scanning

yaml
name: Dependency Check
on:  push:    branches: [main]  schedule:    - cron: '0 0 * * 1'
jobs:  scan:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4        with:          node-version: '20'
      - run: npm audit --audit-level=moderate
      - run: npx snyk test        env:          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}        continue-on-error: true

Trivy Container Scan

yaml
name: Container Security Scan
on:  push:    branches: [main]
jobs:  scan:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4
      - run: docker build -t myapp:${{ github.sha }} .
      - uses: aquasecurity/trivy-action@master        with:          image-ref: 'myapp:${{ github.sha }}'          format: 'sarif'          output: 'trivy-results.sarif'
      - uses: github/codeql-action/upload-sarif@v3        with:          sarif_file: 'trivy-results.sarif'

Composite Actions

Create reusable actions in .github/actions/.

Simple Composite Action

.github/actions/setup-project/action.yml:

yaml
name: 'Setup Project'description: 'Install dependencies and cache'
inputs:  node-version:    description: 'Node.js version'    required: false    default: '20'
runs:  using: 'composite'  steps:    - uses: actions/setup-node@v4      with:        node-version: ${{ inputs.node-version }}        cache: 'npm'
    - run: npm ci      shell: bash

Usage:

yaml
steps:  - uses: actions/checkout@v4  - uses: ./.github/actions/setup-project    with:      node-version: '20'

Reusable Workflows

.github/workflows/reusable-deploy.yml:

yaml
name: Reusable Deploy
on:  workflow_call:    inputs:      environment:        required: true        type: string    secrets:      deploy-token:        required: true
jobs:  deploy:    runs-on: ubuntu-latest    environment: ${{ inputs.environment }}    steps:      - uses: actions/checkout@v4
      - run: ./deploy.sh        env:          DEPLOY_TOKEN: ${{ secrets.deploy-token }}          ENVIRONMENT: ${{ inputs.environment }}

Usage:

yaml
name: Deploy Production
on:  push:    branches: [main]
jobs:  deploy:    uses: ./.github/workflows/reusable-deploy.yml    with:      environment: production    secrets:      deploy-token: ${{ secrets.PRODUCTION_TOKEN }}

Performance Optimization

Dependency Caching

yaml
- uses: actions/cache@v4  with:    path: ~/.npm    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}    restore-keys: |      ${{ runner.os }}-node-

Docker Layer Caching

yaml
- uses: docker/build-push-action@v5  with:    context: .    cache-from: type=gha    cache-to: type=gha,mode=max

Parallelization

yaml
jobs:  lint:    runs-on: ubuntu-latest    steps:      - run: npm run lint
  test-unit:    runs-on: ubuntu-latest    steps:      - run: npm run test:unit
  test-integration:    runs-on: ubuntu-latest    steps:      - run: npm run test:integration
  # All run in parallel

Conditional Job Execution

yaml
jobs:  deploy:    # Skip deploy on draft PRs    if: github.event.pull_request.draft == false    runs-on: ubuntu-latest    steps:      - run: ./deploy.sh

Debugging Workflows

Enable Debug Logging

Set repository secrets:

  • ACTIONS_RUNNER_DEBUG: true
  • ACTIONS_STEP_DEBUG: true

Debug Step

yaml
- name: Debug Info  run: |    echo "Event: ${{ github.event_name }}"    echo "Ref: ${{ github.ref }}"    echo "SHA: ${{ github.sha }}"    echo "Actor: ${{ github.actor }}"    env

Interactive Debugging with tmate

yaml
- name: Setup tmate session  if: failure()  uses: mxschmitt/action-tmate@v3  timeout-minutes: 15

Best Practices

Security

  • Use secrets for sensitive data
  • Pin action versions to SHA: uses: actions/checkout@8e5e7e5a...
  • Minimize token permissions
  • Use environment protection rules
  • Enable branch protection with required checks

Performance

  • Cache dependencies aggressively
  • Use matrix strategies for parallel testing
  • Minimize checkout depth when possible
  • Use artifacts for job-to-job data transfer
  • Optimize Docker builds with multi-stage builds

Maintainability

  • Use reusable workflows for common patterns
  • Create composite actions for repeated steps
  • Document workflow purpose and triggers
  • Use meaningful job and step names
  • Keep workflows focused (single responsibility)

Reliability

  • Set appropriate timeouts
  • Use continue-on-error strategically
  • Implement retry logic for flaky tests
  • Monitor workflow run times
  • Clean up old artifacts and caches

Common Patterns

PR Comment on Failure

yaml
- name: Comment on PR  if: failure() && github.event_name == 'pull_request'  uses: actions/github-script@v7  with:    script: |      github.rest.issues.createComment({        issue_number: context.issue.number,        owner: context.repo.owner,        repo: context.repo.repo,        body: '❌ Tests failed. Please check the workflow logs.'      })

Auto-merge Dependabot PRs

yaml
name: Auto-merge Dependabot
on:  pull_request:    types: [opened, synchronize]
jobs:  auto-merge:    if: github.actor == 'dependabot[bot]'    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4
      - run: npm ci      - run: npm test
      - uses: gh enable-auto-merge --merge        if: success()        env:          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Notify on Deploy

yaml
- name: Slack Notification  if: always()  uses: 8398a7/action-slack@v3  with:    status: ${{ job.status }}    text: 'Deploy to ${{ inputs.environment }}: ${{ job.status }}'    webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Troubleshooting

Common Issues

Workflow not triggering:

  • Check branch filters match actual branch names
  • Verify workflow file is in .github/workflows/
  • Ensure YAML syntax is valid

Job skipped:

  • Check if conditions
  • Verify needs dependencies succeeded
  • Check branch protection rules

Timeout:

  • Default timeout is 360 minutes
  • Set explicit timeout: timeout-minutes: 30
  • Optimize long-running steps

Permission denied:

  • Update workflow permissions:
    yaml
    permissions:  contents: write  pull-requests: write

Secrets not available:

  • Verify secret names match exactly (case-sensitive)
  • Check secret scope (repo, organization, environment)
  • Ensure workflow has access to environment secrets

Local Workflow Patterns (Your Repos)

Python + uv CI (mcp-vector-search)

  • Install uv: astral-sh/setup-uv@v3 and uv python install 3.11.
  • Use uv sync --dev and run uv run ruff, uv run mypy, uv run pytest.
  • Use OS + Python version matrix and upload coverage to Codecov on linux.

Node + pnpm CI (ai-code-review)

  • Use pnpm/action-setup@v4 and actions/setup-node@v4 with pnpm cache.
  • Install with pnpm install --frozen-lockfile, then pnpm run lint, pnpm run build:types, pnpm test.

Release on Tags

  • Trigger on push tags v*.
  • Build, create GitHub Release notes, and publish to npm or PyPI.
  • Use pypa/gh-action-pypi-publish@release/v1 or NODE_AUTH_TOKEN for npm publish.

Homebrew Update Pipeline

  • Trigger on workflow_run after CI success.
  • Run scripts/update_homebrew_formula.py with HOMEBREW_TAP_TOKEN.
  • On failure, open an issue with manual update steps.

Resources

Source and attribution

Source:bobmatnyc/claude-mpm-skillsintoolchains/universal/infrastructure/github-actionsat commit718070a

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal

Github Actions Agent Skill | SourceWeft