Skip to content

Add cross-repo upstream-gating workflow#29

Merged
d4rken merged 1 commit into
mainfrom
feat/cross-repo-verify-workflow
May 21, 2026
Merged

Add cross-repo upstream-gating workflow#29
d4rken merged 1 commit into
mainfrom
feat/cross-repo-verify-workflow

Conversation

@d4rken
Copy link
Copy Markdown
Member

@d4rken d4rken commented May 21, 2026

What changed

No user-facing behavior change. Internal: octi-web's PRs now run app-main and octi-desktop's consumer test suites against the PR's HEAD when wire-format-relevant paths change. A serializer change that drops a required field, retypes a value, or renames an enum entry is blocked at THIS PR rather than discovered later when a consumer happens to bump its pin.

Mirror of the same gate on app-main (d4rken-org/octi#315, merged) — now that both consumers ship support for consuming octi-web's published fixtures (d4rken-org/octi#318 + d4rken-org/octi-desktop#46, both merged), the symmetric direction can land safely.

Technical Context

  • "Always trigger, gate inside" pattern. The workflow fires on every PR without a path filter at the trigger level, then the matcher inside each job decides whether to actually run the consumer suite. Reason: GitHub leaves required checks pending on path-skipped PRs, which breaks branch-protection rules that require the check to pass. By always reporting a result (green when no relevant paths changed, real result when they did), required-check semantics stay clean.
  • Allowlist scope is tight. Only src/modules/, src/__interop__/published/, src/protocol/connector-id.ts, src/util/base64.ts, tools/generate-fixtures.ts, and the workflow file itself. src/crypto/, src/protocol/octi-api.ts, src/linking/ are deliberately NOT in scope — they don't have committed fixtures that consumers exercise. Adding more means adding more producer-side fixtures first.
  • Generator now routes connector IDs through octiServerConnectorId() (Codex finding). The fixture generator previously hardcoded kserver-prod.kserver.octi.darken.eu-aaaa... literals; the actual production function octiServerConnectorId(server, accountId) builds them at runtime. Hardcoding let the function drift while the fixtures kept the old format, masking a wire-format break. Now the generator imports the function + OFFICIAL_SERVERS.PROD/BETA, computes the IDs, and gets byte-identical output (verified via re-running pnpm fixtures:generate — zero churn in the committed JSON). Net effect: a future change to octiServerConnectorId() propagates into the fixtures and trips the producer self-check in the same PR.
  • verify-octi selective task set. Runs only :modules-meta:testDebugUnitTest, :modules-clipboard:testDebugUnitTest, :modules-files:testDebugUnitTest on app-main — the modules that actually consume octi-web's published fixtures. Full :test would build app + UI variants that don't exercise the contract; would waste ~10 minutes per PR for no signal.
  • Override format: INTEROP_FIXTURE_OVERRIDES='{"d4rken-org/octi-web":"<head sha>"}'. The multi-source resolver on both consumers drops the locked manifest_sha256 trust anchor for an overridden source; per-file sha256s in the freshly-fetched manifest stay as the anchor.
  • Cache keys namespaced per consumer repo (Codex follow-up): ${{ runner.os }}-app-main-gradle-caches-… and ${{ runner.os }}-octi-desktop-gradle-caches-… so the two jobs never restore each other's incompatible caches.

Review guidance

  • Compare side-by-side with app-main's .github/workflows/cross-repo-verify.yml (same shape, opposite direction). Concurrency group, allowlist match function, JDK setup, and override env should match the spirit.
  • Fork PR limitation: cross-repo actions/checkout of head.sha works for same-repo branches only. Fork PRs get a clean failure in the verify job (raw fetch of fork-only SHA returns 404). Documented in .claude/rules/testing.md.

Test plan

  • YAML validates (python3 -c "import yaml; yaml.safe_load(...)" green)
  • Generator refactor verified byte-equivalent — pnpm fixtures:generate produces zero diff against committed JSON; vitest run src/__interop__/published-self-check.test.ts 14/14 pass
  • Live end-to-end: this very PR is the first test of the gate. The trigger should fire because tools/generate-fixtures.ts is touched. Expected: both verify-octi and verify-desktop jobs detect the relevant change, check out the consumer at default branch, set the override, run the consumer suite, and pass.

Sister PRs:

Runs app-main + octi-desktop consumer suites against every octi-web PR's HEAD when wire-format-relevant paths change. A serializer change that drops a required field, retypes a value, or renames an enum entry is blocked at this PR rather than caught later when a consumer happens to bump its pin.

Also routes the fixture generator's connector IDs through octiServerConnectorId() so a change to src/protocol/connector-id.ts propagates into the committed fixtures; without this the function could drift while the fixtures kept the old format.

Pairs with octi#318 + octi-desktop#46 (the two consumers, both merged).
@d4rken d4rken added Build/Deploy c: sync/octi Related to the Octi-Server synchronization connector. c: module Component: Info Modules labels May 21, 2026
@d4rken d4rken merged commit 5dac970 into main May 21, 2026
13 of 14 checks passed
@d4rken d4rken deleted the feat/cross-repo-verify-workflow branch May 21, 2026 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Build/Deploy c: module Component: Info Modules c: sync/octi Related to the Octi-Server synchronization connector.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant