Repository navigation
181 lines (174 loc) · 7 KB
/
Copy pathgenerate-qualification.yml
File metadata and controls
181 lines (174 loc) · 7 KB
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
name: Docker generate qualification
on:
# No paths filter. A required check must report on every pull request and
# every queue entry, so `changes` decides whether the shards run and
# `docker-generate` always reports one status for the whole job.
pull_request:
branches: [main]
merge_group:
schedule:
- cron: '23 5 * * *'
workflow_dispatch:
permissions:
contents: read
concurrency:
group: docker-generate-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
# The one row this workflow proves. The shards run its packages under its
# build tag (both derived from pkg/conformance/matrix.json), its gates
# cannot skip, and the summary verifies its receipts across every shard.
CODEFLY_CONFORMANCE_REQUIRED: linux-amd64-docker-generate
jobs:
changes:
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
relevant: ${{ steps.scope.outputs.relevant }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Decide whether anything but documentation changed
id: scope
env:
BASE: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha }}
run: |
set -euo pipefail
# The nightly and a manual run have no base: they always qualify.
if [[ -z "$BASE" ]]; then
echo "relevant=true" >> "$GITHUB_OUTPUT"
exit 0
fi
git fetch --no-tags --depth=1 origin "$BASE"
./scripts/generate-qualification-scope.sh "$BASE" | tee -a "$GITHUB_OUTPUT"
generate:
needs: changes
if: needs.changes.outputs.relevant == 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
# Round-robin over discovered tests. Which shard draws a
# receipt-bearing test moves as tests are added, so receipts are
# verified across all shards in docker-generate, never per shard.
# Separate runners also isolate the Docker daemon; each runner pulls
# the published image only once.
shard: [0, 1, 2]
env:
GOWORK: 'off'
GOFLAGS: -mod=mod
CODEFLY_GENERATE_QUALIFY: '1'
CODEFLY_CONFORMANCE_RECEIPTS: ${{ github.workspace }}/conformance-receipts
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: '24'
- name: Restore Go build cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.cache/go-build
key: cli-go-build-generate-${{ runner.os }}-${{ hashFiles('go.sum') }}
restore-keys: |
cli-go-build-generate-${{ runner.os }}-
- name: Pull the published companion once and provision its buf
run: |
set -euo pipefail
docker info
image=$(go run ./scripts/generate-companion-image)
docker pull "$image"
docker image inspect "$image" --format '{{json .RepoDigests}}'
# The SDK fixture needs host buf. Reuse the static binary shipped
# in the image under test, without another version or download.
container=$(docker create "$image" /bin/true)
trap 'docker rm "$container"' EXIT
mkdir -p "$RUNNER_TEMP/generate-bin"
docker cp "$container:/usr/local/bin/buf" "$RUNNER_TEMP/generate-bin/buf"
"$RUNNER_TEMP/generate-bin/buf" --version
echo "$RUNNER_TEMP/generate-bin" >> "$GITHUB_PATH"
- name: Run tagged and qualification tests in isolated processes
run: ./scripts/test-generate-isolated.sh "${{ matrix.shard }}" "${{ strategy.job-total }}"
- name: Retain test output, timings and conformance receipts
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: docker-generate-evidence-${{ matrix.shard }}
path: |
generate-evidence/
conformance-receipts/
if-no-files-found: error
# The one status to require: it fails unless the shards passed and every
# shard's receipts together prove the row, and it passes without them only
# when `changes` found nothing but documentation.
docker-generate:
needs: [changes, generate]
if: always()
runs-on: ubuntu-latest
timeout-minutes: 5
env:
CODEFLY_CONFORMANCE_RECEIPTS: ${{ github.workspace }}/conformance-receipts
steps:
- name: Read the shards' outcome
id: outcome
env:
CHANGES: ${{ needs.changes.result }}
RELEVANT: ${{ needs.changes.outputs.relevant }}
SHARDS: ${{ needs.generate.result }}
run: |
set -euo pipefail
if [[ "$CHANGES" != success ]]; then
echo "the change classification ended '$CHANGES', so nothing decided whether the row must run" >&2
exit 1
fi
case "$RELEVANT" in
false)
if [[ "$SHARDS" != skipped ]]; then
echo "only documentation changed, yet the shards ended '$SHARDS'" >&2
exit 1
fi
echo "only documentation changed; nothing that generation compiles or reads moved"
echo "verify=false" >> "$GITHUB_OUTPUT"
;;
true)
if [[ "$SHARDS" != success ]]; then
echo "the generate shards ended '$SHARDS'" >&2
exit 1
fi
echo "verify=true" >> "$GITHUB_OUTPUT"
;;
*)
echo "the change classification reported relevant='$RELEVANT', want true or false" >&2
exit 1
;;
esac
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
if: steps.outcome.outputs.verify == 'true'
with:
persist-credentials: false
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
if: steps.outcome.outputs.verify == 'true'
with:
pattern: docker-generate-evidence-*
path: shards
- name: Verify conformance receipts across every shard
if: steps.outcome.outputs.verify == 'true'
run: |
set -euo pipefail
mkdir -p "$CODEFLY_CONFORMANCE_RECEIPTS"
shopt -s nullglob
receipts=(shards/*/conformance-receipts/*.json)
shopt -u nullglob
# Receipt names carry the package and test, and shards run disjoint
# tests, so no copy overwrites another shard's receipt.
if (( ${#receipts[@]} > 0 )); then
cp "${receipts[@]}" "$CODEFLY_CONFORMANCE_RECEIPTS/"
fi
./scripts/verify-conformance-receipts.sh