[build-tools] Add worker-side SSH session helper - #4030
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4030 +/- ##
==========================================
+ Coverage 63.74% 63.95% +0.21%
==========================================
Files 1030 1033 +3
Lines 47477 47747 +270
Branches 9990 10043 +53
==========================================
+ Hits 30260 30530 +270
Misses 17116 17116
Partials 101 101 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
72fb902 to
25fb902
Compare
a7b6154 to
c9e54b9
Compare
25fb902 to
19047e6
Compare
c9e54b9 to
12f0a14
Compare
19047e6 to
1277e59
Compare
12f0a14 to
12feb7a
Compare
1277e59 to
1c822ac
Compare
cb90fa2 to
9409c52
Compare
1c822ac to
45758d8
Compare
9409c52 to
daee76d
Compare
45758d8 to
3906608
Compare
daee76d to
7154d05
Compare
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
420bbef to
3dc29fa
Compare
🤖 AI code reviewDecision: Request changes Overall PR risk: Low. The change is additive: it introduces a new SSH relay session helper (upterm host spawn, GraphQL session registration, redial/idle supervision) without editing any existing function body, and the cross-cutting review found no caller in this diff wiring the new helper into an existing build or job-run path, so the new code stays inert until a later change calls it. The most serious verified issue is a critical secret-leak path: 🔴 Critical (1)
🟡 Warning (2)
This review is advisory — it never blocks a merge and never auto-approves. |
6973f85 to
0a7a451
Compare
2e5bca4 to
61e8f23
Compare
| if (connectedClientCount !== null) { | ||
| if (connectedClientCount > previousClientCount) { | ||
| logger.info( | ||
| connectedClientCount === 1 | ||
| ? 'An SSH client connected.' | ||
| : `An SSH client connected (${connectedClientCount} connected).` | ||
| ); | ||
| } else if (connectedClientCount < previousClientCount) { | ||
| logger.info( | ||
| connectedClientCount === 0 | ||
| ? 'The SSH client disconnected.' | ||
| : `An SSH client disconnected (${connectedClientCount} still connected).` | ||
| ); | ||
| } | ||
| previousClientCount = connectedClientCount; | ||
| } |
There was a problem hiding this comment.
this feels slightly misleading cause ti may happen that a user disconnects and another connects and we won't print anything because the count is still 1
There was a problem hiding this comment.
Good point,, but the limitation is that upterm session current --output json only hands back a count, it does len(connected_clients) server-side and drops the list, so from the worker a 1-for-1 swap looks identical to a steady connection.
To log real join/leave events I think I can read upterm's connected_clients (they carry a public-key fingerprint) off its gRPC admin api instead of the CLI. I might defer now as a known limitation and go for a follow-up if that works for you?
b862057 to
db1ab53
Compare
|
Applied changes but want to do a little more testing before requesting review. |
| turtleJobRunId: target.turtleJobRunId ?? null, | ||
| turtleBuildId: target.turtleBuildId ?? null, |
There was a problem hiding this comment.
just sharing -- what i recently did for logs was https://github.com/expo/universe/blob/1ae9b878798169e2de9e05af590e549061aa2f51/server/www/src/graphql/mutations/RealtimeLogsMutation.ts#L26-L34
i think it works nicely
There was a problem hiding this comment.
Hm... that's a good one, I think I do prefer your way 🤔 (baking a change)
There was a problem hiding this comment.
Update connectionConfig on every redial, linearize ensureConnectedAsync, and parse upterm session objects without a JSON stringify round-trip.
Invalid upterm host URLs, missing process pid, stdout chunks, unknown client counts during the job, and turtleBuild targets.
…w fixes Zod-parse upterm session JSON and move isChildProcessAlive into processes.ts (claimed in review but never landed). Expand unit coverage and stop gitignoring baked upterm binaries now that the worker fetches from GCS.
Restore the orphaned review-fix tip: prefer an image/PATH upterm, else download darwin-arm64 / linux-amd64 from gs://turtle-v2/upterm. Keeps the stricter zod session parse, process-group/admin-socket comments, and GCS cache/path unit coverage.
e675651 to
01bf840
Compare
|
✅ Thank you for adding the changelog entry! |

Why
The worker needs a piece that starts an SSH session on the build VM and keeps the worker alive while someone is connected.
How
New helper resolves the upterm client vendored in the worker package, dials the relay, reports the connection details back so the CLI can attach, and holds on an idle timer. Redialing is capped at a few attempts per drop so a flapping relay can't retry forever. Connection secrets are scrubbed from logs.
Test Plan
Unit tests cover the connection parsing, secret redaction, process-liveness detection, the capped redial, and the idle hold. CI passes.