Basics
GitHub Actions is a powerful automation platform integrated directly into GitHub repositories, enabling you to automate building, testing, and deploying your code without setting up separate CI/CD tools.
What You’ll Learn (The Essential 85%)
This crash course covers:
- Understanding GitHub Actions core concepts
- Setting up your first workflows
- Working with events, jobs, and runners
- Managing secrets and environment variables
- Building practical CI/CD pipelines
- Applying best practices for security and performance
Prerequisites
- A GitHub account
- Basic knowledge of Git operations (commit, push, pull)
- Familiarity with YAML syntax (but we’ll explain the basics)
- A repository to practice with
Key Concepts: How GitHub Actions Works
GitHub Actions operates on a straightforward workflow model:
graph TD A[GitHub Event] -->|Triggers| B[Workflow] B -->|Contains| C[Jobs] C -->|Run on| D[Runners] C -->|Contain| E[Steps] E -->|Execute| F[Shell Commands] E -->|Or use| G[Actions]
Key components:
- Events: Specific activities that trigger a workflow (push, PR, scheduled time)
- Workflows: YAML files defining what happens when events occur
- Jobs: Groups of steps that execute on the same runner
- Runners: Virtual machines that execute your workflows
- Steps: Individual tasks within a job that run commands or actions
- Actions: Reusable units of code for common tasks
Setting Up Your First Workflow
Workflows live in the .github/workflows
directory in your repository as YAML files.
Step 1: Create the workflow directory
mkdir -p .github/workflows
Step 2: Create a basic workflow file
Create a file named .github/workflows/ci.yml
with this content:
name: CI Workflow # Name of your workflow
on: # Events that trigger this workflow
push:
branches: [main]
pull_request:
branches: [main]
jobs: # The jobs to run
build:
runs-on: ubuntu-latest # The type of runner to use
steps: # The steps in this job
- uses: actions/checkout@v4 # Action to check out your code
- name: Set up Node.js # Descriptive name for this step
uses: actions/setup-node@v3 # Action to set up Node.js
with: # Parameters for the action
node-version: '18'
- name: Install dependencies
run: npm ci # Shell command to run
- name: Run tests
run: npm test # Shell command to run tests
Step 3: Commit and push to GitHub
git add .github/workflows/ci.yml
git commit -m "Add CI workflow"
git push
Step 4: View your workflow
Go to the “Actions” tab in your GitHub repository to see your workflow running.
Understanding Events
Events trigger your workflows. Here are the most common event types:
Push and Pull Request Events
on:
push:
branches: [main, development] # Runs on pushes to these branches
paths:
- 'src/**' # Only run when files in src directory change
pull_request:
branches: [main] # Runs on PRs targeting main
Scheduled Events
on:
schedule:
- cron: '0 0 * * *' # Runs at midnight UTC every day
# ┌───────── minute (0-59)
# │ ┌───────── hour (0-23)
# │ │ ┌───────── day of month (1-31)
# │ │ │ ┌───────── month (1-12)
# │ │ │ │ ┌───────── day of week (0-6 or SUN-SAT)
# │ │ │ │ │
# * * * * *
Manual Events
on:
workflow_dispatch: # Allows manual triggering
inputs:
environment:
description: 'Environment to deploy to'
required: true
default: 'staging'
type: choice
options:
- development
- staging
- production
Working with Jobs
Jobs are the building blocks of workflows. Each job runs on a fresh virtual machine instance.
Sequential Jobs with Dependencies
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run build
test:
needs: build # This job only runs after build succeeds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm test
Matrix Builds for Testing Multiple Configurations
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x, 16.x, 18.x]
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }} on ${{ matrix.os }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
This creates 6 parallel jobs testing all combinations of Node.js versions and operating systems.
graph TD A[Matrix Build] -->|Job 1| B[Node 14 + Ubuntu] A -->|Job 2| C[Node 14 + Windows] A -->|Job 3| D[Node 16 + Ubuntu] A -->|Job 4| E[Node 16 + Windows] A -->|Job 5| F[Node 18 + Ubuntu] A -->|Job 6| G[Node 18 + Windows]
Working with Runners
Runners are the virtual machines that execute your workflows.
GitHub-Hosted Runners
jobs:
build:
runs-on: ubuntu-latest # Options: ubuntu-latest, windows-latest, macos-latest
These come with many tools pre-installed and are maintained by GitHub.
Self-Hosted Runners
For special requirements, you can set up runners on your own infrastructure:
jobs:
build:
runs-on: self-hosted # Uses your own runner
Managing Secrets and Environment Variables
Never hardcode sensitive information in your workflows.
Using Secrets
Store secrets in your repository (Settings > Secrets and variables > Actions):
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to production
run: ./deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }} # Access your secret
Environment Variables
env:
GLOBAL_VAR: 'available to all jobs' # Workflow-level variable
jobs:
build:
env:
JOB_VAR: 'available to all steps in this job' # Job-level variable
runs-on: ubuntu-latest
steps:
- name: Use variables
env:
STEP_VAR: 'available only to this step' # Step-level variable
run: |
echo $GLOBAL_VAR
echo $JOB_VAR
echo $STEP_VAR
Practical CI/CD Examples
Building and Testing a Node.js Application
name: Node.js CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm' # Enables caching for faster installs
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
# If linting fails, the workflow stops here
- name: Run tests
run: npm test
# If tests fail, the workflow stops here
- name: Build application
run: npm run build
# Creates production build
Deploying to Production
name: Deploy to Production
on:
push:
branches: [main] # Only deploy from main branch
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Build application
run: npm run build
- name: Deploy to production
uses: actions/aws-cli@v1 # Example action for AWS deployment
with:
args: s3 sync ./build s3://my-website-bucket
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Docker Build and Push Example
name: Build and Push Docker Image
on:
push:
branches: [main]
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: . # Build context is current directory
push: true # Actually push the image
tags: |
yourusername/yourapp:latest # Tag as latest
yourusername/yourapp:${{ github.sha }} # Tag with commit SHA
Advanced Features
Conditional Execution
Run steps only when specific conditions are met:
steps:
- name: Deploy to production
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: ./deploy-to-production.sh
- name: Deploy to staging
if: github.ref == 'refs/heads/development' && github.event_name == 'push'
run: ./deploy-to-staging.sh
Caching Dependencies
Speed up your workflows by caching dependencies:
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Cache Node modules
uses: actions/cache@v3
with:
path: ~/.npm # What to cache
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} # Cache key
restore-keys: | # Fallback keys
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci # Will be much faster with cached dependencies
Artifacts and Sharing Data Between Jobs
Share files between jobs using artifacts:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build-files
path: build/ # Directory to upload
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download build artifacts
uses: actions/download-artifact@v3
with:
name: build-files
path: build/ # Directory to download to
- name: Deploy
run: ./deploy.sh
Best Practices
Security
- Use secrets for sensitive data
- Pin actions to specific commits (instead of using
@v3
, use the full SHA) - Limit permissions by configuring the least privilege necessary
Performance
- Use caching for dependencies and build outputs
- Optimize trigger conditions using paths to only run workflows when relevant files change
- Run jobs in parallel where possible
Organization
- Create separate workflows for different purposes (CI, CD, issue management)
- Use meaningful names for workflows, jobs, and steps
- Keep workflows focused on specific tasks
The Remaining 15%: Advanced Topics to Explore
As you become more comfortable with GitHub Actions, these advanced topics will help you take full advantage of the platform:
- Custom actions development: Build your own reusable actions in JavaScript, Docker, or as composite actions
- Self-hosted runner management: Advanced configuration, security, and scaling
- Advanced workflow orchestration: Complex patterns and event handling
- GitHub Actions API: Programmatically interact with workflows
- Environment deployment protection rules: Add approval workflows
- Organization and enterprise management: Centralized policies
- Cost optimization strategies: For repositories with limited included minutes
- Integration with other GitHub features: GitHub Packages, CodeQL, etc.
- Complex matrix strategies: Dynamic matrix generation
- Custom expressions and contexts: Advanced usage of GitHub’s expression syntax
Getting Help
- Official documentation: GitHub Actions Documentation
- GitHub Community forums: GitHub Community
- GitHub Actions Marketplace: Marketplace
This crash course has equipped you with the essential knowledge that covers approximately 85% of what you’ll need day-to-day with GitHub Actions. As you gain experience, you can progressively explore the advanced topics to master the platform completely.