From 9de90f7bed49a85e24deb33ae0963cb76a5d1d44 Mon Sep 17 00:00:00 2001 From: nicktrn <55853254+nicktrn@users.noreply.github.com> Date: Wed, 19 Aug 2026 08:40:27 +0100 Subject: [PATCH] ci: pre-pull testcontainer images on fork PRs (#4684) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What The `Pre-pull testcontainer images` step is gated on `env.DOCKERHUB_USERNAME`. Fork PRs receive no repository secrets, so that variable is empty and the step is skipped along with the DockerHub login it was grouped with. ## Why With the pre-pull skipped, testcontainers pulls images lazily — inside the first test that resolves the fixture, against that test's `testTimeout`. On PR #4534 that pushed five webapp shards past their 60s cap across three runs, each failing as `Test timed out in 60000ms` while 42 of 43 files in the shard passed. Measured cost of the missing pre-pull, comparing the delta from vitest start to the first container fixture on the same runner class: | Run | Delta | | --- | --- | | internal x2 | +139.9s, +139.4s | | fork x2 | +149.7s, +149.4s | A 10.0s penalty, bimodal to within 0.3s. Note the pulls themselves succeed anonymously — there are no rate-limit errors in any of the failing logs. Only the login needs credentials, so the pre-pull can run unconditionally. ## Scope Removes the `if:` from the pre-pull step in all five workflows that have one. The DockerHub login stays gated, since it genuinely needs secrets. --- .github/workflows/e2e-webapp-auth-full.yml | 1 - .github/workflows/e2e-webapp.yml | 1 - .github/workflows/unit-tests-internal.yml | 1 - .github/workflows/unit-tests-packages.yml | 1 - .github/workflows/unit-tests-webapp.yml | 1 - 5 files changed, 5 deletions(-) diff --git a/.github/workflows/e2e-webapp-auth-full.yml b/.github/workflows/e2e-webapp-auth-full.yml index e88429a34..96e5a437c 100644 --- a/.github/workflows/e2e-webapp-auth-full.yml +++ b/.github/workflows/e2e-webapp-auth-full.yml @@ -99,7 +99,6 @@ jobs: run: echo "DockerHub login skipped because secrets are not available." - name: 🐳 Pre-pull testcontainer images - if: ${{ env.DOCKERHUB_USERNAME }} run: | docker pull postgres:14 docker pull redis:7.2 diff --git a/.github/workflows/e2e-webapp.yml b/.github/workflows/e2e-webapp.yml index 1c1525f31..d6b4ff996 100644 --- a/.github/workflows/e2e-webapp.yml +++ b/.github/workflows/e2e-webapp.yml @@ -74,7 +74,6 @@ jobs: run: echo "DockerHub login skipped because secrets are not available." - name: 🐳 Pre-pull testcontainer images - if: ${{ env.DOCKERHUB_USERNAME }} run: | echo "Pre-pulling Docker images with authenticated session..." docker pull postgres:14 diff --git a/.github/workflows/unit-tests-internal.yml b/.github/workflows/unit-tests-internal.yml index 1a398af9c..78070b0c1 100644 --- a/.github/workflows/unit-tests-internal.yml +++ b/.github/workflows/unit-tests-internal.yml @@ -78,7 +78,6 @@ jobs: run: echo "DockerHub login skipped because secrets are not available." - name: 🐳 Pre-pull testcontainer images - if: ${{ env.DOCKERHUB_USERNAME }} run: | # Retry each pull - DockerHub registry timeouts are a recurring transient CI flake. pull() { diff --git a/.github/workflows/unit-tests-packages.yml b/.github/workflows/unit-tests-packages.yml index ceb0b7b49..38e05fe70 100644 --- a/.github/workflows/unit-tests-packages.yml +++ b/.github/workflows/unit-tests-packages.yml @@ -81,7 +81,6 @@ jobs: run: echo "DockerHub login skipped because secrets are not available." - name: 🐳 Pre-pull testcontainer images - if: ${{ env.DOCKERHUB_USERNAME }} run: | # Retry each pull - DockerHub registry timeouts are a recurring transient CI flake. pull() { diff --git a/.github/workflows/unit-tests-webapp.yml b/.github/workflows/unit-tests-webapp.yml index 680eafd9a..384959e9c 100644 --- a/.github/workflows/unit-tests-webapp.yml +++ b/.github/workflows/unit-tests-webapp.yml @@ -86,7 +86,6 @@ jobs: run: echo "DockerHub login skipped because secrets are not available." - name: 🐳 Pre-pull testcontainer images - if: ${{ env.DOCKERHUB_USERNAME }} run: | # Retry each pull - DockerHub registry timeouts are a recurring transient CI flake. pull() {