Introduction to GitHub Actions

Automating your software development workflows

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.

graph TD A[GitHub Repository] -->|Event Occurs| B[Trigger Workflow] B --> C[Run Actions] C --> D1[Build Code] C --> D2[Run Tests] C --> D3[Deploy App] C --> D4[Send Notifications]

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

graph TB subgraph "Traditional CI/CD" A1[Separate Service] --> B1[Additional Configuration] B1 --> C1[Complex Integration] C1 --> D1[Separate Authentication] end subgraph "GitHub Actions" A2[Built into GitHub] --> B2[YAML in Repository] B2 --> C2[Native Integration] C2 --> D2[GitHub Authentication] end

GitHub Actions provides several advantages over traditional CI/CD tools:

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

  1. Go to your repository on GitHub.
  2. Click on "Settings" > "Secrets" > "Actions".
  3. Click "New repository secret".
  4. 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:

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

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

Python

Java

Visualizing Workflow Execution

GitHub provides a visual representation of your workflow execution, making it easy to identify and debug issues.

Workflow: CI Pipeline Build ✓ Test ✓ Deploy ✓ ✓ Checkout code (0m:12s) ✓ Setup Node.js (0m:5s) ✓ Install dependencies (0m:32s) ✓ Run tests (1m:15s) ✓ Deploy to production (0m:45s)

To access the workflow visualization:

  1. Go to your repository on GitHub.
  2. Click on the "Actions" tab.
  3. Click on a workflow run to see its details.
  4. You'll see a visual representation of all jobs and their status.
  5. 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

  1. Create a new GitHub repository or use an existing one.
  2. Create a directory called .github/workflows in your repository.
  3. Create a file called hello-world.yml in this directory.
  4. 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
  1. Commit and push this file to your repository.
  2. Go to the "Actions" tab of your repository to see your workflow run.

Activity 2: Create a CI Workflow for a JavaScript Project

  1. Create or use a JavaScript/Node.js project with tests.
  2. Create a file called ci.yml in the .github/workflows directory.
  3. Implement a workflow that:
    • Checks out the code
    • Sets up Node.js
    • Installs dependencies
    • Runs linting (if applicable)
    • Runs tests
  4. Commit and push this file to your repository.
  5. 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:

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.