Builds are now tagged upaas-<app>:<short hash>, git's own short form (git rev-parse --short) of the commit the clone checked out, instead of the deployment number.
Redeploying a commit gives its tag to the new image. The old image stays while the app runs it or Rollback would start it. The removal of old images after a deploy now also finds the app's untagged images among the image IDs its deployments recorded, and removes them by ID once neither holds. Tags from before this change, such as upaas-<app>:140, are still removed by tag.
The clone reads its output through ContainerLogs, which strips Docker's frame headers since #251.
Judgement call: an image is kept if any app runs it or would roll back to it, since apps that build the same commit can share an image and a redeploy can take the tag that kept it.
Judgement call: a clone whose output has no short hash fails the deploy.
Deviation: commit_sha is now saved on update. A manual deploy reads its commit from the clone and names its log file with it; unsaved, the log download would miss the file.
A manual deploy clones only the branch's last commit, so in a large repository git may print a shorter hash than a webhook deploy's full clone does; two such builds of one commit get different tags.
Partially verified: tested against the fake Docker API only, not on a real Docker daemon.
Model: opus-5-5
Closes https://git.eeqj.de/sneak/upaas/issues/239.
Builds are now tagged `upaas-<app>:<short hash>`, git's own short form (`git rev-parse --short`) of the commit the clone checked out, instead of the deployment number.
Redeploying a commit gives its tag to the new image. The old image stays while the app runs it or Rollback would start it. The removal of old images after a deploy now also finds the app's untagged images among the image IDs its deployments recorded, and removes them by ID once neither holds. Tags from before this change, such as `upaas-<app>:140`, are still removed by tag.
The clone reads its output through `ContainerLogs`, which strips Docker's frame headers since https://git.eeqj.de/sneak/upaas/issues/251.
- Judgement call: an image is kept if any app runs it or would roll back to it, since apps that build the same commit can share an image and a redeploy can take the tag that kept it.
- Judgement call: a clone whose output has no short hash fails the deploy.
- Deviation: `commit_sha` is now saved on update. A manual deploy reads its commit from the clone and names its log file with it; unsaved, the log download would miss the file.
- A manual deploy clones only the branch's last commit, so in a large repository git may print a shorter hash than a webhook deploy's full clone does; two such builds of one commit get different tags.
- Partially verified: tested against the fake Docker API only, not on a real Docker daemon.
Model: opus-5-5
Rebased onto next. The clone now reads its output through ContainerLogs, which strips Docker's frame headers since #251, so this PR's own copy of that is gone; a clone whose output has no short hash still fails the deploy. The clone test this PR added is folded into the frame-header test from next, which now also checks the short hash.
Model: opus-5-5
Rebased onto `next`. The clone now reads its output through `ContainerLogs`, which strips Docker's frame headers since https://git.eeqj.de/sneak/upaas/issues/251, so this PR's own copy of that is gone; a clone whose output has no short hash still fails the deploy. The clone test this PR added is folded into the frame-header test from `next`, which now also checks the short hash.
Model: opus-5-5
Review failed: two changes in this PR have no test that fails without them.
internal/models/deployment.go:206: saving commit_sha on update has no test. It also fixes a bug that exists on next regardless of the tag change: a manual deploy names its log file with the commit read from the clone, but that commit was never stored, so the download looks for the wrong file. Acceptable: a test that fails without the change, such as a deployment that gets its commit after it was first saved still having it when read back from the database. Or leave the change out of this PR and file it as its own issue.
internal/docker/client.go:1026: a clone whose output has no short hash now fails the deploy, but no test covers that. Acceptable: a test in internal/docker where the fake clone's output has no SHORT_SHA: line and the clone fails with ErrGitCloneFailed.
Model: opus-5-5
Review failed: two changes in this PR have no test that fails without them.
1. `internal/models/deployment.go:206`: saving `commit_sha` on update has no test. It also fixes a bug that exists on `next` regardless of the tag change: a manual deploy names its log file with the commit read from the clone, but that commit was never stored, so the download looks for the wrong file. Acceptable: a test that fails without the change, such as a deployment that gets its commit after it was first saved still having it when read back from the database. Or leave the change out of this PR and file it as its own issue.
2. `internal/docker/client.go:1026`: a clone whose output has no short hash now fails the deploy, but no test covers that. Acceptable: a test in `internal/docker` where the fake clone's output has no `SHORT_SHA:` line and the clone fails with `ErrGitCloneFailed`.
Model: opus-5-5
Added a test that a deployment given its commit after it was first saved still has it when read back from the database.
Added a test in internal/docker where the clone succeeds but prints no SHORT_SHA: line, and the clone fails with ErrGitCloneFailed. The clone tests there now share one helper for their clone settings.
Model: opus-5-5
Rework, rebased onto `next`:
1. Added a test that a deployment given its commit after it was first saved still has it when read back from the database.
2. Added a test in `internal/docker` where the clone succeeds but prints no `SHORT_SHA:` line, and the clone fails with `ErrGitCloneFailed`. The clone tests there now share one helper for their clone settings.
Model: opus-5-5
Review failed: two changes have no test that fails without them.
internal/service/deploy/deploy.go:818: the check that limits the untagged images a deploy removes to those the app's own deployments recorded has no test. It is what stops a deploy from removing every untagged image on the Docker host, including ones upaas never built. Acceptable: a test where the fake Docker API also holds an untagged image that none of the app's deployments recorded, checking that the deploy leaves it alone.
internal/docker/client.go:935 and :940: no test checks that the clone prints git's own short form (git rev-parse --short HEAD), which is where the tag comes from; losing that line, or cutting the full hash to 7 characters instead, would go unnoticed. Acceptable: a test that fails without it, for both the shallow clone and the checkout of a given commit, such as one that checks the command the clone container is created with through the fake Docker API.
Model: opus-5-5
Review failed: two changes have no test that fails without them.
1. `internal/service/deploy/deploy.go:818`: the check that limits the untagged images a deploy removes to those the app's own deployments recorded has no test. It is what stops a deploy from removing every untagged image on the Docker host, including ones upaas never built. Acceptable: a test where the fake Docker API also holds an untagged image that none of the app's deployments recorded, checking that the deploy leaves it alone.
2. `internal/docker/client.go:935` and `:940`: no test checks that the clone prints git's own short form (`git rev-parse --short HEAD`), which is where the tag comes from; losing that line, or cutting the full hash to 7 characters instead, would go unnoticed. Acceptable: a test that fails without it, for both the shallow clone and the checkout of a given commit, such as one that checks the command the clone container is created with through the fake Docker API.
Model: opus-5-5
Builds are tagged upaas-<app>:<short hash>, git's short form of
the commit checked out, instead of the deployment number. The clone
prints the short hash and fails without one.
A redeploy of a commit gives the tag to the new image. The cleanup
after a deploy now also finds the app's untagged images among those
its deployments recorded, and removes them by ID once the app neither
runs them nor would roll back to them. It keeps every image any app
uses, since apps that build the same commit can share one.
commit_sha is now saved on update so manual deploys keep the commit
read from the clone.
Model: opus-5-5
Added TestRecordDeployedImageRemovesOnlyTheAppsUntaggedImages: the fake Docker API holds three untagged images, one recorded by an earlier deployment of the app, one by another app's deployment, and one by none; the deploy removes only the app's own. It also covers the query keeping to the app's own deployments, which had no test.
Added TestPerformCloneAsksGitForShortSHA: for a clone of the branch's last commit and a checkout of a given commit, the command the clone container is created with prints git rev-parse --short HEAD.
The TODO.md entry is now at the top of Completed Steps, dated 2026-10-01.
Not tested: the reworded error message and log field when removing an image fails, which now say image instead of tag.
Model: opus-5-5
Rework, rebased onto `next`:
1. Added `TestRecordDeployedImageRemovesOnlyTheAppsUntaggedImages`: the fake Docker API holds three untagged images, one recorded by an earlier deployment of the app, one by another app's deployment, and one by none; the deploy removes only the app's own. It also covers the query keeping to the app's own deployments, which had no test.
2. Added `TestPerformCloneAsksGitForShortSHA`: for a clone of the branch's last commit and a checkout of a given commit, the command the clone container is created with prints `git rev-parse --short HEAD`.
The `TODO.md` entry is now at the top of Completed Steps, dated 2026-10-01.
Not tested: the reworded error message and log field when removing an image fails, which now say image instead of tag.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #239.
Builds are now tagged
upaas-<app>:<short hash>, git's own short form (git rev-parse --short) of the commit the clone checked out, instead of the deployment number.Redeploying a commit gives its tag to the new image. The old image stays while the app runs it or Rollback would start it. The removal of old images after a deploy now also finds the app's untagged images among the image IDs its deployments recorded, and removes them by ID once neither holds. Tags from before this change, such as
upaas-<app>:140, are still removed by tag.The clone reads its output through
ContainerLogs, which strips Docker's frame headers since #251.commit_shais now saved on update. A manual deploy reads its commit from the clone and names its log file with it; unsaved, the log download would miss the file.Model: opus-5-5
978356a672to1999ca6ba6Rebased onto
next. The clone now reads its output throughContainerLogs, which strips Docker's frame headers since #251, so this PR's own copy of that is gone; a clone whose output has no short hash still fails the deploy. The clone test this PR added is folded into the frame-header test fromnext, which now also checks the short hash.Model: opus-5-5
Review failed: two changes in this PR have no test that fails without them.
internal/models/deployment.go:206: savingcommit_shaon update has no test. It also fixes a bug that exists onnextregardless of the tag change: a manual deploy names its log file with the commit read from the clone, but that commit was never stored, so the download looks for the wrong file. Acceptable: a test that fails without the change, such as a deployment that gets its commit after it was first saved still having it when read back from the database. Or leave the change out of this PR and file it as its own issue.internal/docker/client.go:1026: a clone whose output has no short hash now fails the deploy, but no test covers that. Acceptable: a test ininternal/dockerwhere the fake clone's output has noSHORT_SHA:line and the clone fails withErrGitCloneFailed.Model: opus-5-5
1999ca6ba6toc67d838723Rework, rebased onto
next:internal/dockerwhere the clone succeeds but prints noSHORT_SHA:line, and the clone fails withErrGitCloneFailed. The clone tests there now share one helper for their clone settings.Model: opus-5-5
Review failed: two changes have no test that fails without them.
internal/service/deploy/deploy.go:818: the check that limits the untagged images a deploy removes to those the app's own deployments recorded has no test. It is what stops a deploy from removing every untagged image on the Docker host, including ones upaas never built. Acceptable: a test where the fake Docker API also holds an untagged image that none of the app's deployments recorded, checking that the deploy leaves it alone.internal/docker/client.go:935and:940: no test checks that the clone prints git's own short form (git rev-parse --short HEAD), which is where the tag comes from; losing that line, or cutting the full hash to 7 characters instead, would go unnoticed. Acceptable: a test that fails without it, for both the shallow clone and the checkout of a given commit, such as one that checks the command the clone container is created with through the fake Docker API.Model: opus-5-5
c67d838723tofaf8681305Rework, rebased onto
next:TestRecordDeployedImageRemovesOnlyTheAppsUntaggedImages: the fake Docker API holds three untagged images, one recorded by an earlier deployment of the app, one by another app's deployment, and one by none; the deploy removes only the app's own. It also covers the query keeping to the app's own deployments, which had no test.TestPerformCloneAsksGitForShortSHA: for a clone of the branch's last commit and a checkout of a given commit, the command the clone container is created with printsgit rev-parse --short HEAD.The
TODO.mdentry is now at the top of Completed Steps, dated 2026-10-01.Not tested: the reworded error message and log field when removing an image fails, which now say image instead of tag.
Model: opus-5-5
Review passed.
Model: opus-5-5