Skip to content

feat(ci): self-synced internal refs + PR pipeline self-test#10

Merged
gmaclennan merged 5 commits into
mainfrom
feat/self-synced-refs-and-ci
Jun 11, 2026
Merged

feat(ci): self-synced internal refs + PR pipeline self-test#10
gmaclennan merged 5 commits into
mainfrom
feat/self-synced-refs-and-ci

Conversation

@gmaclennan

Copy link
Copy Markdown
Member

Fixes the workflow-versioning problem that made validating harness changes painful (temporary action-ref pin commits, manual test.yml dispatches — see the validation notes on #9).

1. Self-synced internal references

The composite action was pinned @main inside the reusable workflows (a relative uses: would resolve against the caller's checkout, hence the pin). That decouples the action version from the workflow version: @v2 callers run v2 workflows with main's action, and branch dispatches of test.yml silently run main's action instead of the branch's — which is why validating #9 required temporary commits pointing the ref at the branch.

The reusable workflows now check out this repo at job.workflow_sha — the documented context property that, for a job defined in a reusable workflow, is the commit SHA of the reusable workflow file itself (i.e. whatever the caller's @v2/@main/branch ref resolved to) — and use the action/harness from that checkout:

- uses: actions/checkout@v6
  with:
    repository: ${{ job.workflow_repository }}
    ref: ${{ job.workflow_sha }}
    path: .nodejs-mobile-bare-prebuilds
- uses: ./.nodejs-mobile-bare-prebuilds/.github/actions/prebuild

Workflow, action, and test harness now always travel together at one SHA. harness_ref stays as an optional override (default now self-sync instead of main), and test.yml no longer needs to thread github.sha through. This also resolves the earlier "fix reference pinning" / revert churn — there is no longer anything to pin.

2. PR pipeline self-test (ci.yml)

Every PR touching .github/** or test-harness/** now runs the real pipeline — prebuild (android-x64, quickbit-native@latest) → emulator test, including the floor-API-24 emulator from #9. Combined with (1), the PR's in-flight changes are what actually execute, so changes like #9 get validated automatically with no manual dispatch.

This PR validates itself: the ci.yml run on this very PR exercises the self-synced checkout path end-to-end.

Android-only by design (the cheap leg, and where toolchain regressions live); test.yml remains for manual iOS runs.

🤖 Generated with Claude Code

gmaclennan and others added 3 commits June 10, 2026 22:16
Two changes that together remove the temp-pin-commit dance and manual
test dispatches when changing the harness:

1. The composite action and test harness are now checked out at
   `job.workflow_sha` — the exact ref of the reusable workflow that is
   running — instead of a hard @main pin (action) / 'main' default
   (harness_ref). Workflow, action, and harness always travel together:
   @v2 callers get exactly v2's action, and a branch dispatch of
   test.yml tests the branch's in-flight changes as-is. harness_ref
   remains as an optional override.

2. New ci.yml runs the real prebuild -> emulator-test pipeline
   (android-x64, quickbit-native, incl. the floor-API emulator) on
   every PR touching .github/** or test-harness/**.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ion, no persisted credentials on harness checkouts

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cript input

- move-major-tag.yml force-moves vX to any pushed vX.Y.Z tag, so
  releasing is 'push a semver tag' and @v2 callers follow automatically.
- README gains a 'Versioning and releasing' section documenting the
  major-tag contract, the self-synced internal refs, and the release
  steps (none of this was written down anywhere).
- test.yml now derives test_runner=custom when test_script is set;
  previously a dispatched script was silently ignored (test_runner
  stayed 'smoke') and the run passed without executing it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@gmaclennan

Copy link
Copy Markdown
Member Author

Pushed three additions following review:

  • move-major-tag.yml: pushing any vX.Y.Z tag (or gh release create) now force-moves the floating vX tag automatically — releasing becomes "push a semver tag", and @v2 callers follow with no changes. Addresses the rollout gap flagged in review (v2 currently sits at v2.1.2, pre-fix(android): target API 24 so prebuilds load on Android < 9 #9).
  • README "Versioning and releasing" section: documents the major-tag contract, the self-synced internal refs (and the rule: never @<ref>-reference the composite action from inside this repo), and the release steps. None of this was previously written down.
  • test.yml fix: a dispatched test_script was silently ignored because test_runner stayed smoke (it's only read for custom) — the run passed without executing the script. Now derived: non-empty test_scripttest_runner: custom.

Plus review nits in the previous commit: permissions: contents: read on ci.yml, CI module pinned to quickbit-native@2.4.8, persist-credentials: false on the harness checkouts.

After merging: tag v2.2.0 to move v2 forward — the merged #9 floor-API test matrix and these changes only reach @v2 callers once the tag moves.

🤖 Generated with Claude Code

@gmaclennan
gmaclennan enabled auto-merge (squash) June 10, 2026 22:42
gmaclennan and others added 2 commits June 11, 2026 03:10
…r can't hang the job

The fail-fast pidof check had no timeout. When the emulator itself
wedges (seen as 'Failed to find process owned resources for puid N',
logcat goes silent), the unbounded `adb shell pidof` blocks forever —
and because the SECONDS budget is only re-checked at the loop top, the
loop never returns there and the job stalls to its 45-min wall clock
instead of failing at TIMEOUT_SECONDS.

Wrap the call in `timeout`; key the death decision off timeout's exit
124 (it alone means 'adb hung'), since pidof exits non-zero for a dead
app too. A wedged emulator now falls through and is bounded by the
SECONDS budget; a genuine crash still fails fast.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`am start -W` blocks until the launch completes; on a flaky API 24
emulator that never returns, hanging the job at line ~20 — before the
watch loop, so neither its per-read timeout nor SECONDS budget applies,
and the job rode to its 45-min wall clock (seen twice on API 24).

Start logcat capture before the launch, then dispatch fire-and-forget
under `timeout 60` (drop -W). A stuck launch now falls through to the
watch loop, which bounds the wait and reports a clean failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@gmaclennan
gmaclennan merged commit 7ef0102 into main Jun 11, 2026
5 checks passed
@gmaclennan
gmaclennan deleted the feat/self-synced-refs-and-ci branch June 11, 2026 03:03
gmaclennan added a commit that referenced this pull request Jun 11, 2026
…usted install (#12)

Closes the supply-chain exposure flagged in the #10 security review: the
prebuild jobs check out the caller repo (default persist-credentials:
true) and then run `npm install` on the untrusted third-party target
module, whose lifecycle scripts could read the caller's GITHUB_TOKEN
from $GITHUB_WORKSPACE/.git/config — write-capable in the sibling repos'
release runs, which publish the artifacts shipped in the CoMapeo apps.

- persist-credentials: false on the caller checkout in prebuild.yml and
  prebuild-all.yml (it only exists to resolve patches_dir; needs no
  token). Belt: no token on disk to steal.
- npm install --ignore-scripts for the target module. bare-make drives
  the native build from CMakeLists, so no install-time script is needed
  (the better-sqlite3 workflow already builds this way). Suspenders.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant