Skip to content
Closed
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
25 changes: 25 additions & 0 deletions .github/nix/release-common.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{ repo, version }:

let
flake = builtins.getFlake repo;
pkgs = import flake.inputs.nixpkgs { system = "x86_64-linux"; };
runtime = pkgs.callPackage (flake.outPath + "/nix/package.nix") {
src = flake.outPath;
inherit version;
};
in
runtime.overrideAttrs {
CI = "true";

installPhase = ''
runHook preInstall

mkdir -p "$out/apps/desktop" "$out/apps/server" "$out/wsl-prebuild"
cp -R apps/desktop/dist-electron "$out/apps/desktop/"
cp -R apps/desktop/resources "$out/apps/desktop/"
cp -R apps/server/dist "$out/apps/server/"
cp apps/server/node_modules/node-pty/build/Release/pty.node "$out/wsl-prebuild/"

runHook postInstall
'';
}
193 changes: 94 additions & 99 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
push:
branches:
- main
- "canary/**"

permissions:
contents: read
Expand All @@ -16,8 +17,8 @@ concurrency:
jobs:
check:
name: Check
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 10
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v6
Expand All @@ -43,40 +44,60 @@ jobs:
run-install: true

- name: Ensure Electron runtime is installed
if: github.event_name == 'pull_request'
run: vp run --filter @t3tools/desktop ensure:electron

# Files/dependencies are repo-wide; export checks cover clean workspaces only.
- name: Check unused code
run: vp run knip:check

- name: Check
run: vp check

- name: Typecheck
run: vpr typecheck

- uses: ./.github/actions/setup-apt-mirrors

- name: Install browser secret helper build libraries
run: |
sudo sed -i 's|http://|https://|g' /etc/apt/blacksmith-ubuntu-mirrors.txt /etc/apt/sources.list.d/ubuntu.sources
sudo apt-get update && sudo apt-get install -y libsecret-1-dev pkg-config
if: github.event_name == 'pull_request'
run: sudo apt-get update && sudo apt-get install -y libsecret-1-dev pkg-config

# Release Build Jobs performs this exact build on branch pushes. PRs still
# exercise it here so broken build inputs never reach main.
- name: Build desktop pipeline
if: github.event_name == 'pull_request'
run: vp run build:desktop

- name: Verify preload bundle output
run: node apps/desktop/scripts/verify-preload-bundle.mjs

# Everything except `t3` (apps/server). `--parallel` drops the package
# dependency ordering that `vp run` applies by default: these `test` tasks
# declare no `dependsOn` and resolve workspace deps from source, so ordering
# only bought us idle runners between dependency layers. The concurrency
# limit stays at the default 4 so peak load per runner is unchanged.
test:
name: Test
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 10
if: github.event_name == 'pull_request'
run: |
test -f apps/desktop/dist-electron/preload.cjs
grep -nE "desktopBridge|getLocalEnvironmentBootstrap|PICK_FOLDER_CHANNEL|wsUrl" apps/desktop/dist-electron/preload.cjs
grep -n "__clerk_internal_electron_passkeys" apps/desktop/dist-electron/preload.cjs

test_js:
name: Test shard (${{ matrix.shard }})
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- shard: server 1/3
filters: --filter t3
args: --shard=1/3
artifact_suffix: server-1
- shard: server 2/3
filters: --filter t3
args: --shard=2/3
artifact_suffix: server-2
- shard: server 3/3
filters: --filter t3
args: --shard=3/3
artifact_suffix: server-3
- shard: web
filters: --filter @t3tools/web
- shard: mobile
filters: --filter @t3tools/mobile
- shard: desktop
filters: --filter @t3tools/desktop
- shard: libraries
filters: --filter './packages/*' --filter './scripts' --filter './oxlint-plugin-t3code' --filter './infra/*'
steps:
- name: Checkout
uses: actions/checkout@v6
Expand All @@ -94,104 +115,44 @@ jobs:
run-install: true

- name: Ensure Electron runtime is installed
if: matrix.shard == 'desktop'
run: vp run --filter @t3tools/desktop ensure:electron

- uses: ./.github/actions/setup-apt-mirrors

- name: Install browser secret helper build libraries
run: |
sudo sed -i 's|http://|https://|g' /etc/apt/blacksmith-ubuntu-mirrors.txt /etc/apt/sources.list.d/ubuntu.sources
sudo apt-get update && sudo apt-get install -y libsecret-1-dev pkg-config

- name: Test nightly release checks
run: node --test .github/scripts/check-nightly-release.test.cjs

- name: Test
run: vp run --parallel --concurrency-limit 4 --filter '!t3' --filter '!@t3tools/monorepo' test

# apps/server sets `fileParallelism: false`, so its 239 files run strictly
# one at a time. Sharding spreads them over separate runners instead of
# separate workers, so no two server test files ever share a machine and the
# isolation that flag buys is preserved exactly.
test_server:
name: Test Server ${{ matrix.shard }}
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3]
steps:
- name: Checkout
uses: actions/checkout@v6
with:
sparse-checkout: |
/*
!/.repos/
sparse-checkout-cone-mode: false

- name: Setup Vite+
uses: voidzero-dev/setup-vp@v1
with:
node-version-file: package.json
cache: true
run-install: true
if: matrix.shard == 'desktop'
run: sudo apt-get update && sudo apt-get install -y libsecret-1-dev pkg-config

# No Electron setup here: `t3` (apps/server) has no Electron dependency
# and none of its tests touch the runtime. Only the non-server `test`
# job, which covers @t3tools/desktop, needs the download.
- name: Test
- name: Test ${{ matrix.shard }}
env:
T3CODE_TRANSFER_BUDGET_REPORT_PATH: ${{ runner.temp }}/t3code-transfer-budget.md
T3CODE_TRANSFER_BUDGET_RESULT_PATH: ${{ runner.temp }}/thread-transfer-result.json
run: vp run --filter t3 test --shard ${{ matrix.shard }}/${{ strategy.job-total }}

# src/server.test.ts writes the budget report, so exactly one shard
# produces these files. Gating the upload on their presence keeps a
# single `thread-transfer-results` artifact per run, which is the name
# thread-transfer-report.yml resolves.
- name: Detect transfer budget report
id: transfer_budget
if: always()
run: |
if test -f "${{ runner.temp }}/thread-transfer-result.json"; then
echo "present=true" >> "$GITHUB_OUTPUT"
else
echo "present=false" >> "$GITHUB_OUTPUT"
fi
run: vp run ${{ matrix.filters }} test ${{ matrix.args }}

- name: Publish transfer budget report
if: always() && steps.transfer_budget.outputs.present == 'true'
if: always() && startsWith(matrix.shard, 'server')
run: |
if test -f "${{ runner.temp }}/t3code-transfer-budget.md"; then
tee -a "$GITHUB_STEP_SUMMARY" < "${{ runner.temp }}/t3code-transfer-budget.md"
else
echo "Transfer budget report was not produced." >> "$GITHUB_STEP_SUMMARY"
fi

- name: Upload thread transfer result
if: always() && steps.transfer_budget.outputs.present == 'true'
- name: Upload sharded thread transfer result
if: always() && startsWith(matrix.shard, 'server')
uses: actions/upload-artifact@v7
with:
name: thread-transfer-results
name: thread-transfer-results-${{ matrix.artifact_suffix }}
path: ${{ runner.temp }}/thread-transfer-result.json
if-no-files-found: ignore
retention-days: 30
retention-days: 1

# Split out of Check and Test: both paid ~7-9s to install a Rust toolchain
# for checks that take under 3s, on the critical path of every PR.
rust:
name: Rust
runs-on: blacksmith-4vcpu-ubuntu-2404
test_native:
name: Test shard (resource monitor)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v6
with:
sparse-checkout: |
/*
!/.repos/
sparse-checkout-cone-mode: false
sparse-checkout: native/resource-monitor

- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
Expand All @@ -204,13 +165,47 @@ jobs:
- name: Test resource monitor
run: cargo test --locked --manifest-path native/resource-monitor/Cargo.toml

test:
name: Test
if: always()
needs:
- test_js
- test_native
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- name: Download sharded thread transfer result
if: needs.test_js.result == 'success'
uses: actions/download-artifact@v8
with:
pattern: thread-transfer-results-server-*
merge-multiple: true
path: ${{ runner.temp }}/thread-transfer

- name: Upload thread transfer result
if: needs.test_js.result == 'success'
uses: actions/upload-artifact@v7
with:
name: thread-transfer-results
path: ${{ runner.temp }}/thread-transfer/thread-transfer-result.json
if-no-files-found: error
retention-days: 30

- name: Check shard results
env:
JS_RESULT: ${{ needs.test_js.result }}
NATIVE_RESULT: ${{ needs.test_native.result }}
run: |
test "$JS_RESULT" = success
test "$NATIVE_RESULT" = success

# The static analysis below needs a macOS runner, which bills ~6.7x a Linux
# minute, so gate it on the native sources it actually lints instead of paying
# for it on every push. Detection is API-only (no checkout) and fails open: if
# the diff cannot be resolved, the lint runs.
mobile_native_changes:
name: Mobile Native Changes
runs-on: blacksmith-2vcpu-ubuntu-2404
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
Expand Down Expand Up @@ -288,7 +283,7 @@ jobs:
# Skip only on an explicit "no": a gate job that failed or errored leaves the
# output empty, and that must run the lint rather than silently skip it.
if: ${{ !cancelled() && needs.mobile_native_changes.outputs.changed != 'false' }}
runs-on: blacksmith-6vcpu-macos-26
runs-on: macos-15
timeout-minutes: 10
steps:
- name: Checkout
Expand Down Expand Up @@ -316,7 +311,7 @@ jobs:

release_smoke:
name: Release Smoke
runs-on: blacksmith-8vcpu-ubuntu-2404
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/deploy-relay.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ concurrency:
jobs:
deploy_relay:
name: Deploy production relay
runs-on: blacksmith-8vcpu-ubuntu-2404
if: ${{ false }} # Disabled for the fork: no production relay deployment.
runs-on: ubuntu-latest
timeout-minutes: 15
environment:
name: production
Expand Down
72 changes: 72 additions & 0 deletions .github/workflows/history-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: History validation

on:
push:
branches:
- main
- "canary/**"
pull_request:
types: [opened, synchronize, labeled, unlabeled, ready_for_review]
workflow_dispatch:
inputs:
base_ref:
description: "Fork history base branch"
required: false
default: upstream/main
type: string

permissions:
contents: read

jobs:
validate:
name: History / validate
if: >-
github.event_name == 'push' ||
github.event_name == 'workflow_dispatch' ||
contains(github.event.pull_request.labels.*.name, 'actualization') ||
contains(github.event.pull_request.labels.*.name, 'release')
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha || github.sha }}

- name: Fetch history base
env:
EVENT_NAME: ${{ github.event_name }}
REF_NAME: ${{ github.ref_name }}
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
DISPATCH_BASE_REF: ${{ inputs.base_ref }}
run: |
set -euo pipefail
if [[ "$REF_NAME" == canary/* ]]; then
upstream_branch="t3code/${REF_NAME#canary/}"
git fetch --no-tags https://github.com/pingdotgg/t3code.git \
"$upstream_branch:refs/remotes/upstream/$upstream_branch"
echo "HISTORY_BASE_REF=refs/remotes/upstream/$upstream_branch" >> "$GITHUB_ENV"
exit 0
elif [[ "$EVENT_NAME" == pull_request ]]; then
base_ref="$PR_BASE_REF"
elif [[ -n "$DISPATCH_BASE_REF" ]]; then
base_ref="$DISPATCH_BASE_REF"
else
base_ref=upstream/main
fi
git fetch --no-tags origin "$base_ref:refs/remotes/origin/$base_ref"
echo "HISTORY_BASE_REF=refs/remotes/origin/$base_ref" >> "$GITHUB_ENV"

- name: Setup Vite+
uses: voidzero-dev/setup-vp@v1
with:
node-version-file: package.json
cache: true
run-install: |
args:
- --filter=@t3tools/scripts...

- name: Validate fork history
run: node scripts/validate-fork-history.ts --ref HEAD --upstream-ref "$HISTORY_BASE_REF"
Loading
Loading