diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index de1cf5b1..640d5ee5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -90,7 +90,7 @@ jobs: name: Go lint runs-on: ubuntu-latest env: - GOLANGCI_LINT_VERSION: v2.9.0 + GOLANGCI_LINT_VERSION: v2.11.4 GOPROXY: https://proxy.golang.org,https://u:${{ secrets.RIVERPRO_GO_MOD_CREDENTIAL }}@riverqueue.com/goproxy,direct permissions: contents: read diff --git a/.golangci.yaml b/.golangci.yaml index 52eb3148..98fcd09e 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -92,6 +92,8 @@ linters: exclusions: generated: lax + paths: + - node_modules/ presets: - comments - common-false-positives @@ -108,6 +110,10 @@ formatters: - gofumpt - goimports + exclusions: + paths: + - node_modules/ + settings: gci: sections: diff --git a/handler_test.go b/handler_test.go index 1ebdd157..3fb7ece7 100644 --- a/handler_test.go +++ b/handler_test.go @@ -128,7 +128,7 @@ func TestMountStaticFiles(t *testing.T) { var ( recorder = httptest.NewRecorder() - req = httptest.NewRequest(http.MethodGet, "/robots.txt", nil) + req = httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/robots.txt", nil) ) mux.ServeHTTP(recorder, req) diff --git a/internal/authmiddleware/auth_middleware_test.go b/internal/authmiddleware/auth_middleware_test.go index e645d1da..3e0476ae 100644 --- a/internal/authmiddleware/auth_middleware_test.go +++ b/internal/authmiddleware/auth_middleware_test.go @@ -70,7 +70,7 @@ func TestBasicAuth_Middleware(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - req := httptest.NewRequest(http.MethodGet, "/", nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/", nil) tt.setupRequest(req) rec := httptest.NewRecorder() @@ -112,7 +112,7 @@ func Test_isReqAuthorized(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - req := httptest.NewRequest(http.MethodGet, "/", nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/", nil) if tt.hasAuth { req.SetBasicAuth(tt.reqUser, tt.reqPass) } diff --git a/internal/handlertest/handlertest.go b/internal/handlertest/handlertest.go index c0726148..6bfd3b19 100644 --- a/internal/handlertest/handlertest.go +++ b/internal/handlertest/handlertest.go @@ -48,7 +48,7 @@ func RunIntegrationTest[TClient any](t *testing.T, createClient func(ctx context body = bytes.NewBuffer(payload) } - req := httptest.NewRequest(method, path, body) + req := httptest.NewRequestWithContext(ctx, method, path, body) recorder := httptest.NewRecorder() t.Logf("--> %s %s", method, path) diff --git a/internal/riveruicmd/auth_middleware_test.go b/internal/riveruicmd/auth_middleware_test.go index a892db44..03031170 100644 --- a/internal/riveruicmd/auth_middleware_test.go +++ b/internal/riveruicmd/auth_middleware_test.go @@ -58,7 +58,7 @@ func TestAuthMiddleware(t *testing.T) { //nolint:tparallel t.Parallel() handler := setup(t, "/") - req := httptest.NewRequest(http.MethodGet, "/api/jobs", nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/api/jobs", nil) recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, req) @@ -70,7 +70,7 @@ func TestAuthMiddleware(t *testing.T) { //nolint:tparallel t.Parallel() handler := setup(t, "/") - req := httptest.NewRequest(http.MethodGet, "/api/jobs", nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/api/jobs", nil) req.SetBasicAuth(basicAuthUser, basicAuthPassword) recorder := httptest.NewRecorder() @@ -84,7 +84,7 @@ func TestAuthMiddleware(t *testing.T) { //nolint:tparallel t.Parallel() handler := setup(t, "/") - req := httptest.NewRequest(http.MethodGet, "/api/health-checks/complete", nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/api/health-checks/complete", nil) recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, req) @@ -96,7 +96,7 @@ func TestAuthMiddleware(t *testing.T) { //nolint:tparallel t.Parallel() handler := setup(t, "/test-prefix") - req := httptest.NewRequest(http.MethodGet, "/test-prefix/api/health-checks/complete", nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/test-prefix/api/health-checks/complete", nil) recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, req) diff --git a/internal/riveruicmd/riveruicmd.go b/internal/riveruicmd/riveruicmd.go index 1fb47220..606e439b 100644 --- a/internal/riveruicmd/riveruicmd.go +++ b/internal/riveruicmd/riveruicmd.go @@ -77,10 +77,12 @@ func checkHealth(ctx context.Context, pathPrefix string, healthCheckName string) hostname := net.JoinHostPort(host, port) url := fmt.Sprintf("http://%s%s/api/health-checks/%s", hostname, pathPrefix, healthCheckName) + //nolint:gosec // `-healthcheck` is an operator-invoked probe of the running River UI server's own HTTP health endpoint. req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return fmt.Errorf("error constructing request to health endpoint: %w", err) } + //nolint:gosec // `-healthcheck` intentionally reuses the configured River UI endpoint and isn't treated as a security boundary here. response, err := http.DefaultClient.Do(req) if err != nil { return fmt.Errorf("error requesting health endpoint: %w", err) diff --git a/internal/riveruicmd/riveruicmd_test.go b/internal/riveruicmd/riveruicmd_test.go index 40e881a7..7b2dc201 100644 --- a/internal/riveruicmd/riveruicmd_test.go +++ b/internal/riveruicmd/riveruicmd_test.go @@ -89,7 +89,7 @@ func TestInitServer(t *testing.T) { //nolint:tparallel t.Parallel() initRes, _ := setup(t) - req := httptest.NewRequest(http.MethodGet, "/api/features", nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/api/features", nil) recorder := httptest.NewRecorder() initRes.uiHandler.ServeHTTP(recorder, req) @@ -106,7 +106,7 @@ func TestInitServer(t *testing.T) { //nolint:tparallel // Cannot be parallelized because of Setenv calls. t.Setenv("RIVER_JOB_LIST_HIDE_ARGS_BY_DEFAULT", "true") initRes, _ := setup(t) - req := httptest.NewRequest(http.MethodGet, "/api/features", nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/api/features", nil) recorder := httptest.NewRecorder() initRes.uiHandler.ServeHTTP(recorder, req) @@ -123,7 +123,7 @@ func TestInitServer(t *testing.T) { //nolint:tparallel // Cannot be parallelized because of Setenv calls. t.Setenv("RIVER_JOB_LIST_HIDE_ARGS_BY_DEFAULT", "1") initRes, _ := setup(t) - req := httptest.NewRequest(http.MethodGet, "/api/features", nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/api/features", nil) recorder := httptest.NewRecorder() initRes.uiHandler.ServeHTTP(recorder, req) @@ -198,12 +198,12 @@ func TestSilentHealthchecks_SuppressesLogs(t *testing.T) { initRes := makeServer(t, "/", true) recorder := httptest.NewRecorder() - initRes.httpServer.Handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/api/health-checks/minimal", nil)) + initRes.httpServer.Handler.ServeHTTP(recorder, httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/api/health-checks/minimal", nil)) require.Equal(t, http.StatusOK, recorder.Code) require.Empty(t, memoryHandler.records) recorder = httptest.NewRecorder() - initRes.httpServer.Handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/api/features", nil)) + initRes.httpServer.Handler.ServeHTTP(recorder, httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/api/features", nil)) require.Equal(t, http.StatusOK, recorder.Code) require.NotEmpty(t, memoryHandler.records) @@ -212,7 +212,7 @@ func TestSilentHealthchecks_SuppressesLogs(t *testing.T) { initRes = makeServer(t, "/pfx", true) recorder = httptest.NewRecorder() - initRes.httpServer.Handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/pfx/api/health-checks/minimal", nil)) + initRes.httpServer.Handler.ServeHTTP(recorder, httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/pfx/api/health-checks/minimal", nil)) require.Equal(t, http.StatusOK, recorder.Code) require.Empty(t, memoryHandler.records) @@ -221,7 +221,7 @@ func TestSilentHealthchecks_SuppressesLogs(t *testing.T) { initRes = makeServer(t, "/pfx/", true) recorder = httptest.NewRecorder() - initRes.httpServer.Handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/pfx/api/health-checks/minimal", nil)) + initRes.httpServer.Handler.ServeHTTP(recorder, httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/pfx/api/health-checks/minimal", nil)) require.Equal(t, http.StatusOK, recorder.Code) require.Empty(t, memoryHandler.records) @@ -230,7 +230,7 @@ func TestSilentHealthchecks_SuppressesLogs(t *testing.T) { initRes = makeServer(t, "/", false) recorder = httptest.NewRecorder() - initRes.httpServer.Handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/api/health-checks/minimal", nil)) + initRes.httpServer.Handler.ServeHTTP(recorder, httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/api/health-checks/minimal", nil)) require.Equal(t, http.StatusOK, recorder.Code) require.NotEmpty(t, memoryHandler.records) } diff --git a/packager/packager.go b/packager/packager.go index 5bf0c64d..4e1f8303 100644 --- a/packager/packager.go +++ b/packager/packager.go @@ -65,6 +65,11 @@ func createBundle() error { if err := os.MkdirAll(vOutputDir, 0o700); err != nil { return err } + outputRoot, err := os.OpenRoot(vOutputDir) + if err != nil { + return err + } + defer outputRoot.Close() version := module.Version{ Path: mod, @@ -79,11 +84,11 @@ func createBundle() error { return err } - if err := os.WriteFile(filepath.Join(vOutputDir, modFilename), modFileContents, 0o600); err != nil { + if err := outputRoot.WriteFile(modFilename, modFileContents, 0o600); err != nil { return err } - f, err := os.OpenFile(filepath.Join(vOutputDir, zipFilename), os.O_CREATE|os.O_WRONLY, 0o600) + f, err := outputRoot.OpenFile(zipFilename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o600) if err != nil { return err } @@ -98,7 +103,7 @@ func createBundle() error { Time: timestamp, } - infoFile, err := os.Create(filepath.Join(vOutputDir, version.Version+".info")) + infoFile, err := outputRoot.Create(version.Version + ".info") if err != nil { return err } diff --git a/riverproui/pro_handler_test.go b/riverproui/pro_handler_test.go index 8a87f70a..02bcc978 100644 --- a/riverproui/pro_handler_test.go +++ b/riverproui/pro_handler_test.go @@ -132,7 +132,7 @@ func TestProFeaturesEndpointResponse(t *testing.T) { }() recorder := httptest.NewRecorder() - req := httptest.NewRequest(http.MethodGet, "/api/features", nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/api/features", nil) handler.ServeHTTP(recorder, req) diff --git a/spa_response_writer_test.go b/spa_response_writer_test.go index 5943233e..b0149c90 100644 --- a/spa_response_writer_test.go +++ b/spa_response_writer_test.go @@ -1,6 +1,7 @@ package riverui import ( + "context" "net/http" "net/http/httptest" "strings" @@ -137,7 +138,7 @@ func TestServeIndexHTMLTemplateCaching(t *testing.T) { } func performRequest(handler http.Handler, method string, acceptHeaders []string) *httptest.ResponseRecorder { - req := httptest.NewRequest(method, "/", nil) + req := httptest.NewRequestWithContext(context.Background(), method, "/", nil) for _, header := range acceptHeaders { req.Header.Add("Accept", header) }