Skip to content

Commit

Permalink
Upload a link to the GitHub job
Browse files Browse the repository at this point in the history
Currently, the observability server UI links to the workflow run attempt
that the upload corresponds to. This is fine in the case where the
workflow only contains a single job, as it did in ably-cocoa. But in the
case where there’s more than one job in a workflow (e.g. in the case of
a matrix build), there’s no way to tell which job an upload corresponds
to. So, include this information in the upload.

I originally tried implementing this by passing a job-index input, whose
value was the index to which the current job corresponds in the response
from the "list jobs for a workflow run attempt" GitHub API. However,
some experimentation then showed that that the order in which the jobs
are listed in the action YAML file doesn’t necessarily match that in
which they are returned from the API, so there was no way to calculate
the value to pass for job-index. Hence, switched to using the job’s
`name` instead.

Resolves #18.
  • Loading branch information
lawrence-forooghian committed Jan 22, 2024
1 parent 5b61d9c commit 3a486ca
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,19 @@ on:
- main

jobs:
# An empty job, to allow us to demonstrate how to use job-name inside a
# matrix job that has preceding jobs.
first-job:
runs-on: ubuntu-latest
steps:
- run: echo "Nothing to see here"

check:
runs-on: ubuntu-latest
strategy:
matrix:
# Arbitrary; just used so that we can execute inside a matrix job.
some-value: [1, 2]
steps:
- uses: actions/checkout@v2

Expand All @@ -31,3 +42,13 @@ jobs:
server-url: 'https://test-observability.herokuapp.com'
server-auth: ${{ secrets.TEST_OBSERVABILITY_SERVER_AUTH_KEY }}
path: 'junit'

- name: Test action with job-name
uses: './'
with:
server-url: 'https://test-observability.herokuapp.com'
server-auth: ${{ secrets.TEST_OBSERVABILITY_SERVER_AUTH_KEY }}
path: 'junit'
github-token: ${{ secrets.GITHUB_TOKEN }}
# We replicate the way in which GitHub assigns a name to a matrix job.
job-name: check (${{ matrix.some-value }})
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ An action to push JUnit files to Ably's test observability server.
- `server-url`: the server to publish results to - see [action.yml](./action.yml) for the default value
- `server-auth`: authentication key for the server. The `ably` GitHub organization has an org-wide `TEST_OBSERVABLILITY_SERVER_AUTH_KEY` secret. It is recommended that you [make this secret available to your repository](https://docs.github.com/en/actions/using-workflows/sharing-workflows-secrets-and-runners-with-your-organization#sharing-secrets-within-an-organization) and then use this secret as the `server-auth` input.
- `path`: where to look for `*.junit` files
- `github-token` (optional): A GitHub access token. If provided, the action will perform a GitHub API call in order to discover the web URL for the current job, and will include this URL in the observability server upload. If the repository is private you must use an access token with the `repo` scope.
- `job-name` (optional): The `name` property of the object corresponding to the current job in the response from the ["list jobs for a workflow run attempt" GitHub API](https://docs.github.com/en/rest/actions/workflow-jobs?apiVersion=2022-11-28#list-jobs-for-a-workflow-run-attempt). See the [sample workflow](./.github/workflows/check.yml) for an example of how to calculate this value. If there is more than one object in the response whose `name` property equals this value, the action will fail.

If you specify `github-token` but not `job-name`, and the response from this API contains more than one job, the action will fail.

## Example

Expand All @@ -19,4 +23,5 @@ Workflow step:
with:
server-auth: ${{ secrets.TEST_OBSERVABLILITY_SERVER_AUTH_KEY }}
path: '.'
github-token: ${{ secrets.GITHUB_TOKEN }}
```
6 changes: 6 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ inputs:
description: 'path to .junit report files'
required: false
default: 'junit'
github-token:
description: 'a GitHub access token; if the repository is private then it must have `repo` scope'
required: false
job-name:
description: 'the `name` property of the object corresponding to the current job in the response from the "list jobs for a workflow run attempt" GitHub API (https://docs.github.com/en/rest/actions/workflow-jobs?apiVersion=2022-11-28#list-jobs-for-a-workflow-run-attempt)'
required: false
runs:
using: 'node16'
main: 'dist/index.js'
55 changes: 55 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,58 @@ import fs from 'fs';
import path from 'path';
import {got} from 'got';

/**
* Fetches the currently-running job from the GitHub API,
* so that we can add a link to it in the upload.
*
* It’s a bit surprising that there’s no built-in functionality
* for this (see e.g. https://stackoverflow.com/questions/71240338/obtain-job-id-from-a-workflow-run-using-contexts
* or https://github.com/orgs/community/discussions/8945).
*/
async function fetchJob() {
const githubToken = core.getInput('github-token');
if (!githubToken.length) {
return null;
}

const octokit = github.getOctokit(githubToken);
const response = await octokit.rest.actions.listJobsForWorkflowRunAttempt(
{
owner: github.context.repo.owner,
repo: github.context.repo.repo,
run_id: github.context.runId,
attempt_number: parseInt(process.env.GITHUB_RUN_ATTEMPT!),
},
);

const jobs = response.data.jobs;

const jobName = core.getInput('job-name');

if (jobs.length > 1 && !jobName.length) {
throw new Error(
`Got ${jobs.length} jobs from GitHub API \
but don’t know which one to pick. You need to \
provide a \`job-name\` input.`,
);
}

const matchingJobs = jobs.filter((job) => job.name === jobName);

if (matchingJobs.length === 0) {
throw new Error(
`The GitHub API response contains no job whose \`name\` is ${jobName}. \
This action does not currently handle pagination.`,
);
} else if (matchingJobs.length > 1) {
throw new Error(
`The GitHub API response multiple jobs whose \`name\` is ${jobName}.`,
);
}

return matchingJobs[0];
}

// eslint-disable-next-line require-jsdoc
async function main() {
const auth = core.getInput('server-auth', {required: true});
Expand All @@ -22,6 +74,7 @@ async function main() {
);
}

const job = await fetchJob();

for (const [i, file] of results.entries()) {
const data = fs.readFileSync(file);
Expand All @@ -44,6 +97,8 @@ async function main() {
iteration: i + 1,
github_base_ref: process.env.GITHUB_BASE_REF || null,
github_head_ref: process.env.GITHUB_HEAD_REF || null,
github_job_api_url: job?.url ?? null,
github_job_html_url: job?.html_url ?? null,
};


Expand Down

0 comments on commit 3a486ca

Please sign in to comment.