Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ jobs:
working-directory: apps/electron
run: bun run test:package-smoke

- name: Fresh-install E2E
working-directory: apps/electron
run: bun run test:fresh-install

- name: Verify checksums
working-directory: dist/release
run: shasum -a 256 -c SHA256SUMS.txt
Expand Down
27 changes: 17 additions & 10 deletions apps/electron/e2e/fresh-install.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// (no provider connected → wizard gate opens).

import { execSync, spawn } from 'node:child_process';
import { existsSync, rmSync, mkdirSync } from 'node:fs';
import { existsSync, mkdirSync, readdirSync, rmSync, statSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { createRequire } from 'node:module';
Expand All @@ -25,13 +25,24 @@ const { chromium } = require('playwright-core');
const here = dirname(fileURLToPath(import.meta.url));
const appRoot = join(here, '..');
const repoRoot = join(here, '../../..');
const packagedBinary = join(
repoRoot,
'dist/electron/mac-arm64/Folio.app/Contents/MacOS/Folio'
);
const distDir = join(repoRoot, 'dist', 'electron');
const CDP_PORT = 9347;
const userDataDir = join(appRoot, 'e2e/.user-data-fresh');

function findAppBinary() {
if (!existsSync(distDir)) {
throw new Error(`No dist output at ${distDir}. Run \`bun run package\` first.`);
}
for (const entry of readdirSync(distDir)) {
if (!entry.startsWith('mac')) continue;
const candidate = join(distDir, entry, 'Folio.app', 'Contents', 'MacOS', 'Folio');
if (existsSync(candidate) && statSync(candidate).isFile()) {
return candidate;
}
}
throw new Error(`No Folio.app binary found under ${distDir}/mac*.`);
}

// FINAGENT_E2E_KEEP_OPEN=1 — debugging only, NEVER in automated runs: leave
// the app running when the harness finishes and print where it is, instead of
// killing it. Automated runs/CI rely on the harness cleaning up its port.
Expand Down Expand Up @@ -107,11 +118,7 @@ async function waitForCdp(timeoutMs) {
}

async function main() {
if (!existsSync(packagedBinary)) {
console.error(`Packaged app not found: ${packagedBinary}`);
console.error('Run `bun run package` first.');
process.exit(1);
}
const packagedBinary = findAppBinary();
try {
execSync("pkill -f 'remote-debugging-port=9347' || true", { stdio: 'ignore' });
} catch {
Expand Down
8 changes: 4 additions & 4 deletions docs/v5-blocker-sweep.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ payload, or export surface changed.
bounded by the health probe (health.ts:238, 250: 5s + 10s CLI timeouts, 15s cache TTL
health.ts:217), so worst case the wizard appears after ~15s on a hung CLI. Not stuck,
but add a renderer-side timeout (e.g. 4s) if first-launch polish matters in V5.
2. **CI skips fresh-install gate (info):** release-check.mjs includes it (gate 7) but
release.yml does not run `test:fresh-install`; also "interaction audit"/"secret scan"
from docs are not mechanically enforced. Consider wiring the full `release:check` step
(or the missing gates) into CI.
2. **CI gate coverage:** `release.yml` now runs `test:fresh-install` after packaged smoke,
matching the release gate defined in `release-check.mjs`. The "interaction audit" and
"secret scan" listed in the quality-gate documentation remain informational and are not
yet mechanically enforced by CI.

## 6. Pre-existing failures (NOT from this sweep)

Expand Down