From 49284f80ac3568d3b3a551695a1a4076f5d19642 Mon Sep 17 00:00:00 2001 From: Troy Ciesco Date: Sat, 26 Sep 2026 14:47:18 -0400 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20Tinybird=20slim=20im?= =?UTF-8?q?age=20startup=20(#31017)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ref https://github.com/TryGhost/Ghost/commit/e54e63c96a00fc5d1d279c0e7419dcb586cc787a The Tinybird update replaced MinIO with RustFS, but our slim image kept the old environment variables, so Tinybird couldn't start in CI. This image is only used for E2E tests; production doesn't use it. Updated the variable names to match upstream. Verified locally with all 22 analytics E2E checks passing against the fixed image. --- .github/workflows/ci.yml | 26 +++++++++++++++++++++++--- docker/tinybird-local-slim/Dockerfile | 4 ++-- docker/tinybird-local-slim/README.md | 10 ++++++++-- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1847befbbb2..5dd2d829790 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -222,6 +222,9 @@ jobs: # it — the break lands on main and surfaces in someone else's PR. tb-cli: - 'docker/tb-cli/**' + tinybird-slim: + - 'docker/tinybird-local-slim/**' + - 'compose.dev.analytics.yaml' - name: Define Node test matrix # Node lines the unit / legacy / acceptance suites must keep passing on. @@ -310,6 +313,7 @@ jobs: changed_docs: ${{ steps.changed.outputs.docs }} changed_package_standards: ${{ steps.changed.outputs.package-standards }} changed_tb_cli: ${{ steps.changed.outputs.tb-cli }} + changed_tinybird_slim: ${{ steps.changed.outputs.tinybird-slim }} # Single gate for the build + browser-E2E lane. True for tags, or when a # changed file could affect a running Ghost instance (see the `e2e` path # filter above). A test-only / docs-only change keeps this false. @@ -2013,10 +2017,12 @@ jobs: # # Its GHCR package is internal (the upstream licence only permits # distribution within our own organization), so it is unreadable from a - # cross-repo PR's scoped token — those runs stay on the upstream image. + # cross-repo PR's scoped token — those runs stay on the upstream image + # unless they change the slim image and build it locally below. # infra-up.sh falls back on a failed pull regardless, so an unexpected # permission gap degrades rather than breaks. - GHOST_E2E_TINYBIRD_SLIM: ${{ github.repository_owner == 'TryGhost' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} + GHOST_E2E_TINYBIRD_SLIM: ${{ needs.job_setup.outputs.changed_tinybird_slim == 'true' || (github.repository_owner == 'TryGhost' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)) }} + GHOST_E2E_TINYBIRD_SLIM_IMAGE: ${{ needs.job_setup.outputs.changed_tinybird_slim == 'true' && 'tinybird-local-slim:e2e' || 'ghcr.io/tryghost/tinybird-local-slim:latest' }} strategy: fail-fast: true matrix: @@ -2090,7 +2096,7 @@ jobs: - name: Log in to GitHub Container Registry # Needed to read the internal tinybird-local-slim package. - if: matrix.analytics == 'true' && env.GHOST_E2E_TINYBIRD_SLIM == 'true' + if: matrix.analytics == 'true' && env.GHOST_E2E_TINYBIRD_SLIM == 'true' && needs.job_setup.outputs.changed_tinybird_slim != 'true' uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4 continue-on-error: true with: @@ -2126,6 +2132,20 @@ jobs: docker build --tag "$COMPOSE_IMAGE" --file docker/tb-cli/Dockerfile . docker builder prune --all --force + - name: Build changed Tinybird slim image + if: matrix.analytics == 'true' && needs.job_setup.outputs.changed_tinybird_slim == 'true' + # Build before loading the Ghost image or installing dependencies: the + # upstream layers need several GB that can be reclaimed after flattening. + # This image stays on the runner; only the main publish workflow pushes it. + run: | + sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/.ghcup + upstream_ref=$(grep -oE 'tinybirdco/tinybird-local:[^ ]+' compose.dev.analytics.yaml) + docker build --platform linux/amd64 \ + --build-arg "TINYBIRD_LOCAL_REF=$upstream_ref" \ + --file docker/tinybird-local-slim/Dockerfile \ + --tag "$GHOST_E2E_TINYBIRD_SLIM_IMAGE" . + docker builder prune --all --force + - name: Load Image uses: ./.github/actions/load-docker-image id: load diff --git a/docker/tinybird-local-slim/Dockerfile b/docker/tinybird-local-slim/Dockerfile index 691333138a0..684ea823f4a 100644 --- a/docker/tinybird-local-slim/Dockerfile +++ b/docker/tinybird-local-slim/Dockerfile @@ -29,8 +29,8 @@ ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ CLICKHOUSE_CLUSTER_INTERNAL_HTTP_PORT=8123 \ CLICKHOUSE_INTERNAL_PORT=8123 \ USE_GATHERER=False \ - MINIO_ROOT_USER=admin \ - MINIO_ROOT_PASSWORD=password + OBJECT_STORAGE_ROOT_USER=admin \ + OBJECT_STORAGE_ROOT_PASSWORD=password WORKDIR /app EXPOSE 7181 7182 # Copied verbatim from upstream, notably the licence pointers — the flatten drops diff --git a/docker/tinybird-local-slim/README.md b/docker/tinybird-local-slim/README.md index 7c92cb05e83..bd3934d43c4 100644 --- a/docker/tinybird-local-slim/README.md +++ b/docker/tinybird-local-slim/README.md @@ -5,6 +5,11 @@ A distilled build of `tinybirdco/tinybird-local` for CI. Published to [`publish-tinybird-local-slim.yml`](../../.github/workflows/publish-tinybird-local-slim.yml) and used by the analytics E2E jobs via `GHOST_E2E_TINYBIRD_SLIM=true`. +When `docker/tinybird-local-slim/**` or `compose.dev.analytics.yaml` changes, +analytics E2E jobs build the slim image from the checked-out commit and test +that image instead of the published `latest`. This also applies to fork PRs; +the image stays on the runner and is not published. Other fork PRs use upstream. + ## Why The upstream image is ~2.1GB to pull and ~6.9GB once unpacked, which does not @@ -64,8 +69,9 @@ GHOST_E2E_TINYBIRD_SLIM=true GHOST_E2E_TINYBIRD_SLIM_IMAGE=tinybird-local-slim:l need it access through package settings rather than making it public. An internal package is unreadable from a PR opened from a public fork, whose -token is scoped to the fork. CI leaves `GHOST_E2E_TINYBIRD_SLIM` off for those -runs so they use upstream directly, and `e2e/scripts/infra-up.sh` falls back to +token is scoped to the fork. Unless the run builds the image locally as described +above, CI leaves `GHOST_E2E_TINYBIRD_SLIM` off for those runs so they use upstream +directly. `e2e/scripts/infra-up.sh` also falls back to upstream on any failed pull regardless — so a missing access grant, or the window before the package is first published, degrades to a slower, fatter run rather than a broken one. From 5f7535aa0c538b97780d250a7c4d330b9cbf90ea Mon Sep 17 00:00:00 2001 From: Troy Ciesco Date: Sat, 26 Sep 2026 15:06:15 -0400 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20local=20startup=20wi?= =?UTF-8?q?th=20Stripe=20CLI=20enabled=20(#31014)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ref https://github.com/TryGhost/Ghost/commit/e54e63c96a00fc5d1d279c0e7419dcb586cc787a Stripe CLI v1.51.0 now requires an explicit event selection when forwarding: https://github.com/stripe/stripe-cli/pull/2006 https://github.com/stripe/stripe-cli/releases/tag/v1.51.0 The image update caused the Stripe listener to exit, failing Compose's startup check and stopping Admin from starting whenever Stripe was enabled. Added --all-snapshot to keep the previous behavior. Verified locally by signing up a paid member (and getting the local dev environment to run). All 15 webhooks returned 200 and Ghost created the paid member. --- docker/stripe/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/stripe/entrypoint.sh b/docker/stripe/entrypoint.sh index 28436ea398c..697b46cf998 100755 --- a/docker/stripe/entrypoint.sh +++ b/docker/stripe/entrypoint.sh @@ -92,7 +92,7 @@ fi # Start stripe listen in the background echo "Starting Stripe webhook listener forwarding to ${GHOST_URL}/members/webhooks/stripe/" -stripe listen --forward-to ${GHOST_URL}/members/webhooks/stripe/ --api-key "${STRIPE_SECRET_KEY}" & +stripe listen --all-snapshot --forward-to "${GHOST_URL}/members/webhooks/stripe/" --api-key "${STRIPE_SECRET_KEY}" & child=$! # Wait for the child process