Skip to content

Commit 5047573

Browse files
committed
fix(ci): decouple release helpers from tag checkout
1 parent 2f42562 commit 5047573

5 files changed

Lines changed: 155 additions & 65 deletions

File tree

.github/workflows/release.yml

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,23 @@ jobs:
7676
timeout-minutes: 20
7777

7878
steps:
79-
- name: Checkout
79+
- name: Checkout workflow helpers
80+
uses: actions/checkout@v6
81+
82+
- name: Checkout release source
8083
uses: actions/checkout@v6
8184
with:
8285
ref: ${{ needs.metadata.outputs.checkout_ref }}
86+
path: release-src
8387

8488
- name: Set up Go
8589
uses: actions/setup-go@v6
8690
with:
87-
go-version-file: go.mod
88-
cache-dependency-path: go.sum
91+
go-version-file: release-src/go.mod
92+
cache-dependency-path: release-src/go.sum
8993

9094
- name: Run Go unit tests
95+
working-directory: release-src
9196
run: go test -count=1 -timeout 5m ./...
9297

9398
kind-smoke:
@@ -107,34 +112,44 @@ jobs:
107112
ALL_FEATURES: "true"
108113

109114
steps:
110-
- name: Checkout
115+
- name: Checkout workflow helpers
116+
uses: actions/checkout@v6
117+
118+
- name: Checkout release source
111119
uses: actions/checkout@v6
112120
with:
113121
ref: ${{ needs.metadata.outputs.checkout_ref }}
114122
fetch-depth: 0
123+
path: release-src
115124

116125
- name: Set up Go
117126
uses: actions/setup-go@v6
118127
with:
119-
go-version-file: go.mod
120-
cache-dependency-path: go.sum
128+
go-version-file: release-src/go.mod
129+
cache-dependency-path: release-src/go.sum
121130

122131
- name: Install Kind tooling
132+
working-directory: release-src
123133
run: scripts/ci/install-kind-tools.sh
124134

125135
- name: Create kind cluster
136+
working-directory: release-src
126137
run: scripts/ci/create-kind-cluster.sh
127138

128139
- name: Install Gateway API CRDs
140+
working-directory: release-src
129141
run: scripts/ci/install-gateway-api-crds.sh
130142

131143
- name: Build current control-plane image
144+
working-directory: release-src
132145
run: scripts/ci/build-controlplane-image.sh
133146

134147
- name: Load images into kind
148+
working-directory: release-src
135149
run: scripts/ci/load-kind-images.sh
136150

137151
- name: Deploy Nantian Gateway
152+
working-directory: release-src
138153
run: scripts/ci/deploy-kind-conformance.sh
139154

140155
- name: Record image versions
@@ -145,15 +160,16 @@ jobs:
145160
kubectl get pods -n nantian-gw -o json | jq -r '.items[] | .status.containerStatuses[] | " \(.name): \(.imageID)"'
146161
147162
- name: Run smoke test
148-
run: CLUSTER_NAME="$CLUSTER_NAME" ./test/e2e/smoke/run.sh --no-cleanup
163+
run: CLUSTER_NAME="$CLUSTER_NAME" GATEWAY_HTTP_PORT=80 ./test/e2e/smoke/run.sh --no-cleanup --skip-bootstrap
149164

150165
- name: Run full Gateway API conformance
151166
id: conformance
152167
env:
153168
RELEASE_TAG: ${{ needs.metadata.outputs.release_tag }}
169+
working-directory: release-src
154170
run: |
155171
mkdir -p dist/conformance
156-
report_path="${GITHUB_WORKSPACE}/dist/conformance/report.yaml"
172+
report_path="${GITHUB_WORKSPACE}/release-src/dist/conformance/report.yaml"
157173
set +e
158174
go test -tags=conformance -count=1 -v -timeout 30m ./conformance/ \
159175
-args \
@@ -171,6 +187,7 @@ jobs:
171187
172188
- name: Collect diagnostics on failure
173189
if: failure()
190+
working-directory: release-src
174191
run: ARTIFACT_DIR=tmp/conformance-diagnostics scripts/ci/collect-kind-diagnostics.sh
175192

176193
- name: Upload conformance artifacts
@@ -179,8 +196,8 @@ jobs:
179196
with:
180197
name: conformance-${{ needs.metadata.outputs.release_tag }}
181198
path: |
182-
dist/conformance/
183-
tmp/conformance-diagnostics/
199+
release-src/dist/conformance/
200+
release-src/tmp/conformance-diagnostics/
184201
if-no-files-found: warn
185202

186203
- name: Cleanup
@@ -199,16 +216,20 @@ jobs:
199216
control_digest: ${{ steps.build-controlplane.outputs.digest }}
200217

201218
steps:
202-
- name: Checkout
219+
- name: Checkout workflow helpers
220+
uses: actions/checkout@v6
221+
222+
- name: Checkout release source
203223
uses: actions/checkout@v6
204224
with:
205225
ref: ${{ needs.metadata.outputs.checkout_ref }}
226+
path: release-src
206227

207228
- name: Set up Go
208229
uses: actions/setup-go@v6
209230
with:
210-
go-version-file: go.mod
211-
cache-dependency-path: go.sum
231+
go-version-file: release-src/go.mod
232+
cache-dependency-path: release-src/go.sum
212233

213234
- name: Set up Docker Buildx
214235
uses: docker/setup-buildx-action@v4
@@ -224,13 +245,13 @@ jobs:
224245
id: build-controlplane
225246
uses: docker/build-push-action@v7
226247
with:
227-
context: .
228-
file: Dockerfile
248+
context: release-src
249+
file: release-src/Dockerfile
229250
push: true
230251
tags: ${{ needs.metadata.outputs.control_image }}
231252

232253
- name: Prepare image metadata directory
233-
run: mkdir -p dist/image-metadata
254+
run: mkdir -p release-src/dist/image-metadata
234255

235256
- name: Generate image provenance
236257
env:
@@ -239,7 +260,7 @@ jobs:
239260
CONTROL_IMAGE: ${{ needs.metadata.outputs.control_image }}
240261
TIMESTAMP: ${{ github.event.repository.updated_at }}
241262
run: |
242-
cat > dist/image-metadata/provenance.json <<HEREDOC
263+
cat > release-src/dist/image-metadata/provenance.json <<HEREDOC
243264
{
244265
"release": "${RELEASE_TAG}",
245266
"ci_run": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}",
@@ -256,5 +277,5 @@ jobs:
256277
uses: actions/upload-artifact@v7
257278
with:
258279
name: image-metadata-${{ needs.metadata.outputs.release_tag }}
259-
path: dist/image-metadata/
280+
path: release-src/dist/image-metadata/
260281
if-no-files-found: warn

.github/workflows/security-scans.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,20 @@ jobs:
2929
timeout-minutes: 35
3030

3131
steps:
32-
- name: Checkout
32+
- name: Checkout workflow helpers
33+
uses: actions/checkout@v6
34+
35+
- name: Checkout release source
3336
uses: actions/checkout@v6
3437
with:
3538
ref: ${{ inputs.checkout_ref }}
39+
path: release-src
3640

3741
- name: Set up Go
3842
uses: actions/setup-go@v6
3943
with:
40-
go-version-file: go.mod
41-
cache-dependency-path: go.sum
44+
go-version-file: release-src/go.mod
45+
cache-dependency-path: release-src/go.sum
4246

4347
- name: Install scanner prerequisites
4448
run: |
@@ -70,7 +74,7 @@ jobs:
7074
echo "${RUNNER_TEMP:-/tmp}/bin" >>"${GITHUB_PATH}"
7175
7276
- name: Run security scan bundle
73-
run: scripts/ci/run-security-scans.sh
77+
run: SCAN_ROOT=release-src scripts/ci/run-security-scans.sh
7478

7579
- name: Upload security scan artifacts
7680
if: always()

scripts/ci/ci_assets_test.go

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,17 @@ func TestReleaseWorkflowUsesCurrentCIEntrypoints(t *testing.T) {
162162

163163
for _, want := range []string{
164164
`checkout_ref: ${{ steps.vars.outputs.checkout_ref }}`,
165-
`ref: ${{ needs.metadata.outputs.checkout_ref }}`,
165+
`path: release-src`,
166+
`go-version-file: release-src/go.mod`,
167+
`cache-dependency-path: release-src/go.sum`,
168+
`working-directory: release-src`,
166169
`run: go test -count=1 -timeout 5m ./...`,
167170
`run: scripts/ci/install-kind-tools.sh`,
168171
`run: scripts/ci/create-kind-cluster.sh`,
169172
`run: scripts/ci/install-gateway-api-crds.sh`,
170173
`run: scripts/ci/load-kind-images.sh`,
171174
`run: scripts/ci/deploy-kind-conformance.sh`,
172-
`run: CLUSTER_NAME="$CLUSTER_NAME" ./test/e2e/smoke/run.sh --no-cleanup`,
175+
`run: CLUSTER_NAME="$CLUSTER_NAME" GATEWAY_HTTP_PORT=80 ./test/e2e/smoke/run.sh --no-cleanup --skip-bootstrap`,
173176
`go test -tags=conformance -count=1 -v -timeout 30m ./conformance/ \`,
174177
} {
175178
if !strings.Contains(contents, want) {
@@ -194,11 +197,18 @@ func TestSecurityScanWorkflowUsesExistingHelper(t *testing.T) {
194197
contents := string(readFile(t, repoPath(".github", "workflows", "security-scans.yml")))
195198
helperPath := repoPath("scripts", "ci", "run-security-scans.sh")
196199

197-
if !strings.Contains(contents, `run: scripts/ci/run-security-scans.sh`) {
198-
t.Fatalf("security scan workflow must invoke scripts/ci/run-security-scans.sh")
200+
if !strings.Contains(contents, `path: release-src`) {
201+
t.Fatalf("security scan workflow must checkout the release source into release-src")
199202
}
200-
if !strings.Contains(contents, `ref: ${{ inputs.checkout_ref }}`) {
201-
t.Fatalf("security scan workflow must checkout the caller-provided ref")
203+
if !strings.Contains(contents, `go-version-file: release-src/go.mod`) {
204+
t.Fatalf("security scan workflow must resolve the Go toolchain from release-src")
205+
}
206+
if !strings.Contains(contents, `SCAN_ROOT=release-src scripts/ci/run-security-scans.sh`) {
207+
t.Fatalf("security scan workflow must scan release-src through the branch helper")
208+
}
209+
if strings.Contains(contents, `run: scripts/ci/run-security-scans.sh`) &&
210+
!strings.Contains(contents, `SCAN_ROOT=release-src scripts/ci/run-security-scans.sh`) {
211+
t.Fatalf("security scan workflow must not depend on a helper file from the checked-out release tag")
202212
}
203213

204214
if _, err := os.Stat(helperPath); err != nil {
@@ -210,10 +220,10 @@ func TestSmokeScriptForwardsToProgrammedGatewayListener(t *testing.T) {
210220
contents := string(readFile(t, repoPath("test", "e2e", "smoke", "run.sh")))
211221

212222
for _, want := range []string{
213-
`LOCAL_HTTP_PORT="${LOCAL_HTTP_PORT:-10080}"`,
223+
`GATEWAY_HOST="${GATEWAY_HOST:-127.0.0.1}"`,
214224
`GATEWAY_HTTP_PORT="${GATEWAY_HTTP_PORT:-80}"`,
215-
`service/$DATA_PLANE_SVC`,
216-
`"${LOCAL_HTTP_PORT}:${GATEWAY_HTTP_PORT}"`,
225+
`wait_for_gateway_programmed`,
226+
`http://${GATEWAY_HOST}:${GATEWAY_HTTP_PORT}/echo`,
217227
`request_deadline=`,
218228
} {
219229
if !strings.Contains(contents, want) {
@@ -222,6 +232,9 @@ func TestSmokeScriptForwardsToProgrammedGatewayListener(t *testing.T) {
222232
}
223233

224234
for _, unwanted := range []string{
235+
`LOCAL_HTTP_PORT="${LOCAL_HTTP_PORT:-10080}"`,
236+
`service/$DATA_PLANE_SVC`,
237+
`kubectl port-forward`,
225238
`pod/$dataplane_pod`,
226239
`dataplane_pod=$(kubectl get pod`,
227240
`port-forward to $dataplane_pod exited before request succeeded`,
@@ -246,7 +259,6 @@ func TestCIEntrypointsUseCurrentDeployResourceNames(t *testing.T) {
246259
for _, want := range []string{
247260
`GATEWAY_CLASS_NAME="${GATEWAY_CLASS_NAME:-nantian-gw}"`,
248261
`CONTROL_PLANE_DEPLOYMENT="nantian-gw-controlplane"`,
249-
`DATA_PLANE_SELECTOR="app=nantian-gw-dataplane"`,
250262
`gatewayClassName: $GATEWAY_CLASS_NAME`,
251263
} {
252264
if !strings.Contains(smokeScript, want) {
@@ -265,6 +277,22 @@ func TestCIEntrypointsUseCurrentDeployResourceNames(t *testing.T) {
265277
}
266278
}
267279

280+
func TestSecurityScanHelperSupportsAlternateScanRoot(t *testing.T) {
281+
contents := string(readFile(t, repoPath("scripts", "ci", "run-security-scans.sh")))
282+
283+
for _, want := range []string{
284+
`SCAN_ROOT="${SCAN_ROOT:-${1:-.}}"`,
285+
`cd "$SCAN_ROOT"`,
286+
`osv-scanner scan source -r . --format json --output-file`,
287+
`grype dir:. -o json --file`,
288+
`kubescape scan framework nsa`,
289+
} {
290+
if !strings.Contains(contents, want) {
291+
t.Fatalf("security scan helper missing %q", want)
292+
}
293+
}
294+
}
295+
268296
func TestConformanceOverlayDoesNotEnableExperimentalGatewayFeatures(t *testing.T) {
269297
data := readFile(t, repoPath("deploy", "kubernetes", "overlays", "kind-conformance", "controlplane-config.yaml"))
270298

scripts/ci/run-security-scans.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
33

4+
SCAN_ROOT="${SCAN_ROOT:-${1:-.}}"
45
ARTIFACT_DIR="${ARTIFACT_DIR:-tmp/security-scans/latest}"
6+
WORKSPACE_ROOT="$(pwd)"
7+
8+
case "$ARTIFACT_DIR" in
9+
/*)
10+
;;
11+
*)
12+
ARTIFACT_DIR="$WORKSPACE_ROOT/$ARTIFACT_DIR"
13+
;;
14+
esac
15+
516
mkdir -p "$ARTIFACT_DIR"
17+
cd "$SCAN_ROOT"
618

719
osv-scanner scan source -r . --format json --output-file "$ARTIFACT_DIR/osv-scanner.json"
820
grype dir:. -o json --file "$ARTIFACT_DIR/grype-dir.json"
@@ -14,6 +26,7 @@ kubescape scan framework nsa \
1426

1527
{
1628
echo "Generated security scan artifacts in $ARTIFACT_DIR"
29+
echo "scan root: $(pwd)"
1730
echo "osv-scanner: $(command -v osv-scanner)"
1831
echo "grype: $(command -v grype)"
1932
echo "kubescape: $(command -v kubescape)"

0 commit comments

Comments
 (0)