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

GET /api/v1/repos/:owner/:name/builds/:label/shots/looks carries an ETag and answers a repeat with 304 until a new look of the pin's commit is taken #9289

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`GET /api/v1/repos/:owner/:name/builds/:label/shots/looks` now carries a weak ETag, and a repeat that holds it gets a 304 with no body. `bun scripts/gate.ts` printed nothing, `bun x tsc --noEmit` is clean, and `test/build-shots.test.ts` passes (13 tests). I did not run the full suite.

shipped production is serving it deploy 9e69a5f

opened this

GET /api/v1/repos/:owner/:name/builds/:label/shots/looks now carries a weak ETag, and a repeat that holds it gets a 304 with no body. bun scripts/gate.ts printed nothing, bun x tsc --noEmit is clean, and test/build-shots.test.ts passes (13 tests). I did not run the full suite.

  • Change: the handler in src/http/api/build_shots.ts follows the same shape as GET …/builds. It hashes the JSON it would send with weakEtag, and answers 304 when If-None-Match holds the tag.
  • Per-viewer tag: the hash is taken after the mayFetchLook filter. A viewer who may fetch fewer looks therefore gets a different tag.
  • Headers: the response carries cache-control: private, no-cache and vary: authorization, cookie. The server appends Accept-Encoding to vary, so the header actually reads authorization, cookie, Accept-Encoding. The test checks that it contains authorization, cookie.
  • Test: the new test in test/build-shots.test.ts checks that the first GET has the tag and headers, that a repeat returns an empty 304, and that recording a new look for the pin's commit returns 200 with a different tag. The ETag block is the only code the new test depends on, so it fails without the change.
  • Test placement: I put the new test after the "picks screenshots" test, because recording an extra look earlier changes the ids the later pick test expects.

I did not add a test for the viewer-filter case (a viewer who may fetch fewer looks gets a different tag). It holds because the filter runs before the hash, but nothing tests it.

#9276 edits this file for the sibling route, so whichever of the two lands second will need a rebase.

Closes #9282

commented

GET /api/v1/repos/:owner/:name/builds/:label/shots/looks now carries a weak ETag, and a repeat that holds it gets a 304 with no body. bun scripts/gate.ts printed nothing, bun x tsc --noEmit is clean, and test/build-shots.test.ts passes (13 tests). I did not run the full suite.

  • Change: the handler in src/http/api/build_shots.ts follows the same shape as GET …/builds. It hashes the JSON it would send with weakEtag, and answers 304 when If-None-Match holds the tag.
  • Per-viewer tag: the hash is taken after the mayFetchLook filter. A viewer who may fetch fewer looks therefore gets a different tag.
  • Headers: the response carries cache-control: private, no-cache and vary: authorization, cookie. The server appends Accept-Encoding to vary, so the header actually reads authorization, cookie, Accept-Encoding. The test checks that it contains authorization, cookie.
  • Test: the new test in test/build-shots.test.ts checks that the first GET has the tag and headers, that a repeat returns an empty 304, and that recording a new look for the pin's commit returns 200 with a different tag. The ETag block is the only code the new test depends on, so it fails without the change.
  • Test placement: I put the new test after the "picks screenshots" test, because recording an extra look earlier changes the ids the later pick test expects.

I did not add a test for the viewer-filter case (a viewer who may fetch fewer looks gets a different tag). It holds because the filter runs before the hash, but nothing tests it.

#9276 edits this file for the sibling route, so whichever of the two lands second will need a rebase.

commented

GET /api/v1/repos/:owner/:name/builds/:label/shots/looks now carries a weak ETag. A repeat request that sends it in If-None-Match gets an empty 304 with the same headers. The code is unchanged since the first push.

The gate rejected the pull because no commit message had a Try: line. I added an empty commit whose message carries one and pushed it as a normal push. I did not re-run bun scripts/gate.ts or the tests after this push, so the new check run is the first confirmation. The earlier local run of test/build-shots.test.ts passed, and bun x tsc --noEmit was clean.

  • What changed: src/http/api/build_shots.ts hashes the JSON it would send, after the mayFetchLook filter, with weakEtag. A viewer who may fetch fewer looks gets a different tag. It sends cache-control: private, no-cache and vary: authorization, cookie. The server also appends Accept-Encoding to vary.
  • Test: test/build-shots.test.ts checks the tag and headers, then a repeat that gets a 304. After a new look is recorded for the pin's commit, the same tag gets a 200 with a new tag. I did not add a test for the viewer-filter case.
  • Try it: curl -si -H 'authorization: Bearer <token>' https://lab--9289--forge-trevato-apps.open-platform.sh/api/v1/repos/<owner>/<name>/builds/<label>/shots/looks. Then repeat it with If-None-Match set to the returned etag and expect 304.
  • Conflict risk: #9276 edits the same file for the sibling route, so whichever lands second needs a rebase.
commented

GET …/builds/:label/shots/looks now carries a weak ETag and answers a repeat that holds it with a 304. The last check failed on a duplicate import, and I've fixed that and pushed again.

I rebased by merging main into the branch. #9276 had already landed and added the same etag.ts import to src/http/api/build_shots.ts, so the file imported holds and weakEtag twice. I deleted the extra line. bun x tsc --noEmit is clean and test/build-shots.test.ts passes (14 tests). I did not run the gate script or the rest of the suite here.

  • Change: the route sets etag, cache-control: private, no-cache and vary: authorization, cookie. The tag is taken over the JSON after the mayFetchLook filter, so a viewer who may fetch fewer looks gets a different tag. The server also appends Accept-Encoding to vary.
  • Tests: the new test in test/build-shots.test.ts checks that a repeat gets a 304. It also checks that recording a new look for the pin's commit gives a 200 with a new tag. There is no test of the viewer-filter case.
  • Try it: GET /api/v1/repos/<owner>/<name>/builds/<label>/shots/looks on the preview with a bearer token, then repeat it with If-None-Match set to the returned etag and expect 304.
Changes requested — before the latest push

The route change is correct and the preview serves ETags. One thing to fix: box 2 (a viewer who may fetch fewer looks gets a different tag) is behaviour this pull adds, and nothing tests it. The filter by mayFetchLook sits inside the hash, so a regression that hashed before filtering would pass the suite. Add a test: record a look that alice may fetch and bob may not (or the reverse), then assert the two tags differ and that bob's tag does not match alice's If-None-Match (200, not 304). Also drop the needless reorder of the Handler import in build_shots.ts, which is unrelated churn. Box 1 and box 3 are met.

the crew's run was interrupted: restart, resumes on the next pass — cancelled
commented

Both items are already in commit 16713a8e on the branch, and the pull's head is that commit. I did not re-run the tests or the type check this turn.

Changes since the last description:

  • Viewer-filter test: a new test in test/build-shots.test.ts covers two viewers with different mayFetchLook results. The looks were taken as the owner, so alice (a writer) may fetch them and bob (a reader) may not.

- Bob gets an empty list and a different ETag from alice. - Bob sending alice's tag in If-None-Match gets a 200, not a 304.

  • Import reorder: reverted. The diff against main no longer touches the Handler/etag import lines in src/http/api/build_shots.ts.
  • Code change: GET …/builds/:label/shots/looks hashes the JSON it would send, after the mayFetchLook filter. It sends etag, cache-control: private, no-cache and vary: authorization, cookie. A repeat that holds the tag gets an empty 304. The server also appends Accept-Encoding to vary.

I made no other changes.

To try it, GET /api/v1/repos/<owner>/<name>/builds/<label>/shots/looks on the preview with a bearer token. Repeat it with If-None-Match set to the returned etag and expect 304. Taking a new look of the pin's commit then gives a 200 with a new tag.

Closes #9282

🤖 Generated with Claude Code

Approved

The earlier ask, a test for the per-viewer filter, is met: alice gets items, bob gets [] with a different tag, and bob sending alice's tag gets 200. The route hashes the filtered JSON, sets etag, cache-control private, no-cache and vary authorization, cookie, and answers 304 on a held tag. The preview answers 200 on /. I read the diff only; I did not run the tests.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs