Github Actions

Checkout

Checkout properties and documentation can be found here.

You can checkout the code from the repo on which your github action CI job is running using the checkout action. This adds the repos content to the containerized file system that is running the CI job. You can call subsequent actions on the code as if you were in the root of that file system. The checkout action downloads the code in a detached head state, so commands like git diff with previous commits do not work by default because of this detached head state.

- name: checkout code
  uses: actions/checkout@v2

You can include previous commit history in your checkout by using the fetch-depth property on checkout. This defaults to 1, hence the detached head behavior observed above. If set it 0 it will checkout ALL commits for all branches. For example, if you wanted to checkout the current commit and the previous commit - to git diff them - you would use a fetch-depth of 2.

- name: checkout HEAD^ and HEAD
  uses: actions/checkout@v2
  with:
    fetch-depth: 2

Working Directory

You can set the working directory of a command to run by using the working-directory tag.

- name: Do something in a directory
  working-directory: src/some_directory
  run: |
    ls -la

Commit Tags

You can use the HEAD tag in a github actions job to point to the current commit that the CI is running on.

However you cannot use the HEAD^ relative tag to point to the previous commit in the branch even with a fetch depth greater than 1. Instead you should use the origin/master^ tag to point to the previous commits on the master branch.

git diff origin/master^ HEAD

This is also the method used to diff pull requests with the master branch of a project, by comparing HEAD and origin/master^.

Scheduled Jobs

You can run a CI job on a periodic schedule by using the schedule tag with on and then cron tag followed by a valid cron string. The example below will trigger this job at 23:59 everyday.

on:
  schedule:
  - cron: "59 23 * * *"

Scheduled jobs are not guaranteed to run or guaranteed to run on time. When a scheduled job is called a request is made to Github actions machines for the job to run and is run once a node is free. This can vary the time from 3-10 minutes but it can be as long as an hour and can sometimes not be run at all if the lag time is long enough. More information here.

Update files

You can update files that are modified during a CI job using the test-room-7/action-update-file@v1 action. This takes a path to the file-path to the file that has changed, a commit message and a github-token for committing that can be loaded directly from the actions environment and doesn’t require any additional loading. The changed file will then be changed on the current branch. The file-path is loaded relative to the root directory of the project and should not have / or ./ appended to it for loading.

- name: Update a file
  uses: test-room-7/action-update-file@v1
  with:
    file-path: path/to/file.txt
    commit-msg: Update file.txt
    github-token: $

You can update multiple files by using the multi-line yaml block with the | indicator.

file-path: |
  path/to/file_1.txt
  path/to/file_2.txt
  path/to/file_3.txt

It’s worth noting that if this action is triggered by a commit / push the actions API is intelligent enough to not trigger again when an action commits.

Needs

You can make a job dependent on another job using the needs tag. This should specify the name of a job that should complete successfully before the current job runs.

jobs:
  job_1:
    # body of job
  job_2:
    needs: job_1
    # body of job

You also use the needs tag so that a job can reference another job that it relies on.

jobs:
  job_1:
    # body of job
  job_2:
    needs: job_1
    if: job_1.path.to.property == 'true'
  

Outputs

You can output the result of a step from a job by using the outputs tag and specifying the steps, id and outputs parameter with a name. The output parameter and the name of the property being output should match. You can set an output using a bash block that echos the set-output command. In the example below my_job sets the my_output to true which is then loaded by another_job and used as a conditional to run the job.

my_job:
  - name: Job that outputs a value
    outputs:
      my_output: $
    runs_on: ubuntu-latest
    steps:
      - name: Set output
        id: output_value # set step id so it can be referenced at the job level
        run: |
          echo "::set-output name=my_output::true"

another_job:
  - name: Job that relies on output
    needs: my_job # rely on output and load reference to output
    if: needs.my_job.outputs.my_output == 'true' # access property