Skip to content

Commit ccc7153

Browse files
committed
ci(e2e): pin ttl.sh image by digest and extend TTL to 24h
Address review feedback on the build-once ttl.sh handoff: - The build-image job now exposes the pushed image digest as a job output (build step gets `id: build`, `outputs.digest`). Each leg pulls `ttl.sh/nvml-mock-<sha>@sha256:<digest>` (content-addressed) instead of the bare sha-derived tag, then re-tags it to E2E_IMAGE for the harness kind-load / Helm repo:tag split. ttl.sh accepts anonymous pushes and the tag is derivable from the public sha, so a digest pull closes the window where a third party could overwrite the tag between push and pull. - Bump the ttl.sh TTL from 1h to 24h (ttl.sh max). A 1h TTL broke re-run-failed-jobs: a re-run keeps the same sha and skips the already green build-image, so retrying a flaky leg more than an hour later failed at docker pull on an expired tag and forced a full re-run. Update tests/e2e/README.md CI Behavior to match. Signed-off-by: Giulio Calzolari <gcalzolari@nvidia.com>
1 parent a97b6fc commit ccc7153

2 files changed

Lines changed: 68 additions & 20 deletions

File tree

.github/workflows/nvml-mock-e2e-go.yaml

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@
1919
#
2020
# Image distribution: a single `build-image` job builds the nvml-mock image once
2121
# and pushes it to the ephemeral, auth-free ttl.sh registry (works on fork PRs)
22-
# as E2E_IMAGE. Every leg then pulls that ref and the harness kind-loads it
23-
# (E2E_SKIP_BUILD=true) instead of rebuilding per leg.
22+
# as E2E_IMAGE (24h TTL). Every leg then pulls that image by digest (immune to
23+
# tag overwrite on the anonymous registry), tags it to E2E_IMAGE, and the harness
24+
# kind-loads it (E2E_SKIP_BUILD=true) instead of rebuilding per leg.
2425
name: nvml-mock E2E (Go)
2526

2627
permissions:
@@ -52,9 +53,11 @@ env:
5253
GO_VERSION: ${{ inputs.golang_version }}
5354
KIND_VERSION: "v0.31.0"
5455
KIND_AMD64_SHA256: "eb244cbafcc157dff60cf68693c14c9a75c4e6e6fedaf9cd71c58117cb93e3fa"
55-
# Per-commit, ephemeral (1h TTL) ttl.sh ref the build-image job publishes and
56-
# every leg pulls. Auth-free, so it also works on fork PRs.
57-
E2E_IMAGE: ttl.sh/nvml-mock-${{ github.sha }}:1h
56+
# Per-commit, ephemeral (24h TTL) ttl.sh ref the build-image job publishes and
57+
# every leg pulls (by digest, then tags locally to this ref for the harness).
58+
# Auth-free, so it also works on fork PRs. 24h (ttl.sh max) keeps the image
59+
# alive long enough to re-run individual failed legs without a full rebuild.
60+
E2E_IMAGE: ttl.sh/nvml-mock-${{ github.sha }}:24h
5861
E2E_SKIP_BUILD: "true"
5962
E2E_ARTIFACTS: ${{ github.workspace }}/artifacts/e2e/go
6063

@@ -63,6 +66,11 @@ jobs:
6366
# instead of rebuilding the image per job (see issue #460).
6467
build-image:
6568
runs-on: ubuntu-latest
69+
outputs:
70+
# Digest of the pushed image (sha256:...). Legs pull by digest so an
71+
# anonymous ttl.sh tag overwrite cannot substitute the image between
72+
# this push and their pulls.
73+
digest: ${{ steps.build.outputs.digest }}
6674
steps:
6775
- name: Checkout
6876
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
@@ -71,6 +79,7 @@ jobs:
7179
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
7280

7381
- name: Build and push nvml-mock image to ttl.sh
82+
id: build
7483
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7
7584
with:
7685
context: .
@@ -101,8 +110,15 @@ jobs:
101110
- name: Install Helm
102111
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5
103112

104-
- name: Pull pre-built nvml-mock image from ttl.sh
105-
run: docker pull "${{ env.E2E_IMAGE }}"
113+
- name: Pull pre-built nvml-mock image from ttl.sh (pinned by digest)
114+
run: |
115+
# Content-addressed pull: even if the sha-derived tag is overwritten on
116+
# the anonymous ttl.sh registry, the digest fetches exactly what
117+
# build-image pushed. Re-tag to E2E_IMAGE for the harness kind-load and
118+
# Helm repo:tag split.
119+
pinned="ttl.sh/nvml-mock-${{ github.sha }}@${{ needs.build-image.outputs.digest }}"
120+
docker pull "$pinned"
121+
docker tag "$pinned" "${{ env.E2E_IMAGE }}"
106122
107123
- name: Install Kind
108124
run: |
@@ -150,8 +166,15 @@ jobs:
150166
- name: Install Helm
151167
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5
152168

153-
- name: Pull pre-built nvml-mock image from ttl.sh
154-
run: docker pull "${{ env.E2E_IMAGE }}"
169+
- name: Pull pre-built nvml-mock image from ttl.sh (pinned by digest)
170+
run: |
171+
# Content-addressed pull: even if the sha-derived tag is overwritten on
172+
# the anonymous ttl.sh registry, the digest fetches exactly what
173+
# build-image pushed. Re-tag to E2E_IMAGE for the harness kind-load and
174+
# Helm repo:tag split.
175+
pinned="ttl.sh/nvml-mock-${{ github.sha }}@${{ needs.build-image.outputs.digest }}"
176+
docker pull "$pinned"
177+
docker tag "$pinned" "${{ env.E2E_IMAGE }}"
155178
156179
- name: Install Kind
157180
run: |
@@ -197,8 +220,15 @@ jobs:
197220
- name: Install Helm
198221
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5
199222

200-
- name: Pull pre-built nvml-mock image from ttl.sh
201-
run: docker pull "${{ env.E2E_IMAGE }}"
223+
- name: Pull pre-built nvml-mock image from ttl.sh (pinned by digest)
224+
run: |
225+
# Content-addressed pull: even if the sha-derived tag is overwritten on
226+
# the anonymous ttl.sh registry, the digest fetches exactly what
227+
# build-image pushed. Re-tag to E2E_IMAGE for the harness kind-load and
228+
# Helm repo:tag split.
229+
pinned="ttl.sh/nvml-mock-${{ github.sha }}@${{ needs.build-image.outputs.digest }}"
230+
docker pull "$pinned"
231+
docker tag "$pinned" "${{ env.E2E_IMAGE }}"
202232
203233
- name: Install Kind
204234
run: |
@@ -240,8 +270,15 @@ jobs:
240270
- name: Install Helm
241271
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5
242272

243-
- name: Pull pre-built nvml-mock image from ttl.sh
244-
run: docker pull "${{ env.E2E_IMAGE }}"
273+
- name: Pull pre-built nvml-mock image from ttl.sh (pinned by digest)
274+
run: |
275+
# Content-addressed pull: even if the sha-derived tag is overwritten on
276+
# the anonymous ttl.sh registry, the digest fetches exactly what
277+
# build-image pushed. Re-tag to E2E_IMAGE for the harness kind-load and
278+
# Helm repo:tag split.
279+
pinned="ttl.sh/nvml-mock-${{ github.sha }}@${{ needs.build-image.outputs.digest }}"
280+
docker pull "$pinned"
281+
docker tag "$pinned" "${{ env.E2E_IMAGE }}"
245282
246283
- name: Install Kind
247284
run: |
@@ -285,8 +322,15 @@ jobs:
285322
- name: Install Helm
286323
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5
287324

288-
- name: Pull pre-built nvml-mock image from ttl.sh
289-
run: docker pull "${{ env.E2E_IMAGE }}"
325+
- name: Pull pre-built nvml-mock image from ttl.sh (pinned by digest)
326+
run: |
327+
# Content-addressed pull: even if the sha-derived tag is overwritten on
328+
# the anonymous ttl.sh registry, the digest fetches exactly what
329+
# build-image pushed. Re-tag to E2E_IMAGE for the harness kind-load and
330+
# Helm repo:tag split.
331+
pinned="ttl.sh/nvml-mock-${{ github.sha }}@${{ needs.build-image.outputs.digest }}"
332+
docker pull "$pinned"
333+
docker tag "$pinned" "${{ env.E2E_IMAGE }}"
290334
291335
- name: Install Kind
292336
run: |

tests/e2e/README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -303,11 +303,15 @@ The workflow:
303303
1. Detects the project Go version unless one is explicitly provided.
304304
2. Builds the `nvml-mock` image exactly once in a dedicated `build-image` job
305305
(buildx + GHA cache) and pushes it to the ephemeral, auth-free `ttl.sh`
306-
registry as `E2E_IMAGE` (`ttl.sh/nvml-mock-<sha>:1h`). Using `ttl.sh` keeps
307-
this working on fork PRs, which cannot access authenticated registries.
308-
3. Makes every leg `needs: build-image`, pulls that pre-built ref, and sets
309-
`E2E_SKIP_BUILD=true` so the harness Kind-loads it instead of rebuilding the
310-
image per leg.
306+
registry as `E2E_IMAGE` (`ttl.sh/nvml-mock-<sha>:24h`), exposing the pushed
307+
image digest as a job output. Using `ttl.sh` keeps this working on fork PRs,
308+
which cannot access authenticated registries; the 24h TTL (ttl.sh max) keeps
309+
the image available long enough to re-run an individual failed leg.
310+
3. Makes every leg `needs: build-image`, pulls the image **by digest**
311+
(`ttl.sh/nvml-mock-<sha>@sha256:<digest>`, so a third-party tag overwrite on
312+
the anonymous registry cannot substitute it), tags it back to `E2E_IMAGE`,
313+
and sets `E2E_SKIP_BUILD=true` so the harness Kind-loads it instead of
314+
rebuilding the image per leg.
311315
4. Runs one GPU profile per matrix job.
312316
5. Prints collected diagnostics if the job fails.
313317

0 commit comments

Comments
 (0)