From 124630c3f64843336ac7fefd2417fbe3f75c5c37 Mon Sep 17 00:00:00 2001 From: Trevor Walker Date: Wed, 26 Aug 2026 11:00:23 -0600 Subject: [PATCH] ci: run workflows on GitHub-hosted runners Blacksmith was the CI bill; every job ran there except a few short orchestration steps. Standard GitHub-hosted runners are free on public repositories, and the repository is going public, so every runs-on label moves to ubuntu-24.04, windows-2025, or macos-26. The Android showcase emulator drops from 8 to 4 cores to match the 4-vCPU hosted runner, stale Blacksmith comments and the runner sections in docs/operations are rewritten, and AGENTS.md now describes the repository as public. --- .github/workflows/ci-mobile-native.yml | 6 ++-- .github/workflows/ci.yml | 10 +++--- .github/workflows/deploy-relay.yml | 2 +- .github/workflows/desktop-macos-preview.yml | 2 +- .github/workflows/mobile-eas-preview.yml | 2 +- .github/workflows/mobile-eas-production.yml | 2 +- .../workflows/mobile-showcase-screenshots.yml | 6 ++-- .github/workflows/release.yml | 31 ++++++++----------- AGENTS.md | 2 +- .../mobile-app-store-screenshots.md | 6 ++-- docs/operations/release.md | 19 ++++++------ scripts/mobile-showcase.config.ts | 2 +- 12 files changed, 42 insertions(+), 48 deletions(-) diff --git a/.github/workflows/ci-mobile-native.yml b/.github/workflows/ci-mobile-native.yml index debecf933..c7ee0171f 100644 --- a/.github/workflows/ci-mobile-native.yml +++ b/.github/workflows/ci-mobile-native.yml @@ -1,9 +1,9 @@ name: CI Mobile Native # Split out of ci.yml so it can be path-filtered. The job needs a macOS runner -# for swiftlint, and macOS is the most expensive tier we buy, but the check it +# for swiftlint, and macOS runners are the slowest to provision, but the check it # runs only ever reads .swift/.kt/.kts under apps/mobile -- roughly four seconds -# of actual linting behind about forty seconds of runner setup. Filtering on +# of actual linting behind a runner boot many times longer. Filtering on # apps/mobile/** would still be wrong: only 3 of the last 40 merged PRs touched # native sources, while 18 touched something under apps/mobile, so the broad # filter would boot macOS six times more often than the check can do any work. @@ -43,7 +43,7 @@ permissions: jobs: mobile_native_static_analysis: name: Mobile Native Static Analysis - runs-on: blacksmith-6vcpu-macos-26 + runs-on: macos-26 timeout-minutes: 10 steps: - name: Checkout diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8cfe4267..4ee9141f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ concurrency: jobs: check: name: Check - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: Checkout @@ -67,7 +67,7 @@ jobs: # limit stays at the default 4 so peak load per runner is unchanged. test: name: Test - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: Checkout @@ -97,7 +97,7 @@ jobs: # isolation that flag buys is preserved exactly. test_server: name: Test Server ${{ matrix.shard }} - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 10 strategy: fail-fast: false @@ -174,7 +174,7 @@ jobs: # for checks that take under 3s, on the critical path of every PR. rust: name: Rust - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: Checkout @@ -198,7 +198,7 @@ jobs: release_smoke: name: Release Smoke - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: Checkout diff --git a/.github/workflows/deploy-relay.yml b/.github/workflows/deploy-relay.yml index 66e3827ab..203d1ee74 100644 --- a/.github/workflows/deploy-relay.yml +++ b/.github/workflows/deploy-relay.yml @@ -24,7 +24,7 @@ jobs: # credentials. Set the DEPLOY_RELAY repository variable to "true" once they # exist, so merges to pylon do not fail on a stack that cannot deploy. if: ${{ vars.DEPLOY_RELAY == 'true' }} - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 15 environment: name: production diff --git a/.github/workflows/desktop-macos-preview.yml b/.github/workflows/desktop-macos-preview.yml index 6d1264aa7..3260fd3e9 100644 --- a/.github/workflows/desktop-macos-preview.yml +++ b/.github/workflows/desktop-macos-preview.yml @@ -19,7 +19,7 @@ jobs: github.event.pull_request.head.repo.full_name == github.repository && contains(github.event.pull_request.labels.*.name, 'preview:mac') && (github.event.action != 'labeled' || github.event.label.name == 'preview:mac') - runs-on: blacksmith-12vcpu-macos-26 + runs-on: macos-26 timeout-minutes: 30 steps: - name: Checkout diff --git a/.github/workflows/mobile-eas-preview.yml b/.github/workflows/mobile-eas-preview.yml index 8f90c6fa1..348c9d8b2 100644 --- a/.github/workflows/mobile-eas-preview.yml +++ b/.github/workflows/mobile-eas-preview.yml @@ -10,7 +10,7 @@ jobs: if: | contains(github.event.pull_request.labels.*.name, '🚀 Mobile Continuous Deployment') && (github.event.action != 'labeled' || github.event.label.name == '🚀 Mobile Continuous Deployment') - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 concurrency: group: mobile-eas-preview-${{ github.event.pull_request.number }} cancel-in-progress: true diff --git a/.github/workflows/mobile-eas-production.yml b/.github/workflows/mobile-eas-production.yml index 835eb2ca5..1620e8d33 100644 --- a/.github/workflows/mobile-eas-production.yml +++ b/.github/workflows/mobile-eas-production.yml @@ -33,7 +33,7 @@ on: jobs: production: name: EAS Production ${{ inputs.mode }} - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 permissions: contents: read # Pylon Connect's public config lives in this environment, the same source diff --git a/.github/workflows/mobile-showcase-screenshots.yml b/.github/workflows/mobile-showcase-screenshots.yml index c64bccacd..654447f60 100644 --- a/.github/workflows/mobile-showcase-screenshots.yml +++ b/.github/workflows/mobile-showcase-screenshots.yml @@ -45,7 +45,7 @@ jobs: ios: name: iPhone 6.9, iPhone 6.5, and iPad 13 if: inputs.platform == 'all' || inputs.platform == 'ios' - runs-on: blacksmith-12vcpu-macos-26 + runs-on: macos-26 # Capturing every palette multiplies the device matrix by six, and only the # one native build is shared between them. timeout-minutes: ${{ inputs.theme == 'all' && 300 || 60 }} @@ -94,7 +94,7 @@ jobs: android: name: Android phone, 7-inch tablet, and 10-inch tablet if: inputs.platform == 'all' || inputs.platform == 'android' - runs-on: blacksmith-16vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 # Capturing every palette multiplies the device matrix by six, and only the # one native build is shared between them. timeout-minutes: ${{ inputs.theme == 'all' && 300 || 60 }} @@ -151,7 +151,7 @@ jobs: arch: x86_64 profile: pixel_7_pro avd-name: Pixel_10_Pro - cores: 8 + cores: 4 ram-size: 4096M disable-animations: false script: pnpm screenshots:mobile --platform android --appearance "${{ inputs.appearance }}" --theme "${{ inputs.theme }}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b624b72a4..05b8db522 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,12 +42,11 @@ permissions: id-token: none jobs: - # Runner split: the four platform builds and the preflight suite stay on - # Blacksmith, where the compute is worth paying for. Everything else here is - # short and I/O-bound — API calls, artifact uploads, a git push, a curl — and - # those jobs repeatedly sat unassigned in Blacksmith's queue while heavier - # jobs in the same run picked up immediately. GitHub-hosted runners took them - # in seconds every time, so light orchestration runs there. + # Every job runs on GitHub-hosted standard runners, which are free on this + # public repository. Heavy jobs pin an OS version (`ubuntu-24.04`, + # `windows-2025`, `macos-26`) so a build cannot drift when `-latest` moves; + # the short I/O-bound orchestration jobs use `ubuntu-latest` because nothing + # in them is OS-sensitive. check_changes: name: Check for changes since last nightly if: github.event_name == 'schedule' @@ -91,7 +90,7 @@ jobs: if: | !failure() && !cancelled() && (github.event_name != 'schedule' || needs.check_changes.outputs.has_changes == 'true') - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 # Runs the whole repo's check, typecheck, and test suites. timeout-minutes: 30 outputs: @@ -188,7 +187,7 @@ jobs: name: Release quality checks needs: [preflight] if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' }} - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: Checkout @@ -348,7 +347,7 @@ jobs: name: Build WSL node-pty (linux-x64) needs: [preflight] if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' }} - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 30 steps: - name: Checkout @@ -419,32 +418,28 @@ jobs: matrix: include: - label: macOS arm64 - runner: blacksmith-6vcpu-macos-26 + runner: macos-26 platform: mac target: dmg arch: arm64 rust_target: aarch64-apple-darwin resource_key: darwin-arm64 - label: macOS x64 - runner: blacksmith-6vcpu-macos-26 + runner: macos-26 platform: mac target: dmg arch: x64 rust_target: x86_64-apple-darwin resource_key: darwin-x64 - label: Linux x64 - # GitHub-hosted deliberately. Every stuck job so far has been on a - # blacksmith ubuntu runner, including this build sitting unassigned - # for 43 minutes while the macOS and Windows jobs queued after it - # ran and finished. Slower here, but it actually starts. - runner: ubuntu-latest + runner: ubuntu-24.04 platform: linux target: AppImage arch: x64 rust_target: x86_64-unknown-linux-gnu resource_key: linux-x64 - label: Windows x64 - runner: blacksmith-8vcpu-windows-2025 + runner: windows-2025 platform: win target: nsis arch: x64 @@ -821,7 +816,7 @@ jobs: # trusted publishing configured for it. Set the PUBLISH_CLI_TO_NPM # repository variable to "true" once both exist. if: ${{ !failure() && !cancelled() && vars.PUBLISH_CLI_TO_NPM == 'true' && needs.preflight.result == 'success' && needs.relay_public_config.result == 'success' && needs.quality.result == 'success' && needs.build.result == 'success' }} - runs-on: ubuntu-24.04 # blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 10 permissions: contents: read diff --git a/AGENTS.md b/AGENTS.md index 02ab5a767..f60467b7c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ T3-named environment variables may still be passed to the bundled compatibility Pylon is a long-lived independent product, not a temporary reskin or a patch queue intended to collapse back into T3 Code. Build in Pylon's direction while preserving the upstream qualities described below. -- The canonical repository is the private `pylon-code/pylon` repository. Its writable remote is `origin`, and its default product branch is `pylon`. It moved from `rynfar/pylon` to the `pylon-code` organization; GitHub redirects the old path, but use the organization path. +- The canonical repository is the public `pylon-code/pylon` repository. Its writable remote is `origin`, and its default product branch is `pylon`. It moved from `rynfar/pylon` to the `pylon-code` organization; GitHub redirects the old path, but use the organization path. - Base Pylon work on `pylon` or a task branch created from it. Do not treat the inherited `main` branch as Pylon's product branch. - `t3code-upstream` (`pingdotgg/t3code`) and `t3code-fork` (`rynfar/t3code`) are reference remotes. They are intentionally fetch-only. Never push to them or re-enable their push URLs. - Upstream changes are opt-in. Fetch and inspect upstream commits, then cherry-pick or selectively merge only changes that benefit Pylon. Do not hard-reset, wholesale rebase, or replace Pylon with an upstream branch. diff --git a/docs/operations/mobile-app-store-screenshots.md b/docs/operations/mobile-app-store-screenshots.md index c6c78b1ed..3ad754006 100644 --- a/docs/operations/mobile-app-store-screenshots.md +++ b/docs/operations/mobile-app-store-screenshots.md @@ -104,9 +104,9 @@ appearance settings can never drift apart. Run the `Mobile Showcase Screenshots` workflow from GitHub's Actions tab, choose `all`, `ios`, or `android`, select `light`, `dark`, or `both`, and pick a palette (or `all`, which raises each job's timeout from 60 to 300 minutes). The default dispatch captures both appearances of the `t3-code` -palette and runs iOS and Android concurrently: iPhone and iPad capture on a -12-vCPU Blacksmith macOS runner, while Android phone, 7-inch tablet, and 10-inch tablet capture on a -16-vCPU Blacksmith Linux runner with a KVM-accelerated x86_64 emulator. +palette and runs iOS and Android concurrently: iPhone and iPad capture on a GitHub-hosted +`macos-26` runner, while Android phone, 7-inch tablet, and 10-inch tablet capture on a GitHub-hosted +`ubuntu-24.04` runner with a KVM-accelerated x86_64 emulator. Every job uploads its PNGs even when capture fails, which makes partial runs useful for diagnosis. The separate validation step is success-gated: it runs before upload only when capture succeeds. If diff --git a/docs/operations/release.md b/docs/operations/release.md index a526ffd82..9802eb545 100644 --- a/docs/operations/release.md +++ b/docs/operations/release.md @@ -72,22 +72,21 @@ Release App installation. ## Runners -Every job runs on Blacksmith runners, which requires the Blacksmith app installed on the -`pylon-code` organization — Blacksmith does not support personal accounts. +Every job runs on GitHub-hosted standard runners: `ubuntu-24.04`, `windows-2025`, and `macos-26` +(Apple Silicon; the x64 desktop leg cross-builds on it). Standard runners are free on public +repositories, which is the reason this repository is public. Larger tiers (`-large`, `-xlarge`) and +third-party runner providers are billed regardless of visibility, so do not move a job onto one +without accepting the cost. The workflows ran on Blacksmith until August 2026; switching providers +is a pure `runs-on` label swap with no other change required. -Tiers are deliberately conservative: `blacksmith-8vcpu-ubuntu-2404`, `blacksmith-8vcpu-windows-2025`, -and `blacksmith-6vcpu-macos-26`. Blacksmith's documentation only evidences these sizes, and **an -unavailable tier does not fail the job — it queues until GitHub's 24-hour limit kills it.** That -silent hang is the single most confusing failure this workflow can produce, so raise a tier only -after confirming the plan grants it, and watch the first run after any change. +**An unknown or unavailable label does not fail the job — it queues until GitHub's 24-hour limit +kills it.** That silent hang is the single most confusing failure this workflow can produce, so +watch the first run after any label change. Job timeouts are generous for the same reason a ceiling is cheap: preflight runs the whole repository's check, typecheck, and test suites, and the build matrix packages Electron plus a Rust target with the macOS legs cross-building a second architecture. -Switching back to GitHub-hosted runners is a pure label swap — `ubuntu-24.04`, `windows-2025`, -`macos-26` — with no other change required. - ## Pylon Connect relay deployment The relay is a shared control plane versioned separately from client releases. Stable and nightly diff --git a/scripts/mobile-showcase.config.ts b/scripts/mobile-showcase.config.ts index 45a9f474f..a21ee760b 100644 --- a/scripts/mobile-showcase.config.ts +++ b/scripts/mobile-showcase.config.ts @@ -158,7 +158,7 @@ const config: ShowcaseConfig = { platform: "android", avd: "Pixel_10_Pro", // Apple Silicon uses ARM64 locally; CI overrides this with x86_64 so its - // Blacksmith Linux runner can use KVM acceleration. + // Linux runner can use KVM acceleration. abi: resolveShowcaseAndroidAbi(process.env.T3_SHOWCASE_ANDROID_ABI), appearance: "dark", theme: DEFAULT_SHOWCASE_THEME,