Skip to content

ci: run CI and releases on a fork, with updates from its own releases - #2

Merged
getBoolean merged 8 commits into
mainfrom
feat/fork-releases
Nov 2, 2026
Merged

getBoolean merged 8 commits into
mainfrom
feat/fork-releases

Conversation

@getBoolean

Copy link
Copy Markdown
Owner

Problem

The fork could run neither CI nor releases. Every CI and release job asks for Blacksmith runners, which only upstream has, so runs sat queued forever. The release workflow is limited to pingdotgg/t3code. And even a fork-built app would update from upstream: the CLI, t3 update, the server's update check, the install scripts and the error pages were hard-coded to pingdotgg/t3code and the t3 npm package.

Change

Fork behaviour is now set through repository variables. With none set, upstream runs exactly as before.

  • Runners: every Blacksmith label reads T3CODE_LINUX_RUNNER, T3CODE_LINUX_ARM_RUNNER, T3CODE_MACOS_RUNNER or T3CODE_WINDOWS_RUNNER first. This fork now points them at GitHub-hosted runners, which are free for public repos.
  • Releases: run when T3CODE_RELEASES is true. Jobs that need upstream's accounts are skipped on a fork unless it opts in: npm, AUR, Vercel, the marketing site, Discord and the release app's version bump. Relay tracing is skipped when its deployment state isn't available.
  • Updates follow the repo that built the release. Builds read T3CODE_RELEASE_REPOSITORY, else GITHUB_REPOSITORY, which Actions sets automatically. Desktop updates, t3 update, the server's update check, the install links and the issue link all point at the fork, while local builds keep upstream.
  • No npm needed: a build without the npm package checks GitHub releases for updates. Each release now attaches t3-release.json, which carries the migration number the update check uses to refuse incompatible versions, plus install.sh and install.ps1 that default to the fork.
  • T3 Connect: release builds use the hosted service's public values, kept as repo variables (already set on this fork). The desktop app keeps upstream's app id and t3code:// scheme, so hosted Connect sign-in keeps working.

docs/operations/fork-releases.md lists every variable.

Scope and approval

Requested by the fork's maintainer. It changes no upstream behaviour when the variables are unset.

Verification

  • Unit test for the GitHub update source: picks the newest release per channel, reads the manifest's migration number, accepts releases cut before the manifest existed, and returns nothing for unknown versions. It never touches npm.
  • Typecheck passes for shared, web, desktop, server and scripts. The nearby tests pass. The 10 failing server cloud/CLI tests fail the same way on this Windows machine without these changes.
  • write-release-manifest.ts run locally: wrote {"version":"1.2.3","t3code":{"databaseMigration":76}}.
  • All workflows parse. actionlint reports only two upstream items it doesn't know yet (concurrency.queue, github.run_started_at).
  • Not run yet: a real fork release. It needs T3CODE_RELEASES=true, which starts scheduled nightly releases. macOS builds stay unsigned, so they won't update themselves until Apple signing secrets are added.

Compound Engineering

Claude Opus 5.5 via Claude Code, running in T3 Code.

Test User added 3 commits November 1, 2026 17:21
The CLI, update checks, install links and error pages were hard-coded to
pingdotgg/t3code and the `t3` npm package, so a fork's builds offered
upstream's releases. Builds now take the release repository from
T3CODE_RELEASE_REPOSITORY, else GITHUB_REPOSITORY, which Actions sets, so a
fork's CI points at the fork and local builds keep upstream.

A build that doesn't publish the npm package checks the repository's GitHub
releases for updates instead, reading each release's t3-release.json for the
migration number the update check uses to refuse incompatible versions.

Claude Opus 5.5 via Claude Code (T3 Code)
Every Blacksmith runner label now reads T3CODE_LINUX_RUNNER,
T3CODE_LINUX_ARM_RUNNER, T3CODE_MACOS_RUNNER or T3CODE_WINDOWS_RUNNER first,
so a fork without Blacksmith can point them at GitHub-hosted runners. With
the variables unset, upstream runs unchanged.

Releases run on a fork that sets T3CODE_RELEASES. Publishers that need
upstream's accounts (npm, AUR, Vercel, the marketing site, Discord and the
release app's version bump) run only upstream or when the fork opts in, and
relay tracing is skipped without its deployment state. Each release now
attaches t3-release.json plus install scripts that default to the
repository that cut it.

Claude Opus 5.5 via Claude Code (T3 Code)
Claude Opus 5.5 via Claude Code (T3 Code)
@github-actions github-actions Bot added vouch:trusted Author is trusted by repo permissions or the VOUCHED list. size:L labels Nov 1, 2026
@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 5.0 KiB — 6.8 KiB ✅
Codex Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Codex Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Codex Live turn WebSocket decoded — 21.6 KiB — 24.4 KiB ✅
Codex Live turn messages — 2 — 8 ✅
Claude Total thread wire — 5.0 KiB — 6.8 KiB ✅
Claude Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Claude Live turn WebSocket wire — 1.3 KiB — 2.0 KiB ✅
Claude Live turn WebSocket decoded — 21.9 KiB — 24.4 KiB ✅
Claude Live turn messages — 2 — 8 ✅

Baseline: unavailable · PR result: 354e2b4 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Test User added 5 commits November 1, 2026 19:08
Fork CI showed three problems. Web tests read GITHUB_REPOSITORY through the build defines and expected upstream, so tests now keep upstream's identity. The boot error page imported a package the boot bundle can't load, so it reads the repository the web build injects. The relay tracing step tripped set -u when its smoke test ran it without the step's env.

Claude Opus 5.5 via Claude Code (T3 Code)
The terminal actions this test loads now use the git account guard, which reads server state through the client runtime the test mocks, so the file failed to import.

Claude Opus 5.5 via Claude Code (T3 Code)
Git 2.56 reports a worktree whose .git file points at a deleted directory as 'gitfile does not point to a valid repository' instead of 'not a git repository'. Storage cleanup then marked such a worktree failed instead of changed, and the git driver and manager missed it too. All three now share one check that knows both wordings.

Claude Opus 5.5 via Claude Code (T3 Code)
The test wrote a transcript dated 2026-08-01 and read it on the real clock, so it began failing once that date fell outside the 92-day usage retention on 2026-11-01.

Claude Opus 5.5 via Claude Code (T3 Code)
One test reloaded the PDF five times and needed most of its 15-second budget even on a fast machine, so it timed out on smaller CI runners. It is now two tests with the same assertions.

Claude Opus 5.5 via Claude Code (T3 Code)
@getBoolean
getBoolean merged commit 3e92f76 into main Nov 2, 2026
30 checks passed
@getBoolean
getBoolean deleted the feat/fork-releases branch November 4, 2026 23:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted Author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant