GitHub Actions
Introduction
GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that automates build, test, and deployment pipelines directly from GitHub repositories.
Key Features:
- Automated workflows
- Matrix builds
- Container support
- Self-hosted runners
- Marketplace actions
- Workflow templates
- Environment protection
- Artifact management
Basic Structure
# .github/workflows/main.yml
name: CI/CD Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
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
Workflows
Matrix Strategy
name: Cross-Platform Tests
on: [push, pull_request]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [14, 16, 18]
exclude:
- os: windows-latest
node: 14
steps:
- uses: actions/checkout@v3
- name: Setup Node.js ${{ matrix.node }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Upload coverage
uses: actions/upload-artifact@v3
with:
name: coverage-${{ matrix.os }}-${{ matrix.node }}
path: coverage/
Reusable Workflows
# .github/workflows/reusable.yml
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@v3
- name: Deploy
run: |
echo "Deploying to ${{ inputs.environment }}"
./deploy.sh
env:
DEPLOY_TOKEN: ${{ secrets.deploy-token }}
# Usage in another workflow
jobs:
call-deploy:
uses: ./.github/workflows/reusable.yml
with:
environment: production
secrets:
deploy-token: ${{ secrets.DEPLOY_TOKEN }}
Events & Triggers
Event Types
on:
# Push events
push:
branches: [ main, develop ]
tags: [ 'v*' ]
paths:
- 'src/**'
- '!**.md'
# Pull request events
pull_request:
types: [opened, synchronize, reopened]
branches: [ main ]
# Schedule events
schedule:
- cron: '0 0 * * *' # Daily at midnight
# Manual trigger
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy to'
required: true
default: 'staging'
# Repository dispatch
repository_dispatch:
types: [deploy]
# Issue events
issues:
types: [opened, edited, closed]
Conditional Execution
jobs:
build:
if: github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build
if: ${{ success() && github.ref == 'refs/heads/main' }}
run: npm run build
deploy:
needs: build
if: |
always() &&
needs.build.result == 'success' &&
github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- name: Deploy
run: ./deploy.sh
Jobs & Steps
Job Dependencies
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm test
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm run build
- uses: actions/upload-artifact@v3
with:
name: dist
path: dist/
deploy:
needs: [test, build]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v3
with:
name: dist
- name: Deploy
run: ./deploy.sh
Environment Variables
name: Environment Demo
env:
GLOBAL_VAR: 'Available to all jobs'
jobs:
example:
runs-on: ubuntu-latest
env:
JOB_VAR: 'Available to all steps in job'
steps:
- name: Step with env
env:
STEP_VAR: 'Only available in this step'
API_TOKEN: ${{ secrets.API_TOKEN }}
run: |
echo $GLOBAL_VAR
echo $JOB_VAR
echo $STEP_VAR
echo $API_TOKEN
Secrets & Security
Managing Secrets
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- name: Configure AWS
uses: aws-actions/configure-aws-credentials@v1
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 Production
env:
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
API_TOKEN: ${{ secrets.API_TOKEN }}
run: ./deploy.sh
Security Best Practices:
- Use repository secrets for sensitive data
- Implement environment protection rules
- Limit permissions for GitHub tokens
- Use OpenID Connect for cloud providers
- Regular secret rotation
- Audit secret access
- Use secret scanning
- Implement approval workflows
Common Examples
Node.js Package
name: Node.js Package
on:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
- name: Publish
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Docker Build & Push
name: Docker Build
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: user/app:latest
platforms: linux/amd64,linux/arm64