askhacker

Github Actions

A quick reference to Github Actions for the automation of software workflows, allowing developers to build, test, and deploy code right from their GitHub repositories.

#Getting Started

#Introduction

GitHub Actions is a CI/CD platform that enables automation of software workflows, allowing developers to build, test, and deploy code right from their GitHub repositories.


#Workflow Files

Github Action Workflows are defined in special YAML files, typically stored in a .github/workflows directory in the github repository.

name: hello-world
on: push
jobs:
  hello-world-job:
    runs-on: ubuntu-latest
    steps:
      - name: Hello World
        run: echo "Hello World!"

Viewing your workflow runs

  • On GitHub.com, navigate to the main page of the repository.
  • Under your repository name, click Actions.
  • In the left sidebar, click the workflow you want to display, in this example "hello-world"

#Workflow Syntax

name: learn-github-actions
run-name: ${{ github.actor }} is learning GitHub Actions
on: [push]
jobs:
  check-bats-version:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v3
        with:
          node-version: '14'
      - run: npm install -g bats
      - run: bats -v

#Workflow Syntax Descriptions

Line Description
name: Sets the name of the GitHub Actions workflow. It's a label used for identifying the workflow in the repository.
run-name: Sets a custom name for the run, using a GitHub context ${{ github.actor }} to include the name of the user who initiated the run.
on: Specifies the event that triggers the workflow. In this case, the workflow is triggered on any push event to the repository.
jobs: Defines a group of jobs that will be executed as part of the workflow. Each job runs independently in the workflow.
check-bats-version: Identifier for a specific job within the workflow. This job is named check-bats-version.
runs-on: Specifies the type of machine to run the job on. Here, it's set to run on the latest version of Ubuntu.
steps: Contains a sequence of tasks (steps) that will be executed as part of the job.
uses: Used to specify an action to include as part of a step. For example, actions/checkout@v4 checks out the repository, and actions/setup-node@v3 sets up a Node environment.
with: Specifies additional parameters for the action. It's used in conjunction with uses to configure the action.
node-version: Contains parameter under with, specifying the version of Node.js to be set up by the setup-node action. In this case, it's set to version '14'.

#Events

name: Event-trigger-on-push-example

on: [push] # event is defined here

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Run a script
      run: echo "This workflow runs on every push to the repository."

Event Triggers

Event Name Description
push Triggers on a push to the repository.
pull_request Triggers on pull request events.
pull_request_review Triggers on pull request review events.
pull_request_review_comment Triggers on comments on pull request reviews.
pull_request_target For workflows in forked repositories.
fork Triggers when a repository is forked.
issue_comment Triggers on issue and PR comments.
issues Triggers on issue events.
label Triggers on label events.
milestone Triggers on milestone events.
deployment Triggers on deployment.
deployment_status Triggers on deployment status updates.
public Triggers when repo goes from private to public.
repository_dispatch Triggers on a custom repository event.
schedule Triggers on a defined schedule.
workflow_dispatch Allows manual triggering of the workflow.
workflow_run Triggers on the completion of another workflow.
create Triggers when a branch or tag is created.
delete Triggers when a branch or tag is deleted.
page_build Triggers on GitHub Pages build events.
release Triggers on release events.
watch Triggers when someone stars the repo.
registry_package Triggers on registry package events.
status Triggers on status updates to a Git commit.
project Triggers on project board events.
project_card Triggers on project card events.
project_column Triggers on project column events.
member Triggers on collaborator events.
gollum Triggers on wiki page updates.

#Jobs

Single Job:

name: Single Job
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Run a build script
      run: script/build

Multiple Jobs:

name: CI Workflow

on: [push]

jobs:
  job-1:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Runs job 1 
      run: echo "Running Job 1"

  job-2:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Runs job 2 
      run: echo "Running Job 2"

  job-3:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Runs job 3 
      run: echo "Running Job 3"

#Steps

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    # step 1 
    - name: Check out repository 
      uses: actions/checkout@v2
    
    # step 2 
    - name: Set up Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '14'
    
    # step 3 
    - name: Install dependencies
      run: npm install

    # step 4
    - name: Run tests
      run: npm test

#Github Runners & Self Hosted Runners

Github Hosted Runner:

name: Workflow
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest # default runner 
    steps:
    - uses: actions/checkout@v2
    - name: Run a script
      run: echo "Hello, world!"

Self Hosted Runner

name: Workflow with Self-Hosted Runner
on: [push]
jobs:
  build:
    runs-on: self-hosted
    steps:
    - uses: actions/checkout@v2
    - name: Run a script
      run: echo "Hello from self-hosted runner!"

#Environment Variables

Custom variable defined using environments.

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      CUSTOM_VARIABLE: "Hello, World!" # Custom variable defined using env:
    steps:
      - name: Check environment variable
        run: echo "Value of CUSTOM_VAR is $CUSTOM_VAR"

#Secrets

To add a new secret in your github repository nagivate to Repository > Settings > Security > Secrets and Variables > Actions > New Repository Secret

Example Secrets workflow:

name: Workflow with Secrets

on: [push]

jobs:
  example_job:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout repository
      uses: actions/checkout@v2
    - name: Use a secret
      run: echo "The secret is ${{ secrets.MY_SECRET }}"

#Artifacts

To access your artifact navigate to Repository > Actions > Workflow Run > Artifacts

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Build project
      run: make build
    - name: Upload build artifact
      uses: actions/upload-artifact@v3 # upload Artifacts prebuilt action
      with:
        name: my-artifact
        path: path/to/artifact

#Caching Dependencies

Dependency caches stores downloaded packages or compiled binaries of your workflows.

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Cache dependencies
      uses: actions/cache@v2 # stores downloaded packages or compiled binaries
      with:
        path: |
          path/to/dependencies
          another/path
        key: ${{ runner.os }}-deps-${{ hashFiles('**/lockfile') }} # hash of the dependency lock file is generated in the OS
    - name: Install dependencies
      run: install-command

#Matrix Strategies

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [12.x, 14.x, 16.x]
        # matrix strategy runs enables you to run jobs across multiple combinations of environments and OS's
        os: [ubuntu-latest, windows-latest, macOS-latest] 
    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
    - run: npm install
    - run: npm test
      env:
        CI: true

#Conditions and Expressions

Branch Conditions:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Run build
      if: github.ref == 'refs/heads/main' # "Run build" step will only execute if the current branch is main.
      run: make build

Event Trigger Conditions:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Run tests
      if: github.event_name == 'pull_request' # "Run tests" step is executed only when the workflow is triggered by a pull request event
      run: npm test

#Workflow Commands

Depending on your OS, if you are running ubuntu-latest, bash commands should work

steps:
  - name: Set environment variable
    run: echo "NAME=value" >> $GITHUB_ENV

#Concurrency

The concurrency field creates a group based on the github.head_ref. If a new run starts within the same concurrency group, it cancels any in-progress runs.

jobs:
  my_job:
    runs-on: ubuntu-latest
    concurrency: 
      group: ${{ github.head_ref }}
      cancel-in-progress: true
    steps:
    - name: Run a script
      run: echo "Running script..."

#Also see