Updated checkCancelled() to accept imageID and trigger cleanup
runBuildAndDeploy passes the built imageID when cancellation occurs during deploy phase
Test results (before)
=== RUN TestCleanupCancelledDeploy_RemovesBuildDir
--- PASS: TestCleanupCancelledDeploy_RemovesBuildDir (0.00s)
=== RUN TestCleanupCancelledDeploy_NoBuildDir
--- PASS: TestCleanupCancelledDeploy_NoBuildDir (0.00s)
PASS
Test results (after - full suite)
make test
PASS - all tests pass
Note: make check formatting failures are pre-existing on main (4 files), not introduced by this PR.
When a deploy is cancelled, intermediate Docker images and build temp directories were left behind. This adds cleanup logic to the cancellation path.
## Changes
- Added `docker.Client.RemoveImage()` to remove Docker images by ID
- Added `cleanupCancelledDeploy()` in deploy service that:
- Removes intermediate Docker images from cancelled builds
- Removes deployment-specific build temp directories
- Logs cleanup success/failure
- Updated `checkCancelled()` to accept imageID and trigger cleanup
- `runBuildAndDeploy` passes the built imageID when cancellation occurs during deploy phase
## Test results (before)
```
=== RUN TestCleanupCancelledDeploy_RemovesBuildDir
--- PASS: TestCleanupCancelledDeploy_RemovesBuildDir (0.00s)
=== RUN TestCleanupCancelledDeploy_NoBuildDir
--- PASS: TestCleanupCancelledDeploy_NoBuildDir (0.00s)
PASS
```
## Test results (after - full suite)
```
make test
PASS - all tests pass
```
Note: `make check` formatting failures are pre-existing on main (4 files), not introduced by this PR.
Good cleanup — cancelled deploys now properly remove orphan Docker images and build directories. The RemoveImage with Force: true and PruneChildren: true is correct for cleanup.
A few observations:
Build dir matching uses string prefix — entry.Name()[:len(prefix)] == prefix works but strings.HasPrefix would be more idiomatic Go.
export_test.go duplicates cleanup logic — the CleanupCancelledDeploy export re-implements the directory cleanup instead of calling the real method. If the real implementation changes, this test helper won't catch regressions. Consider finding a way to test the actual method.
os.RemoveAll on build dirs — this is fine since the path is constructed from known prefixes, not user input.
Overall: LGTM, good operational improvement.
Good cleanup — cancelled deploys now properly remove orphan Docker images and build directories. The `RemoveImage` with `Force: true` and `PruneChildren: true` is correct for cleanup.
A few observations:
1. **Build dir matching uses string prefix** — `entry.Name()[:len(prefix)] == prefix` works but `strings.HasPrefix` would be more idiomatic Go.
2. **`export_test.go` duplicates cleanup logic** — the `CleanupCancelledDeploy` export re-implements the directory cleanup instead of calling the real method. If the real implementation changes, this test helper won't catch regressions. Consider finding a way to test the actual method.
3. **`os.RemoveAll` on build dirs** — this is fine since the path is constructed from known prefixes, not user input.
Overall: LGTM, good operational improvement.
Nit: entry.Name()[:len(prefix)] == prefix — prefer strings.HasPrefix(entry.Name(), prefix) for readability and safety (the length guard is easy to get wrong).
Nit: `entry.Name()[:len(prefix)] == prefix` — prefer `strings.HasPrefix(entry.Name(), prefix)` for readability and safety (the length guard is easy to get wrong).
This duplicates the directory cleanup logic from the real cleanupCancelledDeploy. If the real implementation changes (e.g. different naming convention), this test helper won't catch the regression. Consider refactoring so the test exercises the actual code path.
This duplicates the directory cleanup logic from the real `cleanupCancelledDeploy`. If the real implementation changes (e.g. different naming convention), this test helper won't catch the regression. Consider refactoring so the test exercises the actual code path.
Replaced entry.Name()[:len(prefix)] == prefix with strings.HasPrefix(entry.Name(), prefix) in deploy.go
Refactored CleanupCancelledDeploy in export_test.go to call the real cleanupCancelledDeploy method via models.NewApp(nil) / models.NewDeployment(nil) instead of re-implementing the logic
Added nil-db guards in Deployment.Save() and App.Save() to prevent panics when models lack a DB connection
Fixed a wsl_v5 lint issue (missing blank line before assignment)
Test results (all pass):
ok git.eeqj.de/sneak/upaas/internal/database
ok git.eeqj.de/sneak/upaas/internal/docker
ok git.eeqj.de/sneak/upaas/internal/handlers
ok git.eeqj.de/sneak/upaas/internal/middleware
ok git.eeqj.de/sneak/upaas/internal/models
ok git.eeqj.de/sneak/upaas/internal/service/app
ok git.eeqj.de/sneak/upaas/internal/service/auth
ok git.eeqj.de/sneak/upaas/internal/service/deploy
ok git.eeqj.de/sneak/upaas/internal/service/webhook
ok git.eeqj.de/sneak/upaas/internal/ssh
Lint: 16 pre-existing issues (unchanged from main), no new issues introduced.
## Review fixes applied ✅
**Changes:**
1. Replaced `entry.Name()[:len(prefix)] == prefix` with `strings.HasPrefix(entry.Name(), prefix)` in `deploy.go`
2. Refactored `CleanupCancelledDeploy` in `export_test.go` to call the real `cleanupCancelledDeploy` method via `models.NewApp(nil)` / `models.NewDeployment(nil)` instead of re-implementing the logic
3. Added nil-db guards in `Deployment.Save()` and `App.Save()` to prevent panics when models lack a DB connection
4. Fixed a `wsl_v5` lint issue (missing blank line before assignment)
**Test results (all pass):**
```
ok git.eeqj.de/sneak/upaas/internal/database
ok git.eeqj.de/sneak/upaas/internal/docker
ok git.eeqj.de/sneak/upaas/internal/handlers
ok git.eeqj.de/sneak/upaas/internal/middleware
ok git.eeqj.de/sneak/upaas/internal/models
ok git.eeqj.de/sneak/upaas/internal/service/app
ok git.eeqj.de/sneak/upaas/internal/service/auth
ok git.eeqj.de/sneak/upaas/internal/service/deploy
ok git.eeqj.de/sneak/upaas/internal/service/webhook
ok git.eeqj.de/sneak/upaas/internal/ssh
```
**Lint:** 16 pre-existing issues (unchanged from main), no new issues introduced.
Replaced manual prefix check with strings.HasPrefix in cleanupCancelledDeploy — entry.Name()[:len(prefix)] == prefix → strings.HasPrefix(entry.Name(), prefix)
Applied same fix in export_test.go — the CleanupCancelledDeploy test helper had the same pattern
All tests pass.
Fixed the review issues:
1. **Replaced manual prefix check with `strings.HasPrefix`** in `cleanupCancelledDeploy` — `entry.Name()[:len(prefix)] == prefix` → `strings.HasPrefix(entry.Name(), prefix)`
2. **Applied same fix in `export_test.go`** — the `CleanupCancelledDeploy` test helper had the same pattern
All tests pass.
sneak
merged commit 06e8e66443 into main2026-02-20 05:22:59 +01:00
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.
When a deploy is cancelled, intermediate Docker images and build temp directories were left behind. This adds cleanup logic to the cancellation path.
Changes
docker.Client.RemoveImage()to remove Docker images by IDcleanupCancelledDeploy()in deploy service that:checkCancelled()to accept imageID and trigger cleanuprunBuildAndDeploypasses the built imageID when cancellation occurs during deploy phaseTest results (before)
Test results (after - full suite)
Note:
make checkformatting failures are pre-existing on main (4 files), not introduced by this PR.Good cleanup — cancelled deploys now properly remove orphan Docker images and build directories. The
RemoveImagewithForce: trueandPruneChildren: trueis correct for cleanup.A few observations:
Build dir matching uses string prefix —
entry.Name()[:len(prefix)] == prefixworks butstrings.HasPrefixwould be more idiomatic Go.export_test.goduplicates cleanup logic — theCleanupCancelledDeployexport re-implements the directory cleanup instead of calling the real method. If the real implementation changes, this test helper won't catch regressions. Consider finding a way to test the actual method.os.RemoveAllon build dirs — this is fine since the path is constructed from known prefixes, not user input.Overall: LGTM, good operational improvement.
@@ -682,0 +716,4 @@for _, entry := range entries {if entry.IsDir() && len(entry.Name()) > len(prefix) && entry.Name()[:len(prefix)] == prefix {dirPath := filepath.Join(buildDir, entry.Name())Nit:
entry.Name()[:len(prefix)] == prefix— preferstrings.HasPrefix(entry.Name(), prefix)for readability and safety (the length guard is easy to get wrong).@@ -34,0 +52,4 @@ctx context.Context,appName string,deploymentID int64,imageID string,This duplicates the directory cleanup logic from the real
cleanupCancelledDeploy. If the real implementation changes (e.g. different naming convention), this test helper won't catch the regression. Consider refactoring so the test exercises the actual code path.@clawbot pls fix the identified review issues
edc06aa181to25cd02e1d7Review fixes applied ✅
Changes:
entry.Name()[:len(prefix)] == prefixwithstrings.HasPrefix(entry.Name(), prefix)indeploy.goCleanupCancelledDeployinexport_test.goto call the realcleanupCancelledDeploymethod viamodels.NewApp(nil)/models.NewDeployment(nil)instead of re-implementing the logicDeployment.Save()andApp.Save()to prevent panics when models lack a DB connectionwsl_v5lint issue (missing blank line before assignment)Test results (all pass):
Lint: 16 pre-existing issues (unchanged from main), no new issues introduced.
25cd02e1d7to95a690e805Fixed the review issues:
strings.HasPrefixincleanupCancelledDeploy—entry.Name()[:len(prefix)] == prefix→strings.HasPrefix(entry.Name(), prefix)export_test.go— theCleanupCancelledDeploytest helper had the same patternAll tests pass.