HandleAPITriggerDeploy calls h.deploy.Deploy(request.Context(), ...) directly with the HTTP request context. When the API client disconnects (or times out), request.Context() is cancelled, which propagates into the deploy service and cancels the build/deploy mid-operation.
The HTML handler (HandleAppDeploy in app.go:355) correctly uses context.WithoutCancel(request.Context()) and runs the deployment in a goroutine.
Any API-triggered deployment will be cancelled if the HTTP client disconnects before the build finishes (which can take 30+ minutes). The deployment will be left in a partially-built state. This makes the API deploy endpoint essentially unreliable.
Suggested Fix
Use context.WithoutCancel and run in a goroutine, same as the HTML handler. Return 202 Accepted immediately (which it already does, but after the deploy starts synchronously).
## Severity: HIGH
## File & Line
`internal/handlers/api.go:345`
## Description
`HandleAPITriggerDeploy` calls `h.deploy.Deploy(request.Context(), ...)` directly with the HTTP request context. When the API client disconnects (or times out), `request.Context()` is cancelled, which propagates into the deploy service and cancels the build/deploy mid-operation.
The HTML handler (`HandleAppDeploy` in `app.go:355`) correctly uses `context.WithoutCancel(request.Context())` and runs the deployment in a goroutine.
```go
// api.go:345 — BUG: uses request context directly
deployErr := h.deploy.Deploy(request.Context(), application, nil, true)
// app.go:355 — CORRECT: detached context in goroutine
deployCtx := context.WithoutCancel(request.Context())
go func(ctx context.Context, appToDeploy *models.App) {
deployErr := h.deploy.Deploy(ctx, appToDeploy, nil, false)
...
}(deployCtx, application)
```
## Impact
Any API-triggered deployment will be cancelled if the HTTP client disconnects before the build finishes (which can take 30+ minutes). The deployment will be left in a partially-built state. This makes the API deploy endpoint essentially unreliable.
## Suggested Fix
Use `context.WithoutCancel` and run in a goroutine, same as the HTML handler. Return 202 Accepted immediately (which it already does, but after the deploy starts synchronously).
clawbot
added this to the 1.0 milestone 2026-02-20 12:28:13 +01:00
clawbot
added the bug label 2026-02-20 12:28:13 +01:00
clawbot
self-assigned this 2026-02-20 12:28:13 +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.
Severity: HIGH
File & Line
internal/handlers/api.go:345Description
HandleAPITriggerDeploycallsh.deploy.Deploy(request.Context(), ...)directly with the HTTP request context. When the API client disconnects (or times out),request.Context()is cancelled, which propagates into the deploy service and cancels the build/deploy mid-operation.The HTML handler (
HandleAppDeployinapp.go:355) correctly usescontext.WithoutCancel(request.Context())and runs the deployment in a goroutine.Impact
Any API-triggered deployment will be cancelled if the HTTP client disconnects before the build finishes (which can take 30+ minutes). The deployment will be left in a partially-built state. This makes the API deploy endpoint essentially unreliable.
Suggested Fix
Use
context.WithoutCanceland run in a goroutine, same as the HTML handler. Return 202 Accepted immediately (which it already does, but after the deploy starts synchronously).