Skip to content

Commit 1b5ddd5

Browse files
committed
Improved E2E CI runtime
The E2E CI shards were all paying the cost of analytics infrastructure even when they only ran the main Playwright project. Splitting analytics into its own shard set keeps coverage while avoiding repeated Tinybird setup for the main suite.
1 parent 0c4d441 commit 1b5ddd5

7 files changed

Lines changed: 113 additions & 15 deletions

File tree

.github/workflows/ci.yml

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,14 +1263,63 @@ jobs:
12631263
use-artifact: ${{ steps.strategy.outputs.use-artifact }}
12641264

12651265
job_e2e_tests:
1266-
name: E2E Tests (${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
1266+
name: E2E Tests (${{ matrix.projectName }} ${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
12671267
runs-on: ubuntu-latest
12681268
needs: [job_build_e2e_image, job_setup]
12691269
strategy:
12701270
fail-fast: true
12711271
matrix:
1272-
shardIndex: [1, 2, 3, 4, 5, 6, 7, 8]
1273-
shardTotal: [8]
1272+
include:
1273+
- projectName: Main
1274+
projects: main
1275+
analytics: 'false'
1276+
shardIndex: 1
1277+
shardTotal: 8
1278+
- projectName: Main
1279+
projects: main
1280+
analytics: 'false'
1281+
shardIndex: 2
1282+
shardTotal: 8
1283+
- projectName: Main
1284+
projects: main
1285+
analytics: 'false'
1286+
shardIndex: 3
1287+
shardTotal: 8
1288+
- projectName: Main
1289+
projects: main
1290+
analytics: 'false'
1291+
shardIndex: 4
1292+
shardTotal: 8
1293+
- projectName: Main
1294+
projects: main
1295+
analytics: 'false'
1296+
shardIndex: 5
1297+
shardTotal: 8
1298+
- projectName: Main
1299+
projects: main
1300+
analytics: 'false'
1301+
shardIndex: 6
1302+
shardTotal: 8
1303+
- projectName: Main
1304+
projects: main
1305+
analytics: 'false'
1306+
shardIndex: 7
1307+
shardTotal: 8
1308+
- projectName: Main
1309+
projects: main
1310+
analytics: 'false'
1311+
shardIndex: 8
1312+
shardTotal: 8
1313+
- projectName: Analytics
1314+
projects: analytics
1315+
analytics: 'true'
1316+
shardIndex: 1
1317+
shardTotal: 2
1318+
- projectName: Analytics
1319+
projects: analytics
1320+
analytics: 'true'
1321+
shardIndex: 2
1322+
shardTotal: 2
12741323
steps:
12751324
- name: Checkout
12761325
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -1279,6 +1328,7 @@ jobs:
12791328
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
12801329

12811330
- name: Pull or build Tinybird CLI Image
1331+
if: matrix.analytics == 'true'
12821332
run: |
12831333
COMPOSE_IMAGE="${COMPOSE_PROJECT_NAME:-ghost-dev}-tb-cli"
12841334
# Try pulling pre-built image from GHCR first (fast path)
@@ -1314,13 +1364,15 @@ jobs:
13141364
env:
13151365
GHOST_E2E_IMAGE: ${{ steps.load.outputs.image-tag }}
13161366
GHOST_E2E_SKIP_IMAGE_BUILD: 'true'
1367+
GHOST_E2E_ANALYTICS: ${{ matrix.analytics }}
13171368
run: bash ./e2e/scripts/prepare-ci-e2e-job.sh
13181369

13191370
- name: Run e2e tests in Playwright container
13201371
env:
13211372
TEST_WORKERS_COUNT: 1
13221373
GHOST_E2E_MODE: build
13231374
GHOST_E2E_IMAGE: ${{ steps.load.outputs.image-tag }}
1375+
E2E_PLAYWRIGHT_PROJECTS: ${{ matrix.projects }}
13241376
E2E_SHARD_INDEX: ${{ matrix.shardIndex }}
13251377
E2E_SHARD_TOTAL: ${{ matrix.shardTotal }}
13261378
E2E_RETRIES: 2
@@ -1332,21 +1384,23 @@ jobs:
13321384

13331385
- name: Stop E2E infra
13341386
if: always()
1387+
env:
1388+
GHOST_E2E_ANALYTICS: ${{ matrix.analytics }}
13351389
run: pnpm --filter @tryghost/e2e infra:down
13361390

13371391
- name: Upload blob report to GitHub Actions Artifacts
13381392
if: failure()
13391393
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
13401394
with:
1341-
name: blob-report-${{ matrix.shardIndex }}
1395+
name: blob-report-${{ matrix.projectName }}-${{ matrix.shardIndex }}
13421396
path: e2e/blob-report
13431397
retention-days: 1
13441398

13451399
- name: Upload test results artifacts
13461400
if: failure()
13471401
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
13481402
with:
1349-
name: test-results-${{ matrix.shardIndex }}
1403+
name: test-results-${{ matrix.projectName }}-${{ matrix.shardIndex }}
13501404
path: e2e/test-results
13511405
retention-days: 7
13521406

e2e/helpers/environment/environment-manager.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ type GhostEnvOverrides = GhostConfig | Record<string, string>;
2323
* - dev: Uses dev infrastructure with hot-reloading
2424
* - build: Uses pre-built image (set GHOST_E2E_IMAGE for registry images)
2525
*
26-
* All modes use the same infrastructure (MySQL, Redis, Mailpit, Tinybird)
27-
* started via docker compose. Ghost and gateway containers are created
28-
* dynamically per-worker for test isolation.
26+
* All modes use the same core infrastructure (MySQL, Redis, Mailpit) started
27+
* via docker compose. Analytics/Tinybird services are optional. Ghost and
28+
* gateway containers are created dynamically per-worker for test isolation.
2929
*/
3030
export class EnvironmentManager {
3131
private readonly mode: EnvironmentMode;

e2e/helpers/environment/service-availability.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ async function isServiceAvailable(docker: Docker, serviceName: string) {
2121
* Checks for tinybird-local service in ghost-dev compose project.
2222
*/
2323
export async function isTinybirdAvailable(): Promise<boolean> {
24+
if (process.env.GHOST_E2E_ANALYTICS === 'false') {
25+
debug('Tinybird disabled by GHOST_E2E_ANALYTICS=false');
26+
return false;
27+
}
28+
2429
const docker = new Docker();
2530
const tinybirdAvailable = await isServiceAvailable(docker, TINYBIRD.LOCAL_HOST);
2631
debug(`Tinybird availability for compose project ${DEV_ENVIRONMENT.projectNamespace}:`, tinybirdAvailable);

e2e/scripts/infra-down.sh

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,14 @@ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
66

77
cd "$REPO_ROOT"
88

9-
docker compose -f compose.dev.yaml -f compose.dev.analytics.yaml stop \
10-
analytics tb-cli tinybird-local mailpit redis mysql
9+
ANALYTICS_ENABLED="${GHOST_E2E_ANALYTICS:-true}"
10+
11+
compose_files=(-f compose.dev.yaml)
12+
services=(mailpit redis mysql)
13+
14+
if [[ "$ANALYTICS_ENABLED" == "true" ]]; then
15+
compose_files+=(-f compose.dev.analytics.yaml)
16+
services=(analytics tb-cli tinybird-local "${services[@]}")
17+
fi
18+
19+
docker compose "${compose_files[@]}" stop "${services[@]}"

e2e/scripts/infra-up.sh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ cd "$REPO_ROOT"
99

1010
MODE="$(resolve_e2e_mode)"
1111
export GHOST_E2E_MODE="$MODE"
12+
ANALYTICS_ENABLED="${GHOST_E2E_ANALYTICS:-true}"
1213

1314
if [[ "$MODE" != "build" ]]; then
1415
DEV_COMPOSE_PROJECT="${COMPOSE_PROJECT_NAME:-ghost-dev}"
@@ -21,5 +22,12 @@ if [[ "$MODE" != "build" ]]; then
2122
fi
2223
fi
2324

24-
docker compose -f compose.dev.yaml -f compose.dev.analytics.yaml up -d --wait \
25-
mysql redis mailpit tinybird-local analytics
25+
compose_files=(-f compose.dev.yaml)
26+
services=(mysql redis mailpit)
27+
28+
if [[ "$ANALYTICS_ENABLED" == "true" ]]; then
29+
compose_files+=(-f compose.dev.analytics.yaml)
30+
services+=(tinybird-local analytics)
31+
fi
32+
33+
docker compose "${compose_files[@]}" up -d --wait "${services[@]}"

e2e/scripts/prepare-ci-e2e-build-mode.sh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ set -euo pipefail
33

44
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/load-playwright-container-env.sh"
55
GATEWAY_IMAGE="${GHOST_E2E_GATEWAY_IMAGE:-caddy:2-alpine}"
6+
ANALYTICS_ENABLED="${GHOST_E2E_ANALYTICS:-true}"
67

78
echo "Preparing E2E build-mode runtime"
89
echo "Playwright image: ${PLAYWRIGHT_IMAGE}"
910
echo "Gateway image: ${GATEWAY_IMAGE}"
11+
echo "Analytics enabled: ${ANALYTICS_ENABLED}"
1012

1113
pids=()
1214
labels=()
@@ -25,7 +27,7 @@ run_bg() {
2527

2628
run_bg "pull-gateway-image" docker pull "$GATEWAY_IMAGE"
2729
run_bg "pull-playwright-image" docker pull "$PLAYWRIGHT_IMAGE"
28-
run_bg "start-infra" env GHOST_E2E_MODE=build bash "$REPO_ROOT/e2e/scripts/infra-up.sh"
30+
run_bg "start-infra" env GHOST_E2E_MODE=build GHOST_E2E_ANALYTICS="$ANALYTICS_ENABLED" bash "$REPO_ROOT/e2e/scripts/infra-up.sh"
2931

3032
for i in "${!pids[@]}"; do
3133
if ! wait "${pids[$i]}"; then
@@ -34,4 +36,6 @@ for i in "${!pids[@]}"; do
3436
fi
3537
done
3638

37-
node "$REPO_ROOT/e2e/scripts/sync-tinybird-state.mjs"
39+
if [[ "$ANALYTICS_ENABLED" == "true" ]]; then
40+
node "$REPO_ROOT/e2e/scripts/sync-tinybird-state.mjs"
41+
fi

e2e/scripts/run-playwright-container.sh

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ set -euo pipefail
44
SHARD_INDEX="${E2E_SHARD_INDEX:-}"
55
SHARD_TOTAL="${E2E_SHARD_TOTAL:-}"
66
RETRIES="${E2E_RETRIES:-2}"
7+
PROJECTS="${E2E_PLAYWRIGHT_PROJECTS:-main,analytics}"
78

89
if [[ -z "$SHARD_INDEX" || -z "$SHARD_TOTAL" ]]; then
910
echo "Missing E2E_SHARD_INDEX or E2E_SHARD_TOTAL environment variables" >&2
@@ -12,6 +13,22 @@ fi
1213

1314
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/load-playwright-container-env.sh"
1415

16+
project_args=()
17+
IFS=',' read -ra project_names <<< "$PROJECTS"
18+
for project in "${project_names[@]}"; do
19+
project="${project//[[:space:]]/}"
20+
if [[ -n "$project" ]]; then
21+
project_args+=("--project=${project}")
22+
fi
23+
done
24+
25+
if [[ ${#project_args[@]} -eq 0 ]]; then
26+
echo "No Playwright projects configured in E2E_PLAYWRIGHT_PROJECTS" >&2
27+
exit 1
28+
fi
29+
30+
printf -v project_args_string '%q ' "${project_args[@]}"
31+
1532
docker run --rm --network host --ipc host \
1633
-v /var/run/docker.sock:/var/run/docker.sock \
1734
-v "${WORKSPACE_PATH}:${WORKSPACE_PATH}" \
@@ -22,5 +39,6 @@ docker run --rm --network host --ipc host \
2239
-e GHOST_E2E_MODE="${GHOST_E2E_MODE:-build}" \
2340
-e GHOST_E2E_IMAGE="${GHOST_E2E_IMAGE:-ghost-e2e:local}" \
2441
-e GHOST_E2E_GATEWAY_IMAGE="${GHOST_E2E_GATEWAY_IMAGE:-caddy:2-alpine}" \
42+
-e GHOST_E2E_ANALYTICS="${GHOST_E2E_ANALYTICS:-true}" \
2543
"$PLAYWRIGHT_IMAGE" \
26-
bash -c "corepack enable && pnpm test:all --shard=${SHARD_INDEX}/${SHARD_TOTAL} --retries=${RETRIES}"
44+
bash -c "corepack enable && bash ./scripts/run-playwright-host.sh playwright test ${project_args_string}--shard=${SHARD_INDEX}/${SHARD_TOTAL} --retries=${RETRIES}"

0 commit comments

Comments
 (0)