What are GitHub Actions?
GitHub Actions is a powerful automation platform integrated directly into GitHub repositories. It allows you to create custom software development lifecycle workflows directly in your GitHub repository.
Think of GitHub Actions as your personal robot assistant that watches your repository and performs tasks automatically when certain events happen. Just like how a smart home system might turn on your lights when you arrive home, GitHub Actions can run tests, deploy your application, or send notifications when you push code.
Key Concepts in GitHub Actions
Workflows
A workflow is an automated procedure that you add to your repository. Workflows are made up of one or more jobs and can be scheduled or triggered by events in your repository.
Events
Events are specific activities that trigger a workflow. For example, a workflow can be triggered when someone pushes code to a repository, creates a pull request, or opens an issue.
Jobs
A job is a set of steps that execute on the same runner (virtual machine). Jobs can run in parallel or sequentially depending on your workflow configuration.
Steps
Steps are individual tasks that can run commands or actions. Each step in a job executes on the same runner, allowing the actions in that job to share data.
Actions
Actions are standalone commands that are combined into steps to create a job. Actions are the smallest portable building block of a workflow.
Runners
A runner is a server that runs your workflows when they're triggered. GitHub provides Ubuntu Linux, Windows, and macOS runners, and you can also host your own runners.
Workflow File Anatomy
GitHub Actions workflows are defined using YAML files stored in the .github/workflows directory of your repository.
Let's break down a basic workflow file:
name: CI Workflow
# Triggers the workflow on push or pull request events for the main branch
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
steps:
# Checks-out your repository under $GITHUB_WORKSPACE
- uses: actions/checkout@v3
# Sets up Node.js
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
# Install dependencies
- name: Install dependencies
run: npm install
# Run tests
- name: Run tests
run: npm test
This is like a recipe for automation. Just as a cooking recipe has ingredients, steps, and conditions, a workflow file defines what triggers the automation, what environment it runs in, and what actions to perform.
Real-World Use Cases
Continuous Integration (CI)
Every time a developer pushes code, GitHub Actions automatically builds the project and runs tests to ensure the new code integrates well with the existing codebase.
Example: JavaScript CI Workflow
name: Node.js CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x, 16.x, 18.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build --if-present
- run: npm test
Continuous Deployment (CD)
After successful tests, GitHub Actions can automatically deploy your application to staging or production environments.
Example: Deploy to Heroku
name: Deploy to Heroku
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: akhileshns/heroku-deploy@v3.12.12
with:
heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
heroku_app_name: "your-app-name"
heroku_email: "your-email@example.com"
Code Quality Checks
GitHub Actions can run code linters, formatters, and security scanners to maintain code quality and identify vulnerabilities.
Example: ESLint and Prettier Check
name: Code Quality
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- run: npm ci
- run: npm run lint
- run: npm run format-check
GitHub Actions vs. Traditional CI/CD Tools
GitHub Actions provides several advantages over traditional CI/CD tools:
- Integrated experience: GitHub Actions is built directly into GitHub, eliminating the need for a separate service.
- Configuration as code: Workflow files live in your repository, allowing version control of your CI/CD process.
- GitHub Marketplace: Access to thousands of pre-built actions created by the community.
- Matrix builds: Easily test across multiple operating systems and runtime versions.
- Simplified secrets management: Securely store sensitive information directly in your GitHub repository.
Managing Secrets and Environment Variables
Workflows often need access to sensitive information like API keys or passwords. GitHub provides a secure way to store and use these secrets in your workflows.
Setting Up Secrets
- Go to your repository on GitHub.
- Click on "Settings" > "Secrets" > "Actions".
- Click "New repository secret".
- Enter a name for your secret and its value.
Using Secrets in Workflows
steps:
- name: Deploy to Production
run: ./deploy.sh
env:
API_TOKEN: ${{ secrets.API_TOKEN }}
Think of secrets like a safety deposit box at a bank. You store your valuables (sensitive information) in the box, and when needed, you can access them without exposing them to others.
Creating a Custom Action
While GitHub Marketplace offers many pre-built actions, you can also create your own custom actions for specific needs.
There are three types of actions:
- Docker container actions: Run in a Docker container, providing a consistent and reliable unit of work.
- JavaScript actions: Run directly on the runner machine, executing faster than Docker container actions.
- Composite actions: Combine multiple workflow steps within one action.
Example: Simple JavaScript Action
Let's create a basic action that greets users:
# action.yml
name: 'Hello World'
description: 'Greet someone and record the time'
inputs:
who-to-greet:
description: 'Who to greet'
required: true
default: 'World'
outputs:
time:
description: 'The time we greeted you'
runs:
using: 'node16'
main: 'index.js'
// index.js
const core = require('@actions/core');
try {
// Get inputs defined in action.yml
const nameToGreet = core.getInput('who-to-greet');
console.log(`Hello ${nameToGreet}!`);
// Get the current time
const time = new Date().toTimeString();
// Set outputs for other workflow steps to use
core.setOutput("time", time);
} catch (error) {
core.setFailed(error.message);
}
Best Practices for GitHub Actions
- Keep workflows focused: Create separate workflows for different purposes (e.g., testing, deployment).
- Limit workflow triggers: Only trigger workflows when necessary to avoid unnecessary resource consumption.
- Use specific versions of actions: Reference actions with specific version numbers rather than using
@masterto ensure stability. - Cache dependencies: Use GitHub's cache action to speed up workflow runs by caching dependencies.
- Minimize secrets usage: Only use secrets where necessary and ensure they have limited scope.
- Set timeout limits: Add timeout limits to prevent workflows from running indefinitely due to issues.
Example: Using Caching to Speed Up Workflows
steps:
- uses: actions/checkout@v3
- name: Cache Node modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install Dependencies
run: npm ci
GitHub Actions for Different Programming Languages
GitHub Actions is language-agnostic, but has specific features that make it particularly useful for various programming languages:
JavaScript/Node.js
- Native support for running npm scripts
- Easy integration with npm, Yarn, and other JS package managers
- Specialized actions for Node.js testing frameworks
Python
- Built-in support for Python version management
- Integration with pip, conda, and other Python package managers
- Actions for Python testing frameworks like pytest
Java
- Support for Java version management
- Integration with Maven, Gradle, and other Java build tools
- Actions for running JUnit tests
Visualizing Workflow Execution
GitHub provides a visual representation of your workflow execution, making it easy to identify and debug issues.
To access the workflow visualization:
- Go to your repository on GitHub.
- Click on the "Actions" tab.
- Click on a workflow run to see its details.
- You'll see a visual representation of all jobs and their status.
- Click on a specific job to see its steps and logs.
Common GitHub Actions Patterns
Environment-based Deployments
name: Deploy
on:
push:
branches:
- develop
- staging
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to Development
if: github.ref == 'refs/heads/develop'
run: ./deploy.sh development
- name: Deploy to Staging
if: github.ref == 'refs/heads/staging'
run: ./deploy.sh staging
- name: Deploy to Production
if: github.ref == 'refs/heads/main'
run: ./deploy.sh production
Scheduled Jobs
name: Daily Database Backup
on:
schedule:
# Runs at 2am UTC every day
- cron: '0 2 * * *'
jobs:
backup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Backup Database
run: ./backup.sh
env:
DB_CONNECTION: ${{ secrets.DB_CONNECTION }}
Practice Activities
Activity 1: Create Your First GitHub Action Workflow
- Create a new GitHub repository or use an existing one.
- Create a directory called
.github/workflowsin your repository. - Create a file called
hello-world.ymlin this directory. - Add the following YAML to the file:
name: Hello World Workflow
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
greet:
runs-on: ubuntu-latest
steps:
- name: Say Hello
run: echo "Hello, GitHub Actions!"
- name: Show Date
run: date
- name: List Files
run: ls -la
- Commit and push this file to your repository.
- Go to the "Actions" tab of your repository to see your workflow run.
Activity 2: Create a CI Workflow for a JavaScript Project
- Create or use a JavaScript/Node.js project with tests.
- Create a file called
ci.ymlin the.github/workflowsdirectory. - Implement a workflow that:
- Checks out the code
- Sets up Node.js
- Installs dependencies
- Runs linting (if applicable)
- Runs tests
- Commit and push this file to your repository.
- Verify that the workflow runs successfully.
Further Resources
Summary
In this lecture, we've explored GitHub Actions, a powerful automation platform integrated directly into GitHub repositories. We've covered:
- Core concepts like workflows, events, jobs, and runners
- How to create workflow files using YAML syntax
- Real-world use cases including CI/CD and code quality checks
- Managing secrets and environment variables
- Creating custom actions
- Best practices for effective GitHub Actions usage
- Common patterns and visualizing workflow execution
GitHub Actions provides a seamless way to automate your software development workflow directly within your GitHub repository, making your development process more efficient and reliable.