diff --git a/internal/handlers/handlers_test.go b/internal/handlers/handlers_test.go index 77e207c..adec558 100644 --- a/internal/handlers/handlers_test.go +++ b/internal/handlers/handlers_test.go @@ -7,6 +7,7 @@ import ( "net/url" "strings" "testing" + "time" "github.com/go-chi/chi/v5" "github.com/stretchr/testify/assert" @@ -115,6 +116,7 @@ func createAppServices( deploySvc, deployErr := deploy.New(fx.Lifecycle(nil), deploy.ServiceParams{ Logger: logInstance, + Config: cfg, Database: dbInstance, Docker: dockerClient, Notify: notifySvc, @@ -484,4 +486,9 @@ func TestHandleWebhookProcessesValidWebhook(t *testing.T) { handler.ServeHTTP(recorder, request) assert.Equal(t, http.StatusOK, recorder.Code) + + // Allow async deployment goroutine to complete before test cleanup. + // The deployment will fail quickly (docker not connected) but we need + // to wait for it to finish to avoid temp directory cleanup race. + time.Sleep(100 * time.Millisecond) } diff --git a/internal/service/deploy/deploy.go b/internal/service/deploy/deploy.go index 79dd333..e72aad9 100644 --- a/internal/service/deploy/deploy.go +++ b/internal/service/deploy/deploy.go @@ -26,6 +26,8 @@ const ( healthCheckDelaySeconds = 60 // upaasLabelCount is the number of upaas-specific labels added to containers. upaasLabelCount = 1 + // buildsDirPermissions is the permission mode for the builds directory. + buildsDirPermissions = 0o750 ) // Sentinel errors for deployment failures. @@ -202,7 +204,18 @@ func (svc *Service) cloneRepository( app *models.App, deployment *models.Deployment, ) (string, func(), error) { - tempDir, err := os.MkdirTemp("", "upaas-"+app.ID+"-*") + // Use a subdirectory of DataDir for builds since it's mounted from the host + // and accessible to Docker for bind mounts (unlike /tmp inside the container) + buildsDir := filepath.Join(svc.config.DataDir, "builds") + + err := os.MkdirAll(buildsDir, buildsDirPermissions) + if err != nil { + svc.failDeployment(ctx, app, deployment, fmt.Errorf("failed to create builds dir: %w", err)) + + return "", nil, fmt.Errorf("failed to create builds dir: %w", err) + } + + tempDir, err := os.MkdirTemp(buildsDir, app.ID+"-*") if err != nil { svc.failDeployment(ctx, app, deployment, fmt.Errorf("failed to create temp dir: %w", err)) diff --git a/internal/service/webhook/webhook_test.go b/internal/service/webhook/webhook_test.go index 3820cb8..90078a9 100644 --- a/internal/service/webhook/webhook_test.go +++ b/internal/service/webhook/webhook_test.go @@ -63,7 +63,7 @@ func setupTestService(t *testing.T) (*webhook.Service, *database.Database, func( require.NoError(t, err) deploySvc, err := deploy.New(fx.Lifecycle(nil), deploy.ServiceParams{ - Logger: deps.logger, Database: deps.db, Docker: dockerClient, Notify: notifySvc, + Logger: deps.logger, Config: deps.config, Database: deps.db, Docker: dockerClient, Notify: notifySvc, }) require.NoError(t, err)