Github Actions

Summary

GitHub Actions uses YAML syntax to define the events, jobs, and steps. These YAML files are stored in your code repository, in a directory called .github/workflows.

  • GitHub events (e.g. push, pull request) occur, at a scheduled time, manually, or when events outside of GitHub occur.
  • The .github/workflows directory in your repository is searched for workflow files at the associated commit SHA or Git ref. The workflow files must be present in that commit SHA or Git ref to be considered.
    • You can configure workflows to run for one or more events using the on workflow syntax. 
      • A new workflow run is triggered for any workflows that have on: values that match the triggering event.
      • When a workflow runs, GitHub sets the GITHUB_SHA (commit SHA) and GITHUB_REF (Git ref) environment variables in the runner environment.

Github Actions components

  • Runner – virtual host machine running Linux, Windows, or macOS
  • Event – Specific activity on GitHub that will trigger a workflow listening on the specific event.
  • Workflow – What need to be run on the runners on which event that is defined in YAML file inside .github/workflows/ of a Github repository.
    • Jobs – Jobs run on a specific runner or Operation System. Jobs run in parallel by default. To run jobs sequentially, you can define dependencies on other jobs using the jobs.<job_id>.needs keyword.
      • Steps – A step is an individual task that can run commands in a job. A step can be either an action (defined with uses:) or a shell command (defined with run:). 
        • Actions – Actions are the smallest portable building block of a workflow. You can create your own actions, or use actions created by the GitHub community.

Pricing

See: About billing for GitHub Actions

You can also host your own runners if needed. See: About self-hosted runners

Also see

Creating Actions

There are three types of actions.

  • JavaScript Actions: JavaScript actions run on the host machine. The unit of work is decoupled from the environment. Also see: Creating a JavaScript Action
  • Docker Actions: A container action is a container which carries both the unit of work along with the environment and its dependencies packaged up as a container. Also see: Creating a Docker Action
  • Composite Run Steps Actions: A composite run steps action allows you to combine multiple workflow run steps within one action. For example, you can use this feature to bundle together multiple run commands into an action, and then have a workflow that executes the bundled commands a single step using that action.  Also see: Creating a composite run steps action

Both have access to the workspace and the github event payload and context.

Also see: https://github.com/actions/toolkit/tree/master/docs

Trigger Workflow

Example Workflow YAML Files

Workflow syntax

name

The name of your workflow. GitHub displays the names of your workflows on your repository’s actions page. If you omit name, GitHub sets it to the workflow file path relative to the root of the repository.

on.<push|pull_request>

Required The name of the GitHub event that triggers the workflow.

on:
  # Trigger the workflow on push or pull request,
  # but only for the main branch on changes to files under src/
  push:
    branches:
      - main
      # Push events to branches matching refs/heads/releases/10
      - 'releases/**'
      # You can exclude tags and branches using the ! character. The order that you define patterns matters.
      - '!releases/**-alpha'
    # Sequence of patterns matched against refs/heads
    branches-ignore:
      # Push events to branches matching refs/heads/releases/beta/3-alpha
      - 'releases/**-alpha'

    # Sequence of patterns matched against refs/tags
    tags:        
      - v1             # Push events to v1 tag
    # Sequence of patterns matched against refs/tags
    tags-ignore:
      - v1.*           # Push events to tags v1.0, v1.1, and v1.9

    paths:
      - 'src/**'
      - '**.js'
      - '!src/docs/**'
    paths-ignore:
      - 'docs/**'

   pull_request:
    branches:
      - release/**
 

See more examples: workflow-syntax-for-github-actions#on

on.<event_name>.types

on:
  pull_request:
    types: [assigned, opened, synchronize, reopened]

on:
  pull_request_review:
    types: [edited, dismissed]

on.workflow_run

This event occurs when a workflow run is requested or completed, and allows you to execute a workflow based on the finished result of another workflow. For example, if your pull_request workflow generates build artifacts, you can create a new workflow that uses workflow_run to analyze the results and add a comment to the original pull request.

The workflow started by the workflow_run event is able to access the secrets and write tokens used by the original workflow.

on:
  workflow_run:
    workflows: ["Run Tests"]
    branches: [main]
    types: 
      - completed
      - requested

See other event examples: events-that-trigger-workflows#webhook-events

env

map of environment variables that are available to all jobs and steps in the workflow. You can also set environment variables that are only available to a job or step. For more information, see jobs.<job_id>.env and jobs.<job_id>.steps.env.

Also see: default-environment-variables

env:
  type: production

jobs:
  build:
    env:
      baseDir: projects

  - name: Test1
    run: echo $baseDir/$type

  - name: Test2 for $type
    run: echo ${{ baseDir }}/${{ type }}

  - name: Test3 using format
    run: echo ${{ format('{0}/{1}', '$baseDir', '$type') }}

Contexts

Contexts (map or object) are a way to access information about workflow runs, runner environments, jobs, and steps. Contexts use the expression syntax.

${{ <context> }}

As part of an expression, you may access context information using one of two syntaxes.

  • Index syntax: github['sha']
  • Property dereference syntax: github.sha

In order to use property dereference syntax, the property name must:

  • start with a-Z or _.
  • be followed by a-Z 0-9 - or _.

Literal

As part of an expression, you can use booleannullnumber, or string data types.

env:
  myNull: ${{ null }}
  myBoolean: ${{ false }}
  myIntegerNumber: ${{ 711 }}
  myFloatNumber: ${{ -9.2 }}
  myHexNumber: ${{ 0xff }}
  myExponentialNumber: ${{ -2.99-e2 }}
  myString: ${{ 'Mona the Octocat' }}
  myEscapedString: ${{ 'It''s open source!' }}

Expressions are commonly used with the conditional if keyword in a workflow file to determine whether a step should run. When an if conditional is true, the step will run.

steps:
  - uses: actions/hello-world-javascript-action@v1.1
    if: ${{ <expression> }}

Built-in Functions

GitHub offers a set of built-in functions that you can use in expressions. Some functions cast values to a string to perform comparisons. 

# Object filters
# You can use the * syntax to apply a filter and select matching items in a collection.

fruits = [
  { "name": "apple", "quantity": 1 },
  { "name": "orange", "quantity": 2 },
  { "name": "pear", "quantity": 1 }
]

# The filter fruits.*.name returns the array [ "apple", "orange", "pear" ]
# Returns true if search contains item. 
# If search is an array, this function returns true if the item is an element in the array. 
# If search is a string, this function returns true if the item is a substring of search. 
# This function is not case sensitive. Casts values to a string.
contains( search, item )

contains(github.event.issue.labels.*.name, 'bug')
# Returns true
contains('Hello world', 'llo') 


startsWith( searchString, searchValue )

endsWith( searchString, searchValue )
format( string, replaceValue0, replaceValue1, ..., replaceValueN)

# Returns 'Hello Mona the Octocat'
format('Hello {0} {1} {2}', 'Mona', 'the', 'Octocat')
join( array, optionalSeparator )

# May return 'bug, help wanted'
join(github.event.issue.labels.*.name, ', ') 
toJSON(value)

# Might return { "status": "Success" }
toJSON(job) 


fromJSON(value)

# Returns a JSON object for value
fromJson(needs.job1.outputs.matrix)
# Calculates an individual SHA-256 hash for each matched file, 
# and then uses those hashes to calculate a final SHA-256 hash for the set of files.
hashFiles(path)

# Matches any package-lock.json file in the repository.
hashFiles('**/package-lock.json')

# Creates a hash for any package-lock.json and Gemfile.lock files in the repository.
hashFiles('**/package-lock.json', '**/Gemfile.lock')
# Returns true when none of the previous steps have failed or been canceled.
steps:
  ...
  - name: The job has succeeded
    if: ${{ success() }}

# Always returns true, even when canceled. 
# A job or step will not run when a critical failure prevents the task from running. 
if: ${{ always() }}

# Returns true if the workflow was canceled.
if: ${{ cancelled() }}

# Returns true when any previous step of a job fails.
steps:
  ...
  - name: The job has failed
    if: ${{ failure() }}

Also see: context-and-expression-syntax-for-github-actions

defaults

map of default settings that will apply to all jobs in the workflow. You can also set default settings that are only available to a job. For more information, see jobs.<job_id>.defaults.

Actions

actions/first-interaction@v1

An action for filtering pull requests and issues from first-time contributors.

name: FirstPullRequest

on: [pull_request]

jobs:
  greeting:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/first-interaction@v1
      with:
        repo-token: ${{ secrets.GITHUB_TOKEN }}
        issue-message: '# Message with markdown.\nThis is the message that will be displayed on users' first issue.'
        pr-message: |-
          # Hello
          'Message that will be displayed on users' first pr. Look, a `code block` for markdown.'

https://github.com/actions/first-interaction

actions/checkout@v2

Check out multiple repos under workspace directory (e.g. ~/work/myrepo0/myrepo0).

myrepo1 and myrepo2 will be checked out under ~/work/myrepo0/myrepo0/myrepo1 and ~/work/myrepo0/myrepo0/myrepo2

  - uses: actions/checkout@v2
    with:
      repository: myuser/myrepo1
      path: myrepo1
      ref: mybranch
      ssh-key: ${{ secrets.MY_SSH_KEY }}

  - uses: actions/checkout@v2
    with:
      repository: myuser/myrepo2
      path: myrepo2
      ref: mybranch
      ssh-key: ${{ secrets.MY_SSH_KEY }}

https://github.com/actions/checkout#checkout-v2

actions/stale

https://github.com/actions/stale

Leave a Comment

Your email address will not be published. Required fields are marked *