Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit 3d0e6ec

Browse files
authored
bugfix: Step::timeout_minutes can be an expression (#31)
1 parent d0447cf commit 3d0e6ec

File tree

2 files changed

+314
-1
lines changed

2 files changed

+314
-1
lines changed

src/workflow/job.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ pub struct Step {
9595
pub name: Option<String>,
9696

9797
/// An optional timeout for this step, in minutes.
98-
pub timeout_minutes: Option<u64>,
98+
pub timeout_minutes: Option<LoE<u64>>,
9999

100100
/// An optional boolean or expression that, if `true`, prevents the job from failing when
101101
/// this step fails.
Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
# https://github.com/openbao/openbao/blob/76c9470e8d03fce343f38854d10727775d571519/.github/workflows/test-go.yml
2+
3+
# Copyright (c) 2015 HashiCorp, Inc.
4+
# Licensed under MPL 2.0:
5+
# https://github.com/openbao/openbao/blob/76c9470e8d03fce343f38854d10727775d571519/LICENSE
6+
7+
on:
8+
workflow_call:
9+
inputs:
10+
go-arch:
11+
description: The execution architecture (arm, amd64, etc.)
12+
required: true
13+
type: string
14+
total-runners:
15+
description: Number of runners to use for executing non-binary tests.
16+
required: true
17+
type: string
18+
binary-tests:
19+
description: Whether to run the binary tests.
20+
required: false
21+
default: false
22+
type: boolean
23+
env-vars:
24+
description: A map of environment variables as JSON.
25+
required: false
26+
type: string
27+
default: "{}"
28+
extra-flags:
29+
description: A space-separated list of additional build flags.
30+
required: false
31+
type: string
32+
default: ""
33+
runs-on:
34+
description: An expression indicating which kind of runners to use.
35+
required: false
36+
type: string
37+
default: ubuntu-latest
38+
go-tags:
39+
description: A comma-separated list of additional build tags to consider satisfied during the build.
40+
required: false
41+
type: string
42+
name:
43+
description: A suffix to append to archived test results
44+
required: false
45+
default: ""
46+
type: string
47+
go-test-parallelism:
48+
description: The parallelism parameter for Go tests
49+
required: false
50+
default: 20
51+
type: number
52+
timeout-minutes:
53+
description: The maximum number of minutes that this workflow should run
54+
required: false
55+
default: 60
56+
type: number
57+
testonly:
58+
description: Whether to run the tests tagged with testonly.
59+
required: false
60+
default: false
61+
type: boolean
62+
checkout-ref:
63+
description: The ref to use for checkout.
64+
required: false
65+
default: ${{ github.ref }}
66+
type: string
67+
68+
env: ${{ fromJSON(inputs.env-vars) }}
69+
70+
jobs:
71+
test-matrix:
72+
runs-on: ubuntu-latest
73+
steps:
74+
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
75+
with:
76+
ref: ${{ inputs.checkout-ref }}
77+
- uses: ./.github/actions/set-up-go
78+
name: Setup Git configuration (public)
79+
- uses: ./.github/actions/set-up-gotestsum
80+
- run: mkdir -p test-results/go-test
81+
- uses: actions/cache/restore@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1
82+
with:
83+
path: test-results/go-test
84+
key: go-test-reports-${{ github.run_number }}
85+
restore-keys: go-test-reports-
86+
- name: List cached results
87+
id: list-cached-results
88+
run: ls -lhR test-results/go-test
89+
- name: Build matrix excluding binary, integration, and testonly tests
90+
id: build-non-binary
91+
if: ${{ !inputs.testonly }}
92+
run: |
93+
# testonly tests need additional build tag though let's exclude them anyway for clarity
94+
(
95+
go list ./... github.com/openbao/openbao/api/v2/... github.com/openbao/openbao/sdk/v2/... | grep -v "_binary" | grep -v "vault/integ" | grep -v "testonly" | gotestsum tool ci-matrix --debug \
96+
--partitions "${{ inputs.total-runners }}" \
97+
--timing-files 'test-results/go-test/*.json' > matrix.json
98+
)
99+
- name: Build matrix for tests tagged with testonly
100+
if: ${{ inputs.testonly }}
101+
run: |
102+
set -exo pipefail
103+
# enable glob expansion
104+
shopt -s nullglob
105+
# testonly tagged tests need an additional tag to be included
106+
# also running some extra tests for sanity checking with the testonly build tag
107+
(
108+
go list -tags=testonly ./vault/external_tests/{kv,token,*replication-perf*,*testonly*} ./vault/ | gotestsum tool ci-matrix --debug \
109+
--partitions "${{ inputs.total-runners }}" \
110+
--timing-files 'test-results/go-test/*.json' > matrix.json
111+
)
112+
# disable glob expansion
113+
shopt -u nullglob
114+
- name: Capture list of binary tests
115+
if: inputs.binary-tests
116+
id: list-binary-tests
117+
run: |
118+
LIST="$(go list ./... github.com/openbao/openbao/api/v2/... github.com/openbao/openbao/sdk/v2/... | grep "_binary" | xargs)"
119+
echo "list=$LIST" >> "$GITHUB_OUTPUT"
120+
- name: Build complete matrix
121+
id: build
122+
run: |
123+
set -exo pipefail
124+
matrix_file="matrix.json"
125+
if [ "${{ inputs.binary-tests}}" == "true" ] && [ -n "${{ steps.list-binary-tests.outputs.list }}" ]; then
126+
export BINARY_TESTS="${{ steps.list-binary-tests.outputs.list }}"
127+
jq --arg BINARY "${BINARY_TESTS}" --arg BINARY_INDEX "${{ inputs.total-runners }}" \
128+
'.include += [{
129+
"id": $BINARY_INDEX,
130+
"estimatedRuntime": "N/A",
131+
"packages": $BINARY,
132+
"description": "partition $BINARY_INDEX - binary test packages"
133+
}]' matrix.json > new-matrix.json
134+
matrix_file="new-matrix.json"
135+
fi
136+
# convert the json to a map keyed by id
137+
(
138+
echo -n "matrix="
139+
jq -c \
140+
'.include | map( { (.id|tostring): . } ) | add' "$matrix_file"
141+
) >> "$GITHUB_OUTPUT"
142+
# extract an array of ids from the json
143+
(
144+
echo -n "matrix_ids="
145+
jq -c \
146+
'[ .include[].id | tostring ]' "$matrix_file"
147+
) >> "$GITHUB_OUTPUT"
148+
outputs:
149+
matrix: ${{ steps.build.outputs.matrix }}
150+
matrix_ids: ${{ steps.build.outputs.matrix_ids }}
151+
152+
test-go:
153+
needs: test-matrix
154+
runs-on: ubuntu-latest
155+
strategy:
156+
fail-fast: false
157+
matrix:
158+
id: ${{ fromJSON(needs.test-matrix.outputs.matrix_ids) }}
159+
env:
160+
TIMEOUT_IN_MINUTES: ${{ inputs.timeout-minutes }}
161+
steps:
162+
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
163+
with:
164+
ref: ${{ inputs.checkout-ref }}
165+
- uses: ./.github/actions/set-up-go
166+
- id: setup-git-public
167+
name: Setup Git configuration (public)
168+
run: |
169+
git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN}}@github.com".insteadOf https://github.com
170+
- id: build
171+
if: inputs.binary-tests && matrix.id == inputs.total-runners
172+
run: time make ci-bootstrap dev
173+
- uses: ./.github/actions/set-up-gotestsum
174+
- id: run-go-tests
175+
name: Run Go tests
176+
timeout-minutes: ${{ fromJSON(env.TIMEOUT_IN_MINUTES) }}
177+
env:
178+
COMMIT_SHA: ${{ github.sha }}
179+
run: |
180+
set -exo pipefail
181+
182+
# Build the dynamically generated source files.
183+
make prep
184+
185+
packages=$(echo "${{ toJSON(needs.test-matrix.outputs.matrix) }}" | jq -c -r --arg id "${{ matrix.id }}" '.[$id] | .packages')
186+
187+
if [ -z "$packages" ]; then
188+
echo "no test packages to run"
189+
exit 1
190+
fi
191+
192+
# shellcheck disable=SC2034
193+
if [ -f bin/bao ]; then
194+
BAO_BINARY="$(pwd)/bin/bao"
195+
export BAO_BINARY
196+
fi
197+
198+
# On a release branch, add a flag to rerun failed tests
199+
# shellcheck disable=SC2193 # can get false positive for this comparision
200+
if [[ "${{ github.base_ref }}" == release/* ]] || [[ -z "${{ github.base_ref }}" && "${{ github.ref_name }}" == release/* ]]
201+
then
202+
RERUN_FAILS="--rerun-fails"
203+
fi
204+
205+
# shellcheck disable=SC2086 # can't quote RERUN_FAILS
206+
GOARCH=${{ inputs.go-arch }} \
207+
gotestsum --format=short-verbose \
208+
--junitfile test-results/go-test/results-${{ matrix.id }}.xml \
209+
--jsonfile test-results/go-test/results-${{ matrix.id }}.json \
210+
--jsonfile-timing-events failure-summary-${{ matrix.id }}${{ inputs.name != '' && '-' || '' }}${{ inputs.name }}.json \
211+
$RERUN_FAILS \
212+
--packages "$packages" \
213+
-- \
214+
-tags "${{ inputs.go-tags }}" \
215+
-timeout=${{ env.TIMEOUT_IN_MINUTES }}m \
216+
-parallel=${{ inputs.go-test-parallelism }} \
217+
${{ inputs.extra-flags }} \
218+
- name: Archive test results
219+
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
220+
with:
221+
name: test-results-${{ matrix.id }}${{ inputs.name != '' && '-' || '' }}${{ inputs.name }}
222+
path: test-results/go-test-${{ matrix.id }}
223+
if: success() || failure()
224+
# GitHub Actions doesn't expose the job ID or the URL to the job execution,
225+
# so we have to fetch it from the API
226+
- name: Fetch job logs URL
227+
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
228+
if: success() || failure()
229+
continue-on-error: true
230+
with:
231+
retries: 3
232+
script: |
233+
// We surround the whole script with a try-catch block, to avoid each of the matrix jobs
234+
// displaying an error in the GHA workflow run annotations, which gets very noisy.
235+
// If an error occurs, it will be logged so that we don't lose any information about the reason for failure.
236+
try {
237+
const fs = require("fs");
238+
const result = await github.rest.actions.listJobsForWorkflowRun({
239+
owner: context.repo.owner,
240+
per_page: 100,
241+
repo: context.repo.repo,
242+
run_id: context.runId,
243+
});
244+
245+
// Determine what job name to use for the query. These values are hardcoded, because GHA doesn't
246+
// expose them in any of the contexts available within a workflow run.
247+
let prefixToSearchFor;
248+
switch ("${{ inputs.name }}") {
249+
case "race":
250+
prefixToSearchFor = 'Run Go tests with data race detection / test-go (${{ matrix.id }})'
251+
break
252+
case "fips":
253+
prefixToSearchFor = 'Run Go tests with FIPS configuration / test-go (${{ matrix.id }})'
254+
break
255+
default:
256+
prefixToSearchFor = 'Run Go tests / test-go (${{ matrix.id }})'
257+
}
258+
259+
const jobData = result.data.jobs.filter(
260+
(job) => job.name.startsWith(prefixToSearchFor)
261+
);
262+
const url = jobData[0].html_url;
263+
const envVarName = "GH_JOB_URL";
264+
const envVar = envVarName + "=" + url;
265+
const envFile = process.env.GITHUB_ENV;
266+
267+
fs.appendFile(envFile, envVar, (err) => {
268+
if (err) throw err;
269+
console.log("Successfully set " + envVarName + " to: " + url);
270+
});
271+
} catch (error) {
272+
console.log("Error: " + error);
273+
return
274+
}
275+
- name: Prepare failure summary
276+
if: success() || failure()
277+
continue-on-error: true
278+
run: |
279+
# This jq query filters out successful tests, leaving only the failures.
280+
# Then, it formats the results into rows of a Markdown table.
281+
# An example row will resemble this:
282+
# | github.com/openbao/openbao/package | TestName | fips | 0 | 2 | [view results](github.com/link-to-logs) |
283+
jq -r -n 'inputs
284+
| select(.Action == "fail")
285+
| "| ${{inputs.name}} | \(.Package) | \(.Test // "-") | \(.Elapsed) | ${{ matrix.id }} | [view test results :scroll:](${{ env.GH_JOB_URL }}) |"' \
286+
failure-summary-${{ matrix.id }}${{ inputs.name != '' && '-' || '' }}${{inputs.name}}.json \
287+
>> failure-summary-${{ matrix.id }}${{ inputs.name != '' && '-' || '' }}${{inputs.name}}.md
288+
- name: Upload failure summary
289+
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
290+
if: success() || failure()
291+
with:
292+
name: failure-summary-${{ matrix.id }}${{ inputs.name != '' && '-' || '' }}${{inputs.name}}
293+
path: failure-summary-${{ matrix.id }}${{ inputs.name != '' && '-' || '' }}${{inputs.name}}.md
294+
295+
test-collect-reports:
296+
if: ${{ ! cancelled() }}
297+
needs: test-go
298+
runs-on: ubuntu-latest
299+
steps:
300+
- uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1
301+
with:
302+
path: test-results/go-test
303+
key: go-test-reports-${{ github.run_number }}
304+
restore-keys: go-test-reports-
305+
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
306+
with:
307+
path: test-results/go-test
308+
pattern: test-results-*
309+
merge-multiple: true
310+
- run: |
311+
ls -lhR test-results/go-test
312+
find test-results/go-test -type f -mindepth 1 -mtime +3 -delete
313+
ls -lhR test-results/go-test

0 commit comments

Comments
 (0)