Skip to content
Merged
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
20 changes: 19 additions & 1 deletion .github/workflows/deploy-relay.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read
Expand All @@ -17,7 +18,6 @@ concurrency:
jobs:
deploy_relay:
name: Deploy production relay
if: github.repository == 'pingdotgg/t3code'
runs-on: ubuntu-24.04
timeout-minutes: 15
environment:
Expand All @@ -37,7 +37,22 @@ jobs:
APNS_BUNDLE_ID: ${{ vars.APNS_BUNDLE_ID }}
ALCHEMY_TELEMETRY_DISABLED: "1"
steps:
- id: cloudflare_config
name: Detect Cloudflare configuration
shell: bash
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
run: |
if [[ -n "${CLOUDFLARE_ACCOUNT_ID:-}" && -n "${CLOUDFLARE_API_TOKEN:-}" ]]; then
echo "enabled=true" >> "$GITHUB_OUTPUT"
exit 0
fi

echo "enabled=false" >> "$GITHUB_OUTPUT"
echo "::notice::Relay deployment skipped because Cloudflare credentials are not configured."

- name: Checkout
if: steps.cloudflare_config.outputs.enabled == 'true'
uses: actions/checkout@v6
with:
sparse-checkout: |
Expand All @@ -46,6 +61,7 @@ jobs:
sparse-checkout-cone-mode: false

- name: Setup Vite+
if: steps.cloudflare_config.outputs.enabled == 'true'
uses: voidzero-dev/setup-vp@v1
with:
node-version-file: package.json
Expand All @@ -55,6 +71,7 @@ jobs:
- --filter=t3code-relay...

- name: Deploy production relay stage
if: steps.cloudflare_config.outputs.enabled == 'true'
id: deploy
run: vp run --filter t3code-relay deploy --stage prod --yes --github-output
env:
Expand All @@ -66,6 +83,7 @@ jobs:
APNS_PRIVATE_KEY: ${{ secrets.APNS_PRIVATE_KEY }}

- name: Publish relay deploy commit status
if: steps.cloudflare_config.outputs.enabled == 'true'
uses: actions/github-script@v8
with:
script: |
Expand Down
88 changes: 70 additions & 18 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ jobs:
is_prerelease: ${{ steps.release_meta.outputs.is_prerelease }}
make_latest: ${{ steps.release_meta.outputs.make_latest }}
ref: ${{ github.sha }}
connect_enabled: ${{ steps.connect_config.outputs.enabled }}
steps:
- name: Checkout
uses: actions/checkout@v6
Expand Down Expand Up @@ -174,10 +175,25 @@ jobs:
--current-tag "${{ steps.release_meta.outputs.tag }}" \
--github-output

- id: connect_config
name: Detect T3 Connect configuration
shell: bash
env:
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
run: |
if [[ -n "${CLOUDFLARE_ACCOUNT_ID:-}" && -n "${CLOUDFLARE_API_TOKEN:-}" ]]; then
echo "enabled=true" >> "$GITHUB_OUTPUT"
exit 0
fi

echo "enabled=false" >> "$GITHUB_OUTPUT"
echo "::notice::T3 Connect public config is disabled because Cloudflare credentials are not configured."

relay_public_config:
name: Resolve T3 Connect public config
needs: preflight
if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' }}
if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' && needs.preflight.outputs.connect_enabled == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 5
environment:
Expand Down Expand Up @@ -324,16 +340,25 @@ jobs:
# build_wsl_node_pty, so a failed Linux prebuild doesn't skip the macOS/Linux
# builds. `!cancelled()` (not `!failure()`) lets the job run even when
# build_wsl_node_pty failed; the Windows-only download step below then fails
# that single platform if the prebuild is missing.
# that single platform if the prebuild is missing. A skipped relay config is
# also valid when this repository has not enabled T3 Connect.
needs: [preflight, relay_public_config, build_wsl_node_pty]
if: ${{ !cancelled() && needs.preflight.result == 'success' && needs.relay_public_config.result == 'success' }}
if: >-
${{
!cancelled() &&
needs.preflight.result == 'success' &&
(
(needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.result == 'success') ||
(needs.preflight.outputs.connect_enabled != 'true' && needs.relay_public_config.result == 'skipped')
)
}}
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
env:
T3CODE_CLERK_PUBLISHABLE_KEY: ${{ needs.relay_public_config.outputs.clerk_publishable_key }}
T3CODE_CLERK_JWT_TEMPLATE: ${{ needs.relay_public_config.outputs.clerk_jwt_template }}
T3CODE_CLERK_CLI_OAUTH_CLIENT_ID: ${{ needs.relay_public_config.outputs.clerk_cli_oauth_client_id }}
T3CODE_RELAY_URL: ${{ needs.relay_public_config.outputs.relay_url }}
T3CODE_CLERK_PUBLISHABLE_KEY: ${{ needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.outputs.clerk_publishable_key || '' }}
T3CODE_CLERK_JWT_TEMPLATE: ${{ needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.outputs.clerk_jwt_template || '' }}
T3CODE_CLERK_CLI_OAUTH_CLIENT_ID: ${{ needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.outputs.clerk_cli_oauth_client_id || '' }}
T3CODE_RELAY_URL: ${{ needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.outputs.relay_url || '' }}
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -398,12 +423,14 @@ jobs:
targets: ${{ matrix.rust_target }}

- name: Download relay client tracing config
if: needs.preflight.outputs.connect_enabled == 'true'
uses: actions/download-artifact@v8
with:
name: relay-client-tracing-config
path: ${{ runner.temp }}/relay-client-tracing

- name: Load relay client tracing config
if: needs.preflight.outputs.connect_enabled == 'true'
shell: bash
run: |
config_path="$RUNNER_TEMP/relay-client-tracing/relay-client-tracing.env"
Expand Down Expand Up @@ -665,17 +692,26 @@ jobs:
publish_cli:
name: Publish CLI to npm
needs: [preflight, relay_public_config, build]
if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' && needs.relay_public_config.result == 'success' && needs.build.result == 'success' }}
if: >-
${{
!failure() && !cancelled() &&
needs.preflight.result == 'success' &&
needs.build.result == 'success' &&
(
(needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.result == 'success') ||
(needs.preflight.outputs.connect_enabled != 'true' && needs.relay_public_config.result == 'skipped')
)
}}
runs-on: ubuntu-24.04 # ubuntu-24.04
timeout-minutes: 10
permissions:
contents: read
id-token: write
env:
T3CODE_CLERK_PUBLISHABLE_KEY: ${{ needs.relay_public_config.outputs.clerk_publishable_key }}
T3CODE_CLERK_JWT_TEMPLATE: ${{ needs.relay_public_config.outputs.clerk_jwt_template }}
T3CODE_CLERK_CLI_OAUTH_CLIENT_ID: ${{ needs.relay_public_config.outputs.clerk_cli_oauth_client_id }}
T3CODE_RELAY_URL: ${{ needs.relay_public_config.outputs.relay_url }}
T3CODE_CLERK_PUBLISHABLE_KEY: ${{ needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.outputs.clerk_publishable_key || '' }}
T3CODE_CLERK_JWT_TEMPLATE: ${{ needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.outputs.clerk_jwt_template || '' }}
T3CODE_CLERK_CLI_OAUTH_CLIENT_ID: ${{ needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.outputs.clerk_cli_oauth_client_id || '' }}
T3CODE_RELAY_URL: ${{ needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.outputs.relay_url || '' }}
steps:
- name: Checkout
uses: actions/checkout@v6
Expand All @@ -698,12 +734,14 @@ jobs:
- --filter=@t3tools/scripts...

- name: Download relay client tracing config
if: needs.preflight.outputs.connect_enabled == 'true'
uses: actions/download-artifact@v8
with:
name: relay-client-tracing-config
path: ${{ runner.temp }}/relay-client-tracing

- name: Load relay client tracing config
if: needs.preflight.outputs.connect_enabled == 'true'
shell: bash
run: |
config_path="$RUNNER_TEMP/relay-client-tracing/relay-client-tracing.env"
Expand Down Expand Up @@ -865,14 +903,23 @@ jobs:
deploy_web:
name: Deploy hosted web app
needs: [preflight, relay_public_config, release]
if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' && needs.relay_public_config.result == 'success' && needs.release.result == 'success' }}
if: >-
${{
!failure() && !cancelled() &&
needs.preflight.result == 'success' &&
needs.release.result == 'success' &&
(
(needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.result == 'success') ||
(needs.preflight.outputs.connect_enabled != 'true' && needs.relay_public_config.result == 'skipped')
)
}}
runs-on: ubuntu-24.04
timeout-minutes: 10
env:
T3CODE_CLERK_PUBLISHABLE_KEY: ${{ needs.relay_public_config.outputs.clerk_publishable_key }}
T3CODE_CLERK_JWT_TEMPLATE: ${{ needs.relay_public_config.outputs.clerk_jwt_template }}
T3CODE_CLERK_CLI_OAUTH_CLIENT_ID: ${{ needs.relay_public_config.outputs.clerk_cli_oauth_client_id }}
T3CODE_RELAY_URL: ${{ needs.relay_public_config.outputs.relay_url }}
T3CODE_CLERK_PUBLISHABLE_KEY: ${{ needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.outputs.clerk_publishable_key || '' }}
T3CODE_CLERK_JWT_TEMPLATE: ${{ needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.outputs.clerk_jwt_template || '' }}
T3CODE_CLERK_CLI_OAUTH_CLIENT_ID: ${{ needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.outputs.clerk_cli_oauth_client_id || '' }}
T3CODE_RELAY_URL: ${{ needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.outputs.relay_url || '' }}
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
Expand Down Expand Up @@ -901,12 +948,14 @@ jobs:
- --filter=@t3tools/web...

- name: Download relay client tracing config
if: needs.preflight.outputs.connect_enabled == 'true'
uses: actions/download-artifact@v8
with:
name: relay-client-tracing-config
path: ${{ runner.temp }}/relay-client-tracing

- name: Load relay client tracing config
if: needs.preflight.outputs.connect_enabled == 'true'
shell: bash
run: |
config_path="$RUNNER_TEMP/relay-client-tracing/relay-client-tracing.env"
Expand Down Expand Up @@ -1065,7 +1114,10 @@ jobs:
if: |
always() && !cancelled() &&
needs.preflight.result == 'success' &&
needs.relay_public_config.result == 'success' &&
(
(needs.preflight.outputs.connect_enabled == 'true' && needs.relay_public_config.result == 'success') ||
(needs.preflight.outputs.connect_enabled != 'true' && needs.relay_public_config.result == 'skipped')
) &&
needs.release.result == 'success' &&
needs.deploy_web.result == 'success' &&
(needs.finalize.result == 'success' || needs.finalize.result == 'skipped')
Expand Down
11 changes: 8 additions & 3 deletions docs/operations/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ This document covers the unified release workflow for stable and nightly desktop
- scheduled nightly check every three hours
- manual `workflow_dispatch` for either channel
- Runs quality gates first: lint, typecheck, test.
- Reads the shared production T3 Connect relay URL and Clerk client configuration before packaging clients.
- Reads the shared production T3 Connect relay URL and Clerk client configuration before packaging
clients when the repository has enabled Connect; otherwise builds artifacts without Connect.
- Builds four artifacts in parallel for both channels:
- macOS `arm64` DMG
- macOS `x64` DMG
Expand Down Expand Up @@ -46,8 +47,12 @@ them again in the finalize job, which can commit and push aligned package versio
## T3 Connect relay deployment

The relay is a shared control plane versioned separately from client releases. Stable and nightly
client builds must point at the same relay so users see the same linked environments when switching
release channels.
client builds that enable Connect must point at the same relay so users see the same linked
environments when switching release channels. Repositories without Cloudflare credentials skip
relay resolution and build without Connect.

See [Self-host the T3 Connect relay](./self-host-relay.md) for fork setup, Cloudflare token scopes,
first-deploy bootstrap, and release fallback behavior.

`.github/workflows/deploy-relay.yml` deploys Alchemy stage `prod` on every push to `main`. The
release workflow reads the relay URL and Clerk client configuration from the existing `production`
Expand Down
Loading
Loading