authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-10-05 19:53:50-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-05 19:53:50-07:00
log18c1210810cbdb798d28edda1826fa4de91992d1
treea528dddfdcc9ce593609993fb069f15d0dddfb76
parent9c49228f5425f644cff9b41ae88ca564d40d79fa
signature Signed by PGP key B5690EEEBB952194

fix(relay): stop forcing manual relay deploys by default (#13563)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

2 files changed, 16 insertions(+), 15 deletions(-)

.github/workflows/deploy-relay.yml+5-5
...@@ -4,15 +4,15 @@ on:...@@ -4,15 +4,15 @@ on:
4 push:4 push:
5 branches:5 branches:
6 - main6 - main
7 # Alchemy does not redeploy the Worker when only a Config value read in its7 # Redeploys main after a variable or secret change. Alchemy redeploys the
8 # Init changes (alchemy-run/alchemy#1831), so a changed repository variable8 # Worker when a value it reads changes, so force is rarely needed, and it
9 # needs a forced deploy to reach production.9 # replaces the Postgres runtime role (alchemy-run/alchemy#1832).
10 workflow_dispatch:10 workflow_dispatch:
11 inputs:11 inputs:
12 force:12 force:
13 description: Redeploy every resource, including ones with no detected changes13 description: Redeploy every resource, including ones with no detected changes. Replaces the Postgres runtime role.
14 type: boolean14 type: boolean
15 default: true15 default: false
1616
17permissions:17permissions:
18 contents: read18 contents: read
docs/operations/release.md+11-10
...@@ -140,10 +140,11 @@ Required `production` environment secrets:...@@ -140,10 +140,11 @@ Required `production` environment secrets:
140- `CLERK_SECRET_KEY`140- `CLERK_SECRET_KEY`
141- `APNS_PRIVATE_KEY`141- `APNS_PRIVATE_KEY`
142142
143The relay Worker reads these variables and secrets when it is deployed. Alchemy does not redeploy the143After changing a variable or secret, run the **Deploy T3 Connect relay** workflow manually from
144Worker when only one of these values changes ([alchemy-run/alchemy#1831](https://github.com/alchemy-run/alchemy/issues/1831)),144`main` with **force** unchecked. Alchemy compares the values the Worker reads and redeploys it when
145so a push to `main` without relay code changes leaves the old value in place. After changing one, run145one changed. Check **force** only to redeploy resources with no detected change: a forced run also
146the **Deploy T3 Connect relay** workflow manually from `main` with **force** checked.146replaces the Postgres runtime role and its password
147([alchemy-run/alchemy#1832](https://github.com/alchemy-run/alchemy/issues/1832)).
147148
148The account-scoped repository credentials are consumed by Alchemy while provisioning relay stages; they149The account-scoped repository credentials are consumed by Alchemy while provisioning relay stages; they
149are not bound into the relay Worker. The production deployment uses an Axiom personal access token,150are not bound into the relay Worker. The production deployment uses an Axiom personal access token,
...@@ -168,7 +169,7 @@ because those builds register recovery and replace a deleted tunnel after wake....@@ -168,7 +169,7 @@ because those builds register recovery and replace a deleted tunnel after wake.
1681. Deploy the relay and migration with cleanup `off`.1691. Deploy the relay and migration with cleanup `off`.
1692. Release the server build and confirm current hosts register recovery. Older hosts stay marked1702. Release the server build and confirm current hosts register recovery. Older hosts stay marked
170 legacy and are never candidates.171 legacy and are never candidates.
1713. Set `dry-run`, run a forced relay deploy, and read the sweep counters (`scanned`, `wouldDelete`,1723. Set `dry-run`, run a relay deploy, and read the sweep counters (`scanned`, `wouldDelete`,
172 `skippedLegacy`, `skippedOrphan`, `failed`, `truncated`) across several sweeps. Each sweep records173 `skippedLegacy`, `skippedOrphan`, `failed`, `truncated`) across several sweeps. Each sweep records
173 them, and the active `mode`, as `relay.managed_endpoint_reaper.*` attributes on its174 them, and the active `mode`, as `relay.managed_endpoint_reaper.*` attributes on its
174 `relay.managed_endpoint_reaper.sweep` span in Axiom.175 `relay.managed_endpoint_reaper.sweep` span in Axiom.
...@@ -178,10 +179,10 @@ because those builds register recovery and replace a deleted tunnel after wake....@@ -178,10 +179,10 @@ because those builds register recovery and replace a deleted tunnel after wake.
178The job runs every five minutes with a five-minute grace period for tunnels that lost their179The job runs every five minutes with a five-minute grace period for tunnels that lost their
179connector, so a candidate is usually removed five to ten minutes after it goes down. Tunnels that180connector, so a candidate is usually removed five to ten minutes after it goes down. Tunnels that
180never connected wait an hour. One sweep attempts at most 100 deletions, so a backlog takes longer.181never connected wait an hour. One sweep attempts at most 100 deletions, so a backlog takes longer.
181Changing `RELAY_TUNNEL_CLEANUP_MODE`, including turning cleanup off during an incident, needs a forced182Changing `RELAY_TUNNEL_CLEANUP_MODE`, including turning cleanup off during an incident, needs a relay
182relay deploy. Confirm the new `mode` on the next sweep span.183deploy without force. Confirm the new `mode` on the next sweep span.
183184
184To roll back, set cleanup to `off` and run a forced relay deploy before downgrading any host. Keep the185To roll back, set cleanup to `off` and run a relay deploy before downgrading any host. Keep the
185recovery endpoints deployed while current server builds are in use. The nullable columns can stay.186recovery endpoints deployed while current server builds are in use. The nullable columns can stay.
186187
187### Disposable-host canary188### Disposable-host canary
...@@ -201,8 +202,8 @@ stage, test Cloudflare account, disposable host, and disposable T3 home. Keep pr...@@ -201,8 +202,8 @@ stage, test Cloudflare account, disposable host, and disposable T3 home. Keep pr
201 and pause it with `kill -STOP <first-pid>`. Wait until Cloudflare reports it down for over five202 and pause it with `kill -STOP <first-pid>`. Wait until Cloudflare reports it down for over five
202 minutes.203 minutes.
2035. Confirm dry-run counts the first tunnel in `wouldDelete` and the second in `skippedLegacy`.2045. Confirm dry-run counts the first tunnel in `wouldDelete` and the second in `skippedLegacy`.
2046. Set cleanup `enabled` on the disposable stage and deploy it with `--force`. Confirm in the test2056. Set cleanup `enabled` on the disposable stage and deploy. Confirm in the test Cloudflare account
205 Cloudflare account that the first tunnel is deleted and the legacy tunnel still exists.206 that the first tunnel is deleted and the legacy tunnel still exists.
2067. Resume the first child with `kill -CONT <first-pid>`. Confirm the running server detects the2077. Resume the first child with `kill -CONT <first-pid>`. Confirm the running server detects the
207 repeated rejection, requests recovery, and becomes reachable at the same hostname without a208 repeated rejection, requests recovery, and becomes reachable at the same hostname without a
208 restart.209 restart.