fix: resolve all 47 noctx lint findings in tests
All checks were successful
Check / check (pull_request) Successful in 3m10s

Replace every httptest.NewRequest call with
httptest.NewRequestWithContext using the test's t.Context(). Thread
t *testing.T through the createSetupFormRequest and
createLoginFormRequest helpers so they can supply a context.

make lint under golangci-lint 2.12.2 drops from 94 findings to 47
(remaining: 23 gosec, 24 goconst, tracked in #176/#177/#178). make
test and make fmt-check pass unchanged.

Closes #175
This commit is contained in:
2026-08-07 16:47:16 +00:00
parent 291f85f3ed
commit 21642900e6
7 changed files with 120 additions and 64 deletions

View File

@@ -193,7 +193,8 @@ func TestHandleHealthCheck(t *testing.T) {
testCtx := setupTestHandlers(t)
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodGet,
"/.well-known/healthcheck.json",
nil,
@@ -218,7 +219,7 @@ func TestHandleSetupGET(t *testing.T) {
testCtx := setupTestHandlers(t)
request := httptest.NewRequest(http.MethodGet, "/setup", nil)
request := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/setup", nil)
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleSetupGET()
@@ -230,14 +231,18 @@ func TestHandleSetupGET(t *testing.T) {
}
func createSetupFormRequest(
t *testing.T,
username, password, confirm string,
) *http.Request {
t.Helper()
form := url.Values{}
form.Set("username", username)
form.Set("password", password)
form.Set("password_confirm", confirm)
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/setup",
strings.NewReader(form.Encode()),
@@ -252,7 +257,7 @@ func TestHandleSetupPOSTCreatesUserAndRedirects(t *testing.T) {
testCtx := setupTestHandlers(t)
request := createSetupFormRequest("admin", "password123", "password123")
request := createSetupFormRequest(t, "admin", "password123", "password123")
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleSetupPOST()
@@ -267,7 +272,7 @@ func TestHandleSetupPOSTRejectsEmptyUsername(t *testing.T) {
testCtx := setupTestHandlers(t)
request := createSetupFormRequest("", "password123", "password123")
request := createSetupFormRequest(t, "", "password123", "password123")
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleSetupPOST()
@@ -282,7 +287,7 @@ func TestHandleSetupPOSTRejectsShortPassword(t *testing.T) {
testCtx := setupTestHandlers(t)
request := createSetupFormRequest("admin", "short", "short")
request := createSetupFormRequest(t, "admin", "short", "short")
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleSetupPOST()
@@ -297,7 +302,7 @@ func TestHandleSetupPOSTRejectsMismatchedPasswords(t *testing.T) {
testCtx := setupTestHandlers(t)
request := createSetupFormRequest("admin", "password123", "different123")
request := createSetupFormRequest(t, "admin", "password123", "different123")
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleSetupPOST()
@@ -315,7 +320,7 @@ func TestHandleLoginGET(t *testing.T) {
testCtx := setupTestHandlers(t)
request := httptest.NewRequest(http.MethodGet, "/login", nil)
request := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/login", nil)
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleLoginGET()
@@ -326,12 +331,15 @@ func TestHandleLoginGET(t *testing.T) {
})
}
func createLoginFormRequest(username, password string) *http.Request {
func createLoginFormRequest(t *testing.T, username, password string) *http.Request {
t.Helper()
form := url.Values{}
form.Set("username", username)
form.Set("password", password)
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/login",
strings.NewReader(form.Encode()),
@@ -354,7 +362,7 @@ func TestHandleLoginPOSTAuthenticatesValidCredentials(t *testing.T) {
)
require.NoError(t, createErr)
request := createLoginFormRequest("testuser", "testpass123")
request := createLoginFormRequest(t, "testuser", "testpass123")
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleLoginPOST()
@@ -377,7 +385,7 @@ func TestHandleLoginPOSTRejectsInvalidCredentials(t *testing.T) {
)
require.NoError(t, createErr)
request := createLoginFormRequest("testuser", "wrongpassword")
request := createLoginFormRequest(t, "testuser", "wrongpassword")
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleLoginPOST()
@@ -395,7 +403,7 @@ func TestHandleDashboard(t *testing.T) {
testCtx := setupTestHandlers(t)
request := httptest.NewRequest(http.MethodGet, "/", nil)
request := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/", nil)
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleDashboard()
@@ -413,7 +421,7 @@ func TestHandleDashboard(t *testing.T) {
// Create an app so the template iterates over AppStats and hits .CSRFField
createTestApp(t, testCtx, "csrf-test-app")
request := httptest.NewRequest(http.MethodGet, "/", nil)
request := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/", nil)
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleDashboard()
@@ -433,7 +441,9 @@ func TestHandleAppNew(t *testing.T) {
testCtx := setupTestHandlers(t)
request := httptest.NewRequest(http.MethodGet, "/apps/new", nil)
request := httptest.NewRequestWithContext(
t.Context(), http.MethodGet, "/apps/new", nil,
)
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleAppNew()
@@ -501,7 +511,8 @@ func TestHandleWebhookRejectsOversizedBody(t *testing.T) {
// Create a body larger than 1MB - it should be silently truncated
// and the webhook should still process (or fail gracefully on parse)
largePayload := strings.Repeat("x", 2*1024*1024) // 2MB
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/webhook/"+createdApp.WebhookSecret,
strings.NewReader(largePayload),
@@ -544,7 +555,8 @@ func testOwnershipVerification(t *testing.T, cfg ownedResourceTestConfig) {
resourceID := cfg.createFn(t, testCtx, app1)
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
cfg.deletePath(app2.ID, resourceID),
nil,
@@ -583,7 +595,8 @@ func TestHandleEnvVarSaveBulk(t *testing.T) {
r := chi.NewRouter()
r.Post("/apps/{id}/env", testCtx.handlers.HandleEnvVarSave())
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/apps/"+createdApp.ID+"/env",
strings.NewReader(body),
@@ -625,7 +638,8 @@ func TestHandleEnvVarSaveAppNotFound(t *testing.T) {
r := chi.NewRouter()
r.Post("/apps/{id}/env", testCtx.handlers.HandleEnvVarSave())
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/apps/nonexistent-id/env",
strings.NewReader(body),
@@ -651,7 +665,8 @@ func TestHandleEnvVarSaveEmptyKeyRejected(t *testing.T) {
r := chi.NewRouter()
r.Post("/apps/{id}/env", testCtx.handlers.HandleEnvVarSave())
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/apps/"+createdApp.ID+"/env",
strings.NewReader(body),
@@ -678,7 +693,8 @@ func TestHandleEnvVarSaveDuplicateKeyRejected(t *testing.T) {
r := chi.NewRouter()
r.Post("/apps/{id}/env", testCtx.handlers.HandleEnvVarSave())
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/apps/"+createdApp.ID+"/env",
strings.NewReader(body),
@@ -716,7 +732,8 @@ func TestHandleEnvVarSaveCrossAppIsolation(t *testing.T) {
r := chi.NewRouter()
r.Post("/apps/{id}/env", testCtx.handlers.HandleEnvVarSave())
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/apps/"+appA.ID+"/env",
strings.NewReader(body),
@@ -779,7 +796,8 @@ func TestHandleEnvVarSaveBodySizeLimit(t *testing.T) {
r := chi.NewRouter()
r.Post("/apps/{id}/env", testCtx.handlers.HandleEnvVarSave())
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/apps/"+createdApp.ID+"/env",
strings.NewReader(sb.String()),
@@ -848,7 +866,8 @@ func TestDeleteVolumeOwnershipVerification(t *testing.T) {
require.NoError(t, volume.Save(context.Background()))
// Try to delete app1's volume using app2's URL path
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/apps/"+app2.ID+"/volumes/"+strconv.FormatInt(volume.ID, 10)+"/delete",
nil,
@@ -889,7 +908,8 @@ func TestDeletePortOwnershipVerification(t *testing.T) {
require.NoError(t, port.Save(context.Background()))
// Try to delete app1's port using app2's URL path
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/apps/"+app2.ID+"/ports/"+strconv.FormatInt(port.ID, 10)+"/delete",
nil,
@@ -930,7 +950,8 @@ func TestHandleEnvVarSaveEmptyClears(t *testing.T) {
r := chi.NewRouter()
r.Post("/apps/{id}/env", testCtx.handlers.HandleEnvVarSave())
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/apps/"+createdApp.ID+"/env",
strings.NewReader("[]"),
@@ -979,7 +1000,8 @@ func TestHandleVolumeAddValidatesPaths(t *testing.T) {
form.Set("host_path", tt.hostPath)
form.Set("container_path", tt.containerPath)
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/apps/"+createdApp.ID+"/volumes",
strings.NewReader(form.Encode()),
@@ -1038,7 +1060,7 @@ func TestSetupRequiredExemptsHealthAndStaticAndAPI(t *testing.T) {
t.Run(path, func(t *testing.T) {
t.Parallel()
req := httptest.NewRequest(http.MethodGet, path, nil)
req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, path, nil)
rr := httptest.NewRecorder()
wrapped.ServeHTTP(rr, req)
@@ -1051,7 +1073,7 @@ func TestSetupRequiredExemptsHealthAndStaticAndAPI(t *testing.T) {
t.Run("non-exempt redirects", func(t *testing.T) {
t.Parallel()
req := httptest.NewRequest(http.MethodGet, "/", nil)
req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/", nil)
rr := httptest.NewRecorder()
wrapped.ServeHTTP(rr, req)
@@ -1067,7 +1089,8 @@ func TestHandleCancelDeployRedirects(t *testing.T) {
createdApp := createTestApp(t, testCtx, "cancel-deploy-app")
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/apps/"+createdApp.ID+"/deployments/cancel",
nil,
@@ -1087,7 +1110,8 @@ func TestHandleCancelDeployReturns404ForUnknownApp(t *testing.T) {
testCtx := setupTestHandlers(t)
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/apps/nonexistent/deployments/cancel",
nil,
@@ -1108,7 +1132,8 @@ func TestHandleWebhookReturns404ForUnknownSecret(t *testing.T) {
webhookURL := "/webhook/unknown-secret"
payload := `{"ref": "refs/heads/main"}`
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
webhookURL,
strings.NewReader(payload),
@@ -1143,7 +1168,8 @@ func TestHandleWebhookProcessesValidWebhook(t *testing.T) {
payload := `{"ref": "refs/heads/main", "after": "abc123"}`
webhookURL := "/webhook/" + createdApp.WebhookSecret
request := httptest.NewRequest(
request := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
webhookURL,
strings.NewReader(payload),