Skip to content

Build the E2E image once and reuse it across CI shards#27050

Merged
9larsons merged 3 commits intomainfrom
codex/e2e-image-build-once
Apr 1, 2026
Merged

Build the E2E image once and reuse it across CI shards#27050
9larsons merged 3 commits intomainfrom
codex/e2e-image-build-once

Conversation

@9larsons
Copy link
Copy Markdown
Contributor

@9larsons 9larsons commented Apr 1, 2026

Summary

  • build the public app bundles for E2E once in a dedicated job
  • build the final E2E Docker image once from the production Ghost image plus those bundles
  • have each E2E shard load the prebuilt image and skip rebuilding app assets and the overlay image

Why

Each shard currently runs yarn workspace @tryghost/e2e build:apps and build:docker during prepare-ci-e2e-job.sh, which duplicates the same work eight times.

Validation

  • parsed .github/workflows/ci.yml with Ruby YAML
  • ran bash -n e2e/scripts/prepare-ci-e2e-job.sh
  • full GitHub Actions run not executed locally

Notes

  • expected to reduce total runner time substantially
  • expected to improve wall clock some, but likely by less than the runner-time savings because runtime preflight still remains in each shard

ref https://github.com/TryGhost/Ghost/actions/workflows/ci.yml

Built the public app bundles once and moved the E2E overlay image build out of each shard so CI stops repeating the same work eight times.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e571793f-b322-4ecc-a10a-b1cff50da98e

📥 Commits

Reviewing files that changed from the base of the PR and between b531626 and b4b01cc.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml

Walkthrough

CI now builds a dedicated E2E Docker image and separates E2E app bundle creation from image assembly. New jobs job_build_e2e_public_apps (produces e2e-public-apps) and job_build_e2e_image (loads production base image, decides artifact vs push, generates docker metadata, builds e2e/Dockerfile.e2e, and outputs docker-image-e2e with image-tags and use-artifact) were added. job_e2e_tests now depends on job_build_e2e_image, loads the docker-image-e2e artifact, uses GHOST_E2E_IMAGE, and sets GHOST_E2E_SKIP_IMAGE_BUILD: 'true'. The prepare-ci-e2e-job.sh script can skip image build when GHOST_E2E_SKIP_IMAGE_BUILD=true, making the base-image input optional in that case.

Possibly related issues

  • TryGhost/Toast issue 376: Implements CI jobs and wiring for building, tagging, and publishing Docker images for E2E, which aligns with this PR's added E2E image build/publish jobs and outputs.
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main objective: building the E2E image once in a centralized job and reusing it across multiple CI shards, eliminating duplicate build work.
Description check ✅ Passed The description is directly related to the changeset, explaining the rationale for the changes and providing validation details. It clearly describes the work being done to consolidate E2E image building.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/e2e-image-build-once

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@9larsons 9larsons marked this pull request as ready for review April 1, 2026 13:17
…-once

# Conflicts:
#	.github/workflows/ci.yml
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
e2e/scripts/prepare-ci-e2e-job.sh (1)

16-22: Consider validating GHOST_E2E_IMAGE when skipping build.

When SKIP_IMAGE_BUILD=true, the script doesn't validate that GHOST_E2E_IMAGE is actually set. While the CI workflow always provides it, manual invocations could silently fall back to ghost-e2e:local which may not exist.

🛡️ Optional: Add validation for manual usage
 echo "Preparing CI E2E job"
 echo "E2E image: ${GHOST_E2E_IMAGE:-ghost-e2e:local}"
 echo "Skip image build: ${SKIP_IMAGE_BUILD}"

 if [[ "$SKIP_IMAGE_BUILD" != "true" ]]; then
     echo "Base image: ${GHOST_E2E_BASE_IMAGE}"
+else
+    if [[ -z "${GHOST_E2E_IMAGE:-}" ]]; then
+        echo "Warning: GHOST_E2E_IMAGE not set, using default ghost-e2e:local" >&2
+    fi
 fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/scripts/prepare-ci-e2e-job.sh` around lines 16 - 22, When
SKIP_IMAGE_BUILD is true the script must validate the GHOST_E2E_IMAGE value; add
a guard in prepare-ci-e2e-job.sh after the SKIP_IMAGE_BUILD check that inspects
the GHOST_E2E_IMAGE environment variable (and ensure it is not empty or the
fallback literal "ghost-e2e:local") and if invalid print an error and exit
non‑zero. Update the branch that currently prints "Skip image build" to perform
this validation so manual runs fail fast instead of silently using the local
default.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@e2e/scripts/prepare-ci-e2e-job.sh`:
- Around line 16-22: When SKIP_IMAGE_BUILD is true the script must validate the
GHOST_E2E_IMAGE value; add a guard in prepare-ci-e2e-job.sh after the
SKIP_IMAGE_BUILD check that inspects the GHOST_E2E_IMAGE environment variable
(and ensure it is not empty or the fallback literal "ghost-e2e:local") and if
invalid print an error and exit non‑zero. Update the branch that currently
prints "Skip image build" to perform this validation so manual runs fail fast
instead of silently using the local default.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f64c678c-8385-4428-830c-499e69279b8d

📥 Commits

Reviewing files that changed from the base of the PR and between f0b9fda and 7b5247b.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml
  • e2e/scripts/prepare-ci-e2e-job.sh

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/ci.yml (1)

1084-1223: Consider mirroring the main-branch Slack hook on the new E2E build jobs.

If either new build job fails, job_e2e_tests never starts, so the existing E2E Slack notification at Lines 1314-1319 won’t fire. Adding the usual slack-build step here would keep early E2E-pipeline failures visible.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 1084 - 1223, Add the same Slack
notification step used for main-branch E2E builds to both
job_build_e2e_public_apps and job_build_e2e_image so failures are reported
immediately; specifically, add a step named "slack-build" (matching the existing
slack step id/name) that runs on failure (use if: failure() or the project's
existing conditional), uses the existing slack action (the repo's
.github/actions/slack-build or the same uses: and with: signature as the other
E2E Slack step), and wires the same inputs/secrets/labels (e.g., channel,
status, build metadata) so the notification format matches the existing E2E
Slack hook.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 1124-1228: The job_required_tests dependency list must include the
new E2E build jobs so failures block the aggregate gate: update the
job_required_tests "needs" to add job_build_e2e_image and
job_build_e2e_public_apps (these are the new upstream jobs) alongside existing
entries; ensure job_e2e_tests remains dependent on job_build_e2e_image but also
list the two build jobs in job_required_tests.needs so their failures cause
job_required_tests to fail rather than skip.

---

Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 1084-1223: Add the same Slack notification step used for
main-branch E2E builds to both job_build_e2e_public_apps and job_build_e2e_image
so failures are reported immediately; specifically, add a step named
"slack-build" (matching the existing slack step id/name) that runs on failure
(use if: failure() or the project's existing conditional), uses the existing
slack action (the repo's .github/actions/slack-build or the same uses: and with:
signature as the other E2E Slack step), and wires the same inputs/secrets/labels
(e.g., channel, status, build metadata) so the notification format matches the
existing E2E Slack hook.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 607bd36f-0d73-4eef-a8e4-9c5c2ed57f9d

📥 Commits

Reviewing files that changed from the base of the PR and between 7b5247b and b531626.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 1, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.26%. Comparing base (5beca11) to head (b4b01cc).
⚠️ Report is 17 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #27050      +/-   ##
==========================================
- Coverage   73.26%   73.26%   -0.01%     
==========================================
  Files        1530     1530              
  Lines      121767   121768       +1     
  Branches    14710    14710              
==========================================
- Hits        89218    89215       -3     
- Misses      31555    31557       +2     
- Partials      994      996       +2     
Flag Coverage Δ
admin-tests 54.38% <ø> (-0.03%) ⬇️
e2e-tests 73.26% <ø> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 1, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
4 Security Hotspots

See analysis details on SonarQube Cloud

@9larsons 9larsons merged commit 626ecf3 into main Apr 1, 2026
40 of 41 checks passed
@9larsons 9larsons deleted the codex/e2e-image-build-once branch April 1, 2026 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant