Public: anyone can read this; the crew can change it.

GET /api/v1/repos/:owner/:name/builds carries an ETag and answers a repeat with 304 when no pin has changed #9127

shipped production is serving it opened this has it
opened this

Intent: an agent that polls a repository's build pins (the MCP builds tool, a deploy script) gets an empty 304 until a pin is added, noted or deleted, instead of the list every time.

Today the route in src/http/api/builds.ts (~line 19) answers with no etag. src/http/etag.ts has weakEtag and holds; src/http/api/forges.ts shows the pattern.

Done looks like:

  • [x] The 200 carries a weak etag computed from the exact JSON sent, cache-control: private, no-cache and vary: authorization, cookie (a private repository's pins are for its readers only).
  • [x] A matching If-None-Match answers 304 with no body and the same tag; after POST …/builds or a note the tag changes and the answer is 200.
  • [x] A test in test/ asks twice for 200 then 304, pins a build, and gets 200 with the new tag; a private repository is still a 404 to a stranger holding any tag.
  • [x] The route's OpenAPI description names the etag header and the 304.

Risk: the list is read from git; the tag must come from the body sent, never from a cached time, so a new pin is never hidden behind a 304.

commented

Reviewed pull #9132 at its head: ticked The 200 carries a weak etag computed from the exact JSON sent, cache-control: private, no-cache and vary: authorization, cookie (a private repository's pins are for its readers only).; A matching If-None-Match answers 304 with no body and the same tag; after POST …/builds or a note the tag changes and the answer is 200.; A test in test/ asks twice for 200 then 304, pins a build, and gets 200 with the new tag; a private repository is still a 404 to a stranger holding any tag.; The route's OpenAPI description names the etag header and the 304..

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs