Deep Links to GitHub Actions Job Logs
In GitHub Actions, you can rather easily create a link to the current workflow run:
${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
However, it’s not as easy to link to a specific job within that workflow run.
The variable ${{
github.job
}}
says it contains a job ID,
but in this case it means the key from your workflow:
jobs:
run_tests:
name: Run Tests
runs-on: ubuntu-latest
steps:
- run: echo ${{ github.job }} # outputs 'run_tests'
To link to the job logs, you can use the GitHub CLI which is available on all GitHub-hosted runners:
jobs:
run_tests:
name: Run Tests
runs-on: ubuntu-latest
steps:
- env:
GH_TOKEN: ${{ github.token }}
run: |
gh run view ${{ github.run_id }} --json jobs --jq '
.jobs[] | select(.name == "Run Tests") | .url'
You need to provide the GH_TOKEN
environment variable for the CLI tool. If
you’ve modified the default token permissions, you need at least read access
to actions:
permissions:
actions: read
The CLI tool determines the repo from the current working directory. If you haven’t
performed an actions/checkout
step, or you are referencing a different repo,
pass the relevant flag to the CLI tool:
gh -R ${{ github.repository }} run view ...
The JQ filter selects the job by name. If you don’t want to hardcode the job name, you need a further API call:
JOB_NAME=$(gh workflow view '${{ github.workflow }}' -r ${{ github.ref}} -y |
yq eval .jobs.${{ github.job }}.name -)
gh run view ${{ github.run_id }} --json jobs --jq "
.jobs[] | select(.name == \"$JOB_NAME\") | .url"
Linking back to Pull Requests
This URL can be useful when posting comments in a Pull Request. By default it
doesn’t link to the PR, but you can add the ?pr
query string parameter to add
a backlink:
gh run view ${{ github.run_id }} --json jobs --jq '
.jobs[] | select(.name == "Run Tests") | (.url + "?pr=${{ github.event.number }}")'
Expanding the logs for a specific step
Within the job there are a number of ordered steps. To expand the logs for a
specific step, add a fragment like #step:x:y
, corresponding to the step
number and line number. The step number is based on the order, so you can use
the API for that too:
jobs:
run_tests:
name: Run Tests
runs-on: ubuntu-latest
steps:
- name: Run Test Script
run: make test
- name: Get URL
env:
GH_TOKEN: ${{ github.token }}
run: |
gh run view ${{ github.run_id }} --json jobs --jq '
.jobs[] | select(.name == "Run Tests")
| (.url + (.steps[] | select(.name == "Run Test Script")
| "#step:\(.number):1"))'
If you run this example, you might find that the URL step happens so quickly
after the test step that the API response doesn’t contain the previous step’s
result yet. You can either perform the API call a little later in the job, in
a separate dependent job, or add a small sleep
before calling the API.
Inspired by Grant G’s answer on Stack Overflow.
Expanding the logs for a step used to require the check_suite_focus
query
string param, but this lo longer seems to be needed.
Leave a Reply