Skip to content

Commit 2f42562

Browse files
committed
fix(ci): repair release workflow entrypoints
1 parent 3b24c07 commit 2f42562

4 files changed

Lines changed: 150 additions & 60 deletions

File tree

.github/workflows/release.yml

Lines changed: 67 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
runs-on: ubuntu-latest
2929
outputs:
3030
release_tag: ${{ steps.vars.outputs.release_tag }}
31+
checkout_ref: ${{ steps.vars.outputs.checkout_ref }}
3132
control_image: ${{ steps.vars.outputs.control_image }}
3233
control_image_name: ${{ steps.vars.outputs.control_image_name }}
3334

@@ -47,21 +48,26 @@ jobs:
4748
fi
4849
4950
owner_lc="${GITHUB_REPOSITORY_OWNER,,}"
51+
checkout_ref="refs/tags/${release_tag}"
5052
control_image_name="ghcr.io/${owner_lc}/nantian-controlplane"
5153
control_image="${control_image_name}:${release_tag}"
5254
5355
{
5456
echo "release_tag=${release_tag}"
57+
echo "checkout_ref=${checkout_ref}"
5558
echo "control_image=${control_image}"
5659
echo "control_image_name=${control_image_name}"
5760
} >>"${GITHUB_OUTPUT}"
5861
5962
security-scans:
6063
name: Security Scans
64+
needs: metadata
6165
permissions:
6266
contents: read
6367
security-events: read
6468
uses: ./.github/workflows/security-scans.yml
69+
with:
70+
checkout_ref: ${{ needs.metadata.outputs.checkout_ref }}
6571

6672
controlplane:
6773
name: Controlplane Tests
@@ -72,6 +78,8 @@ jobs:
7278
steps:
7379
- name: Checkout
7480
uses: actions/checkout@v6
81+
with:
82+
ref: ${{ needs.metadata.outputs.checkout_ref }}
7583

7684
- name: Set up Go
7785
uses: actions/setup-go@v6
@@ -80,8 +88,7 @@ jobs:
8088
cache-dependency-path: go.sum
8189

8290
- name: Run Go unit tests
83-
working-directory: controlplane
84-
run: go test ./...
91+
run: go test -count=1 -timeout 5m ./...
8592

8693
kind-smoke:
8794
name: Kind Validation
@@ -90,11 +97,20 @@ jobs:
9097
- metadata
9198
- controlplane
9299
timeout-minutes: 90
100+
env:
101+
CLUSTER_NAME: release-validation
102+
GATEWAY_API_VERSION: v1.5.1
103+
CONTROLPLANE_IMAGE: ${{ needs.metadata.outputs.control_image }}
104+
DATAPLANE_IMAGE: ghcr.io/nantian-gw/dataplane:latest
105+
DASHBOARD_IMAGE: ghcr.io/nantian-gw/dashboard:latest
106+
CONFORMANCE_EXPERIMENTAL: "true"
107+
ALL_FEATURES: "true"
93108

94109
steps:
95110
- name: Checkout
96111
uses: actions/checkout@v6
97112
with:
113+
ref: ${{ needs.metadata.outputs.checkout_ref }}
98114
fetch-depth: 0
99115

100116
- name: Set up Go
@@ -103,82 +119,73 @@ jobs:
103119
go-version-file: go.mod
104120
cache-dependency-path: go.sum
105121

106-
- name: Install release validation dependencies
122+
- name: Install Kind tooling
123+
run: scripts/ci/install-kind-tools.sh
124+
125+
- name: Create kind cluster
126+
run: scripts/ci/create-kind-cluster.sh
127+
128+
- name: Install Gateway API CRDs
129+
run: scripts/ci/install-gateway-api-crds.sh
130+
131+
- name: Build current control-plane image
132+
run: scripts/ci/build-controlplane-image.sh
133+
134+
- name: Load images into kind
135+
run: scripts/ci/load-kind-images.sh
136+
137+
- name: Deploy Nantian Gateway
138+
run: scripts/ci/deploy-kind-conformance.sh
139+
140+
- name: Record image versions
107141
run: |
108-
sudo apt-get update
109-
sudo apt-get install -y --no-install-recommends protobuf-compiler libprotobuf-dev jq socat
110-
go install sigs.k8s.io/kind@v0.27.0
111-
sudo curl -fsSL "https://dl.k8s.io/release/v1.32.2/bin/linux/amd64/kubectl" -o /usr/local/bin/kubectl
112-
sudo chmod +x /usr/local/bin/kubectl
113-
echo "$(go env GOPATH)/bin" >>"${GITHUB_PATH}"
114-
115-
- name: Run Kind smoke test with release tag
116-
env:
117-
IMAGE_TAG: ${{ needs.metadata.outputs.release_tag }}
118-
run: ./tests/e2e/run-kind.sh
142+
echo "=== Images under test ==="
143+
kubectl get pods -n nantian-gw -o json | jq -r '.items[] | .spec.containers[] | " \(.name): \(.image)"'
144+
echo "=== Image digests ==="
145+
kubectl get pods -n nantian-gw -o json | jq -r '.items[] | .status.containerStatuses[] | " \(.name): \(.imageID)"'
146+
147+
- name: Run smoke test
148+
run: CLUSTER_NAME="$CLUSTER_NAME" ./test/e2e/smoke/run.sh --no-cleanup
119149

120150
- name: Run full Gateway API conformance
121151
id: conformance
122152
env:
123153
RELEASE_TAG: ${{ needs.metadata.outputs.release_tag }}
124-
REPORT_PATH: ${{ github.workspace }}/dist/conformance/report.yaml
125-
LOG_PATH: ${{ github.workspace }}/dist/conformance/run.log
126154
run: |
127155
mkdir -p dist/conformance
156+
report_path="${GITHUB_WORKSPACE}/dist/conformance/report.yaml"
128157
set +e
129-
ALL_FEATURES=true \
130-
IMPLEMENTATION_VERSION="${RELEASE_TAG}" \
131-
REPORT_OUTPUT="${REPORT_PATH}" \
132-
./tests/conformance/run.sh 2>&1 | tee "${LOG_PATH}"
158+
go test -tags=conformance -count=1 -v -timeout 30m ./conformance/ \
159+
-args \
160+
-gateway-class nantian-gw \
161+
-report-output "$report_path" \
162+
-organization "Nantian Gateway" \
163+
-project "Nantian Gateway" \
164+
-url "https://github.com/nantian-gw/gateway" \
165+
-version "${RELEASE_TAG}" \
166+
-contact "https://github.com/nantian-gw/gateway/issues" 2>&1 \
167+
| tee dist/conformance/run.log
133168
status=${PIPESTATUS[0]}
134169
echo "exit_code=${status}" >>"${GITHUB_OUTPUT}"
135170
exit "${status}"
136171
137-
- name: Archive conformance report into repository layout
138-
if: always()
139-
env:
140-
RELEASE_TAG: ${{ needs.metadata.outputs.release_tag }}
141-
SOURCE_COMMAND: ALL_FEATURES=true IMPLEMENTATION_VERSION=${{ needs.metadata.outputs.release_tag }} REPORT_OUTPUT=${{ github.workspace }}/dist/conformance/report.yaml ./tests/conformance/run.sh
142-
SOURCE_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
143-
run: |
144-
if [[ ! -f dist/conformance/report.yaml ]]; then
145-
echo "no report produced; skipping archival"
146-
exit 0
147-
fi
148-
149-
if [[ "${{ steps.conformance.outputs.exit_code }}" == "0" ]]; then
150-
export RESULT_STATUS=passed
151-
else
152-
export RESULT_STATUS=failed
153-
fi
154-
export REPORT_SCOPE=releases
155-
156-
scripts/archive-conformance-report.sh \
157-
"${RELEASE_TAG}" \
158-
"${GITHUB_WORKSPACE}/dist/conformance/report.yaml" \
159-
"${GITHUB_WORKSPACE}/dist/conformance/run.log"
160-
161-
cp "reports/conformance/releases/${RELEASE_TAG}/metadata.yaml" "dist/conformance/metadata.yaml"
172+
- name: Collect diagnostics on failure
173+
if: failure()
174+
run: ARTIFACT_DIR=tmp/conformance-diagnostics scripts/ci/collect-kind-diagnostics.sh
162175

163-
- name: Upload conformance artifact
176+
- name: Upload conformance artifacts
164177
if: always()
165178
uses: actions/upload-artifact@v7
166179
with:
167180
name: conformance-${{ needs.metadata.outputs.release_tag }}
168-
path: dist/conformance/
181+
path: |
182+
dist/conformance/
183+
tmp/conformance-diagnostics/
169184
if-no-files-found: warn
170185

171-
- name: Publish conformance reports branch
186+
- name: Cleanup
172187
if: always()
173-
env:
174-
COMMIT_MESSAGE: "conformance: archive ${{ needs.metadata.outputs.release_tag }}"
175-
run: |
176-
if [[ ! -f reports/conformance/latest/report.yaml ]]; then
177-
echo "no archived report available; skipping branch publish"
178-
exit 0
179-
fi
180-
181-
scripts/publish-conformance-reports.sh conformance-reports
188+
run: command -v kind >/dev/null 2>&1 && kind delete cluster --name "$CLUSTER_NAME" || true
182189

183190
publish:
184191
name: Publish Release Images
@@ -194,6 +201,8 @@ jobs:
194201
steps:
195202
- name: Checkout
196203
uses: actions/checkout@v6
204+
with:
205+
ref: ${{ needs.metadata.outputs.checkout_ref }}
197206

198207
- name: Set up Go
199208
uses: actions/setup-go@v6
@@ -248,4 +257,4 @@ jobs:
248257
with:
249258
name: image-metadata-${{ needs.metadata.outputs.release_tag }}
250259
path: dist/image-metadata/
251-
if-no-files-found: warn
260+
if-no-files-found: warn

.github/workflows/security-scans.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,17 @@ name: Security Scans
22

33
"on":
44
workflow_call:
5+
inputs:
6+
checkout_ref:
7+
description: "Git ref to scan"
8+
required: true
9+
type: string
510
workflow_dispatch:
11+
inputs:
12+
checkout_ref:
13+
description: "Git ref to scan"
14+
required: true
15+
type: string
616

717
permissions:
818
contents: read
@@ -21,6 +31,8 @@ jobs:
2131
steps:
2232
- name: Checkout
2333
uses: actions/checkout@v6
34+
with:
35+
ref: ${{ inputs.checkout_ref }}
2436

2537
- name: Set up Go
2638
uses: actions/setup-go@v6
@@ -58,12 +70,12 @@ jobs:
5870
echo "${RUNNER_TEMP:-/tmp}/bin" >>"${GITHUB_PATH}"
5971
6072
- name: Run security scan bundle
61-
run: scripts/run-security-scans.sh
73+
run: scripts/ci/run-security-scans.sh
6274

6375
- name: Upload security scan artifacts
6476
if: always()
6577
uses: actions/upload-artifact@v7
6678
with:
6779
name: security-scans
6880
path: tmp/security-scans/latest/
69-
if-no-files-found: warn
81+
if-no-files-found: warn

scripts/ci/ci_assets_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,55 @@ func TestWorkflowsUseSharedKindClusterHelper(t *testing.T) {
157157
}
158158
}
159159

160+
func TestReleaseWorkflowUsesCurrentCIEntrypoints(t *testing.T) {
161+
contents := string(readFile(t, repoPath(".github", "workflows", "release.yml")))
162+
163+
for _, want := range []string{
164+
`checkout_ref: ${{ steps.vars.outputs.checkout_ref }}`,
165+
`ref: ${{ needs.metadata.outputs.checkout_ref }}`,
166+
`run: go test -count=1 -timeout 5m ./...`,
167+
`run: scripts/ci/install-kind-tools.sh`,
168+
`run: scripts/ci/create-kind-cluster.sh`,
169+
`run: scripts/ci/install-gateway-api-crds.sh`,
170+
`run: scripts/ci/load-kind-images.sh`,
171+
`run: scripts/ci/deploy-kind-conformance.sh`,
172+
`run: CLUSTER_NAME="$CLUSTER_NAME" ./test/e2e/smoke/run.sh --no-cleanup`,
173+
`go test -tags=conformance -count=1 -v -timeout 30m ./conformance/ \`,
174+
} {
175+
if !strings.Contains(contents, want) {
176+
t.Fatalf("release workflow missing %q", want)
177+
}
178+
}
179+
180+
for _, unwanted := range []string{
181+
`working-directory: controlplane`,
182+
`./tests/e2e/run-kind.sh`,
183+
`./tests/conformance/run.sh`,
184+
`scripts/archive-conformance-report.sh`,
185+
`scripts/publish-conformance-reports.sh`,
186+
} {
187+
if strings.Contains(contents, unwanted) {
188+
t.Fatalf("release workflow still contains stale path %q", unwanted)
189+
}
190+
}
191+
}
192+
193+
func TestSecurityScanWorkflowUsesExistingHelper(t *testing.T) {
194+
contents := string(readFile(t, repoPath(".github", "workflows", "security-scans.yml")))
195+
helperPath := repoPath("scripts", "ci", "run-security-scans.sh")
196+
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")
199+
}
200+
if !strings.Contains(contents, `ref: ${{ inputs.checkout_ref }}`) {
201+
t.Fatalf("security scan workflow must checkout the caller-provided ref")
202+
}
203+
204+
if _, err := os.Stat(helperPath); err != nil {
205+
t.Fatalf("security scan helper %s is missing: %v", helperPath, err)
206+
}
207+
}
208+
160209
func TestSmokeScriptForwardsToProgrammedGatewayListener(t *testing.T) {
161210
contents := string(readFile(t, repoPath("test", "e2e", "smoke", "run.sh")))
162211

scripts/ci/run-security-scans.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ARTIFACT_DIR="${ARTIFACT_DIR:-tmp/security-scans/latest}"
5+
mkdir -p "$ARTIFACT_DIR"
6+
7+
osv-scanner scan source -r . --format json --output-file "$ARTIFACT_DIR/osv-scanner.json"
8+
grype dir:. -o json --file "$ARTIFACT_DIR/grype-dir.json"
9+
kubescape scan framework nsa \
10+
--format json \
11+
--format-version v2 \
12+
--output "$ARTIFACT_DIR/kubescape-nsa.json" \
13+
deploy/kubernetes/overlays/kind-conformance
14+
15+
{
16+
echo "Generated security scan artifacts in $ARTIFACT_DIR"
17+
echo "osv-scanner: $(command -v osv-scanner)"
18+
echo "grype: $(command -v grype)"
19+
echo "kubescape: $(command -v kubescape)"
20+
} >"$ARTIFACT_DIR/summary.txt"

0 commit comments

Comments
 (0)