Name the revision a bundle upload collided with #30

Merged
geusebio merged 3 commits from feature/name-the-revision-a-bundle-collided-with into main 2026-08-17 08:19:20 +00:00
Owner

The sc half of the "at minimum" ask in Someones.Computer#792.

BLOCKED on scclient#9

agent/ vendors scclient, so APIError.Collision() does not exist here until go.mod is bumped to a pseudo-version containing that commit and go mod vendor is re-run. The bump is deliberately not in this PR — pinning go.mod at an unmerged branch commit is how a pin ends up on a commit that never lands. Sequence: scclient#9 → bump + re-vendor here → un-draft.

What it does

A refused deploy ended like this:

$ sc deploy
Uploading 3.8 MiB to https://someones.computer…
sc: bundle upload failed: An identical bundle has already been deployed.

The platform had already said which revision the digest matched — number, status and a URL — and sc printed only the message. So the refusal read like a statement about the platform, when what it meant was this tree is already revision #2, and it is running. Now:

sc: bundle upload failed: An identical bundle has already been deployed.

It matches revision #2, which is running.
See it:       https://someones.computer/applications/…/deployments/…
  • The error is returned unchanged, so the exit code and the message are exactly what they were. This only adds the fact that was being dropped.
  • Nothing extra is printed when there is no revision to point at — the other 409 on this API is an ambiguous application slug, which names organizations instead.
  • A URL-less collision still names the revision; only the link is skipped.

Verification

  • go build ./..., go vet ./..., go test ./... clean with the workspace (go.work resolves scclient by path). The vendored build is what fails, per above.
  • Four new tests: the collision is named and linked, the error passes through unchanged, an ambiguous-slug 409 prints nothing, a plain transport error is not inspected as an *APIError, and a collision without a URL still names the revision.
  • Coverage ratchet holds and rose: internal/cli 81.5% against a floor of 80.7%. coverage.floor not bumped — the figures are Linux numbers and this run is macOS.

Note

After Someones.Computer#820 lands, this 409 no longer fires for a failed revision at all — that case is now retried in place rather than refused. What remains is a collision with a revision that genuinely has been deployed, which is exactly the case where naming it and linking it is most useful.

The `sc` half of the "at minimum" ask in [Someones.Computer#792](https://git.grey.ooo/Grey.ooo/Someones.Computer/issues/792). ## BLOCKED on [scclient#9](https://git.grey.ooo/Grey.ooo/someones.computer_scclient/pulls/9) `agent/` vendors `scclient`, so `APIError.Collision()` does not exist here until `go.mod` is bumped to a pseudo-version containing that commit and `go mod vendor` is re-run. The bump is deliberately not in this PR — pinning `go.mod` at an unmerged branch commit is how a pin ends up on a commit that never lands. Sequence: scclient#9 → bump + re-vendor here → un-draft. ## What it does A refused deploy ended like this: ```console $ sc deploy Uploading 3.8 MiB to https://someones.computer… sc: bundle upload failed: An identical bundle has already been deployed. ``` The platform had already said *which* revision the digest matched — number, status and a URL — and `sc` printed only the message. So the refusal read like a statement about the platform, when what it meant was **this tree is already revision #2, and it is running**. Now: ```console sc: bundle upload failed: An identical bundle has already been deployed. It matches revision #2, which is running. See it: https://someones.computer/applications/…/deployments/… ``` - **The error is returned unchanged**, so the exit code and the message are exactly what they were. This only adds the fact that was being dropped. - **Nothing extra is printed when there is no revision to point at** — the other `409` on this API is an ambiguous application slug, which names organizations instead. - **A URL-less collision still names the revision**; only the link is skipped. ## Verification - `go build ./...`, `go vet ./...`, `go test ./...` clean **with the workspace** (`go.work` resolves `scclient` by path). The vendored build is what fails, per above. - Four new tests: the collision is named and linked, the error passes through unchanged, an ambiguous-slug 409 prints nothing, a plain transport error is not inspected as an `*APIError`, and a collision without a URL still names the revision. - Coverage ratchet holds and rose: `internal/cli` 81.5% against a floor of 80.7%. `coverage.floor` not bumped — the figures are Linux numbers and this run is macOS. ## Note After [Someones.Computer#820](https://git.grey.ooo/Grey.ooo/Someones.Computer/pulls/820) lands, this `409` no longer fires for a **failed** revision at all — that case is now retried in place rather than refused. What remains is a collision with a revision that genuinely has been deployed, which is exactly the case where naming it and linking it is most useful.
Name the revision a bundle upload collided with
Some checks failed
CI / build (pull_request) Failing after 1m6s
4fd0d634c9
The platform's 409 has always said which revision the digest matched — number,
status and a URL — and `sc` printed only the message, so a refused deploy ended
with "bundle upload failed: An identical bundle has already been deployed." and
nothing to act on. That reads like a statement about the platform rather than
what it is: this tree is already revision #2, and it is running.

The refusal now names it and links it. The error is returned unchanged, so the
exit code and the message are what they always were; this only adds the fact
that was being dropped.
Bump scclient to the release carrying Collision
All checks were successful
CI / build (pull_request) Successful in 6m44s
c7d6c69d0e
The renderer reads a method this module vendors, so the pin has to move before
it compiles. scclient main now carries the managed-service verbs as well, so
this is one forward move that drops nothing.

The two test calls that ignore withCollision's return are assigned to _ —
errcheck is right that a discarded error return should say so on purpose.
geusebio changed title from WIP: Name the revision a bundle upload collided with to Name the revision a bundle upload collided with 2026-08-17 08:17:05 +00:00
geusebio deleted branch feature/name-the-revision-a-bundle-collided-with 2026-08-17 08:19:21 +00:00
Sign in to join this conversation.
No reviewers
No labels
in-progress
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Grey.ooo/someones.computer_agent!30
No description provided.