Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

actions/checkout's fetches from g1t.sh go to the repos service over g1t's network, with the real action #285

Mergedsyntaqx merged 239-checkout-internal-git into main
syntaqxopened this pull request

Closes #239. Replaces #276, which reimplemented actions/checkout in the runner; this keeps the real action and moves only where its git goes.

Mechanism

The runner Worker intercepts the sandbox's HTTPS to g1t.sh itself. A sandbox already passes its traffic through the Worker once any of it is intercepted (interceptHttps, the abuse host), and it already trusts the re-signing certificate, so nothing inside the sandbox changes:

  • Jobs whose other requests go straight out get a new git outbound handler for g1t.sh (setOutboundByHost); brokered jobs reach the same code through egress.
  • A signed-in git-upload-pack request (info/refs?service=git-upload-pack or the POST) is handed to the repos service over its binding, exactly as the website's front door does (proxyGit), and the answer streams back, never buffered (unlike forward's 8 MB read of a replayable answer). The repos service authorizes it as any clone and answers from the git edge.
  • origin stays https://g1t.sh/<owner>/<repo> and the action's http.https://g1t.sh/.extraheader is sent as it is, so the token reaching the repos service is the action's own, and later git fetch/git push in the job work as before. No insteadOf, no extra config, no token injected by the Worker.

I chose this over url.insteadOf to an internal host because the rewritten URL would no longer match the action's extraheader, and putting the credential back would mean the Worker injecting the job's token (a bypass of what the job itself sent).

What stays on the public path

  • Pushes (git-receive-pack): the pack is streamed and cannot be replayed for a fallback.
  • Anonymous clones: the front door counts them by address.
  • Pages, packages and anything else at g1t.sh, unchanged (fetch, as the containers library did; brokered/forward for brokered jobs).
  • A brokered request carrying a stand-in, so it is still filled in.

Fallback

The fetch's small request body (wants and haves) is held; when the repos service throws or answers 5xx, the same request is sent the public way. A 4xx (e.g. 401) is the answer, as it would be on the public path. If the host cannot be routed (setOutboundByHost fails), the job's git goes out as before.

Expected gain

Recent Deploy runs' Run actions/checkout@v5 step: Plan (fetch-depth: 0) 6.6 s on #483, 27.6 s on #481, 34.6 s on #478 (26.5 s of it the fetch); shallow checkouts 3 to 16 s. The full-history variance is the public round trip through the front door plus the egress buffering; on the internal path the pack comes straight from the git edge over the service binding. I could not measure it on a real job since this is not deployed; compare the Plan job's checkout on the first Deploy after merge.

Checked

  • node --test services/runner/src/*.test.ts: 118 pass, including internal-git.test.ts (adapted from #276): what takes the path, the request as handed on, refusals passed through, redirects, fallback on a throw and on 503 with the body intact, and everything else never reaching the repos service.
  • tsc in services/runner and prettier --check on the touched files: clean.
  • Docs: the actions/checkout row in guides/actions.md and the Egress section of architecture/compute.
syntaqxmerged this·

All checks have passed

2 passed · on 58b62fa

Workflows

CI / pull_request — CI passedDetails
Dependency review — No dependency changesDetails

Merged and closed: the branch can be deleted safely

Everything on it is in its base now.

Sign in to comment.