test(e2e): packaged-build smoke suite + Linux x64 release gate (smoke phase 1) - #214
Conversation
Phase 1 of automating the release smoke test (release-process.md §6): launch, version and persistence, run against the artifact a release actually ships instead of against the source tree. - test-e2e/fixtures.js: launch through FREEDOM_E2E_EXECUTABLE when it is set (plus --no-sandbox under FREEDOM_E2E_NO_SANDBOX=1), otherwise exactly as before. The scratch profile moves into its own `userDataDir` fixture so a spec can quit the app and start another instance on the same on-disk state (`relaunchApp`). - playwright.config.js: new `packaged` project over test-e2e/packaged/, fronted by a `packaged-preflight` setup project that fails the run with a usage message when FREEDOM_E2E_EXECUTABLE is missing or does not name an executable file. `harness` now excludes the new directory. - test-e2e/packaged/: launch (chrome mounts, one window, really a packaged Electron), version (app.getVersion() — the About panel's source — matches FREEDOM_E2E_EXPECTED_VERSION or package.json), and persistence (theme change survives a full quit and relaunch). - release.yml: `smoke-linux-x64` runs that suite against the run's own .deb (/opt/Freedom/freedom) and then its AppImage, and `release` now needs it, so a Linux x64 artifact that cannot launch, misreports its version, or loses a setting across a restart never reaches a release. - Docs: §6 and Appendix B of the release playbook, plus the testing section of docs/development.md.
Runner verification of the workflow change
smoke-linux-x64 job — every step green: Quoted from its log: The whole smoke job adds ~3 minutes to a release run, and no secrets are involved. Local artifact coverageBeyond the
Acceptance evidence (packaged binary, not the source build)Freedom launched from The same executable after a full quit and relaunch against the same scratch profile, still rendering the persisted Notes for review
|
|
[alan-review R1] — reviewed What I verified
Minor findings (non-blocking)M1 — M2 — M3 — a bare For the record
|
- Compare real paths in the packaged-build assertion: process.execPath is symlink-resolved, so /usr/bin/freedom (the .deb's alternatives chain to /opt/Freedom/freedom) or a relative dist/linux-unpacked/freedom would have false-failed. - Register the packaged projects only when FREEDOM_E2E_EXECUTABLE is set or --project packaged is requested, so a bare `npx playwright test` keeps running harness+live instead of failing in the preflight. - Note that the X_OK preflight check is an existence check on Windows.
|
Landed R1's three minors in Verified locally on a fresh |


Summary
Phase 1 of automating the release smoke test (
docs/agent-playbooks/release-process.md§6): launch, version and persistence, run against the artifact a release actually ships instead of against the source tree. Nodes, navigation, the headline feature and upgrade-from-previous-version stay manual (later phases / other platforms).test-e2e/fixtures.js— the harness fixture launches throughFREEDOM_E2E_EXECUTABLEwhen that variable is set (executablePath, no'.'argument, plus--no-sandboxwhenFREEDOM_E2E_NO_SANDBOX=1), and behaves exactly as before when it is not. The scratch profile moved out ofelectronAppinto its ownuserDataDirfixture so a spec can quit the app and start a second instance on the same on-disk state; that is the newrelaunchAppfixture.browserWindow(app)is exported so a relaunched app can be waited on the same way.live-fixtures.js/onboarding-fixtures.jsare untouched.playwright.config.js— newpackagedproject overtest-e2e/packaged/, withharnessnarrowed to exclude that directory. Apackaged-preflightsetup project (dependencies: ['packaged-preflight']) validatesFREEDOM_E2E_EXECUTABLEbefore any Electron process starts: unset, unreadable, not a file, or not executable each fail with the fix in the message and every packaged spec is skipped. (A top-levelglobalSetupwas the first attempt and is wrong here —config.projectsinglobalSetupis not filtered by--project, so the guard fired on plainnpm run test:e2eruns too.)test-e2e/packaged/—launch.spec.js(chrome mounts, exactly one liveBrowserWindow,process.versions.electron/chromenon-empty and matching the renderer's UA,app.isPackaged),version.spec.js(app.getVersion()— the valueindex.jsfeeds tosetAboutPanelOptions, i.e. what About shows — equalsFREEDOM_E2E_EXPECTED_VERSIONorpackage.json),persistence.spec.js(theme change survives a full quit and relaunch of the same executable against the same profile).npm run test:e2e:packaged..github/workflows/release.yml— newsmoke-linux-x64job:needs: [linux],npm ci --ignore-scripts(nothing is rebuilt here), Playwright system deps via the existing composite action, downloads thefreedom-linux-x64artifact, installs the.debthroughscripts/ci/apt-hardening.sh(bounded/retried, like every other apt call on a Linux runner), runs the suite against/opt/Freedom/freedom, then extracts the AppImage and runs it again againstsquashfs-root/freedom. Reports/traces upload assmoke-linux-x64-reportwithif: always().releasenowneedsthis job as well, so a Linux x64 artifact that cannot launch, misreports its version, or loses a setting across a restart never reaches a release page. The mac/windows/linux-arm64 jobs and the attach script are unchanged.docs/development.md.Related issue
Verification
Everything below was run on this branch (
b361ab9c), Linux x64, Node 24.19.0.npm run lint— clean.npm test(see comment below for the summary line; nosrc/file changed, so this is a no-regression check).xvfb-run -a npm run test:e2e -- test-e2e/settings.spec.js→ 6 passed (34.0s).npm run build -- --linux --x64(afteradblock/ant/ipfs/radicle --linux --x64/myotisdownloads; Tor skipped), thenFREEDOM_E2E_EXECUTABLE="$PWD/dist/linux-unpacked/freedom" FREEDOM_E2E_NO_SANDBOX=1 xvfb-run -a npm run test:e2e:packaged→ 5 passed (27.6s) (4 specs + the preflight setup test).FREEDOM_E2E_EXPECTED_VERSION=0.0.1-bogus→ version spec fails (Expected "0.0.1-bogus", Received "0.8.5-dev").relaunchApptemporarily pointed at a fresh profile dir → persistence spec fails (Expected "light", Received "system"); reverted.FREEDOM_E2E_EXECUTABLEpointed at the unpackagednode_modules/electron/dist/electron→ both launch specs fail.The "packaged" project needs FREEDOM_E2E_EXECUTABLE and it is not set+4 did not run;/no/such/freedom→ "cannot be read"; a non-executable file (package.json) → "is not executable".npx prettier --checkon every changed file — clean (.github/workflows/release.yml, both docs,package.json,playwright.config.js,test-e2e/fixtures.js,test-e2e/packaged/*.js).git diff --check— clean.shellcheckon the new job'srun:blocks (extracted from the YAML) — clean.actionlintis not installed on this machine; the workflow parses as YAML and the job graph was asserted programmatically (smoke-linux-x64 needs [linux],release needs [mac-arm64, linux, windows-x64, smoke-linux-x64]).Runner verification of the workflow change is in a follow-up comment — a
workflow_dispatchrun on this branch (signed=false,bundle_tor=false) is the only way to exercise it, since the job cannot run on a PR trigger. Thereleasejob is push-only and shows as skipped on a dispatch run, which is expected.Visual changes
No UI change. Screenshots below are acceptance evidence from the packaged binary the new suite drives (see follow-up comment): the app after launch, and after the quit/relaunch with the persisted
theme: light.Security and privacy
No change. No new dependency, no new IPC channel, no runtime code touched — the app-side change is zero; everything new is test/CI/doc. The new job runs on a public repo's
ubuntu-latestrunner with the default read-only token, reads no secrets, and only installs the run's own artifact.AI assistance
Written by an automated agent (Claude, via the alan PR loop). Every command quoted above was actually run in this working tree and its output read; the mutation tests exist precisely so the new assertions are not taken on trust. A human should still review the workflow job before merging.