Skip to content

Commit 7fa45d6

Browse files
ci(e2e): release-prereleased workflow + published-binary smoke (Phase 7)
1 parent 492ace6 commit 7fa45d6

5 files changed

Lines changed: 136 additions & 0 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"playground-cli": patch
3+
---
4+
5+
CI now validates published RC binaries: a new `e2e-release.yml` workflow fires on `release: prereleased`, downloads the `dot-linux-x64` SEA asset, and runs `e2e/cli/published.test.ts` smoke tests (`--version`, `--help`). Catches packaging regressions before stable release.

.github/workflows/e2e-release.yml

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
name: E2E (Published Binary)
2+
3+
on:
4+
release:
5+
types: [prereleased]
6+
workflow_dispatch:
7+
inputs:
8+
tag:
9+
description: "Release tag to test (e.g. v0.16.0-rc.1)"
10+
required: true
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
smoke:
17+
name: "E2E · release-smoke"
18+
runs-on: ubuntu-latest
19+
timeout-minutes: 15
20+
env:
21+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22+
steps:
23+
- uses: actions/checkout@v4
24+
25+
- uses: pnpm/action-setup@v4
26+
27+
- uses: actions/setup-node@v4
28+
with:
29+
node-version: "22"
30+
31+
- run: pnpm install
32+
33+
- name: Resolve release tag
34+
id: tag
35+
shell: bash
36+
run: |
37+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
38+
TAG="${{ inputs.tag }}"
39+
else
40+
TAG="${{ github.event.release.tag_name }}"
41+
fi
42+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
43+
44+
- name: Wait for SEA asset to be uploaded
45+
shell: /usr/bin/bash -euo pipefail {0}
46+
run: |
47+
TAG="${{ steps.tag.outputs.tag }}"
48+
for i in $(seq 1 30); do
49+
if gh release view "$TAG" --json assets --jq '.assets[].name' | grep -q "^dot-linux-x64$"; then
50+
echo "Found dot-linux-x64 asset on attempt $i"
51+
exit 0
52+
fi
53+
echo " attempt $i/30: waiting for asset..."
54+
sleep 10
55+
done
56+
echo "::error::Timed out waiting for dot-linux-x64 asset on $TAG"
57+
exit 1
58+
59+
- name: Download SEA asset
60+
shell: bash
61+
run: |
62+
TAG="${{ steps.tag.outputs.tag }}"
63+
mkdir -p ./bin
64+
gh release download "$TAG" --pattern "dot-linux-x64" --dir ./bin
65+
chmod +x ./bin/dot-linux-x64
66+
ls -la ./bin/dot-linux-x64
67+
68+
- name: Smoke test the published binary
69+
uses: nick-fields/retry@v3
70+
with:
71+
timeout_minutes: 5
72+
max_attempts: 2
73+
retry_wait_seconds: 15
74+
command: pnpm exec vitest run --config e2e/vitest.config.ts e2e/cli/published.test.ts
75+
env:
76+
DOT_E2E_BINARY: ${{ github.workspace }}/bin/dot-linux-x64
77+
DOT_TAG: e2e-ci-release
78+
DOT_TELEMETRY: "1"
79+
80+
- name: Upload forensic artefacts
81+
if: always()
82+
continue-on-error: true
83+
uses: actions/upload-artifact@v4
84+
with:
85+
name: e2e-reports-release-smoke
86+
path: e2e-reports/
87+
retention-days: 7
88+
if-no-files-found: ignore

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ These are things that aren't self-evident from reading the code and have bitten
5757
- **Local launcher:** `tools/e2e-local.sh [smoke|pr|nightly]` — also callable via `pnpm test:e2e:smoke`, `pnpm test:e2e:pr`, `pnpm test:e2e:nightly`.
5858
- **CI workflow:** `.github/workflows/e2e.yml` — runs on PR / push:main / cron 06:00 UTC / workflow_dispatch.
5959
- **CI matrix:** 12 cells across four matrices — `test-no-publish` (parallel: pr-install, pr-preflight, pr-mod, pr-init-session) + `test-publish` (max-parallel: 1: pr-deploy-frontend, pr-deploy-foundry) + `test-nightly-no-publish` (parallel, schedule/dispatch only: nightly-mod-miss, nightly-diagnostic, nightly-rejections, nightly-chaos-sigint) + `test-nightly-publish` (max-parallel: 1, schedule/dispatch only: nightly-deploy-hardhat, nightly-deploy-multi). Each cell runs a subset via `vitest -t "<pattern>"`.
60+
- **Release smoke:** `.github/workflows/e2e-release.yml` fires on `release: prereleased`, downloads the `dot-linux-x64` SEA asset, and runs `e2e/cli/published.test.ts` against it. Validates the published binary before stable release.
6061
- **Test files:** `e2e/cli/*.test.ts` (vitest, spawned via `bun run src/index.ts`).
6162
- **Reports directory:** `e2e-reports/junit.xml` + `e2e-reports/dot-runs.log` (gitignored).
6263
- **Tag prefix:** `DOT_TAG=e2e-{ci|local}-{trigger}` so Sentry dashboards filter test traffic. The CLI plumbs `DOT_TAG` into the `cli.tag` root-span attribute via `src/telemetry-config.ts`.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* Resolves the path to the `dot` binary for E2E tests against a published
3+
* artefact. When `DOT_E2E_BINARY` is set, return that path (tests run against
4+
* the SEA binary). Otherwise return null and the caller should use the
5+
* source-build path via dot.ts.
6+
*/
7+
export function getPublishedBinaryPath(): string | null {
8+
return process.env.DOT_E2E_BINARY ?? null;
9+
}

e2e/cli/published.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* Smoke tests for the published SEA binary. Skipped when DOT_E2E_BINARY is
3+
* unset (i.e. on PR / dev runs). Exercised by the e2e-release.yml workflow
4+
* after downloading the SEA asset from a prerelease tag.
5+
*
6+
* Coverage scope (per spec design §11, S20a):
7+
* - Binary launches and reports a sane version
8+
* - Binary exits 0 on --help with the expected sections
9+
*
10+
* The keystroke-handling regression (S20-unit / Bun stdin warm-up) is
11+
* covered by src/index.test.ts at the source level. We deliberately do NOT
12+
* use a PTY here — node-pty is rejected per spec.
13+
*/
14+
15+
import { describe, test, expect } from "vitest";
16+
import { execa } from "execa";
17+
import { getPublishedBinaryPath } from "./helpers/published-binary.js";
18+
19+
const binary = getPublishedBinaryPath();
20+
21+
describe.skipIf(!binary)("dot — published SEA binary smoke", () => {
22+
test("--version exits 0 with semver output", async () => {
23+
const result = await execa(binary!, ["--version"], { reject: false });
24+
expect(result.exitCode).toBe(0);
25+
expect(result.stdout).toMatch(/\d+\.\d+\.\d+/);
26+
});
27+
28+
test("--help exits 0 with usage section", async () => {
29+
const result = await execa(binary!, ["--help"], { reject: false });
30+
expect(result.exitCode).toBe(0);
31+
expect(result.stdout + result.stderr).toMatch(/Usage:/i);
32+
});
33+
});

0 commit comments

Comments
 (0)