feat(ci): add cross-platform final build checks#279
Conversation
Adding .gitkeep for PR creation (default mode). This file will be removed when the task is complete. Issue: ProverCoderAI#278
Working session summaryDone. Updated existing PR 279 and marked it ready: Implemented:
Verified locally: Verified CI on latest SHA SOURCE: n/a. This summary was automatically extracted from the AI working session output. |
🤖 Solution Draft LogThis log file contains the complete execution trace of the AI solution draft process. 💰 Cost estimation:
📊 Context and tokens usage:
Total: (672.7K + 22.4M cached) input tokens, 61.0K output tokens, $31.863471 cost 🤖 Models used:
📎 Log file uploaded as Repository (83153KB)Now working session is ended, feel free to review and add any feedback on the solution draft. |
✅ Ready to mergeThis pull request is now ready to be merged:
Monitored by hive-mind with --auto-restart-until-mergeable flag |
|
в Final build надо ещё проверить что запускается browser |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR establishes cross-platform support for Linux, macOS, and Windows by introducing portable executable marking, simplifying CLI scripts to remove bash wrappers, restricting git mirror refresh scope, and implementing a CI/CD workflow that validates the build across all three platforms. ChangesCross-platform build and CI pipeline
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/final-build.yml:
- Around line 27-33: The workflow .github/workflows/final-build.yml currently
only checks CLIs ("Verify docker-git CLI starts" and "Verify session sync CLI
starts"); add a new step after those that performs the requested browser/UI
clone smoke check by launching a headless browser and exercising the UI clone
path (open app served from the build, navigate to the clone UI/menu, trigger a
clone, and assert success). Name the step clearly (e.g., "Verify browser UI
clone smoke check") and implement it using your existing test runner or a
lightweight headless tool (Playwright/puppeteer or an npm script) so it starts
the built web app, runs the UI clone flow, and fails the job on error.
In `@packages/app/tests/docker-git/package-scripts-cross-platform.test.ts`:
- Around line 24-34: Add fast-check property-based assertions covering the same
invariants currently tested by the table-driven checks: the "no bash" invariant
for each launch script and the "no chmod" invariant for the package build
script. Use fast-check's fc.assert with an fc.property that generates indices or
script entries from the existing launchScripts array and validates that the
selected entry.script does not match /\bbash(?:\.exe)?\b/u (referencing
launchScripts and entry.scriptName/entry.packageName for contextual failure
messages), and another property that checks sessionSyncPackage.scripts.build
does not match /\bchmod\s+/u. Replace or augment the existing for-loop and
single expect with these fc.assert(fc.property(...)) calls so the test file
package-scripts-cross-platform.test.ts uses property-based testing for the
invariants.
In `@packages/lib/tests/core/templates.test.ts`:
- Around line 77-86: The test for "renderEntrypoint clone cache" is missing
negative assertions for pull-request and merge-request refspecs; update the spec
for the entrypoint returned by renderEntrypoint(makeTemplateConfig()) to assert
it does not contain the undesired refs by adding checks that entrypoint does not
contain "'+refs/pull/*:refs/pull/*'" and
"'+refs/merge-requests/*:refs/merge-requests/*'". Ensure you add these two
expect(...).not.toContain(...) assertions alongside the existing negative check
so the test prevents regressions.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: f798fdcc-08da-4eff-8545-a01201bd5aac
📒 Files selected for processing (11)
.changeset/cross-platform-final-build.md.github/actions/setup/action.yml.github/workflows/final-build.ymlpackage.jsonpackages/app/package.jsonpackages/app/src/lib/core/templates-entrypoint/tasks.tspackages/app/tests/docker-git/package-scripts-cross-platform.test.tspackages/docker-git-session-sync/package.jsonpackages/lib/src/core/templates-entrypoint/tasks.tspackages/lib/tests/core/templates.test.tsscripts/mark-executable.mjs
| - name: Build final workspace packages | ||
| run: bun run build | ||
| - name: Verify docker-git CLI starts | ||
| run: bun ./packages/app/dist/src/docker-git/main.js --help | ||
| - name: Verify session sync CLI starts | ||
| run: bun ./packages/docker-git-session-sync/dist/docker-git-session-sync.js --help | ||
| - name: Prepare package artifacts directory |
There was a problem hiding this comment.
Final Build is missing the requested browser/UI clone smoke check.
The workflow currently validates CLI startup only. It does not cover the reviewer-requested runtime path: browser launch and cloning via UI/menu, so the PR acceptance criteria in discussion remain partially unverified.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/final-build.yml around lines 27 - 33, The workflow
.github/workflows/final-build.yml currently only checks CLIs ("Verify docker-git
CLI starts" and "Verify session sync CLI starts"); add a new step after those
that performs the requested browser/UI clone smoke check by launching a headless
browser and exercising the UI clone path (open app served from the build,
navigate to the clone UI/menu, trigger a clone, and assert success). Name the
step clearly (e.g., "Verify browser UI clone smoke check") and implement it
using your existing test runner or a lightweight headless tool
(Playwright/puppeteer or an npm script) so it starts the built web app, runs the
UI clone flow, and fails the job on error.
| describe("package scripts cross-platform contract", () => { | ||
| it("keeps user-facing launch scripts independent from bash", () => { | ||
| for (const entry of launchScripts) { | ||
| expect(entry.script, `${entry.packageName}:${entry.scriptName}`).not.toMatch(/\bbash(?:\.exe)?\b/u) | ||
| } | ||
| }) | ||
|
|
||
| it("keeps final package build independent from raw chmod", () => { | ||
| expect(sessionSyncPackage.scripts.build).not.toMatch(/\bchmod\s+/u) | ||
| }) | ||
| }) |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Add property-based assertions for script invariants.
This test is table-driven only; please add fast-check property tests for the bash/chmod invariants to satisfy the test policy for .test.ts files.
Proposed direction
+import fc from "fast-check"
...
+ it("bash-free launch scripts hold for all declared launch entries", () => {
+ fc.assert(
+ fc.property(fc.constantFrom(...launchScripts), (entry) => {
+ expect(entry.script).not.toMatch(/\bbash(?:\.exe)?\b/u)
+ })
+ )
+ })As per coding guidelines "**/*.test.{ts,tsx}: Implement property-based testing using fast-check for mathematical properties and invariants."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/app/tests/docker-git/package-scripts-cross-platform.test.ts` around
lines 24 - 34, Add fast-check property-based assertions covering the same
invariants currently tested by the table-driven checks: the "no bash" invariant
for each launch script and the "no chmod" invariant for the package build
script. Use fast-check's fc.assert with an fc.property that generates indices or
script entries from the existing launchScripts array and validates that the
selected entry.script does not match /\bbash(?:\.exe)?\b/u (referencing
launchScripts and entry.scriptName/entry.packageName for contextual failure
messages), and another property that checks sessionSyncPackage.scripts.build
does not match /\bchmod\s+/u. Replace or augment the existing for-loop and
single expect with these fc.assert(fc.property(...)) calls so the test file
package-scripts-cross-platform.test.ts uses property-based testing for the
invariants.
| describe("renderEntrypoint clone cache", () => { | ||
| it("refreshes mirrors without broad remote refs", () => { | ||
| const entrypoint = renderEntrypoint(makeTemplateConfig()) | ||
|
|
||
| expect(entrypoint).toContain("git --git-dir '$CACHE_REPO_DIR' fetch") | ||
| expect(entrypoint).toContain("'+refs/heads/*:refs/heads/*'") | ||
| expect(entrypoint).toContain("'+refs/tags/*:refs/tags/*'") | ||
| expect(entrypoint).not.toContain("'+refs/*:refs/*'") | ||
| }) | ||
| }) |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
What is the recommended way to run fast-check property-based tests in Vitest 4.1.5 (including TypeScript examples)?
💡 Result:
Recommended way: use fast-check through the dedicated Vitest connector package @fast-check/vitest, and run property-based “prop” tests via the connector’s enriched test/it APIs (e.g., test.prop / it.prop). This is the safest/simplest integration because the connector wires up Vitest-specific concerns like timeouts and lifecycle hooks. [1][2] Setup (TypeScript) 1) Install: - npm i -D vitest fast-check @fast-check/vitest [1] 2) Write property-based tests using @fast-check/vitest instead of importing test/it directly from vitest. The connector provides.prop variants for property inputs. Example: tuple (positional) notation ts // your-test.spec.ts import { test, expect, fc } from '@fast-check/vitest'; a function isSubstring(text: string, pattern: string) { return text.includes(pattern); } test.prop([fc.string(), fc.string(), fc.string()])( 'should detect substring', (a, b, c) => { const text = a + b + c; return expect(isSubstring(text, b)).toBe(true); }, ); Property inputs can be provided positionally with test.prop([arb1, arb2,...]). [1][2] Example: record (named) notation ts import { test, expect, fc } from '@fast-check/vitest'; function isSubstring(text: string, pattern: string) { return text.includes(pattern); } test.prop({ a: fc.string(), b: fc.string(), c: fc.string() })( 'should detect substring', ({ a, b, c }) => { const text = a + b + c; expect(isSubstring(text, b)).toBe(true); }, ); Record notation passes inputs as a named object to the predicate. [1][2] Reproducibility / replaying failures (seed) You can pass fast-check parameters (including a seed) to test.prop so failures are replayable. [2] Example (seeded run) ts import { test, expect, fc } from '@fast-check/vitest'; test.prop([fc.nat(), fc.nat()], { seed: 4242 })( 'should replay the test for the seed 4242', (a, b) => { expect(a + b === b + a).toBe(true); }, ); [2] How this relates to “fast” execution in Vitest 4.1.5 - The recommended approach is to delegate property-test orchestration to @fast-check/vitest; it takes care of Vitest integration details (timeouts and beforeEach/afterEach lifecycle wiring) so property predicates run correctly under Vitest’s execution model. [1][2] - For more extensive property testing, @fast-check/vitest supports a full property-based mode that repeatedly generates inputs to find edge cases. [2] Alternative (not recommended for Vitest): using fast-check directly fast-check itself works with any runner, but fast-check’s Vitest docs specifically recommend the connector as the “safest and simplest path” for Vitest integration, rather than using Vitest’s test/it directly. [1]
Citations:
- 1: https://fast-check.dev/docs/tutorials/setting-up-your-test-environment/property-based-testing-with-vitest/
- 2: https://www.npmjs.com/package/@fast-check/vitest
🏁 Script executed:
# First, locate the test file and examine its content
find . -path "*/packages/lib/tests/core/templates.test.ts" -type fRepository: ProverCoderAI/docker-git
Length of output: 112
🏁 Script executed:
# Check if file exists using git ls-files as fallback
git ls-files | grep -E "templates\.test\.ts"Repository: ProverCoderAI/docker-git
Length of output: 110
🏁 Script executed:
# Search for templates test file more broadly
fd "templates.test.ts" --type fRepository: ProverCoderAI/docker-git
Length of output: 110
🏁 Script executed:
# Look for the renderEntrypoint function
rg "renderEntrypoint" -t ts -t tsx -A 5 --max-count 20Repository: ProverCoderAI/docker-git
Length of output: 96
🏁 Script executed:
# Check project dependencies for Vitest and fast-check
cat package.json | jq '.devDependencies | to_entries[] | select(.key | test("vitest|fast-check")) | "\(.key): \(.value)"'Repository: ProverCoderAI/docker-git
Length of output: 50
🏁 Script executed:
# Search for existing fast-check usage in test files
fd ".test.ts" -o ".spec.ts" --type f -x rg "fast-check|fc\." {} --max-count 5Repository: ProverCoderAI/docker-git
Length of output: 204
🏁 Script executed:
# Read the test file
cat -n packages/lib/tests/core/templates.test.ts | head -100Repository: ProverCoderAI/docker-git
Length of output: 5439
🏁 Script executed:
# Search for renderEntrypoint function definition
rg "function renderEntrypoint|const renderEntrypoint|export.*renderEntrypoint" -A 10Repository: ProverCoderAI/docker-git
Length of output: 50380
🏁 Script executed:
# Check package.json for dependencies
cat package.json | head -100Repository: ProverCoderAI/docker-git
Length of output: 4503
🏁 Script executed:
# Look for fast-check imports or usage
rg "from.*fast-check|import.*fc\." --type tsRepository: ProverCoderAI/docker-git
Length of output: 50
🏁 Script executed:
# Find renderCloneBody and git ref generation logic
rg "renderCloneBody|git.*fetch.*refs|refs/heads|refs/tags" -A 3 -B 2Repository: ProverCoderAI/docker-git
Length of output: 17230
🏁 Script executed:
# Check if fast-check is mentioned anywhere in the codebase (even if not installed)
rg "fast-check|fc\." --type ts --max-count 10Repository: ProverCoderAI/docker-git
Length of output: 50
🏁 Script executed:
# Look at the package.json for lib package specifically
cat packages/lib/package.json | head -150Repository: ProverCoderAI/docker-git
Length of output: 3283
Add explicit negative assertions for merge-request and pull-request refs.
The test validates the clone-cache refspec invariant (documented in tasks.ts) but is incomplete. Add expect(entrypoint).not.toContain("'+refs/pull/*:refs/pull/*'") and expect(entrypoint).not.toContain("'+refs/merge-requests/*:refs/merge-requests/*'") to prevent regression if those refs are accidentally reintroduced.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/lib/tests/core/templates.test.ts` around lines 77 - 86, The test for
"renderEntrypoint clone cache" is missing negative assertions for pull-request
and merge-request refspecs; update the spec for the entrypoint returned by
renderEntrypoint(makeTemplateConfig()) to assert it does not contain the
undesired refs by adding checks that entrypoint does not contain
"'+refs/pull/*:refs/pull/*'" and
"'+refs/merge-requests/*:refs/merge-requests/*'". Ensure you add these two
expect(...).not.toContain(...) assertions alongside the existing negative check
so the test prevents regressions.
Summary
Final BuildGitHub Actions workflow for Ubuntu, macOS, and Windows that builds both packages, smoke-tests both CLIs, and uploads package tarballs.chmodwith a Bun helper.Reproduction and Verification
packages/app/tests/docker-git/package-scripts-cross-platform.test.tsbefore implementing the script changes.25728183189:E2E (Clone cache)timed out after1800son the second cache reuse case while refreshing broadrefs/*.packages/lib/tests/core/templates.test.tsproving mirror refreshes includerefs/heads/*andrefs/tags/*but not broadrefs/*.Local Checks
bun run --cwd packages/lib test -- tests/core/templates.test.tsbun run --cwd packages/app test -- tests/docker-git/package-scripts-cross-platform.test.tsbun run buildbun run typecheckbun run lintbun run lint:effectbun run check:dist-deps-prunebun run testgit diff --checkMathematical Guarantees
Invariants
forall os in {linux, macos, windows}: final-build(os) -> build(os) and cli_help(app, os) and cli_help(session_sync, os)forall r in clone_cache_refresh_refs: r in refs/heads/* union refs/tags/*forall npm_script in checked_scripts: not contains(npm_script, "bash -lc")Preconditions
Postconditions
refs/pull/*orrefs/merge-requests/*through broadrefs/*.Complexity
O(|all remote refs|)toO(|heads| + |tags|).SOURCE: n/a
Fixes #278