-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaction.yaml
111 lines (104 loc) · 5.04 KB
/
action.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
---
name: Job Context
description: Provides additional context for the currently running job
branding:
icon: box
color: black
outputs:
name:
description: The rendered job name.
value: ${{ steps.render.outputs.name }}
id:
description: >-
The numeric job ID as used by the GitHub API. Not be be confused with the workflow
job key `github.job`.
value: ${{ steps.job-api.outputs.id }}
runs:
using: composite
steps:
# In order to determine the job name we'll extract the non-rendered job name from the workflow and then evaulate
# any expressions contained within. Using `action/checkout` requires that we set the path under `$GITHUB_WORSPACE`.
- uses: actions/checkout@v4
id: checkout
with:
ref: ${{ github.workflow_sha }}
path: ${{ format('{0}/.job-context-repo', github.workspace) }}
- id: workflow
shell: bash
run: |
# Workflow job name template
[[ "$RUNNER_DEBUG" -eq 1 ]] && set -x
set -euo pipefail
# e.g. octocat/hello-world/.github/workflows/my-workflow.yml@refs/heads/my_branch -> .github/workflows/my-workflow.yml
workflow_path="$(echo "${workflow_ref%@*}" | cut -d/ -f3-)"
job_name_template="$(job_key="${job_key}" yq '.jobs[env(job_key)] | select(has("name")).name | select(. != null)' "${repo_path}/${workflow_path:?}")"
echo "name-template=${job_name_template}" | tee -a "$GITHUB_OUTPUT"
env:
repo_path: ${{ format('{0}/.job-context-repo', github.workspace) }}
workflow_ref: ${{ github.workflow_ref }}
job_key: ${{ github.job }} # User supplied job key cannot be allowed as we cannot properly render `matrix` expressions later
- id: render
shell: bash
run: |
# Render job name
[[ "$RUNNER_DEBUG" -eq 1 ]] && set -x
set -euo pipefail
# Determine if job name contains GitHub expressions. As GitHub expressions must be
# closed we can just check for the opening sequence.
if grep -qE '\$\{\{' <<<"${job_name_template}"; then
# Convert GHA expressions into jq Bash expressions. Converts `null` results into `""` to match GHA behavior.
# e.g. `{{ matrix.demo.version }}` -> `$(jq -r '.demo.version | select(type != "null")' <<<"${matrix_json:?}")`
job_name_expr="$(perl -pe 's/\$\{\{\s*([a-z]+)\.([a-z0-9._-]+)\s*}}/\$(jq -r --arg p "\2" '\''getpath(\$p | split(".")) | select(type != "null")'\'' <<<"\${\1_json:?}")/g' <<<"${job_name_template}")"
job_name="$(eval "echo \"${job_name_expr}\"")"
else
job_name="${job_name_template}"
if [ -z "${job_name}" ]; then
job_name="${job_key:?}"
fi
# GitHub adds job matrix values to job names which do not contain expressions.
matrix_values="$(jq -r '[.. | select(type != "object")] | join(", ")' <<<"${matrix_json}")"
if [[ -n "${matrix_values}" ]]; then
job_name="${job_name:?} (${matrix_values})"
fi
fi
echo "name=${job_name:?}" | tee -a "$GITHUB_OUTPUT"
env:
job_name_template: ${{ steps.workflow.outputs.name-template }}
job_key: ${{ github.job }}
# `jobs.<job_id>.name` can use the contexts: [github, needs, strategy, matrix, vars, inputs]. No functions are allowed.
# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/contexts#context-availability
github_json: ${{ toJSON(github) }}
# needs_json: ${{ toJSON(needs) }}
strategy_json: ${{ toJSON(strategy) }}
matrix_json: ${{ toJSON(matrix) }}
# vars_json: ${{ toJSON(vars) }}
# inputs_json: ${{ toJSON(inputs) }}
# With the rendered job name we can use the GitHub API to fetch the job ID from the API
# as long as the job name is distinct within the workflow.
- id: job-api
shell: bash
run: |
# Fetch job ID
[[ "$RUNNER_DEBUG" -eq 1 ]] && set -x
set -euo pipefail
# https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#get-a-workflow-run-attempt
jobs="$(gh api -X GET "/repos/{owner}/{repo}/actions/runs/${run_id:?}/attempts/${run_attempt:?}/jobs")"
job_ids="$(jq -c --arg name "$job_name" '[.jobs[] | select(.name == $name) | .id]' <<<"${jobs}")"
if [[ $(jq length <<<"${job_ids}") -eq 1 ]]; then
echo "id=$(jq 'first' <<<"${job_ids}")" | tee -a "$GITHUB_OUTPUT"
else
echo "ERROR: Unable to determine job ID. The job name \"${job_name:?}\" is not unique within the workflow." >&2
exit 1
fi
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run_id: ${{ github.run_id }}
run_attempt: ${{ github.run_attempt }}
job_name: ${{ steps.render.outputs.name }}
- name: Cleanup
if: ${{ always() && steps.checkout.output == 'success' }}
shell: bash
run: rm -rf "${repo_path:?}"
env:
repo_path: ${{ format('{0}/.job-context-repo', github.workspace) }}