Skip to content
Merged
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
5 changes: 3 additions & 2 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
# CodeRabbit is the first-pass reviewer for every PR, including drafts and
# fork PRs. CircleCI pr-check runs the builds and tests (fork PRs need the
# ci:run label, see .github/workflows/fork-ci-mirror.yml). UI proof on a real
# fork PRs. CircleCI pr-check runs the builds and tests. Fork PRs are checked
# with main's -Slice ci steps in an isolated, credential-free Windows
# environment (.github/CI.md). UI proof on a real
# Windows build stays a human or agent responsibility (AGENTS.md).
language: en-US
reviews:
Expand Down
35 changes: 19 additions & 16 deletions .github/CI.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ credential.
The hosted PR check delegates to scripts/local-check.ps1 -Slice ci:

~~~powershell
powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -File scripts\circleci-pr.tests.ps1
cargo fmt --all --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
pnpm --dir apps/desktop-tauri install --frozen-lockfile
pnpm --dir apps/desktop-tauri run lint
pnpm --dir apps/desktop-tauri run check:anti-slop
pnpm --dir apps/desktop-tauri run test:anti-slop
pnpm --dir apps/desktop-tauri test
pnpm --dir apps/desktop-tauri run build
Expand All @@ -38,22 +40,23 @@ second tag trigger.

## Fork pull requests

CircleCI GitHub App pipelines never fire for pull requests from forks. To
build one:

1. Read the fork PR's diff. The build runs the contributor's code on CircleCI
with this project's environment variables.
2. Add the `ci:run` label. .github/workflows/fork-ci-mirror.yml pushes
exactly that head commit to ci/pr-<number> in this repository.
3. CircleCI builds the ci/pr-<number> push. The trigger gate in
scripts/circleci-pr-common.ps1 lets those branches through, and the
docs-only gate finds the PR base from the number. The check lands on the
same commit, so it shows on the fork PR.

Any new push to the fork PR removes the label; re-add it after reviewing the
new commits. Closing the PR removes the mirror branch. GITHUB_TOKEN cannot
push commits that change .github/workflows/**, so the mirror fails for those
PRs; review them by hand and use the manual Blacksmith workflow if needed.
CircleCI GitHub App pipelines never fire for pull requests from forks, and
this project does not trigger hosted CircleCI runs any other way (no API
token). Validate a fork PR locally instead:

1. Read the whole diff first, including build.rs, Cargo and package
manifests, scripts and tests. Building and testing a fork runs its code.
2. Run the check in a disposable, credential-free Windows environment, such
as Windows Sandbox or a throwaway VM. It must have no GitHub, CircleCI,
SignPath or provider logins, and no access to your profile. A worktree on
your own machine is not isolation.
3. In that environment, fetch the head (`git fetch origin pull/<number>/head`),
check it out (`git checkout --detach FETCH_HEAD`), and run the commands
listed under "CircleCI validation" above one by one. Take the list from
main's copy of scripts/local-check.ps1, and don't run either copy of that
script; the fork can change its own.
4. Post the result on the PR. The PR has no `ci/circleci: pr-check`, so a
maintainer merges it with an admin override.

## Code review

Expand Down
107 changes: 0 additions & 107 deletions .github/workflows/fork-ci-mirror.yml

This file was deleted.

6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ pnpm run tauri:build

- Rust: prefer focused `#[cfg(test)]` unit tests near the changed module. Run both manifests after Rust changes.
- Frontend: Vitest 3 + jsdom + Testing Library. From `apps/desktop-tauri`: `pnpm test` (`src/**/*.{test,spec}.{ts,tsx}`).
- **Hosted PR check**: CircleCI Windows is primary and runs `scripts/local-check.ps1 -Slice ci` for ordinary/canonical PRs and `main`; micro PRs targeting `port/upstream-*` intentionally skip hosted Windows compute; a micro-named PR targeting `main` does not. `.github/workflows/pr-check.yml` is manual Blacksmith Windows reserve only. Budget details: `CONTEXT.md`, `.github/CI.md`, and ADRs under `docs/adr/`.
- **Fork PRs and reviews**: CircleCI never triggers on fork PRs by itself. After reading the diff, a maintainer adds the `ci:run` label; `fork-ci-mirror.yml` copies that head to `ci/pr-<number>` for CircleCI, and any new push removes the label. CodeRabbit (`.coderabbit.yaml`) reviews every PR, drafts included, against these rules; fix or answer its findings before merging.
- **Hosted PR check**: CircleCI Windows is primary and runs `scripts/local-check.ps1 -Slice ci` for same-repository ordinary/canonical PRs and `main` (never for fork PRs); micro PRs targeting `port/upstream-*` intentionally skip hosted Windows compute; a micro-named PR targeting `main` does not. `.github/workflows/pr-check.yml` is manual Blacksmith Windows reserve only. Budget details: `CONTEXT.md`, `.github/CI.md`, and ADRs under `docs/adr/`.
- **Fork PRs and reviews**: CircleCI never runs on fork PRs, and this project adds no CircleCI API token. Read the full diff, then run the `-Slice ci` steps from main's copy of `scripts/local-check.ps1` against the fork head (`pull/<number>/head`) in a disposable, credential-free Windows environment (Windows Sandbox or a throwaway VM; a worktree is not isolation), and post the result (see `.github/CI.md`). CodeRabbit (`.coderabbit.yaml`) reviews every PR, drafts included, against these rules; fix or answer its findings before merging.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- **Hosted mirror**: `.\scripts\local-check.ps1 -Slice ci`. The default no-parameter developer slice remains available and does not run full installer/smoke unless requested.
- Parser / fetcher changes: add deterministic samples or fixtures where practical.
- No coverage thresholds are configured — do not invent any.
Expand Down Expand Up @@ -174,7 +174,7 @@ Then follow post-install instructions (permissions / accessibility as prompted).
- Commands run (`cargo test`, `pnpm test`, `.\scripts\local-check.ps1`, etc.)
- Screenshots / GIFs for UI changes (Windows)
- Linked issue / reference when relevant
- Hosted PR check exists: `ci/circleci: pr-check` is the primary Windows gate; `.github/workflows/pr-check.yml` is manual Blacksmith backup. Porting micro PRs targeting `port/upstream-*` use focused local evidence and intentionally skip automatic hosted Windows CI; `main`-bound PRs always get the hosted gate.
- Hosted PR check exists: `ci/circleci: pr-check` is the primary Windows gate; `.github/workflows/pr-check.yml` is manual Blacksmith backup. Porting micro PRs targeting `port/upstream-*` use focused local evidence and intentionally skip automatic hosted Windows CI; same-repository `main`-bound PRs always get the hosted gate; fork PRs never do (see Fork PRs and reviews).
- UI / tray / settings / float-bar / visual PRs: **CUA Driver proof is the default** ([trycua/cua](https://github.com/trycua/cua)) after a **fresh local rebuild** — see [UI validation with CUA](#ui-validation-with-cua-trycuacua). If CUA cannot be used, explain why and attach equivalent manual proof (PR template checkboxes).
- Before non-trivial merge: thermo-nuclear structure review when the project process requires it.

Expand Down
22 changes: 3 additions & 19 deletions scripts/circleci-pr-common.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -50,37 +50,21 @@ function Get-TriggerGateDecision {
# every other branch push skips. CircleCI delivers same-repo PR builds
# as branch pipelines, so PR association comes from the compile-time
# GitHub App pipeline value pipeline.event.context.github.pr_url.
# GitHub App pipelines never fire for fork PRs, so the fork-ci-mirror
# workflow copies a maintainer-approved fork head to ci/pr-<number>;
# those pushes run the checks too.
$isPr = -not [string]::IsNullOrWhiteSpace($PrUrl)
$isMainPush = $Branch -in @('main', 'master')
$isForkMirror = -not [string]::IsNullOrWhiteSpace((Get-ForkMirrorPrNumber -Branch $Branch))
if (-not $isPr -and -not $isMainPush -and -not $isForkMirror) {
if (-not $isPr -and -not $isMainPush) {
return [pscustomobject]@{
Skip = $true
Reason = "Branch push to '$Branch' (not a PR, not main/master, not a ci/pr-<number> fork mirror): hosted pr-check skips."
Reason = "Branch push to '$Branch' (not a PR, not main/master): hosted pr-check skips."
}
}

return [pscustomobject]@{
Skip = $false
Reason = "Trigger gate passed (PR: $isPr, fork mirror: $isForkMirror, branch: '$Branch')."
Reason = "Trigger gate passed (PR: $isPr, branch: '$Branch')."
}
}

<#
.SYNOPSIS
PR number of a ci/pr-<number> fork-mirror branch, or '' for any other
branch. The fork-ci-mirror workflow is the only writer of these branches.
#>
function Get-ForkMirrorPrNumber {
param([AllowEmptyString()][string]$Branch)

if ($Branch -match '^ci/pr-([1-9]\d*)$') { return $Matches[1] }
return ''
}

<#
.SYNOPSIS
Extract a SHA-256 digest for FileName from official checksum text.
Expand Down
2 changes: 1 addition & 1 deletion scripts/circleci-pr-gates.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ if ($isMainPush) {
# PR association without a populated event value (e.g. api trigger):
# resolve the base from the public GitHub pulls API.
try {
$prNumber = Get-ForkMirrorPrNumber -Branch $Branch
$prNumber = ''
if ($PrUrl -match '/pull/(\d+)') { $prNumber = $Matches[1] }
if ([string]::IsNullOrWhiteSpace($prNumber)) { throw 'PR number not available from pipeline values.' }
if ([string]::IsNullOrWhiteSpace($env:CIRCLE_PROJECT_USERNAME) -or [string]::IsNullOrWhiteSpace($env:CIRCLE_PROJECT_REPONAME)) {
Expand Down
10 changes: 0 additions & 10 deletions scripts/circleci-pr.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,6 @@ Assert-True $decision.Skip 'non-PR topic branch skips'
Assert-True ($decision.Reason -match 'codex/topic') 'topic branch skip reason'
$decision = Get-TriggerGateDecision -BudgetMode 'off' -Branch 'main' -PrUrl ''
Assert-True $decision.Skip 'budget off wins over main push'
$decision = Get-TriggerGateDecision -BudgetMode 'normal' -Branch 'ci/pr-750' -PrUrl ''
Assert-True (-not $decision.Skip) 'fork mirror branch runs'
$decision = Get-TriggerGateDecision -BudgetMode 'off' -Branch 'ci/pr-750' -PrUrl ''
Assert-True $decision.Skip 'budget off wins over fork mirror'
foreach ($branch in @('ci/pr-', 'ci/pr-0', 'ci/pr-12x', 'ci/pr-7/extra', 'x/ci/pr-7', 'ci/pr-7-old')) {
$decision = Get-TriggerGateDecision -BudgetMode 'normal' -Branch $branch -PrUrl ''
Assert-True $decision.Skip "look-alike mirror branch '$branch' skips"
}
Assert-Equal (Get-ForkMirrorPrNumber -Branch 'ci/pr-750') '750' 'mirror PR number parsed'
Assert-Equal (Get-ForkMirrorPrNumber -Branch 'main') '' 'non-mirror branch has no PR number'

Write-Host '==> Hosted Node provisioning guard'
$prRunnerText = Get-Content -Raw -LiteralPath (Join-Path $scriptRoot 'run-circleci-pr-check.ps1')
Expand Down