diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index cb42e57176e..456292ec499 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -333,7 +333,7 @@ jobs: uses: ./.github/actions/pnpm-install - name: Install Go mise tools - run: ./.github/scripts/retry.sh -- mise install --locked go:github.com/golangci/golangci-lint/cmd/golangci-lint go:github.com/coder/paralleltestctx/cmd/paralleltestctx go:github.com/rhysd/actionlint/cmd/actionlint + run: ./.github/scripts/retry.sh -- mise install --locked go:github.com/golangci/golangci-lint/v2/cmd/golangci-lint go:github.com/coder/paralleltestctx/cmd/paralleltestctx go:github.com/rhysd/actionlint/cmd/actionlint - name: Get golangci-lint cache dir run: | diff --git a/.golangci.yaml b/.golangci.yaml index 07c12dac4f0..cb147e92ad2 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,294 +1,220 @@ -# See https://golangci-lint.run/usage/configuration/ -# Over time we should try tightening some of these. - -linters-settings: - dupl: - # goal: 100 - threshold: 412 - - depguard: - rules: - aibridge_import_isolation: - list-mode: lax - files: - - "aibridge/*.go" - - "aibridge/**/*.go" - allow: - - $gostd - - github.com/coder/coder/v2/aibridge - - github.com/coder/coder/v2/buildinfo - deny: - - pkg: github.com/coder/coder/v2 - desc: aibridge code must not import coder packages outside aibridge; buildinfo is the only exception - - exhaustruct: - include: - # Gradually extend to cover more of the codebase. - - 'httpmw\.\w+' - # We want to enforce all values are specified when inserting or updating - # a database row. Ref: #9936 - - 'github.com/coder/coder/v2/coderd/database\.[^G][^e][^t]\w+Params' - gocognit: - min-complexity: 300 - - goconst: - min-len: 4 # Min length of string consts (def 3). - min-occurrences: 3 # Min number of const occurrences (def 3). - - gocritic: - enabled-checks: - # - appendAssign - # - appendCombine - # - assignOp - # - badCall - - badLock - - badRegexp - - boolExprSimplify - # - builtinShadow - - builtinShadowDecl - # - commentedOutCode - - commentedOutImport - - deferUnlambda - # - deprecatedComment - # - docStub - - dupImport - # - elseif - - emptyFallthrough - # - emptyStringTest - # - equalFold - # - evalOrder - # - exitAfterDefer - # - exposedSyncMutex - # - filepathJoin - - hexLiteral - # - httpNoBody - # - hugeParam - # - ifElseChain - # - importShadow - - indexAlloc - - initClause - - methodExprCall - # - nestingReduce - - nilValReturn - # - octalLiteral - # - paramTypeCombine - # - preferStringWriter - # - preferWriteByte - # - ptrToRefParam - # - rangeExprCopy - # - rangeValCopy - - regexpPattern - # - regexpSimplify - - ruleguard - # - sloppyReassign - - sortSlice - - sprintfQuotedString - - sqlQuery - # - stringConcatSimplify - # - stringXbytes - # - suspiciousSorting - - truncateCmp - - typeAssertChain - # - typeDefFirst - # - typeUnparen - # - unlabelStmt - # - unlambda - # - unnamedResult - # - unnecessaryBlock - # - unnecessaryDefer - # - unslice - - weakCond - # - whyNoLint - # - wrapperFunc - # - yodaStyleExpr - settings: - ruleguard: - failOn: all - rules: "${configDir}/scripts/rules.go" - - staticcheck: - # https://staticcheck.io/docs/options#checks - # We disable SA1019 because it gets angry about our usage of xerrors. We - # intentionally xerrors because stack frame support didn't make it into the - # stdlib port. - checks: ["all", "-SA1019"] - - goimports: - local-prefixes: coder.com,cdr.dev,go.coder.com,github.com/cdr,github.com/coder - - importas: - no-unaliased: true - - misspell: - locale: US - ignore-words: - - trialer - - nestif: - # goal: 10 - min-complexity: 20 - - revive: - # see https://github.com/mgechev/revive#available-rules for details. - ignore-generated-header: true - severity: warning - rules: - - name: atomic - - name: bare-return - - name: blank-imports - - name: bool-literal-in-expr - - name: call-to-gc - - name: confusing-naming - - name: confusing-results - - name: constant-logical-expr - - name: context-as-argument - - name: context-keys-type - - name: deep-exit - - name: defer - - name: dot-imports - - name: duplicated-imports - - name: early-return - - name: empty-block - - name: empty-lines - - name: error-naming - - name: error-return - - name: error-strings - - name: errorf - - name: exported - - name: flag-parameter - - name: get-return - - name: identical-branches - - name: if-return - - name: import-shadowing - - name: increment-decrement - - name: indent-error-flow - # - name: modifies-parameter - - name: modifies-value-receiver - - name: package-comments - - name: range - - name: receiver-naming - - name: redefines-builtin-id - - name: string-of-int - - name: struct-tag - - name: superfluous-else - - name: time-naming - - name: unconditional-recursion - - name: unexported-naming - - name: unexported-return - - name: unhandled-error - - name: unnecessary-stmt - - name: unreachable-code - - name: unused-parameter - exclude: "**/*_test.go" - - name: unused-receiver - - name: var-declaration - - name: var-naming - - name: waitgroup-by-value - usetesting: - # Only os-setenv is enabled because we migrated to usetesting from another linter that - # only covered os-setenv. - os-setenv: true - os-create-temp: false - os-mkdir-temp: false - os-temp-dir: false - os-chdir: false - context-background: false - context-todo: false - - # irrelevant as of Go v1.22: https://go.dev/blog/loopvar-preview - govet: - disable: - - loopclosure - gosec: - excludes: - # Implicit memory aliasing of items from a range statement (irrelevant as of Go v1.22) - - G601 - -issues: - exclude-dirs: - - node_modules - - .git - - exclude-files: - - scripts/rules.go - - # Rules listed here: https://github.com/securego/gosec#available-rules - exclude-rules: - - path: _test\.go - linters: - # We use assertions rather than explicitly checking errors in tests - - errcheck - - forcetypeassert - - exhaustruct # This is unhelpful in tests. - - path: scripts/* - linters: - - exhaustruct - - path: scripts/rules.go - linters: - - ALL - - fix: true - max-issues-per-linter: 0 - max-same-issues: 0 - -run: - timeout: 10m - -# Over time, add more and more linters from -# https://golangci-lint.run/usage/linters/ as the code improves. +version: "2" linters: - disable-all: true + default: none enable: - asciicheck - bidichk - bodyclose - depguard - dogsled + - dupl - errcheck - errname - errorlint - exhaustruct - forcetypeassert - - gocritic - # gocyclo is may be useful in the future when we start caring - # about testing complexity, but for the time being we should - # create a good culture around cognitive complexity. - # - gocyclo - gocognit - - nestif - - goimports + - gocritic - gomodguard - gosec - - gosimple - govet - importas - ineffassign - makezero - misspell + - nestif - nilnil - noctx - paralleltest - revive - - # These don't work until the following issue is solved. - # https://github.com/golangci/golangci-lint/issues/2649 - # - rowserrcheck - # - sqlclosecheck - # - structcheck - # - wastedassign - - staticcheck - # In Go, it's possible for a package to test it's internal functionality - # without testing any exported functions. This is enabled to promote - # decomposing a package before testing it's internals. A function caller - # should be able to test most of the functionality from exported functions. - # - # There are edge-cases to this rule, but they should be carefully considered - # to avoid structural inconsistency. - testpackage - tparallel - - typecheck - unconvert - unused - usetesting - - dupl + settings: + depguard: + rules: + aibridge_import_isolation: + list-mode: lax + files: + - aibridge/*.go + - aibridge/**/*.go + allow: + - $gostd + - github.com/coder/coder/v2/aibridge + - github.com/coder/coder/v2/buildinfo + deny: + - pkg: github.com/coder/coder/v2 + desc: + aibridge code must not import coder packages outside aibridge; + buildinfo is the only exception + dupl: + threshold: 412 + exhaustruct: + include: + - httpmw\.\w+ + - github.com/coder/coder/v2/coderd/database\.[^G][^e][^t]\w+Params + gocognit: + min-complexity: 300 + goconst: + min-len: 4 + min-occurrences: 3 + gocritic: + enabled-checks: + - badLock + - badRegexp + - boolExprSimplify + - builtinShadowDecl + - commentedOutImport + - deferUnlambda + - dupImport + - emptyFallthrough + - hexLiteral + - indexAlloc + - initClause + - methodExprCall + - nilValReturn + - regexpPattern + - ruleguard + - sortSlice + - sprintfQuotedString + - sqlQuery + - truncateCmp + - typeAssertChain + - weakCond + settings: + ruleguard: + failOn: all + rules: ${base-path}/scripts/rules.go + gosec: + excludes: + - G601 + govet: + disable: + - loopclosure + importas: + no-unaliased: true + misspell: + locale: US + ignore-rules: + - trialer + nestif: + min-complexity: 20 + revive: + severity: warning + rules: + - name: atomic + - name: bare-return + - name: blank-imports + - name: bool-literal-in-expr + - name: call-to-gc + - name: confusing-naming + - name: confusing-results + - name: constant-logical-expr + - name: context-as-argument + - name: context-keys-type + - name: deep-exit + - name: defer + - name: dot-imports + - name: duplicated-imports + - name: early-return + - name: empty-block + - name: empty-lines + - name: error-naming + - name: error-return + - name: error-strings + - name: errorf + - name: exported + - name: flag-parameter + - name: get-return + - name: identical-branches + - name: if-return + - name: import-shadowing + - name: increment-decrement + - name: indent-error-flow + - name: modifies-value-receiver + - name: package-comments + - name: range + - name: receiver-naming + - name: redefines-builtin-id + - name: string-of-int + - name: struct-tag + - name: superfluous-else + - name: time-naming + - name: unconditional-recursion + - name: unexported-naming + - name: unexported-return + - name: unhandled-error + - name: unnecessary-stmt + - name: unreachable-code + - name: unused-parameter + exclude: + - "**/*_test.go" + - name: unused-receiver + - name: var-declaration + - name: var-naming + - name: waitgroup-by-value + staticcheck: + checks: + - all + - -SA1019 + usetesting: + context-background: false + context-todo: false + os-chdir: false + os-mkdir-temp: false + os-setenv: true + os-temp-dir: false + os-create-temp: false + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - linters: + - errcheck + - exhaustruct + - forcetypeassert + path: _test\.go + - linters: + - exhaustruct + path: scripts/* + - linters: + - ALL + path: scripts/rules.go + paths: + - scripts/rules.go + - node_modules + - .git + - third_party$ + - builtin$ + - examples$ +issues: + max-issues-per-linter: 0 + max-same-issues: 0 + fix: true +formatters: + enable: + - goimports + settings: + goimports: + local-prefixes: + - coder.com + - cdr.dev + - go.coder.com + - github.com/cdr + - github.com/coder + exclusions: + generated: lax + paths: + - scripts/rules.go + - node_modules + - .git + - third_party$ + - builtin$ + - examples$ diff --git a/agent/agent_test.go b/agent/agent_test.go index f11cde7467b..84e43ddfdee 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -4344,9 +4344,10 @@ func TestAgent_Metrics_SSH(t *testing.T) { for _, m := range mf.GetMetric() { assert.Equal(t, expected[i].Name, mf.GetName()) assert.Equal(t, expected[i].Type.String(), mf.GetType().String()) - if expected[i].Type == proto.Stats_Metric_GAUGE { + switch expected[i].Type { + case proto.Stats_Metric_GAUGE: assert.NoError(t, expected[i].CheckFn(m.GetGauge().GetValue()), "check fn for %s failed", expected[i].Name) - } else if expected[i].Type == proto.Stats_Metric_COUNTER { + case proto.Stats_Metric_COUNTER: assert.NoError(t, expected[i].CheckFn(m.GetCounter().GetValue()), "check fn for %s failed", expected[i].Name) } for j, lbl := range expected[i].Labels { diff --git a/agent/agentfiles/files.go b/agent/agentfiles/files.go index 1ee83e73716..df6e1cb957e 100644 --- a/agent/agentfiles/files.go +++ b/agent/agentfiles/files.go @@ -1006,10 +1006,10 @@ func buildReplacementLines(matched, searchLines []string, replace, forcedEnding case prefix > 0 && suffix > 0: prefixRLead := leadOnly(repLines[prefix-1]) suffixRLead := leadOnly(repLines[len(repLines)-suffix]) - switch { - case rLeadForI == suffixRLead: + switch rLeadForI { + case suffixRLead: refIdx = len(searchLines) - suffix - case rLeadForI == prefixRLead: + case prefixRLead: refIdx = prefix - 1 default: refIdx = len(searchLines) - suffix diff --git a/agent/agentfiles/files_test.go b/agent/agentfiles/files_test.go index 8fcdaba8105..3ec6fba9142 100644 --- a/agent/agentfiles/files_test.go +++ b/agent/agentfiles/files_test.go @@ -58,7 +58,7 @@ func (fs *testFs) Create(name string) (afero.File, error) { } // Unlike os, afero lets you create files where directories already exist and // lets you nest them underneath files, somehow. - stat, err := fs.Fs.Stat(name) + stat, err := fs.Stat(name) if err == nil && stat.IsDir() { return nil, &os.PathError{ Op: "open", @@ -66,7 +66,7 @@ func (fs *testFs) Create(name string) (afero.File, error) { Err: syscall.EISDIR, } } - stat, err = fs.Fs.Stat(filepath.Dir(name)) + stat, err = fs.Stat(filepath.Dir(name)) if err == nil && !stat.IsDir() { return nil, &os.PathError{ Op: "open", @@ -83,7 +83,7 @@ func (fs *testFs) MkdirAll(name string, mode os.FileMode) error { } // Unlike os, afero lets you create directories where files already exist and // lets you nest them underneath files somehow. - stat, err := fs.Fs.Stat(filepath.Dir(name)) + stat, err := fs.Stat(filepath.Dir(name)) if err == nil && !stat.IsDir() { return &os.PathError{ Op: "mkdir", @@ -91,7 +91,7 @@ func (fs *testFs) MkdirAll(name string, mode os.FileMode) error { Err: syscall.ENOTDIR, } } - stat, err = fs.Fs.Stat(name) + stat, err = fs.Stat(name) if err == nil && !stat.IsDir() { return &os.PathError{ Op: "mkdir", diff --git a/agent/boundarylogproxy/proxy_test.go b/agent/boundarylogproxy/proxy_test.go index 8fadeaeeed1..86b08a678b8 100644 --- a/agent/boundarylogproxy/proxy_test.go +++ b/agent/boundarylogproxy/proxy_test.go @@ -305,7 +305,7 @@ func TestServer_MessageTooLarge(t *testing.T) { defer conn.Close() // Send a message claiming to be larger than the max message size. - var length uint32 = codec.MaxMessageSizeV1 + 1 + length := codec.MaxMessageSizeV1 + 1 err = binary.Write(conn, binary.BigEndian, length) require.NoError(t, err) diff --git a/agent/reconnectingpty/server.go b/agent/reconnectingpty/server.go index d915aded34a..15f0ad4883b 100644 --- a/agent/reconnectingpty/server.go +++ b/agent/reconnectingpty/server.go @@ -64,10 +64,7 @@ func NewServer(logger slog.Logger, commandCreator *agentssh.Server, reportConnec func (s *Server) Serve(ctx, hardCtx context.Context, l net.Listener) (retErr error) { var wg sync.WaitGroup - for { - if ctx.Err() != nil { - break - } + for ctx.Err() == nil { conn, err := l.Accept() if err != nil { s.logger.Debug(ctx, "accept pty failed", slog.Error(err)) diff --git a/agent/unit/manager.go b/agent/unit/manager.go index 8805abfc7a9..2547929d9fd 100644 --- a/agent/unit/manager.go +++ b/agent/unit/manager.go @@ -277,7 +277,7 @@ func (m *Manager) GetUnmetDependencies(unit ID) ([]Dependency, error) { return nil, err } - var unmetDependencies []Dependency = slice.Filter(allDependencies, func(dependency Dependency) bool { + unmetDependencies := slice.Filter(allDependencies, func(dependency Dependency) bool { return !dependency.IsSatisfied }) diff --git a/agent/x/agentdesktop/api_test.go b/agent/x/agentdesktop/api_test.go index a8c232d9785..50d2ed453f5 100644 --- a/agent/x/agentdesktop/api_test.go +++ b/agent/x/agentdesktop/api_test.go @@ -162,7 +162,7 @@ func (f *fakeDesktop) StartRecording(_ context.Context, recordingID string) erro if err != nil { return err } - _, _ = tmpFile.Write([]byte(fmt.Sprintf("fake-mp4-data-%s-%d", recordingID, f.startCount))) + _, _ = fmt.Fprintf(tmpFile, "fake-mp4-data-%s-%d", recordingID, f.startCount) _ = tmpFile.Close() f.recordings[recordingID] = tmpFile.Name() return nil @@ -257,9 +257,9 @@ func (f *oversizedFakeDesktop) StopRecording(ctx context.Context, recordingID st artifact.Reader.Close() // Look up the path from the fakeDesktop recordings. - f.fakeDesktop.recMu.Lock() - path := f.fakeDesktop.recordings[recordingID] - f.fakeDesktop.recMu.Unlock() + f.recMu.Lock() + path := f.recordings[recordingID] + f.recMu.Unlock() // Expand the file to exceed the maximum recording size. if err := os.Truncate(path, workspacesdk.MaxRecordingSize+1); err != nil { diff --git a/agent/x/agentdesktop/portabledesktop.go b/agent/x/agentdesktop/portabledesktop.go index 99fa422db4a..2b9fdf727e4 100644 --- a/agent/x/agentdesktop/portabledesktop.go +++ b/agent/x/agentdesktop/portabledesktop.go @@ -129,7 +129,7 @@ func (p *portableDesktop) Start(ctx context.Context) (DisplayConfig, error) { // If we have an existing session, check if it's still alive. if p.session != nil { - if !(p.session.cmd.ProcessState != nil && p.session.cmd.ProcessState.Exited()) { + if p.session.cmd.ProcessState == nil || !p.session.cmd.ProcessState.Exited() { return DisplayConfig{ Width: p.session.width, Height: p.session.height, diff --git a/aibridge/intercept/chatcompletions/blocking.go b/aibridge/intercept/chatcompletions/blocking.go index 10733ca5905..5a55c3a39f9 100644 --- a/aibridge/intercept/chatcompletions/blocking.go +++ b/aibridge/intercept/chatcompletions/blocking.go @@ -58,7 +58,7 @@ func (*BlockingInterception) Streaming() bool { } func (i *BlockingInterception) TraceAttributes(r *http.Request) []attribute.KeyValue { - return i.interceptionBase.baseTraceAttributes(r, false) + return i.baseTraceAttributes(r, false) } func (i *BlockingInterception) ProcessRequest(w http.ResponseWriter, r *http.Request) (outErr error) { diff --git a/aibridge/intercept/chatcompletions/paramswrap.go b/aibridge/intercept/chatcompletions/paramswrap.go index da1d0a3cfa1..86d1a130b08 100644 --- a/aibridge/intercept/chatcompletions/paramswrap.go +++ b/aibridge/intercept/chatcompletions/paramswrap.go @@ -41,11 +41,11 @@ func (c *ChatCompletionNewParamsWrapper) UnmarshalJSON(raw []byte) error { c.Stream = gjson.GetBytes(raw, "stream").Bool() if c.Stream { - c.ChatCompletionNewParams.StreamOptions = openai.ChatCompletionStreamOptionsParam{ + c.StreamOptions = openai.ChatCompletionStreamOptionsParam{ IncludeUsage: openai.Bool(true), // Always include usage when streaming. } } else { - c.ChatCompletionNewParams.StreamOptions = openai.ChatCompletionStreamOptionsParam{} + c.StreamOptions = openai.ChatCompletionStreamOptionsParam{} } return nil diff --git a/aibridge/intercept/chatcompletions/streaming.go b/aibridge/intercept/chatcompletions/streaming.go index a947201161d..b9fdf0715fd 100644 --- a/aibridge/intercept/chatcompletions/streaming.go +++ b/aibridge/intercept/chatcompletions/streaming.go @@ -61,7 +61,7 @@ func (*StreamingInterception) Streaming() bool { } func (i *StreamingInterception) TraceAttributes(r *http.Request) []attribute.KeyValue { - return i.interceptionBase.baseTraceAttributes(r, true) + return i.baseTraceAttributes(r, true) } // ProcessRequest handles a request to /v1/chat/completions. diff --git a/aibridge/intercept/messages/base.go b/aibridge/intercept/messages/base.go index a3e98fda0d7..89793f828db 100644 --- a/aibridge/intercept/messages/base.go +++ b/aibridge/intercept/messages/base.go @@ -534,14 +534,14 @@ func (i *interceptionBase) writeUpstreamError(w http.ResponseWriter, antErr *Res i.logger.Warn(context.Background(), "failed to marshal upstream error", slog.Error(err), slog.F("error_payload", fmt.Sprintf("%+v", antErr))) // Response has to match expected format. // See https://docs.claude.com/en/api/errors#error-shapes. - _, _ = w.Write([]byte(fmt.Sprintf(`{ + _, _ = fmt.Fprintf(w, `{ "type":"error", "error": { "type": "error", "message":"error marshaling upstream error" }, "request_id": "%s" -}`, i.ID().String()))) +}`, i.ID().String()) } else { _, _ = w.Write(out) } diff --git a/aibridge/intercept/messages/blocking.go b/aibridge/intercept/messages/blocking.go index 9bcffb40973..992110b867c 100644 --- a/aibridge/intercept/messages/blocking.go +++ b/aibridge/intercept/messages/blocking.go @@ -56,7 +56,7 @@ func (i *BlockingInterception) Setup(logger slog.Logger, rec recorder.Recorder, } func (i *BlockingInterception) TraceAttributes(r *http.Request) []attribute.KeyValue { - return i.interceptionBase.baseTraceAttributes(r, false) + return i.baseTraceAttributes(r, false) } func (*BlockingInterception) Streaming() bool { diff --git a/aibridge/intercept/messages/streaming.go b/aibridge/intercept/messages/streaming.go index 8322de557f2..6aeacba006d 100644 --- a/aibridge/intercept/messages/streaming.go +++ b/aibridge/intercept/messages/streaming.go @@ -65,7 +65,7 @@ func (*StreamingInterception) Streaming() bool { } func (i *StreamingInterception) TraceAttributes(r *http.Request) []attribute.KeyValue { - return i.interceptionBase.baseTraceAttributes(r, true) + return i.baseTraceAttributes(r, true) } // ProcessRequest handles a request to /v1/messages. diff --git a/aibridge/intercept/responses/blocking.go b/aibridge/intercept/responses/blocking.go index 6038e2e1e6b..9bc4a183b55 100644 --- a/aibridge/intercept/responses/blocking.go +++ b/aibridge/intercept/responses/blocking.go @@ -55,7 +55,7 @@ func (*BlockingResponsesInterceptor) Streaming() bool { } func (i *BlockingResponsesInterceptor) TraceAttributes(r *http.Request) []attribute.KeyValue { - return i.responsesInterceptionBase.baseTraceAttributes(r, false) + return i.baseTraceAttributes(r, false) } func (i *BlockingResponsesInterceptor) ProcessRequest(w http.ResponseWriter, r *http.Request) (outErr error) { diff --git a/aibridge/intercept/responses/streaming.go b/aibridge/intercept/responses/streaming.go index 572de64b432..9368e1f8bba 100644 --- a/aibridge/intercept/responses/streaming.go +++ b/aibridge/intercept/responses/streaming.go @@ -63,7 +63,7 @@ func (*StreamingResponsesInterceptor) Streaming() bool { } func (i *StreamingResponsesInterceptor) TraceAttributes(r *http.Request) []attribute.KeyValue { - return i.responsesInterceptionBase.baseTraceAttributes(r, true) + return i.baseTraceAttributes(r, true) } func (i *StreamingResponsesInterceptor) ProcessRequest(w http.ResponseWriter, r *http.Request) (outErr error) { diff --git a/cli/cliui/prompt.go b/cli/cliui/prompt.go index 661c256db5c..ca038db3de5 100644 --- a/cli/cliui/prompt.go +++ b/cli/cliui/prompt.go @@ -228,19 +228,19 @@ func readSecretInput(f *os.File, w io.Writer) (string, error) { return "", err } - switch { - case r == '\r' || r == '\n': + switch r { + case '\r', '\n': // Finish on Enter if _, err := fmt.Fprint(w, "\r\n"); err != nil { return "", err } return string(runes), nil - case r == 3: + case 3: // Ctrl+C return "", ErrCanceled - case r == 127 || r == '\b': + case 127, '\b': // Backspace/Delete: remove last rune if len(runes) > 0 { // Erase the last '*' on the screen diff --git a/cli/configssh.go b/cli/configssh.go index 2164996c1ae..f618418e5d3 100644 --- a/cli/configssh.go +++ b/cli/configssh.go @@ -461,7 +461,7 @@ func (r *RootCmd) configSSH() *serpent.Command { // TODO: Remove this in 2 months (May 31, 2023). Just return the error // and remove this 404 check. var sdkErr *codersdk.Error - if !(xerrors.As(err, &sdkErr) && sdkErr.StatusCode() == http.StatusNotFound) { + if !xerrors.As(err, &sdkErr) || sdkErr.StatusCode() != http.StatusNotFound { return xerrors.Errorf("fetch coderd config failed: %w", err) } coderdConfig.HostnamePrefix = "coder." diff --git a/cli/create.go b/cli/create.go index 325e2515c96..3507717de01 100644 --- a/cli/create.go +++ b/cli/create.go @@ -232,7 +232,7 @@ func (r *RootCmd) Create(opts CreateOptions) *serpent.Command { // If the user specified an organization via a flag or env var, the template **must** // be in that organization. Otherwise, we should throw an error. orgValue, orgValueSource := orgContext.ValueSource(inv) - if orgValue != "" && !(orgValueSource == serpent.ValueSourceDefault || orgValueSource == serpent.ValueSourceNone) { + if orgValue != "" && orgValueSource != serpent.ValueSourceDefault && orgValueSource != serpent.ValueSourceNone { selectedOrg, err := orgContext.Selected(inv, client) if err != nil { return err diff --git a/cli/create_test.go b/cli/create_test.go index b8fb1b4e64d..f29581158e3 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -877,7 +877,7 @@ func TestCreateWithRichParameters(t *testing.T) { removeTmpDirUntilSuccessAfterTest(t, tempDir) parameterFile, _ := os.CreateTemp(tempDir, "testParameterFile*.yaml") for _, param := range params { - _, err := parameterFile.WriteString(fmt.Sprintf("%s: %s\n", param.name, param.value)) + _, err := fmt.Fprintf(parameterFile, "%s: %s\n", param.name, param.value) require.NoError(t, err) } diff --git a/cli/exp_mcp.go b/cli/exp_mcp.go index 61ece46ed94..100a26a1ee1 100644 --- a/cli/exp_mcp.go +++ b/cli/exp_mcp.go @@ -736,25 +736,25 @@ func (s *mcpServer) startServer(ctx context.Context, inv *serpent.Invocation, in for _, tool := range toolsdk.All { // Skip if not allowed. if len(allowedTools) > 0 && !slices.ContainsFunc(allowedTools, func(t string) bool { - return t == tool.Tool.Name + return t == tool.Name }) { continue } // Skip user-dependent tools if no authenticated user client. if !tool.UserClientOptional && s.client == nil { - cliui.Warnf(inv.Stderr, "Tool %q requires authentication and will not be available", tool.Tool.Name) + cliui.Warnf(inv.Stderr, "Tool %q requires authentication and will not be available", tool.Name) continue } // Skip the coder_report_task tool if there is no socket client or slug. - if tool.Tool.Name == "coder_report_task" && (s.socketClient == nil || s.appStatusSlug == "") { - cliui.Warnf(inv.Stderr, "Tool %q requires the task reporter and will not be available", tool.Tool.Name) + if tool.Name == "coder_report_task" && (s.socketClient == nil || s.appStatusSlug == "") { + cliui.Warnf(inv.Stderr, "Tool %q requires the task reporter and will not be available", tool.Name) continue } coderdmcp.RegisterSDKTool(mcpSrv, tool, toolDeps) - registeredTools[tool.Tool.Name] = true + registeredTools[tool.Name] = true } // Skip prompts whose referenced tools are unavailable so clients are diff --git a/cli/exp_scaletest.go b/cli/exp_scaletest.go index d8979b675ab..b0c79f0a049 100644 --- a/cli/exp_scaletest.go +++ b/cli/exp_scaletest.go @@ -249,7 +249,7 @@ func (s *scaletestStrategyFlags) attach(opts *serpent.OptionSet) { } func (s *scaletestStrategyFlags) toStrategy() harness.ExecutionStrategy { - return s.timeoutFlags.wrapStrategy(s.concurrencyFlags.toStrategy()) + return s.wrapStrategy(s.concurrencyFlags.toStrategy()) } type scaleTestOutputFormat string @@ -1715,10 +1715,10 @@ func (r *RootCmd) scaletestDashboard() *serpent.Command { return err } - if !(interval > 0) { + if interval <= 0 { return xerrors.Errorf("--interval must be greater than zero") } - if !(jitter < interval) { + if jitter >= interval { return xerrors.Errorf("--jitter must be less than --interval") } targetUserStart, targetUserEnd, err := parseTargetRange("users", targetUsers) diff --git a/cli/root.go b/cli/root.go index ecc2c25f940..747e01f971e 100644 --- a/cli/root.go +++ b/cli/root.go @@ -1505,7 +1505,7 @@ func formatCoderSDKError(from string, err *codersdk.Error, opts *formatOpts) str if opts.Verbose { // If all these fields are empty, then do not print this information. // This can occur if the error is being used outside the api. - if !(err.Method() == "" && err.URL() == "" && err.StatusCode() == 0) { + if err.Method() != "" || err.URL() != "" || err.StatusCode() != 0 { _, _ = str.WriteString(pretty.Sprint(headLineStyle(), fmt.Sprintf("API request error to \"%s:%s\". Status code %d", err.Method(), err.URL(), err.StatusCode()))) _, _ = str.WriteString("\n") } diff --git a/cli/server.go b/cli/server.go index b0f344694a1..cf87254fbcf 100644 --- a/cli/server.go +++ b/cli/server.go @@ -446,7 +446,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd. } if vals.AccessURL.String() != "" && - !(vals.AccessURL.Scheme == "http" || vals.AccessURL.Scheme == "https") { + (vals.AccessURL.Scheme != "http" && vals.AccessURL.Scheme != "https") { return xerrors.Errorf("access-url must include a scheme (e.g. 'http://' or 'https://)") } @@ -1212,7 +1212,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd. if vals.Prometheus.Enable { // Agent metrics require reference to the tailnet coordinator, so must be initiated after Coder API. - closeAgentsFunc, err := prometheusmetrics.Agents(ctx, logger, options.PrometheusRegistry, coderAPI.Database, &coderAPI.TailnetCoordinator, coderAPI.DERPMap, coderAPI.Options.AgentInactiveDisconnectTimeout, 0) + closeAgentsFunc, err := prometheusmetrics.Agents(ctx, logger, options.PrometheusRegistry, coderAPI.Database, &coderAPI.TailnetCoordinator, coderAPI.DERPMap, coderAPI.AgentInactiveDisconnectTimeout, 0) if err != nil { return xerrors.Errorf("register agents prometheus metric: %w", err) } @@ -2925,7 +2925,7 @@ func ConfigureHTTPServers(logger slog.Logger, inv *serpent.Invocation, cfg *code } if cfg.AccessURL.String() != "" && - !(cfg.AccessURL.Scheme == "http" || cfg.AccessURL.Scheme == "https") { + (cfg.AccessURL.Scheme != "http" && cfg.AccessURL.Scheme != "https") { return nil, xerrors.Errorf("access-url must include a scheme (e.g. 'http://' or 'https://)") } diff --git a/cli/util.go b/cli/util.go index 9f86f3cbc95..3f3fcf83ba4 100644 --- a/cli/util.go +++ b/cli/util.go @@ -27,7 +27,7 @@ var ( func userSetOption(inv *serpent.Invocation, flagName string) bool { for _, opt := range inv.Command.Options { if opt.Name == flagName { - return !(opt.ValueSource == serpent.ValueSourceNone || opt.ValueSource == serpent.ValueSourceDefault) + return opt.ValueSource != serpent.ValueSourceNone && opt.ValueSource != serpent.ValueSourceDefault } } return false diff --git a/cli/vscodessh.go b/cli/vscodessh.go index eb91950f0ab..03c22b8dc8c 100644 --- a/cli/vscodessh.go +++ b/cli/vscodessh.go @@ -128,7 +128,7 @@ func (r *RootCmd) vscodeSSH() *serpent.Command { appearanceCfg, err := client.Appearance(ctx) if err != nil { var sdkErr *codersdk.Error - if !(xerrors.As(err, &sdkErr) && sdkErr.StatusCode() == http.StatusNotFound) { + if !xerrors.As(err, &sdkErr) || sdkErr.StatusCode() != http.StatusNotFound { return xerrors.Errorf("get appearance config: %w", err) } appearanceCfg.DocsURL = codersdk.DefaultDocsURL() diff --git a/cmd/cliui/main.go b/cmd/cliui/main.go index 6a363a34046..c73ec502545 100644 --- a/cmd/cliui/main.go +++ b/cmd/cliui/main.go @@ -174,16 +174,16 @@ func main() { Output: fmt.Sprintf("Some log %d", count), Level: codersdk.LogLevelInfo, } - switch { - case count == 10: + switch count { + case 10: log.Stage = "Setting Up" - case count == 20: + case 20: log.Stage = "Executing Hook" - case count == 30: + case 30: log.Stage = "Parsing Variables" - case count == 40: + case 40: log.Stage = "Provisioning" - case count == 50: + case 50: log.Stage = "Cleaning Up" } if count%5 == 0 { diff --git a/coderd/agentapi/api.go b/coderd/agentapi/api.go index ce697bc4826..2175505921f 100644 --- a/coderd/agentapi/api.go +++ b/coderd/agentapi/api.go @@ -297,7 +297,7 @@ func (a *API) Serve(ctx context.Context, l net.Listener) error { return xerrors.Errorf("create agent API server: %w", err) } - if err := a.ResourcesMonitoringAPI.InitMonitors(ctx); err != nil { + if err := a.InitMonitors(ctx); err != nil { return xerrors.Errorf("initialize resource monitoring: %w", err) } diff --git a/coderd/agentapi/metadatabatcher/metadata_batcher.go b/coderd/agentapi/metadatabatcher/metadata_batcher.go index 25b09d2dcde..d0b8dffe6d9 100644 --- a/coderd/agentapi/metadatabatcher/metadata_batcher.go +++ b/coderd/agentapi/metadatabatcher/metadata_batcher.go @@ -192,7 +192,7 @@ func (b *Batcher) Close() { // to the same metadata key for the same agent are deduplicated in the batch, // keeping only the value with the most recent collectedAt timestamp. func (b *Batcher) Add(agentID uuid.UUID, keys []string, values []string, errors []string, collectedAt []time.Time) error { - if !(len(keys) == len(values) && len(values) == len(errors) && len(errors) == len(collectedAt)) { + if len(keys) != len(values) || len(values) != len(errors) || len(errors) != len(collectedAt) { return xerrors.Errorf("invalid Add call, all inputs must have the same number of items; keys: %d, values: %d, errors: %d, collectedAt: %d", len(keys), len(values), len(errors), len(collectedAt)) } diff --git a/coderd/aibridged.go b/coderd/aibridged.go index e7c8295fed0..6f946bb6611 100644 --- a/coderd/aibridged.go +++ b/coderd/aibridged.go @@ -43,7 +43,7 @@ func (api *API) RegisterInMemoryAIBridgedHTTPHandler(srv http.Handler) { api.aiGatewayHandler = srv factory := aibridged.NewTransportFactory(http.StripPrefix(agplaibridge.AIGatewayRootPath, srv)) - var asInterface agplaibridge.TransportFactory = factory + asInterface := factory api.AIBridgeTransportFactory.Store(&asInterface) } diff --git a/coderd/aitasks.go b/coderd/aitasks.go index 545db5d0896..9a598ff2714 100644 --- a/coderd/aitasks.go +++ b/coderd/aitasks.go @@ -383,12 +383,12 @@ func deriveTaskCurrentState( ws.LatestBuild.Status == codersdk.WorkspaceStatusStarting: message = fmt.Sprintf("Workspace is %s", ws.LatestBuild.Status) case taskAgentLifecycle != nil: - switch { - case *taskAgentLifecycle == codersdk.WorkspaceAgentLifecycleCreated: + switch *taskAgentLifecycle { + case codersdk.WorkspaceAgentLifecycleCreated: message = "Agent is connecting" - case *taskAgentLifecycle == codersdk.WorkspaceAgentLifecycleStarting: + case codersdk.WorkspaceAgentLifecycleStarting: message = "Agent is starting" - case *taskAgentLifecycle == codersdk.WorkspaceAgentLifecycleReady: + case codersdk.WorkspaceAgentLifecycleReady: if taskAppHealth != nil && *taskAppHealth == codersdk.WorkspaceAppHealthInitializing { message = "App is initializing" } else { @@ -572,7 +572,7 @@ func (api *API) taskGet(rw http.ResponseWriter, r *http.Request) { workspace, data.builds[0], data.templates[0], - api.Options.AllowWorkspaceRenames, + api.AllowWorkspaceRenames, appStatus, ) if err != nil { diff --git a/coderd/aitasks_test.go b/coderd/aitasks_test.go index 0d16cd6c520..5668163993f 100644 --- a/coderd/aitasks_test.go +++ b/coderd/aitasks_test.go @@ -2377,10 +2377,11 @@ func TestTasksNotification(t *testing.T) { startedAt sql.NullTime readyAt sql.NullTime ) - if tc.agentLifecycle == database.WorkspaceAgentLifecycleStateReady { + switch tc.agentLifecycle { + case database.WorkspaceAgentLifecycleStateReady: startedAt = sql.NullTime{Time: clock.Now(), Valid: true} readyAt = sql.NullTime{Time: clock.Now(), Valid: true} - } else if tc.agentLifecycle == database.WorkspaceAgentLifecycleStateStarting { + case database.WorkspaceAgentLifecycleStateStarting: startedAt = sql.NullTime{Time: clock.Now(), Valid: true} } diff --git a/coderd/audit/request.go b/coderd/audit/request.go index 944c0a891da..fed41ba5df9 100644 --- a/coderd/audit/request.go +++ b/coderd/audit/request.go @@ -93,7 +93,7 @@ func ResourceTarget[T Auditable](tgt T) string { case database.GitSSHKey: return typed.PublicKey case database.AuditableGroup: - return typed.Group.Name + return typed.Name case database.APIKey: if typed.TokenName != "nil" { return typed.TokenName @@ -206,7 +206,7 @@ func ResourceID[T Auditable](tgt T) uuid.UUID { case database.GitSSHKey: return typed.UserID case database.AuditableGroup: - return typed.Group.ID + return typed.ID case database.APIKey: return typed.UserID case database.License: diff --git a/coderd/authlink/authlink.go b/coderd/authlink/authlink.go index 1f3f177f557..0d3a5d1f536 100644 --- a/coderd/authlink/authlink.go +++ b/coderd/authlink/authlink.go @@ -46,10 +46,10 @@ func AnalyzeOIDCLinks(ctx context.Context, db database.Store, expectedIssuer str for _, row := range rows { count := int(row.Count) analysis.Total += count - switch { - case row.IssuerPrefix == "": + switch row.IssuerPrefix { + case "": analysis.Unlinked += count - case row.IssuerPrefix == expectedIssuer: + case expectedIssuer: analysis.CorrectIssuer += count default: analysis.MismatchedCounts[row.IssuerPrefix] += count diff --git a/coderd/coderd.go b/coderd/coderd.go index 4a5efba16c4..1ce598fcecd 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -988,8 +988,8 @@ func New(options *Options) *API { } api.NetworkTelemetryBatcher = tailnet.NewNetworkTelemetryBatcher( quartz.NewReal(), - api.Options.NetworkTelemetryBatchFrequency, - api.Options.NetworkTelemetryBatchMaxSize, + api.NetworkTelemetryBatchFrequency, + api.NetworkTelemetryBatchMaxSize, api.handleNetworkTelemetry, ) if options.CoordinatorResumeTokenProvider == nil { @@ -998,10 +998,10 @@ func New(options *Options) *API { api.TailnetClientService, err = tailnet.NewClientService(tailnet.ClientServiceOptions{ Logger: api.Logger.Named("tailnetclient"), CoordPtr: &api.TailnetCoordinator, - DERPMapUpdateFrequency: api.Options.DERPMapUpdateFrequency, + DERPMapUpdateFrequency: api.DERPMapUpdateFrequency, DERPMapFn: api.DERPMap, NetworkTelemetryHandler: api.NetworkTelemetryBatcher.Handler, - ResumeTokenProvider: api.Options.CoordinatorResumeTokenProvider, + ResumeTokenProvider: api.CoordinatorResumeTokenProvider, WorkspaceUpdatesProvider: api.UpdatesProvider, }) if err != nil { @@ -2743,10 +2743,10 @@ func (api *API) CreateInMemoryTaggedProvisionerDaemon(dialCtx context.Context, n func (api *API) DERPMap() *tailcfg.DERPMap { fn := api.DERPMapper.Load() if fn != nil { - return (*fn)(api.Options.BaseDERPMap) + return (*fn)(api.BaseDERPMap) } - return api.Options.BaseDERPMap + return api.BaseDERPMap } // nolint:revive diff --git a/coderd/coderd_test.go b/coderd/coderd_test.go index 77a41e379dc..16dda77f86a 100644 --- a/coderd/coderd_test.go +++ b/coderd/coderd_test.go @@ -441,12 +441,12 @@ func TestDERPMetrics(t *testing.T) { _, _, api := coderdtest.NewWithAPI(t, nil) - require.NotNil(t, api.Options.DERPServer, "DERP server should be configured") - require.NotNil(t, api.Options.PrometheusRegistry, "Prometheus registry should be configured") + require.NotNil(t, api.DERPServer, "DERP server should be configured") + require.NotNil(t, api.PrometheusRegistry, "Prometheus registry should be configured") // The registry is created internally by coderd. Gather from it // to verify DERP metrics were registered during startup. - metrics, err := api.Options.PrometheusRegistry.Gather() + metrics, err := api.PrometheusRegistry.Gather() require.NoError(t, err) names := make(map[string]struct{}) @@ -518,7 +518,7 @@ func TestWebSocketProbeMetrics(t *testing.T) { // Assert the probe metric was recorded. testutil.Eventually(ctx, t, func(context.Context) bool { - metrics, err := api.Options.PrometheusRegistry.Gather() + metrics, err := api.PrometheusRegistry.Gather() assert.NoError(t, err) return testutil.PromCounterHasValue(t, metrics, 1, "coderd_api_websocket_probes_total", "/api/v2/notifications/inbox/watch", "ok") diff --git a/coderd/coderdtest/oidctest/idp.go b/coderd/coderdtest/oidctest/idp.go index 4bf6d0287da..5a1fb7a5055 100644 --- a/coderd/coderdtest/oidctest/idp.go +++ b/coderd/coderdtest/oidctest/idp.go @@ -1258,7 +1258,7 @@ func (f *FakeIDP) httpHandler(t testing.TB) http.Handler { mux.Handle(revokeTokenPath, http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { if f.revokeTokenGitHubFormat { u, p, ok := r.BasicAuth() - if !ok || !(u == f.clientID && p == f.clientSecret) { + if !ok || (u != f.clientID || p != f.clientSecret) { httpError(rw, http.StatusForbidden, xerrors.Errorf("basic auth failed")) return } diff --git a/coderd/coderdtest/swaggerparser.go b/coderd/coderdtest/swaggerparser.go index c5cd690aaf7..2fe62ecd1ad 100644 --- a/coderd/coderdtest/swaggerparser.go +++ b/coderd/coderdtest/swaggerparser.go @@ -121,9 +121,10 @@ func parseSwaggerComment(commentGroup *ast.CommentGroup) SwaggerComment { r.model = args[2] } - if annotationName == "@Success" { + switch annotationName { + case "@Success": c.successes = append(c.successes, r) - } else if annotationName == "@Failure" { + case "@Failure": c.failures = append(c.failures, r) } case "@Param": diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index 4a45c0fb9b1..2a776824d77 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -2283,8 +2283,7 @@ func (q *querier) DeleteExpiredAPIKeys(ctx context.Context, arg database.DeleteE func (q *querier) DeleteExternalAuthLink(ctx context.Context, arg database.DeleteExternalAuthLinkParams) error { return fetchAndExec(q.log, q.auth, policy.ActionUpdatePersonal, func(ctx context.Context, arg database.DeleteExternalAuthLinkParams) (database.ExternalAuthLink, error) { - //nolint:gosimple - return q.db.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{UserID: arg.UserID, ProviderID: arg.ProviderID}) + return q.db.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams(arg)) }, q.db.DeleteExternalAuthLink)(ctx, arg) } @@ -9028,7 +9027,7 @@ func (q *querier) UpsertChatTitleGenerationModelOverride(ctx context.Context, va return q.db.UpsertChatTitleGenerationModelOverride(ctx, value) } -//nolint:revive // Parameter name matches the generated querier interface. +//nolint:revive,staticcheck // Parameter name matches the generated querier interface. func (q *querier) UpsertChatWorkspaceTTL(ctx context.Context, workspaceTtl string) error { if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceDeploymentConfig); err != nil { return err diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go index 841ae296dc6..792f5fb9416 100644 --- a/coderd/database/dbgen/dbgen.go +++ b/coderd/database/dbgen/dbgen.go @@ -803,7 +803,7 @@ func WorkspaceAgentScriptTiming(t testing.TB, db database.Store, orig database.W } // Some tests run WorkspaceAgentScriptTiming in a loop and run into // a unique violation - 2 rows get the same started_at value. - if (database.IsUniqueViolation(err, database.UniqueWorkspaceAgentScriptTimingsScriptIDStartedAtKey) && orig.StartedAt == time.Time{}) { + if (database.IsUniqueViolation(err, database.UniqueWorkspaceAgentScriptTimingsScriptIDStartedAtKey) && orig.StartedAt.Equal(time.Time{})) { // Wait 1 millisecond so dbtime.Now() changes time.Sleep(time.Millisecond * 1) continue @@ -1174,7 +1174,7 @@ func GroupMember(t testing.TB, db database.Store, member database.GroupMemberTab require.NotEqual(t, member.UserID, uuid.Nil, "A user id is required to use 'dbgen.GroupMember', use 'dbgen.User'.") require.NotEqual(t, member.GroupID, uuid.Nil, "A group id is required to use 'dbgen.GroupMember', use 'dbgen.Group'.") - //nolint:gosimple + //nolint:staticcheck err := db.InsertGroupMember(genCtx, database.InsertGroupMemberParams{ UserID: member.UserID, GroupID: member.GroupID, diff --git a/coderd/database/dbtestutil/postgres.go b/coderd/database/dbtestutil/postgres.go index a55a99f972c..f24279f2689 100644 --- a/coderd/database/dbtestutil/postgres.go +++ b/coderd/database/dbtestutil/postgres.go @@ -197,8 +197,8 @@ func createDatabaseFromTemplate(t TBSubset, connParams ConnectionParams, db *sql // Template database already exists and we successfully created the new database. return nil } - tplDbDoesNotExistOccurred := strings.Contains(err.Error(), "template database") && strings.Contains(err.Error(), "does not exist") - if (tplDbDoesNotExistOccurred && !emptyTemplateDBName) || !tplDbDoesNotExistOccurred { + tplDBDoesNotExistOccurred := strings.Contains(err.Error(), "template database") && strings.Contains(err.Error(), "does not exist") + if (tplDBDoesNotExistOccurred && !emptyTemplateDBName) || !tplDBDoesNotExistOccurred { // First and case: user passed a templateDBName that doesn't exist. // Second and case: some other error. return xerrors.Errorf("create db with template: %w", err) @@ -273,26 +273,26 @@ func createAndInitDatabase(t TBSubset, connParams ConnectionParams, db *sql.DB, if _, err := db.Exec("CREATE DATABASE " + tmpDBName); err != nil { return xerrors.Errorf("create tmp db: %w", err) } - tmpDbURL := ConnectionParams{ + tmpDBURL := ConnectionParams{ Username: connParams.Username, Password: connParams.Password, Host: connParams.Host, Port: connParams.Port, DBName: tmpDBName, }.DSN() - tmpDb, err := sql.Open("postgres", tmpDbURL) + tmpDB, err := sql.Open("postgres", tmpDBURL) if err != nil { return xerrors.Errorf("connect to template db: %w", err) } defer func() { - if err := tmpDb.Close(); err != nil { + if err := tmpDB.Close(); err != nil { t.Logf("failed to close temp db: %s\n", err.Error()) } }() - if err := initialize(tmpDb); err != nil { + if err := initialize(tmpDB); err != nil { return xerrors.Errorf("initialize: %w", err) } - if err := tmpDb.Close(); err != nil { + if err := tmpDB.Close(); err != nil { return xerrors.Errorf("close template db: %w", err) } if _, err := db.Exec("ALTER DATABASE " + tmpDBName + " RENAME TO " + name); err != nil { diff --git a/coderd/database/dbtestutil/postgres_test.go b/coderd/database/dbtestutil/postgres_test.go index ecf18c9cfde..a9c96aa7d73 100644 --- a/coderd/database/dbtestutil/postgres_test.go +++ b/coderd/database/dbtestutil/postgres_test.go @@ -58,12 +58,12 @@ func TestOpen_ValidDBFrom(t *testing.T) { require.NoError(t, err) templateDBName := "tpl_" + migrations.GetMigrationsHash()[:32] - tplDbExistsRes, err := db.Query("SELECT 1 FROM pg_database WHERE datname = $1", templateDBName) + tplDBExistsRes, err := db.Query("SELECT 1 FROM pg_database WHERE datname = $1", templateDBName) if err != nil { require.NoError(t, err) } - require.True(t, tplDbExistsRes.Next()) - require.NoError(t, tplDbExistsRes.Close()) + require.True(t, tplDBExistsRes.Next()) + require.NoError(t, tplDBExistsRes.Close()) // now populate the db with some data and use it as a new template db // to verify that dbtestutil.Open respects WithDBFrom @@ -91,13 +91,13 @@ func TestOpen_ValidDBFrom(t *testing.T) { newDsn, err := dbtestutil.Open(t, dbtestutil.WithDBFrom(freshTemplateDBName)) require.NoError(t, err) - newDb, err := sql.Open("postgres", newDsn) + newDB, err := sql.Open("postgres", newDsn) require.NoError(t, err) t.Cleanup(func() { - require.NoError(t, newDb.Close()) + require.NoError(t, newDB.Close()) }) - rows, err = newDb.Query("SELECT 1 FROM my_wonderful_table WHERE name = 'test'") + rows, err = newDB.Query("SELECT 1 FROM my_wonderful_table WHERE name = 'test'") require.NoError(t, err) require.True(t, rows.Next()) require.NoError(t, rows.Close()) diff --git a/coderd/database/legacy_chat_provider_compat.go b/coderd/database/legacy_chat_provider_compat.go index 77499379877..9783b3a2195 100644 --- a/coderd/database/legacy_chat_provider_compat.go +++ b/coderd/database/legacy_chat_provider_compat.go @@ -9,7 +9,7 @@ import ( // ChatProvider is the fixture shape accepted by dbgen.ChatProvider. // -//nolint:revive +//nolint:revive,staticcheck // Field names match the legacy generated database models. type ChatProvider struct { ID uuid.UUID Provider string @@ -29,7 +29,7 @@ type ChatProvider struct { // InsertChatProviderParams is the callback parameter shape accepted by // dbgen.ChatProvider. // -//nolint:revive +//nolint:revive,staticcheck // Field names match the legacy generated database parameters. type InsertChatProviderParams struct { Provider string DisplayName string diff --git a/coderd/database/querier_test.go b/coderd/database/querier_test.go index f39374f5814..c09f38e7313 100644 --- a/coderd/database/querier_test.go +++ b/coderd/database/querier_test.go @@ -3858,7 +3858,7 @@ func TestGetAuthorizedConnectionLogsOffset(t *testing.T) { var allLogs []database.ConnectionLog db, _ := dbtestutil.NewDB(t) authz := rbac.NewAuthorizer(prometheus.NewRegistry()) - authDb := dbauthz.New(db, authz, slogtest.Make(t, &slogtest.Options{}), coderdtest.AccessControlStorePointer()) + authDB := dbauthz.New(db, authz, slogtest.Make(t, &slogtest.Options{}), coderdtest.AccessControlStorePointer()) orgA := dbfake.Organization(t, db).Do() orgB := dbfake.Organization(t, db).Do() @@ -3891,7 +3891,7 @@ func TestGetAuthorizedConnectionLogsOffset(t *testing.T) { } for orgID, ids := range orgConnectionLogs { for _, id := range ids { - allLogs = append(allLogs, dbgen.ConnectionLog(t, authDb, database.UpsertConnectionLogParams{ + allLogs = append(allLogs, dbgen.ConnectionLog(t, authDB, database.UpsertConnectionLogParams{ WorkspaceID: wsID, WorkspaceOwnerID: user.ID, ID: id, @@ -3928,12 +3928,12 @@ func TestGetAuthorizedConnectionLogsOffset(t *testing.T) { }) // When: The user queries for connection logs - logs, err := authDb.GetConnectionLogsOffset(memberCtx, database.GetConnectionLogsOffsetParams{}) + logs, err := authDB.GetConnectionLogsOffset(memberCtx, database.GetConnectionLogsOffsetParams{}) require.NoError(t, err) // Then: No logs returned require.Len(t, logs, 0, "no logs should be returned") // And: The count matches the number of logs returned - count, err := authDb.CountConnectionLogs(memberCtx, database.CountConnectionLogsParams{}) + count, err := authDB.CountConnectionLogs(memberCtx, database.CountConnectionLogsParams{}) require.NoError(t, err) require.EqualValues(t, len(logs), count) }) @@ -3951,12 +3951,12 @@ func TestGetAuthorizedConnectionLogsOffset(t *testing.T) { }) // When: the auditor queries for connection logs - logs, err := authDb.GetConnectionLogsOffset(siteAuditorCtx, database.GetConnectionLogsOffsetParams{}) + logs, err := authDB.GetConnectionLogsOffset(siteAuditorCtx, database.GetConnectionLogsOffsetParams{}) require.NoError(t, err) // Then: All logs are returned require.ElementsMatch(t, connectionOnlyIDs(allLogs), connectionOnlyIDs(logs)) // And: The count matches the number of logs returned - count, err := authDb.CountConnectionLogs(siteAuditorCtx, database.CountConnectionLogsParams{}) + count, err := authDB.CountConnectionLogs(siteAuditorCtx, database.CountConnectionLogsParams{}) require.NoError(t, err) require.EqualValues(t, len(logs), count) }) @@ -3975,12 +3975,12 @@ func TestGetAuthorizedConnectionLogsOffset(t *testing.T) { }) // When: The auditor queries for connection logs - logs, err := authDb.GetConnectionLogsOffset(orgAuditCtx, database.GetConnectionLogsOffsetParams{}) + logs, err := authDB.GetConnectionLogsOffset(orgAuditCtx, database.GetConnectionLogsOffsetParams{}) require.NoError(t, err) // Then: Only the logs for the organization are returned require.ElementsMatch(t, orgConnectionLogs[orgID], connectionOnlyIDs(logs)) // And: The count matches the number of logs returned - count, err := authDb.CountConnectionLogs(orgAuditCtx, database.CountConnectionLogsParams{}) + count, err := authDB.CountConnectionLogs(orgAuditCtx, database.CountConnectionLogsParams{}) require.NoError(t, err) require.EqualValues(t, len(logs), count) }) @@ -4000,12 +4000,12 @@ func TestGetAuthorizedConnectionLogsOffset(t *testing.T) { }) // When: The user queries for connection logs - logs, err := authDb.GetConnectionLogsOffset(multiOrgAuditCtx, database.GetConnectionLogsOffsetParams{}) + logs, err := authDB.GetConnectionLogsOffset(multiOrgAuditCtx, database.GetConnectionLogsOffsetParams{}) require.NoError(t, err) // Then: All logs for both organizations are returned require.ElementsMatch(t, append(orgConnectionLogs[first], orgConnectionLogs[second]...), connectionOnlyIDs(logs)) // And: The count matches the number of logs returned - count, err := authDb.CountConnectionLogs(multiOrgAuditCtx, database.CountConnectionLogsParams{}) + count, err := authDB.CountConnectionLogs(multiOrgAuditCtx, database.CountConnectionLogsParams{}) require.NoError(t, err) require.EqualValues(t, len(logs), count) }) @@ -4023,12 +4023,12 @@ func TestGetAuthorizedConnectionLogsOffset(t *testing.T) { }) // When: The user queries for audit logs - logs, err := authDb.GetConnectionLogsOffset(userCtx, database.GetConnectionLogsOffsetParams{}) + logs, err := authDB.GetConnectionLogsOffset(userCtx, database.GetConnectionLogsOffsetParams{}) require.NoError(t, err) // Then: No logs are returned require.Len(t, logs, 0, "no logs should be returned") // And: The count matches the number of logs returned - count, err := authDb.CountConnectionLogs(userCtx, database.CountConnectionLogsParams{}) + count, err := authDB.CountConnectionLogs(userCtx, database.CountConnectionLogsParams{}) require.NoError(t, err) require.EqualValues(t, len(logs), count) }) @@ -6207,15 +6207,17 @@ func TestGetUserStatusCounts(t *testing.T) { case row.Date.Before(userCreatedAt): require.Equal(t, int64(0), row.Count) case row.Date.Before(firstStatusChange): - if row.Status == stc.initialStatus { + switch row.Status { + case stc.initialStatus: require.Equal(t, int64(1), row.Count) - } else if row.Status == stc.targetStatus { + case stc.targetStatus: require.Equal(t, int64(0), row.Count) } case !row.Date.After(tc.reportUntil): - if row.Status == stc.initialStatus { + switch row.Status { + case stc.initialStatus: require.Equal(t, int64(0), row.Count) - } else if row.Status == stc.targetStatus { + case stc.targetStatus: require.Equal(t, int64(1), row.Count) } default: diff --git a/coderd/database/types.go b/coderd/database/types.go index cfa518c7ca2..185b300b836 100644 --- a/coderd/database/types.go +++ b/coderd/database/types.go @@ -184,7 +184,7 @@ func (t *WorkspaceACL) Scan(src interface{}) error { return xerrors.Errorf("unexpected type %T", src) } -//nolint:revive +//nolint:revive,staticcheck // Receiver name matches the other WorkspaceACL methods in this file. func (w WorkspaceACL) RBACACL() map[string][]policy.Action { // Convert WorkspaceACL to a map of string to []policy.Action. // This is used for RBAC checks. diff --git a/coderd/debug.go b/coderd/debug.go index 5df6bda4a4b..d562f9bfea5 100644 --- a/coderd/debug.go +++ b/coderd/debug.go @@ -64,7 +64,7 @@ func (api *API) debugTailnet(rw http.ResponseWriter, r *http.Request) { // @Param force query boolean false "Force a healthcheck to run" func (api *API) debugDeploymentHealth(rw http.ResponseWriter, r *http.Request) { apiKey := httpmw.APITokenFromRequest(r) - ctx, cancel := context.WithTimeout(r.Context(), api.Options.HealthcheckTimeout) + ctx, cancel := context.WithTimeout(r.Context(), api.HealthcheckTimeout) defer cancel() // Load sections previously marked as dismissed. @@ -78,7 +78,7 @@ func (api *API) debugDeploymentHealth(rw http.ResponseWriter, r *http.Request) { // Get cached report if it exists and the requester did not force a refresh. if !forced { if report := api.healthCheckCache.Load(); report != nil { - if time.Since(report.Time) < api.Options.HealthcheckRefresh { + if time.Since(report.Time) < api.HealthcheckRefresh { formatHealthcheck(ctx, rw, r, *report, dismissed...) return } @@ -87,7 +87,7 @@ func (api *API) debugDeploymentHealth(rw http.ResponseWriter, r *http.Request) { resChan := api.healthCheckGroup.DoChan("", func() (*healthsdk.HealthcheckReport, error) { // Create a new context not tied to the request. - ctx, cancel := context.WithTimeout(context.Background(), api.Options.HealthcheckTimeout) + ctx, cancel := context.WithTimeout(context.Background(), api.HealthcheckTimeout) defer cancel() // Create and store progress tracker for timeout diagnostics. diff --git a/coderd/dynamicparameters/error.go b/coderd/dynamicparameters/error.go index 289484ee4ac..262b68898fd 100644 --- a/coderd/dynamicparameters/error.go +++ b/coderd/dynamicparameters/error.go @@ -117,10 +117,10 @@ func DiagnosticErrorString(d *hcl.Diagnostic) string { func DiagnosticsErrorString(d hcl.Diagnostics) string { count := len(d) - switch { - case count == 0: + switch count { + case 0: return "no diagnostics" - case count == 1: + case 1: return DiagnosticErrorString(d[0]) default: for _, d := range d { diff --git a/coderd/exp_chats_test.go b/coderd/exp_chats_test.go index 87e9bca9171..cfb8e00b1f9 100644 --- a/coderd/exp_chats_test.go +++ b/coderd/exp_chats_test.go @@ -659,7 +659,7 @@ func TestPostChats(t *testing.T) { OrganizationID: firstUser.OrganizationID, Enabled: true, }) - disabledCfg, err := client.Client.UpdateMCPServerConfig(ctx, enabledCfg.OrganizationID, enabledCfg.ID, codersdk.UpdateMCPServerConfigRequest{ + disabledCfg, err := client.UpdateMCPServerConfig(ctx, enabledCfg.OrganizationID, enabledCfg.ID, codersdk.UpdateMCPServerConfigRequest{ Enabled: ptr.Ref(false), }) require.NoError(t, err) @@ -734,7 +734,7 @@ func TestPostChats(t *testing.T) { }) require.NoError(t, err) - _, err = client.Client.UpdateMCPServerConfig(ctx, cfg.OrganizationID, cfg.ID, codersdk.UpdateMCPServerConfigRequest{ + _, err = client.UpdateMCPServerConfig(ctx, cfg.OrganizationID, cfg.ID, codersdk.UpdateMCPServerConfigRequest{ Enabled: ptr.Ref(false), }) require.NoError(t, err) @@ -761,7 +761,7 @@ func TestPostChats(t *testing.T) { OrganizationID: firstUser.OrganizationID, Enabled: true, }) - _, err = client.Client.UpdateMCPServerConfig(ctx, secondCfg.OrganizationID, secondCfg.ID, codersdk.UpdateMCPServerConfigRequest{ + _, err = client.UpdateMCPServerConfig(ctx, secondCfg.OrganizationID, secondCfg.ID, codersdk.UpdateMCPServerConfigRequest{ Enabled: ptr.Ref(false), }) require.NoError(t, err) @@ -1385,7 +1385,7 @@ func TestChats_ForceOnMCPServerEnforced(t *testing.T) { _ = createChatModelConfig(t, client) // An admin marks an MCP server as Force On. - forced, err := client.Client.CreateMCPServerConfig(ctx, firstUser.OrganizationID, codersdk.CreateMCPServerConfigRequest{ + forced, err := client.CreateMCPServerConfig(ctx, firstUser.OrganizationID, codersdk.CreateMCPServerConfigRequest{ DisplayName: "Forced Server", Slug: "forced-server", Transport: "streamable_http", @@ -1931,7 +1931,7 @@ func TestListChats(t *testing.T) { Pagination: codersdk.Pagination{Limit: pageSize}, } if afterID != uuid.Nil { - opts.Pagination.AfterID = afterID + opts.AfterID = afterID } page, listErr := client.ListChats(ctx, opts) require.NoError(t, listErr) @@ -11359,7 +11359,7 @@ This arrived as octet-stream. client := newChatClient(t) firstUser := coderdtest.CreateFirstUser(t, client.Client) - _, err := client.UploadChatFile(ctx, firstUser.OrganizationID, "application/octet-stream", "payload.zip", bytes.NewReader([]byte("PK"))) + _, err := client.UploadChatFile(ctx, firstUser.OrganizationID, "application/octet-stream", "payload.zip", bytes.NewReader([]byte("PK\x03\x04"))) sdkErr := requireSDKError(t, err, http.StatusBadRequest) require.Contains(t, sdkErr.Message, "Unsupported file type") }) @@ -11370,7 +11370,7 @@ This arrived as octet-stream. client := newChatClient(t) firstUser := coderdtest.CreateFirstUser(t, client.Client) - _, err := client.UploadChatFile(ctx, firstUser.OrganizationID, "application/zip", "test.zip", bytes.NewReader([]byte("PK"))) + _, err := client.UploadChatFile(ctx, firstUser.OrganizationID, "application/zip", "test.zip", bytes.NewReader([]byte("PK\x03\x04"))) requireSDKError(t, err, http.StatusBadRequest) }) @@ -11912,7 +11912,7 @@ func TestChatFileDownloadURL(t *testing.T) { // Suspending the minting user invalidates the URL because // redemption requires the token's user to still be active. - _, err = client.Client.UpdateUserStatus(ctx, member.ID.String(), codersdk.UserStatusSuspended) + _, err = client.UpdateUserStatus(ctx, member.ID.String(), codersdk.UserStatusSuspended) require.NoError(t, err) res := get(t, ctx, download.URL) diff --git a/coderd/externalauth/externalauth.go b/coderd/externalauth/externalauth.go index e4e9809fe2f..25af6510b60 100644 --- a/coderd/externalauth/externalauth.go +++ b/coderd/externalauth/externalauth.go @@ -636,7 +636,7 @@ func (c *Config) ValidateToken(ctx context.Context, token *oauth2.Token) (bool, } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token.AccessToken)) - res, err := c.InstrumentedOAuth2Config.Do(ctx, promoauth.SourceValidateToken, req) + res, err := c.Do(ctx, promoauth.SourceValidateToken, req) if err != nil { return false, nil, err } @@ -765,7 +765,7 @@ func (c *Config) AppInstallations(ctx context.Context, token string) ([]codersdk return nil, false, err } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) - res, err := c.InstrumentedOAuth2Config.Do(ctx, promoauth.SourceAppInstallations, req) + res, err := c.Do(ctx, promoauth.SourceAppInstallations, req) if err != nil { return nil, false, err } @@ -817,7 +817,7 @@ func (c *Config) RevokeToken(ctx context.Context, link database.ExternalAuthLink return false, err } - res, err := c.InstrumentedOAuth2Config.Do(ctx, promoauth.SourceRevoke, req) + res, err := c.Do(ctx, promoauth.SourceRevoke, req) if err != nil { return false, err } @@ -1634,8 +1634,8 @@ func (s *entraV1TokenSource) Token() (*oauth2.Token, error) { oauth2.SetAuthURLParam("grant_type", "refresh_token"), oauth2.SetAuthURLParam("refresh_token", refreshToken), } - if len(s.cfg.Config.Scopes) > 0 { - refreshOpts = append(refreshOpts, oauth2.SetAuthURLParam("scope", strings.Join(s.cfg.Config.Scopes, " "))) + if len(s.cfg.Scopes) > 0 { + refreshOpts = append(refreshOpts, oauth2.SetAuthURLParam("scope", strings.Join(s.cfg.Scopes, " "))) } token, err := s.cfg.Exchange(s.ctx, "", refreshOpts...) diff --git a/coderd/healthcheck/derphealth/derp.go b/coderd/healthcheck/derphealth/derp.go index cdaea4ed3cc..6cc3ef9c4ce 100644 --- a/coderd/healthcheck/derphealth/derp.go +++ b/coderd/healthcheck/derphealth/derp.go @@ -256,7 +256,7 @@ func (r *NodeReport) derpURL() *url.URL { if r.Node.HostName == "" { derpURL.Host = r.Node.IPv4 } - if r.Node.DERPPort != 0 && !(r.Node.DERPPort == 443 && derpURL.Scheme == "https") && !(r.Node.DERPPort == 80 && derpURL.Scheme == "http") { + if r.Node.DERPPort != 0 && (r.Node.DERPPort != 443 || derpURL.Scheme != "https") && (r.Node.DERPPort != 80 || derpURL.Scheme != "http") { derpURL.Host = fmt.Sprintf("%s:%d", derpURL.Host, r.Node.DERPPort) } diff --git a/coderd/healthcheck/websocket.go b/coderd/healthcheck/websocket.go index b83089ea05f..7e8837953a8 100644 --- a/coderd/healthcheck/websocket.go +++ b/coderd/healthcheck/websocket.go @@ -120,7 +120,7 @@ func (s *WebsocketEchoServer) ServeHTTP(rw http.ResponseWriter, r *http.Request) c, err := websocket.Accept(rw, r, &websocket.AcceptOptions{}) if err != nil { rw.WriteHeader(http.StatusBadRequest) - _, _ = rw.Write([]byte(fmt.Sprint("unable to accept:", err))) + _, _ = fmt.Fprint(rw, "unable to accept:", err) return } defer c.Close(websocket.StatusGoingAway, "goodbye") diff --git a/coderd/httpapi/httpapi.go b/coderd/httpapi/httpapi.go index 336f7bc95ab..c78e4b386be 100644 --- a/coderd/httpapi/httpapi.go +++ b/coderd/httpapi/httpapi.go @@ -392,7 +392,7 @@ func ServerSentEventSender(rw http.ResponseWriter, r *http.Request) ( sendEvent := func(newEvent codersdk.ServerSentEvent) error { buf := &bytes.Buffer{} - _, err := buf.WriteString(fmt.Sprintf("event: %s\n", newEvent.Type)) + _, err := fmt.Fprintf(buf, "event: %s\n", newEvent.Type) if err != nil { return err } diff --git a/coderd/httpmw/organizationparam_test.go b/coderd/httpmw/organizationparam_test.go index ce0571e8f19..5ebbc429e15 100644 --- a/coderd/httpmw/organizationparam_test.go +++ b/coderd/httpmw/organizationparam_test.go @@ -193,10 +193,10 @@ func TestOrganizationParam(t *testing.T) { assert.Equal(t, user.AvatarURL, orgMem.AvatarURL) assert.NotEmpty(t, orgMem.Roles) assert.NotZero(t, orgMem.OrganizationMember) - assert.NotEmpty(t, orgMem.OrganizationMember.CreatedAt) - assert.NotEmpty(t, orgMem.OrganizationMember.UpdatedAt) - assert.NotEmpty(t, orgMem.OrganizationMember.UserID) - assert.NotEmpty(t, orgMem.OrganizationMember.Roles) + assert.NotEmpty(t, orgMem.CreatedAt) + assert.NotEmpty(t, orgMem.UpdatedAt) + assert.NotEmpty(t, orgMem.UserID) + assert.NotEmpty(t, orgMem.Roles) orgMems := httpmw.OrganizationMembersParam(r) assert.NotZero(t, orgMems) diff --git a/coderd/idpsync/group.go b/coderd/idpsync/group.go index ec82a021ae8..d9fe3a637f6 100644 --- a/coderd/idpsync/group.go +++ b/coderd/idpsync/group.go @@ -32,7 +32,7 @@ func (AGPLIDPSync) GroupSyncEntitled() bool { func (s AGPLIDPSync) UpdateGroupSyncSettings(ctx context.Context, orgID uuid.UUID, db database.Store, settings GroupSyncSettings) error { orgResolver := s.Manager.OrganizationResolver(db, orgID) - err := s.SyncSettings.Group.SetRuntimeValue(ctx, orgResolver, &settings) + err := s.Group.SetRuntimeValue(ctx, orgResolver, &settings) if err != nil { return xerrors.Errorf("update group sync settings: %w", err) } @@ -42,7 +42,7 @@ func (s AGPLIDPSync) UpdateGroupSyncSettings(ctx context.Context, orgID uuid.UUI func (s AGPLIDPSync) GroupSyncSettings(ctx context.Context, orgID uuid.UUID, db database.Store) (*GroupSyncSettings, error) { orgResolver := s.Manager.OrganizationResolver(db, orgID) - settings, err := s.SyncSettings.Group.Resolve(ctx, orgResolver) + settings, err := s.Group.Resolve(ctx, orgResolver) if err != nil { if !xerrors.Is(err, runtimeconfig.ErrEntryNotFound) { return nil, xerrors.Errorf("resolve group sync settings: %w", err) @@ -52,7 +52,7 @@ func (s AGPLIDPSync) GroupSyncSettings(ctx context.Context, orgID uuid.UUID, db settings = &GroupSyncSettings{} // Check for legacy settings if the default org. - if s.DeploymentSyncSettings.Legacy.GroupField != "" { + if s.Legacy.GroupField != "" { defaultOrganization, err := db.GetDefaultOrganization(ctx) if err != nil { return nil, xerrors.Errorf("get default organization: %w", err) diff --git a/coderd/idpsync/organization.go b/coderd/idpsync/organization.go index c83c1b8911a..7684e812a75 100644 --- a/coderd/idpsync/organization.go +++ b/coderd/idpsync/organization.go @@ -35,7 +35,7 @@ func (AGPLIDPSync) OrganizationSyncEnabled(_ context.Context, _ database.Store) func (s AGPLIDPSync) UpdateOrganizationSyncSettings(ctx context.Context, db database.Store, settings OrganizationSyncSettings) error { rlv := s.Manager.Resolver(db) - err := s.SyncSettings.Organization.SetRuntimeValue(ctx, rlv, &settings) + err := s.Organization.SetRuntimeValue(ctx, rlv, &settings) if err != nil { return xerrors.Errorf("update organization sync settings: %w", err) } @@ -47,7 +47,7 @@ func (s AGPLIDPSync) OrganizationSyncSettings(ctx context.Context, db database.S // If this logic is ever updated, make sure to update the corresponding // checkIDPOrgSync in coderd/telemetry/telemetry.go. rlv := s.Manager.Resolver(db) - orgSettings, err := s.SyncSettings.Organization.Resolve(ctx, rlv) + orgSettings, err := s.Organization.Resolve(ctx, rlv) if err != nil { if !xerrors.Is(err, runtimeconfig.ErrEntryNotFound) { return nil, xerrors.Errorf("resolve org sync settings: %w", err) @@ -55,9 +55,9 @@ func (s AGPLIDPSync) OrganizationSyncSettings(ctx context.Context, db database.S // Default to the statically assigned settings if they exist. orgSettings = &OrganizationSyncSettings{ - Field: s.DeploymentSyncSettings.OrganizationField, - Mapping: s.DeploymentSyncSettings.OrganizationMapping, - AssignDefault: s.DeploymentSyncSettings.OrganizationAssignDefault, + Field: s.OrganizationField, + Mapping: s.OrganizationMapping, + AssignDefault: s.OrganizationAssignDefault, } } return orgSettings, nil diff --git a/coderd/idpsync/role.go b/coderd/idpsync/role.go index 410c1f8b973..67de32812ac 100644 --- a/coderd/idpsync/role.go +++ b/coderd/idpsync/role.go @@ -44,7 +44,7 @@ func (AGPLIDPSync) SiteRoleSyncEnabled() bool { func (s AGPLIDPSync) UpdateRoleSyncSettings(ctx context.Context, orgID uuid.UUID, db database.Store, settings RoleSyncSettings) error { orgResolver := s.Manager.OrganizationResolver(db, orgID) - err := s.SyncSettings.Role.SetRuntimeValue(ctx, orgResolver, &settings) + err := s.Role.SetRuntimeValue(ctx, orgResolver, &settings) if err != nil { return xerrors.Errorf("update role sync settings: %w", err) } diff --git a/coderd/jobreaper/detector.go b/coderd/jobreaper/detector.go index b0bcc2d25d1..e21a1378f38 100644 --- a/coderd/jobreaper/detector.go +++ b/coderd/jobreaper/detector.go @@ -222,7 +222,7 @@ func (d *Detector) run(t time.Time) Stats { err := reapJob(ctx, log, d.db, d.pubsub, job) if err != nil { - if !(xerrors.As(err, &acquireLockError{}) || xerrors.As(err, &jobIneligibleError{})) { + if (!xerrors.As(err, &acquireLockError{}) && !xerrors.As(err, &jobIneligibleError{})) { log.Error(ctx, "error forcefully terminating provisioner job", slog.F("type", job.Type), slog.Error(err)) } continue diff --git a/coderd/mcp_test.go b/coderd/mcp_test.go index d2a4f93b2ac..aff79d5fe75 100644 --- a/coderd/mcp_test.go +++ b/coderd/mcp_test.go @@ -1010,7 +1010,7 @@ type mcpServerConfigDeleteRaceStore struct { func (s *mcpServerConfigDeleteRaceStore) GetMCPServerConfigByID(ctx context.Context, id uuid.UUID) (database.MCPServerConfig, error) { config, err := s.Store.GetMCPServerConfigByID(ctx, id) if err == nil && s.armed.CompareAndSwap(true, false) { - if err := s.Store.DeleteMCPServerConfigByID(ctx, id); err != nil { + if err := s.DeleteMCPServerConfigByID(ctx, id); err != nil { return database.MCPServerConfig{}, err } } diff --git a/coderd/members.go b/coderd/members.go index 13918163205..21728c065d5 100644 --- a/coderd/members.go +++ b/coderd/members.go @@ -113,7 +113,7 @@ func (api *API) deleteOrganizationMember(rw http.ResponseWriter, r *http.Request Action: database.AuditActionDelete, }) ) - aReq.Old = member.OrganizationMember.Auditable(member.Username) + aReq.Old = member.Auditable(member.Username) defer commitAudit() // Note: we disallow adding OIDC users if organization sync is enabled. @@ -421,7 +421,7 @@ func (api *API) putMemberRoles(rw http.ResponseWriter, r *http.Request) { Action: database.AuditActionWrite, }) ) - aReq.Old = member.OrganizationMember.Auditable(member.Username) + aReq.Old = member.Auditable(member.Username) defer commitAudit() // Check if changing roles is allowed @@ -429,7 +429,7 @@ func (api *API) putMemberRoles(rw http.ResponseWriter, r *http.Request) { return } - if apiKey.UserID == member.OrganizationMember.UserID { + if apiKey.UserID == member.UserID { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ Message: "You cannot change your own organization roles.", Detail: "Another user with the appropriate permissions must change your roles.", diff --git a/coderd/notifications/dispatch/webhook_test.go b/coderd/notifications/dispatch/webhook_test.go index ebd41569f47..bc697aae5c3 100644 --- a/coderd/notifications/dispatch/webhook_test.go +++ b/coderd/notifications/dispatch/webhook_test.go @@ -64,7 +64,7 @@ func TestWebhook(t *testing.T) { assert.Equal(t, bodyMarkdown, payload.BodyMarkdown) w.WriteHeader(http.StatusOK) - _, err = w.Write([]byte(fmt.Sprintf("received %s", payload.MsgID))) + _, err = fmt.Fprintf(w, "received %s", payload.MsgID) assert.NoError(t, err) }, expectSuccess: true, diff --git a/coderd/prometheusmetrics/aggregator.go b/coderd/prometheusmetrics/aggregator.go index 028e1b00fb7..1e5b0e73602 100644 --- a/coderd/prometheusmetrics/aggregator.go +++ b/coderd/prometheusmetrics/aggregator.go @@ -250,7 +250,7 @@ func (a *labelAggregator) aggregate(am annotatedMetric, labels []string) error { } // Memoize based on the metric name & the unique combination of labels. - key := fmt.Sprintf("%s:%v", am.Stats_Metric.Name, labelSet.FastFingerprint()) + key := fmt.Sprintf("%s:%v", am.Name, labelSet.FastFingerprint()) // Aggregate the value based on the key. a.aggregations[key] += am.Value @@ -297,7 +297,7 @@ func (ma *MetricsAggregator) Run(ctx context.Context) func() { key := hashKey(&req, m) if val, ok := ma.store[key]; ok { - val.Stats_Metric.Value = m.Value + val.Value = m.Value val.expiryDate = req.timestamp.Add(ma.metricsCleanupInterval) ma.store[key] = val } else { diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go index dc8e3956a8e..f3d9c18f551 100644 --- a/coderd/provisionerdserver/provisionerdserver_test.go +++ b/coderd/provisionerdserver/provisionerdserver_test.go @@ -5485,7 +5485,7 @@ func (s *fakeStream) Send(j *proto.AcquiredJob) error { func (s *fakeStream) Recv() (*proto.CancelAcquire, error) { s.c.L.Lock() defer s.c.L.Unlock() - for !(s.canceled || s.closed) { + for !s.canceled && !s.closed { s.c.Wait() } if s.canceled { @@ -5528,7 +5528,7 @@ func (s *fakeStream) Close() error { func (s *fakeStream) waitForJob() (*proto.AcquiredJob, error) { s.c.L.Lock() defer s.c.L.Unlock() - for !(s.sendCalled || s.closed) { + for !s.sendCalled && !s.closed { s.c.Wait() } if s.sendCalled { diff --git a/coderd/rbac/authz.go b/coderd/rbac/authz.go index 32756525d3f..3fb873a64c8 100644 --- a/coderd/rbac/authz.go +++ b/coderd/rbac/authz.go @@ -478,7 +478,7 @@ func (a RegoAuthorizer) authorize(ctx context.Context, subject Subject, action p // The caller should use either 1 or the other (or none). // Using "AnyOrgOwner" and an OrgID is a contradiction. // An empty uuid or a nil uuid means "no org owner". - if object.AnyOrgOwner && !(object.OrgID == "" || object.OrgID == "00000000-0000-0000-0000-000000000000") { + if object.AnyOrgOwner && object.OrgID != "" && object.OrgID != "00000000-0000-0000-0000-000000000000" { return xerrors.Errorf("object cannot have 'any_org' and an 'org_id' specified, values are mutually exclusive") } diff --git a/coderd/render/markdown.go b/coderd/render/markdown.go index ed0c16bc840..e77ad93d1e0 100644 --- a/coderd/render/markdown.go +++ b/coderd/render/markdown.go @@ -146,10 +146,7 @@ func InnerTextFromMarkdown(markdown string) (out string, err error) { // after the start tag. Skip just that token (not a running depth) so a stray // or unterminated tag can't swallow the rest of the document. skipNextText := false - for { - if z.Next() == xhtml.ErrorToken { - break // includes io.EOF - } + for z.Next() != xhtml.ErrorToken { switch tok := z.Token(); tok.Type { case xhtml.StartTagToken: skipNextText = tok.Data == "script" || tok.Data == "style" diff --git a/coderd/tailnet.go b/coderd/tailnet.go index ec061f015b6..75ea1d3493f 100644 --- a/coderd/tailnet.go +++ b/coderd/tailnet.go @@ -396,7 +396,7 @@ type MultiAgentController struct { } func (m *MultiAgentController) New(client tailnet.CoordinatorClient) tailnet.CloserWaiter { - b := m.BasicCoordinationController.NewCoordination(client) + b := m.NewCoordination(client) // resync all destinations m.mu.Lock() defer m.mu.Unlock() diff --git a/coderd/telemetry/telemetry.go b/coderd/telemetry/telemetry.go index 495c4f49b87..3574fdbd8d0 100644 --- a/coderd/telemetry/telemetry.go +++ b/coderd/telemetry/telemetry.go @@ -1104,11 +1104,11 @@ func buildTaskEvent( // Below only relevant for "resumed" tasks, not when initially created. if isResumed { event.LastResumedAt = &row.StartBuildCreatedAt.Time - switch { + switch row.StartBuildReason.BuildReason { // TODO(Cian): will this exist? Future readers may know better than I. // case row.StartBuildReason == database.BuildReasonTaskAutoResume: // event.ResumeReason = ptr.Ref("auto") - case row.StartBuildReason.BuildReason == database.BuildReasonTaskResume: + case database.BuildReasonTaskResume: event.ResumeReason = ptr.Ref("manual") default: // Task resumed by starting workspace? event.ResumeReason = ptr.Ref("other") diff --git a/coderd/templates_test.go b/coderd/templates_test.go index 2283a33d984..0b716c44da6 100644 --- a/coderd/templates_test.go +++ b/coderd/templates_test.go @@ -1144,7 +1144,7 @@ func TestPatchTemplateMeta(t *testing.T) { template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) require.Equal(t, codersdk.WorkspaceAgentPortShareLevelPublic, template.MaxPortShareLevel) - var level codersdk.WorkspaceAgentPortShareLevel = codersdk.WorkspaceAgentPortShareLevelAuthenticated + level := codersdk.WorkspaceAgentPortShareLevelAuthenticated req := codersdk.UpdateTemplateMeta{ MaxPortShareLevel: &level, } diff --git a/coderd/templateversions.go b/coderd/templateversions.go index d680260e599..0fd66a829a7 100644 --- a/coderd/templateversions.go +++ b/coderd/templateversions.go @@ -1887,7 +1887,7 @@ func (api *API) dynamicTemplateVersionTags(ctx context.Context, rw http.Response func (api *API) classicTemplateVersionTags(ctx context.Context, rw http.ResponseWriter, file database.File) (map[string]string, bool) { // Try to parse template tags from the given file. - tempDir, err := os.MkdirTemp(api.Options.CacheDir, "tfparse-*") + tempDir, err := os.MkdirTemp(api.CacheDir, "tfparse-*") if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ Message: "Internal error checking workspace tags", diff --git a/coderd/tracing/slog_test.go b/coderd/tracing/slog_test.go index 04ea03e707d..f815fde52d0 100644 --- a/coderd/tracing/slog_test.go +++ b/coderd/tracing/slog_test.go @@ -156,7 +156,7 @@ func mapToSlogFields(m map[string]interface{}) slog.Map { func mapToBasicMap(m map[string]interface{}) map[string]interface{} { basic := make(map[string]interface{}, len(m)) for k, v := range m { - var val interface{} = v + val := v switch v := v.(type) { case float32: val = float64(v) diff --git a/coderd/users_test.go b/coderd/users_test.go index 12d45d1bd25..6c9c132a3fb 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -3246,11 +3246,7 @@ func assertPagination(ctx context.Context, t *testing.T, client *codersdk.Client require.Equalf(t, onlyUsernames(page.Users), onlyUsernames(allUsers[:limit]), "first page, limit=%d", limit) count += len(page.Users) - for { - if len(page.Users) == 0 { - break - } - + for len(page.Users) != 0 { afterCursor := page.Users[len(page.Users)-1].ID // Assert each page is the next expected page // This is using a cursor, and only works if all users created_at diff --git a/coderd/usersecrets_test.go b/coderd/usersecrets_test.go index 1b4a6c97768..71bb22f049f 100644 --- a/coderd/usersecrets_test.go +++ b/coderd/usersecrets_test.go @@ -872,10 +872,10 @@ func requireSecretAPIError(t *testing.T, err error, status int, detailContains s var sdkErr *codersdk.Error require.ErrorAs(t, err, &sdkErr) assert.Equal(t, status, sdkErr.StatusCode()) - combined := sdkErr.Message + " " + sdkErr.Response.Detail + combined := sdkErr.Message + " " + sdkErr.Detail assert.Containsf(t, combined, detailContains, "expected response to contain %q; got Message=%q Detail=%q", - detailContains, sdkErr.Message, sdkErr.Response.Detail) + detailContains, sdkErr.Message, sdkErr.Detail) } func TestDeleteUserSecret(t *testing.T) { diff --git a/coderd/workspaceagents.go b/coderd/workspaceagents.go index 6bbee110cb8..6eb30b8c90b 100644 --- a/coderd/workspaceagents.go +++ b/coderd/workspaceagents.go @@ -1267,7 +1267,7 @@ func (api *API) derpMapUpdates(rw http.ResponseWriter, r *http.Request) { } }(ctx) - ticker := time.NewTicker(api.Options.DERPMapUpdateFrequency) + ticker := time.NewTicker(api.DERPMapUpdateFrequency) defer ticker.Stop() var lastDERPMap *tailcfg.DERPMap @@ -1281,7 +1281,7 @@ func (api *API) derpMapUpdates(rw http.ResponseWriter, r *http.Request) { lastDERPMap = derpMap } - ticker.Reset(api.Options.DERPMapUpdateFrequency) + ticker.Reset(api.DERPMapUpdateFrequency) select { case <-ctx.Done(): return @@ -1456,7 +1456,7 @@ func (api *API) logTunnelConnection(agentID uuid.UUID, statusCode int32, userID return } - staleInterval := api.Options.WorkspaceAppAuditSessionTimeout + staleInterval := api.WorkspaceAppAuditSessionTimeout if staleInterval == 0 { staleInterval = time.Hour } @@ -1527,7 +1527,7 @@ func (api *API) handleResumeToken(ctx context.Context, rw http.ResponseWriter, r peerID = uuid.New() resumeToken := r.URL.Query().Get("resume_token") if resumeToken != "" { - peerID, err = api.Options.CoordinatorResumeTokenProvider.VerifyResumeToken(ctx, resumeToken) + peerID, err = api.CoordinatorResumeTokenProvider.VerifyResumeToken(ctx, resumeToken) // If the token is missing the key ID, it's probably an old token in which // case we just want to generate a new peer ID. switch { diff --git a/coderd/workspaceagentsrpc.go b/coderd/workspaceagentsrpc.go index 1c4e14c3552..91285c0346b 100644 --- a/coderd/workspaceagentsrpc.go +++ b/coderd/workspaceagentsrpc.go @@ -184,7 +184,7 @@ func (api *API) workspaceAgentRPC(rw http.ResponseWriter, r *http.Request) { AgentStatsRefreshInterval: api.AgentStatsRefreshInterval, DisableDirectConnections: api.DeploymentValues.DERP.Config.BlockDirect.Value(), DerpForceWebSockets: api.DeploymentValues.DERP.Config.ForceWebSockets.Value(), - DerpMapUpdateFrequency: api.Options.DERPMapUpdateFrequency, + DerpMapUpdateFrequency: api.DERPMapUpdateFrequency, ExternalAuthConfigs: api.ExternalAuthConfigs, Experiments: api.Experiments, LifecycleMetrics: api.lifecycleMetrics, diff --git a/coderd/workspaceapps/apptest/apptest.go b/coderd/workspaceapps/apptest/apptest.go index f0993e8f02f..0454e7b58d7 100644 --- a/coderd/workspaceapps/apptest/apptest.go +++ b/coderd/workspaceapps/apptest/apptest.go @@ -1094,7 +1094,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) { require.NoError(t, err) // Verify the prefix is in the token. - require.Equal(t, prefixedOwnerApp.Prefix, tok.Request.Prefix) + require.Equal(t, prefixedOwnerApp.Prefix, tok.Prefix) // Ensure the signed app token cookie is valid by making a request with // it with no session token. diff --git a/coderd/workspaceapps/db.go b/coderd/workspaceapps/db.go index fbd69aa3f10..a1487f9cfa4 100644 --- a/coderd/workspaceapps/db.go +++ b/coderd/workspaceapps/db.go @@ -322,8 +322,8 @@ func (p *DBTokenProvider) authorizeRequest(ctx context.Context, roles *rbac.Subj // Figure out which RBAC resource to check. For terminals we use execution // instead of application connect. var ( - rbacAction policy.Action = policy.ActionApplicationConnect - rbacResource rbac.Object = dbReq.Workspace.RBACObject() + rbacAction = policy.ActionApplicationConnect + rbacResource = dbReq.Workspace.RBACObject() // rbacResourceOwned is for the level "authenticated". We still need to // make sure the API key has permissions to connect to the actor's own // workspace. Scopes would prevent this. @@ -336,7 +336,7 @@ func (p *DBTokenProvider) authorizeRequest(ctx context.Context, roles *rbac.Subj // the object to check the proper permissions. AnyOrg is almost the same, // but technically excludes users who are not in any organization. This is // the closest we can get though without more significant refactoring. - rbacResourceOwned rbac.Object = rbac.ResourceWorkspace.WithOwner(roles.ID).AnyOrganization() + rbacResourceOwned = rbac.ResourceWorkspace.WithOwner(roles.ID).AnyOrganization() ) if dbReq.AccessMethod == AccessMethodTerminal { rbacAction = policy.ActionSSH @@ -446,7 +446,7 @@ func (p *DBTokenProvider) connLogInitRequest(w http.ResponseWriter, r *http.Requ // Approximation of the status code. // #nosec G115 - Safe conversion as HTTP status code is expected to be within int32 range (typically 100-599) - var statusCode int32 = int32(sw.Status) + statusCode := int32(sw.Status) if statusCode == 0 { statusCode = http.StatusOK } diff --git a/coderd/workspaceapps/db_test.go b/coderd/workspaceapps/db_test.go index 5e341a7bc80..e2796cfb0e3 100644 --- a/coderd/workspaceapps/db_test.go +++ b/coderd/workspaceapps/db_test.go @@ -835,7 +835,7 @@ func Test_ResolveRequest(t *testing.T) { require.Equal(t, req.BasePath, token.BasePath) require.Empty(t, token.UsernameOrID) require.Empty(t, token.WorkspaceNameOrID) - require.Equal(t, req.AgentNameOrID, token.Request.AgentNameOrID) + require.Equal(t, req.AgentNameOrID, token.AgentNameOrID) require.Empty(t, token.AppSlugOrPort) require.Empty(t, token.AppURL) assertConnLogContains(t, rw, r, connLogger, workspace, agentName, "terminal", database.ConnectionTypeWorkspaceApp, me.ID) diff --git a/coderd/workspaceapps/token.go b/coderd/workspaceapps/token.go index a3dbc02b61d..5bca2d63079 100644 --- a/coderd/workspaceapps/token.go +++ b/coderd/workspaceapps/token.go @@ -32,7 +32,7 @@ type SignedToken struct { // MatchesRequest returns true if the token matches the request. Any token that // does not match the request should be considered invalid. func (t SignedToken) MatchesRequest(req Request) bool { - tokenBasePath := t.Request.BasePath + tokenBasePath := t.BasePath if !strings.HasSuffix(tokenBasePath, "/") { tokenBasePath += "/" } @@ -111,7 +111,7 @@ func FromRequest(r *http.Request, mgr cryptokeys.SigningKeycache) (*SignedToken, Time: time.Now(), })) if err == nil { - req := token.Request.Normalize() + req := token.Normalize() if hasQueryParam && req.AccessMethod != AccessMethodTerminal { // The request must be a terminal request if we're using a // query parameter. diff --git a/coderd/workspaceapps/token_test.go b/coderd/workspaceapps/token_test.go index 47bcd7be8d4..be62526b093 100644 --- a/coderd/workspaceapps/token_test.go +++ b/coderd/workspaceapps/token_test.go @@ -316,7 +316,7 @@ func Test_FromRequest(t *testing.T) { // Add an expired cookie expired := token - expired.RegisteredClaims.Expiry = jwt.NewNumericDate(time.Now().Add(time.Hour * -1)) + expired.Expiry = jwt.NewNumericDate(time.Now().Add(time.Hour * -1)) expiredStr, err := jwtutils.Sign(ctx, signer, expired) require.NoError(t, err) r.AddCookie(&http.Cookie{ diff --git a/coderd/workspacebuilds_on_success_test.go b/coderd/workspacebuilds_on_success_test.go index a49ef56147e..a5a50769a85 100644 --- a/coderd/workspacebuilds_on_success_test.go +++ b/coderd/workspacebuilds_on_success_test.go @@ -347,7 +347,7 @@ func TestPostWorkspaceBuildsOnSuccessPinnedChildVersionRequiresTemplateUpdate(t var apiErr *codersdk.Error require.ErrorAs(t, err, &apiErr) require.Equal(t, http.StatusForbidden, apiErr.StatusCode()) - require.Contains(t, apiErr.Response.Detail, "template update permission") + require.Contains(t, apiErr.Detail, "template update permission") // THEN: no new workspace build is created. builds, err := userClient.WorkspaceBuilds(ctx, codersdk.WorkspaceBuildsRequest{WorkspaceID: workspace.ID}) diff --git a/coderd/workspaces.go b/coderd/workspaces.go index 5f3455c17ee..6502740cc2a 100644 --- a/coderd/workspaces.go +++ b/coderd/workspaces.go @@ -122,7 +122,7 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) { workspace, data.builds[0], data.templates[0], - api.Options.AllowWorkspaceRenames, + api.AllowWorkspaceRenames, appStatus, ) if err != nil { @@ -339,7 +339,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request) workspace, data.builds[0], data.templates[0], - api.Options.AllowWorkspaceRenames, + api.AllowWorkspaceRenames, appStatus, ) if err != nil { @@ -851,7 +851,7 @@ func createWorkspace( workspace, apiBuild, template, - api.Options.AllowWorkspaceRenames, + api.AllowWorkspaceRenames, codersdk.WorkspaceAppStatus{}, ) if err != nil { @@ -1154,7 +1154,7 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) { // patched in the future, it's enough if one changes. name := workspace.Name if req.Name != "" || req.Name != workspace.Name { - if !api.Options.AllowWorkspaceRenames { + if !api.AllowWorkspaceRenames { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ Message: "Workspace renames are not allowed.", }) @@ -1593,7 +1593,7 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) { workspace, data.builds[0], data.templates[0], - api.Options.AllowWorkspaceRenames, + api.AllowWorkspaceRenames, appStatus, ) if err != nil { @@ -2172,7 +2172,7 @@ func (api *API) watchWorkspace( workspace, data.builds[0], data.templates[0], - api.Options.AllowWorkspaceRenames, + api.AllowWorkspaceRenames, appStatus, ) if err != nil { @@ -2760,7 +2760,7 @@ func (api *API) workspaceData(ctx context.Context, workspaces []database.Workspa templates: templates, appStatuses: db2sdk.WorkspaceAppStatuses(appStatuses), builds: apiBuilds, - allowRenames: api.Options.AllowWorkspaceRenames, + allowRenames: api.AllowWorkspaceRenames, }, nil } diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index fdf33461af1..e84e633e444 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -5796,9 +5796,10 @@ func TestWorkspaceListTasks(t *testing.T) { // Then: verify TaskID is only set for task workspaces for _, workspace := range workspaces.Workspaces { - if workspace.ID == workspaceWithoutTask.ID { + switch workspace.ID { + case workspaceWithoutTask.ID: assert.False(t, workspace.TaskID.Valid) - } else if workspace.ID == workspaceWithTask.ID { + case workspaceWithTask.ID: assert.True(t, workspace.TaskID.Valid) assert.Equal(t, task.ID, workspace.TaskID.UUID) } diff --git a/coderd/x/chatd/chatd.go b/coderd/x/chatd/chatd.go index 36548aad184..3ea82a68deb 100644 --- a/coderd/x/chatd/chatd.go +++ b/coderd/x/chatd/chatd.go @@ -1924,6 +1924,8 @@ var ErrArchiveRequiresRootChat = xerrors.New( // Child chats must not be archived independently. ArchiveChat // rejects them with [ErrArchiveRequiresRootChat] so callers cannot // silently break the parent-implies-child archive invariant. +// +//nolint:staticcheck // Receiver name matches the other Server methods in this file. func (p *Server) ArchiveChat(ctx context.Context, chat database.Chat) error { if chat.ID == uuid.Nil { return xerrors.New("chat_id is required") diff --git a/coderd/x/chatd/chatd_test.go b/coderd/x/chatd/chatd_test.go index c623356d351..f1a0ac78152 100644 --- a/coderd/x/chatd/chatd_test.go +++ b/coderd/x/chatd/chatd_test.go @@ -161,7 +161,7 @@ func recordOpenAIRequest(req *chattest.OpenAIRequest) recordedOpenAIRequest { var contentLength int64 if req.Request != nil { - contentLength = req.Request.ContentLength + contentLength = req.ContentLength } return recordedOpenAIRequest{ diff --git a/coderd/x/chatd/chatprovider/chatprovider.go b/coderd/x/chatd/chatprovider/chatprovider.go index 3cf24c15dfb..b69d2437c99 100644 --- a/coderd/x/chatd/chatprovider/chatprovider.go +++ b/coderd/x/chatd/chatprovider/chatprovider.go @@ -927,7 +927,7 @@ func ModelFromConfig( apiKey := providerKeys.APIKey(provider) if apiKey == "" && - !(ProviderAllowsAmbientCredentials(provider) && providerKeys.HasProvider(provider)) { + (!ProviderAllowsAmbientCredentials(provider) || !providerKeys.HasProvider(provider)) { return Model{}, missingProviderAPIKeyError(provider) } baseURL := providerKeys.BaseURL(provider) diff --git a/coderd/x/chatd/chatprovider/responses_api_test.go b/coderd/x/chatd/chatprovider/responses_api_test.go index f6c29534bcb..c9a37582605 100644 --- a/coderd/x/chatd/chatprovider/responses_api_test.go +++ b/coderd/x/chatd/chatprovider/responses_api_test.go @@ -47,7 +47,7 @@ func TestModelFromConfig_OpenAIResponsesAPIOverride(t *testing.T) { var gotPath string serverURL := chattest.NewOpenAI(t, func(req *chattest.OpenAIRequest) chattest.OpenAIResponse { mu.Lock() - gotPath = req.Request.URL.Path + gotPath = req.URL.Path mu.Unlock() return chattest.OpenAINonStreamingResponse("ok") }) @@ -135,7 +135,7 @@ func TestModelTransportConsumersAgree(t *testing.T) { var gotPath string serverURL := chattest.NewOpenAI(t, func(req *chattest.OpenAIRequest) chattest.OpenAIResponse { mu.Lock() - gotPath = req.Request.URL.Path + gotPath = req.URL.Path mu.Unlock() return chattest.OpenAINonStreamingResponse("ok") }) diff --git a/codersdk/audit.go b/codersdk/audit.go index 96b718a86ac..1e8131dd373 100644 --- a/codersdk/audit.go +++ b/codersdk/audit.go @@ -261,7 +261,7 @@ type CreateTestAuditLogRequest struct { // AuditLogs retrieves audit logs from the given page. func (c *Client) AuditLogs(ctx context.Context, req AuditLogsRequest) (AuditLogResponse, error) { - res, err := c.Request(ctx, http.MethodGet, "/api/v2/audit", nil, req.Pagination.asRequestOption(), func(r *http.Request) { + res, err := c.Request(ctx, http.MethodGet, "/api/v2/audit", nil, req.asRequestOption(), func(r *http.Request) { q := r.URL.Query() var params []string if req.SearchQuery != "" { diff --git a/codersdk/chats.go b/codersdk/chats.go index 21f14b9235b..cc0c495cedd 100644 --- a/codersdk/chats.go +++ b/codersdk/chats.go @@ -1982,7 +1982,7 @@ type ListChatsOptions struct { func (c *ExperimentalClient) ListChats(ctx context.Context, opts *ListChatsOptions) ([]Chat, error) { var reqOpts []RequestOption if opts != nil { - reqOpts = append(reqOpts, opts.Pagination.asRequestOption()) + reqOpts = append(reqOpts, opts.asRequestOption()) query := opts.Query if opts.Source != "" { if query != "" { diff --git a/codersdk/client_internal_test.go b/codersdk/client_internal_test.go index 23941eda983..ca347988fed 100644 --- a/codersdk/client_internal_test.go +++ b/codersdk/client_internal_test.go @@ -237,8 +237,8 @@ func Test_readBodyAsError(t *testing.T) { sdkErr := assertSDKError(t, err) assert.Equal(t, simpleResponse, sdkErr.Response) - assert.ErrorContains(t, err, sdkErr.Response.Message) - assert.ErrorContains(t, err, sdkErr.Response.Detail) + assert.ErrorContains(t, err, sdkErr.Message) + assert.ErrorContains(t, err, sdkErr.Detail) assert.Equal(t, http.StatusNotFound, sdkErr.StatusCode()) assert.ErrorContains(t, err, strconv.Itoa(sdkErr.StatusCode())) @@ -284,8 +284,8 @@ func Test_readBodyAsError(t *testing.T) { assert: func(t *testing.T, err error) { sdkErr := assertSDKError(t, err) - assert.Contains(t, sdkErr.Response.Message, "unexpected non-JSON response") - assert.Equal(t, "hello world", sdkErr.Response.Detail) + assert.Contains(t, sdkErr.Message, "unexpected non-JSON response") + assert.Equal(t, "hello world", sdkErr.Detail) }, }, { @@ -295,10 +295,10 @@ func Test_readBodyAsError(t *testing.T) { assert: func(t *testing.T, err error) { sdkErr := assertSDKError(t, err) - assert.Contains(t, sdkErr.Response.Message, "unexpected non-JSON response") + assert.Contains(t, sdkErr.Message, "unexpected non-JSON response") expected := longResponse[0:2048] + "..." - assert.Equal(t, expected, sdkErr.Response.Detail) + assert.Equal(t, expected, sdkErr.Detail) }, }, { @@ -308,7 +308,7 @@ func Test_readBodyAsError(t *testing.T) { assert: func(t *testing.T, err error) { sdkErr := assertSDKError(t, err) - assert.Contains(t, sdkErr.Response.Message, "empty response body") + assert.Contains(t, sdkErr.Message, "empty response body") assert.Equal(t, http.MethodGet, sdkErr.method) assert.ErrorContains(t, err, sdkErr.method) @@ -324,9 +324,9 @@ func Test_readBodyAsError(t *testing.T) { assert: func(t *testing.T, err error) { sdkErr := assertSDKError(t, err) - assert.Contains(t, sdkErr.Response.Message, "unexpected status code") - assert.Contains(t, sdkErr.Response.Message, "has no message") - assert.Equal(t, unexpectedJSON, sdkErr.Response.Detail) + assert.Contains(t, sdkErr.Message, "unexpected status code") + assert.Contains(t, sdkErr.Message, "has no message") + assert.Equal(t, unexpectedJSON, sdkErr.Detail) }, }, { diff --git a/codersdk/connectionlog.go b/codersdk/connectionlog.go index 19b79ae24c4..5a5c2bd628c 100644 --- a/codersdk/connectionlog.go +++ b/codersdk/connectionlog.go @@ -103,7 +103,7 @@ type ConnectionLogResponse struct { } func (c *Client) ConnectionLogs(ctx context.Context, req ConnectionLogsRequest) (ConnectionLogResponse, error) { - res, err := c.Request(ctx, http.MethodGet, "/api/v2/connectionlog", nil, req.Pagination.asRequestOption(), func(r *http.Request) { + res, err := c.Request(ctx, http.MethodGet, "/api/v2/connectionlog", nil, req.asRequestOption(), func(r *http.Request) { q := r.URL.Query() var params []string if req.SearchQuery != "" { diff --git a/codersdk/templates.go b/codersdk/templates.go index 3ae936577e7..4c382b6ae46 100644 --- a/codersdk/templates.go +++ b/codersdk/templates.go @@ -452,7 +452,7 @@ func (c *Client) TemplateVersionsByTemplate(ctx context.Context, req TemplateVer if req.IncludeArchived { u += "?include_archived=true" } - res, err := c.Request(ctx, http.MethodGet, u, nil, req.Pagination.asRequestOption()) + res, err := c.Request(ctx, http.MethodGet, u, nil, req.asRequestOption()) if err != nil { return nil, err } diff --git a/codersdk/toolsdk/chatgpt.go b/codersdk/toolsdk/chatgpt.go index 4761bb7b1fa..0e40139678d 100644 --- a/codersdk/toolsdk/chatgpt.go +++ b/codersdk/toolsdk/chatgpt.go @@ -102,7 +102,7 @@ type SearchQuery struct { func parseSearchQuery(query string) (SearchQuery, error) { parts := strings.Split(query, "/") queryType := SearchQueryType(parts[0]) - if !(queryType == SearchQueryTypeTemplates || queryType == SearchQueryTypeWorkspaces) { + if queryType != SearchQueryTypeTemplates && queryType != SearchQueryTypeWorkspaces { return SearchQuery{}, xerrors.Errorf("invalid query: %s", query) } queryString := "" diff --git a/codersdk/workspaces.go b/codersdk/workspaces.go index 6a78ecd7b36..94ab3dee86e 100644 --- a/codersdk/workspaces.go +++ b/codersdk/workspaces.go @@ -218,7 +218,7 @@ func (c *Client) WorkspaceBuilds(ctx context.Context, req WorkspaceBuildsRequest res, err := c.Request( ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaces/%s/builds", req.WorkspaceID), - nil, req.Pagination.asRequestOption(), WithQueryParam("since", req.Since.Format(time.RFC3339)), + nil, req.asRequestOption(), WithQueryParam("since", req.Since.Format(time.RFC3339)), ) if err != nil { return nil, err diff --git a/codersdk/workspacesdk/agentconn.go b/codersdk/workspacesdk/agentconn.go index 1cdb45e4ca5..41ac28707d9 100644 --- a/codersdk/workspacesdk/agentconn.go +++ b/codersdk/workspacesdk/agentconn.go @@ -247,7 +247,7 @@ func (c *agentConn) ReconnectingPTY(ctx context.Context, id uuid.UUID, height, w return nil, xerrors.Errorf("workspace agent not reachable in time: %v", ctx.Err()) } - conn, err := c.Conn.DialContextTCP(ctx, netip.AddrPortFrom(c.agentAddress(), AgentReconnectingPTYPort)) + conn, err := c.DialContextTCP(ctx, netip.AddrPortFrom(c.agentAddress(), AgentReconnectingPTYPort)) if err != nil { return nil, err } @@ -334,8 +334,8 @@ func (c *agentConn) Speedtest(ctx context.Context, direction speedtest.Direction return nil, xerrors.Errorf("workspace agent not reachable in time: %v", ctx.Err()) } - c.Conn.SendConnectedTelemetry(c.agentAddress(), tailnet.TelemetryApplicationSpeedtest) - speedConn, err := c.Conn.DialContextTCP(ctx, netip.AddrPortFrom(c.agentAddress(), AgentSpeedtestPort)) + c.SendConnectedTelemetry(c.agentAddress(), tailnet.TelemetryApplicationSpeedtest) + speedConn, err := c.DialContextTCP(ctx, netip.AddrPortFrom(c.agentAddress(), AgentSpeedtestPort)) if err != nil { return nil, xerrors.Errorf("dial speedtest: %w", err) } @@ -364,9 +364,9 @@ func (c *agentConn) DialContext(ctx context.Context, network string, addr string switch network { case "tcp": - return c.Conn.DialContextTCP(ctx, ipp) + return c.DialContextTCP(ctx, ipp) case "udp": - return c.Conn.DialContextUDP(ctx, ipp) + return c.DialContextUDP(ctx, ipp) default: return nil, xerrors.Errorf("unknown network %q", network) } @@ -1510,7 +1510,7 @@ func (c *agentConn) apiClient(reqCtx context.Context) *http.Client { } // Always dial the pinned agent address, never the request host. - conn, err := c.Conn.DialContextTCP(ctx, agentAddr) + conn, err := c.DialContextTCP(ctx, agentAddr) if err != nil { return nil, xerrors.Errorf("dial http api: %w", err) } diff --git a/enterprise/cli/aigatewaystart_test.go b/enterprise/cli/aigatewaystart_test.go index b15a4f2aeb1..980fac40777 100644 --- a/enterprise/cli/aigatewaystart_test.go +++ b/enterprise/cli/aigatewaystart_test.go @@ -346,7 +346,7 @@ func TestAIGatewayStartE2E_RevokedKey(t *testing.T) { // Given: a ready gateway, and a coderd whose key check ticker the test drives. keyCheck := make(chan time.Time, 1) dep := setupAIGatewayDeployment(ctx, t, withAIGatewayCoderdOptions(func(opts *coderdenttest.Options) { - opts.Options.NewTicker = func(time.Duration) (<-chan time.Time, func()) { + opts.NewTicker = func(time.Duration) (<-chan time.Time, func()) { return keyCheck, func() {} } })) diff --git a/enterprise/cli/provisionerdaemons.go b/enterprise/cli/provisionerdaemons.go index 690762dcc61..d113f6c37b0 100644 --- a/enterprise/cli/provisionerdaemons.go +++ b/enterprise/cli/provisionerdaemons.go @@ -5,7 +5,7 @@ import ( ) func (r *RootCmd) provisionerDaemons() *serpent.Command { - cmd := r.RootCmd.Provisioners() + cmd := r.Provisioners() cmd.AddSubcommands( r.provisionerDaemonStart(), r.provisionerKeys(), diff --git a/enterprise/cli/proxyserver.go b/enterprise/cli/proxyserver.go index 6a3f99a4a2c..54d44a70c69 100644 --- a/enterprise/cli/proxyserver.go +++ b/enterprise/cli/proxyserver.go @@ -83,7 +83,7 @@ func (r *RootCmd) proxyServer() *serpent.Command { YAML: "primaryAccessURL", Required: true, Value: serpent.Validate(&primaryAccessURL, func(value *serpent.URL) error { - if !(value.Scheme == "http" || value.Scheme == "https") { + if value.Scheme != "http" && value.Scheme != "https" { return xerrors.Errorf("'--primary-access-url' value must be http or https: url=%s", primaryAccessURL.String()) } return nil diff --git a/enterprise/cli/sharing_test.go b/enterprise/cli/sharing_test.go index c972cd6cd9e..860f7d6e24f 100644 --- a/enterprise/cli/sharing_test.go +++ b/enterprise/cli/sharing_test.go @@ -61,7 +61,7 @@ func TestSharingShare(t *testing.T) { acl, err := workspaceOwnerClient.WorkspaceACL(inv.Context(), workspace.ID) require.NoError(t, err) assert.Len(t, acl.Groups, 1) - assert.Equal(t, acl.Groups[0].Group.ID, group.ID) + assert.Equal(t, acl.Groups[0].ID, group.ID) assert.Equal(t, acl.Groups[0].Role, codersdk.WorkspaceRoleUse) found := false @@ -119,10 +119,10 @@ func TestSharingShare(t *testing.T) { type workspaceGroup []codersdk.WorkspaceGroup assert.NotEqual(t, -1, slices.IndexFunc(workspaceGroup(acl.Groups), func(g codersdk.WorkspaceGroup) bool { - return g.Group.ID == wibbleGroup.ID + return g.ID == wibbleGroup.ID })) assert.NotEqual(t, -1, slices.IndexFunc(workspaceGroup(acl.Groups), func(g codersdk.WorkspaceGroup) bool { - return g.Group.ID == wobbleGroup.ID + return g.ID == wobbleGroup.ID })) t.Run("ShareWithGroups_Role", func(t *testing.T) { @@ -160,7 +160,7 @@ func TestSharingShare(t *testing.T) { acl, err := workspaceOwnerClient.WorkspaceACL(inv.Context(), workspace.ID) require.NoError(t, err) assert.Len(t, acl.Groups, 1) - assert.Equal(t, acl.Groups[0].Group.ID, group.ID) + assert.Equal(t, acl.Groups[0].ID, group.ID) assert.Equal(t, acl.Groups[0].Role, codersdk.WorkspaceRoleAdmin) found := false diff --git a/enterprise/cli/workspaceproxy.go b/enterprise/cli/workspaceproxy.go index 70467f3ce74..d3ab2d977ff 100644 --- a/enterprise/cli/workspaceproxy.go +++ b/enterprise/cli/workspaceproxy.go @@ -243,8 +243,8 @@ func (r *RootCmd) createProxy() *serpent.Command { formatter = newUpdateProxyResponseFormatter() ) validateIcon := func(s *serpent.String) error { - if !(strings.HasPrefix(s.Value(), "/emojis/") || strings.HasPrefix(s.Value(), "http")) { - return xerrors.New("icon must be a relative path to an emoji or a publicly hosted image URL") + if !strings.HasPrefix(s.Value(), "/emojis/") && !strings.HasPrefix(s.Value(), "/icon/") && !strings.HasPrefix(s.Value(), "http") { + return xerrors.New("icon must be a relative path to a built-in image or an absolute HTTP/HTTPS URL to an external image") } return nil } diff --git a/enterprise/coderd/aibridge_test.go b/enterprise/coderd/aibridge_test.go index cba71e26178..f6be14eb793 100644 --- a/enterprise/coderd/aibridge_test.go +++ b/enterprise/coderd/aibridge_test.go @@ -265,8 +265,8 @@ func TestAIBridgeListSessions(t *testing.T) { t.Parallel() db, ps := dbtestutil.NewDB(t) opts := aibridgeOpts(t) - opts.Options.Database = db - opts.Options.Pubsub = ps + opts.Database = db + opts.Pubsub = ps client, _, firstUser := coderdenttest.NewWithDatabase(t, opts) ctx := testutil.Context(t, testutil.WaitLong) @@ -1711,8 +1711,8 @@ func TestAIBridgeGetSessionThreads(t *testing.T) { // role grants boundary_log:create; they are written by the agent path. db, ps := dbtestutil.NewDB(t) opts := aibridgeOpts(t) - opts.Options.Database = db - opts.Options.Pubsub = ps + opts.Database = db + opts.Pubsub = ps client, _, firstUser := coderdenttest.NewWithDatabase(t, opts) ctx := testutil.Context(t, testutil.WaitLong) @@ -1799,8 +1799,8 @@ func TestAIBridgeGetSessionThreads(t *testing.T) { // its own sequence) is excluded by the exclusive lower bound. db, ps := dbtestutil.NewDB(t) opts := aibridgeOpts(t) - opts.Options.Database = db - opts.Options.Pubsub = ps + opts.Database = db + opts.Pubsub = ps client, _, firstUser := coderdenttest.NewWithDatabase(t, opts) ctx := testutil.Context(t, testutil.WaitLong) @@ -1867,8 +1867,8 @@ func TestAIBridgeGetSessionThreads(t *testing.T) { // by session B's interception and B's calls never bleed into A's counts. db, ps := dbtestutil.NewDB(t) opts := aibridgeOpts(t) - opts.Options.Database = db - opts.Options.Pubsub = ps + opts.Database = db + opts.Pubsub = ps client, _, firstUser := coderdenttest.NewWithDatabase(t, opts) ctx := testutil.Context(t, testutil.WaitLong) @@ -1935,8 +1935,8 @@ func TestAIBridgeGetSessionThreads(t *testing.T) { // truncated but the summary total stays authoritative. db, ps := dbtestutil.NewDB(t) opts := aibridgeOpts(t) - opts.Options.Database = db - opts.Options.Pubsub = ps + opts.Database = db + opts.Pubsub = ps client, _, firstUser := coderdenttest.NewWithDatabase(t, opts) ctx := testutil.Context(t, testutil.WaitLong) diff --git a/enterprise/coderd/aibridgeserve_test.go b/enterprise/coderd/aibridgeserve_test.go index 9a702f3af54..5bb7a23632c 100644 --- a/enterprise/coderd/aibridgeserve_test.go +++ b/enterprise/coderd/aibridgeserve_test.go @@ -267,7 +267,7 @@ func setupActiveAIGatewayServeSession(ctx context.Context, t *testing.T) activeA tick := make(chan time.Time, 1) opts := aibridgeOpts(t) - opts.Options.NewTicker = func(time.Duration) (<-chan time.Time, func()) { + opts.NewTicker = func(time.Duration) (<-chan time.Time, func()) { return tick, func() {} } diff --git a/enterprise/coderd/aigatewaykeys_test.go b/enterprise/coderd/aigatewaykeys_test.go index e2fc326f76e..9957d61edca 100644 --- a/enterprise/coderd/aigatewaykeys_test.go +++ b/enterprise/coderd/aigatewaykeys_test.go @@ -213,9 +213,9 @@ func TestAIGatewayKeyAudit(t *testing.T) { ) opts := aibridgeOpts(t) opts.AuditLogging = true - opts.Options.Database = db - opts.Options.Pubsub = ps - opts.Options.Auditor = auditor + opts.Database = db + opts.Pubsub = ps + opts.Auditor = auditor opts.LicenseOptions.Features[codersdk.FeatureAuditLog] = 1 ownerClient, _ := coderdenttest.New(t, opts) @@ -365,8 +365,8 @@ func TestAIGatewayKeysDatabaseErrors(t *testing.T) { errStore.Store = db opts := aibridgeOpts(t) - opts.Options.Database = &errStore - opts.Options.Pubsub = ps + opts.Database = &errStore + opts.Pubsub = ps ownerClient, _ := coderdenttest.New(t, opts) ctx := testutil.Context(t, testutil.WaitLong) diff --git a/enterprise/coderd/coderd.go b/enterprise/coderd/coderd.go index b9367f97e89..fcf9b8f09d7 100644 --- a/enterprise/coderd/coderd.go +++ b/enterprise/coderd/coderd.go @@ -85,8 +85,8 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { if options.PrometheusRegistry == nil { options.PrometheusRegistry = prometheus.NewRegistry() } - if options.Options.Authorizer == nil { - options.Options.Authorizer = rbac.NewCachingAuthorizer(options.PrometheusRegistry) + if options.Authorizer == nil { + options.Authorizer = rbac.NewCachingAuthorizer(options.PrometheusRegistry) if buildinfo.IsDev() { options.Authorizer = rbac.Recorder(options.Authorizer) } @@ -99,12 +99,12 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { if options.Entitlements == nil { options.Entitlements = entitlements.New() } - if options.Options.UsageInserter == nil { - options.Options.UsageInserter = &atomic.Pointer[agplusage.Inserter]{} + if options.UsageInserter == nil { + options.UsageInserter = &atomic.Pointer[agplusage.Inserter]{} } - if options.Options.UsageInserter.Load() == nil { + if options.UsageInserter.Load() == nil { collector := usage.NewDBInserter() - options.Options.UsageInserter.Store(&collector) + options.UsageInserter.Store(&collector) } ctx, cancelFunc := context.WithCancel(ctx) @@ -207,7 +207,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { // chat processor receives it. replicaHTTPClient := replicaRelayHTTPClient(options.HTTPClient, meshTLSConfig) if replicaHTTPClient == nil { - replicaHTTPClient = options.Options.HTTPClient + replicaHTTPClient = options.HTTPClient } if replicaHTTPClient == nil { replicaHTTPClient = http.DefaultClient @@ -215,7 +215,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { // Use a closure that captures api by reference so it can access // api.AGPL.ID after coderd.New is called. The parts dialer is // only invoked from stream subscriptions, which happen after init. - options.Options.ChatStreamPartsDialer = entchatd.NewStreamPartsDialer(entchatd.StreamPartsDialerConfig{ + options.ChatStreamPartsDialer = entchatd.NewStreamPartsDialer(entchatd.StreamPartsDialerConfig{ ResolveReplicaAddress: resolveReplicaAddress, ReplicaHTTPClient: replicaHTTPClient, ReplicaIDFn: func() uuid.UUID { @@ -223,7 +223,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { }, }) - options.Options.ChatAgentCapacityUnlock = entchatd.NewAgentCapacityUnlock(options.Entitlements) + options.ChatAgentCapacityUnlock = entchatd.NewAgentCapacityUnlock(options.Entitlements) api.AGPL = coderd.New(options.Options) api.aiSeatTracker = aiseats.New(options.Database, api.Logger.Named("aiseats"), quartz.NewReal(), &api.AGPL.Auditor) @@ -235,7 +235,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { } }() - api.AGPL.Options.ParseLicenseClaims = func(rawJWT string) (email string, trial bool, err error) { + api.AGPL.ParseLicenseClaims = func(rawJWT string) (email string, trial bool, err error) { c, err := license.ParseClaims(rawJWT, Keys) if err != nil { return "", false, err @@ -254,7 +254,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { api.tailnetService, err = tailnet.NewClientService(agpltailnet.ClientServiceOptions{ Logger: api.Logger.Named("tailnetclient"), CoordPtr: &api.AGPL.TailnetCoordinator, - DERPMapUpdateFrequency: api.Options.DERPMapUpdateFrequency, + DERPMapUpdateFrequency: api.DERPMapUpdateFrequency, DERPMapFn: api.AGPL.DERPMap, NetworkTelemetryHandler: api.AGPL.NetworkTelemetryBatcher.Handler, ResumeTokenProvider: api.AGPL.CoordinatorResumeTokenProvider, @@ -940,13 +940,13 @@ func (api *API) Close() error { _ = api.derpMesh.Close() } - if api.Options.CheckInactiveUsersCancelFunc != nil { - api.Options.CheckInactiveUsersCancelFunc() + if api.CheckInactiveUsersCancelFunc != nil { + api.CheckInactiveUsersCancelFunc() } // Close the connection logger to flush any remaining batched // entries before shutting down the database connection. - if cl, ok := api.Options.ConnectionLogger.(io.Closer); ok { + if cl, ok := api.ConnectionLogger.(io.Closer); ok { _ = cl.Close() } @@ -1092,7 +1092,7 @@ func (api *API) updateEntitlements(ctx context.Context) error { api.replicaManager.SetCallback("derp", func() { // Only update DERP mesh if the built-in server is enabled. - if api.Options.DeploymentValues.DERP.Server.Enable { + if api.DeploymentValues.DERP.Server.Enable { addresses := make([]string, 0) for _, replica := range api.replicaManager.DERPReplicasThisRegion() { // Don't add replicas with an empty relay address. @@ -1107,7 +1107,7 @@ func (api *API) updateEntitlements(ctx context.Context) error { }) } else { coordinator = agpltailnet.NewCoordinator(api.Logger) - if api.Options.DeploymentValues.DERP.Server.Enable { + if api.DeploymentValues.DERP.Server.Enable { api.derpMesh.SetAddresses([]string{}, false) } api.replicaManager.SetCallback("derp", func() { @@ -1168,7 +1168,7 @@ func (api *API) updateEntitlements(ctx context.Context) error { } if initial, changed, enabled := featureChanged(codersdk.FeatureControlSharedPorts); shouldUpdate(initial, changed, enabled) { - var ps agplportsharing.PortSharer = agplportsharing.DefaultPortSharer + ps := agplportsharing.DefaultPortSharer if enabled { ps = portsharing.NewEnterprisePortSharer() } diff --git a/enterprise/coderd/coderdenttest/proxytest.go b/enterprise/coderd/coderdenttest/proxytest.go index f64acb2bd72..89e3c48e6b5 100644 --- a/enterprise/coderd/coderdenttest/proxytest.go +++ b/enterprise/coderd/coderdenttest/proxytest.go @@ -138,7 +138,7 @@ func NewWorkspaceProxyReplica(t *testing.T, coderdAPI *coderd.API, owner *coders } // Inherit collector options from coderd, but keep the wsproxy reporter. - statsCollectorOptions := coderdAPI.Options.WorkspaceAppsStatsCollectorOptions + statsCollectorOptions := coderdAPI.WorkspaceAppsStatsCollectorOptions statsCollectorOptions.Reporter = nil if options.FlushStats != nil { statsCollectorOptions.Flush = options.FlushStats diff --git a/enterprise/coderd/dormancy/dormantusersjob_test.go b/enterprise/coderd/dormancy/dormantusersjob_test.go index 7e1b1642bf9..da3bd9382f9 100644 --- a/enterprise/coderd/dormancy/dormantusersjob_test.go +++ b/enterprise/coderd/dormancy/dormantusersjob_test.go @@ -65,9 +65,10 @@ func TestCheckInactiveUsers(t *testing.T) { var dormant, suspended int for _, row := range rows { - if row.Status == database.UserStatusDormant { + switch row.Status { + case database.UserStatusDormant: dormant++ - } else if row.Status == database.UserStatusSuspended { + case database.UserStatusSuspended: suspended++ } } diff --git a/enterprise/coderd/enidpsync/role.go b/enterprise/coderd/enidpsync/role.go index 73c63b349c6..092134d25ea 100644 --- a/enterprise/coderd/enidpsync/role.go +++ b/enterprise/coderd/enidpsync/role.go @@ -39,7 +39,7 @@ func (e EnterpriseIDPSync) SiteRoleSyncEnabled() bool { if !e.RoleSyncEntitled() { return false } - return e.AGPLIDPSync.SiteRoleField != "" + return e.SiteRoleField != "" } func (e EnterpriseIDPSync) ParseRoleClaims(ctx context.Context, mergedClaims jwt.MapClaims) (idpsync.RoleParams, *idpsync.HTTPError) { @@ -48,15 +48,15 @@ func (e EnterpriseIDPSync) ParseRoleClaims(ctx context.Context, mergedClaims jwt } var claimRoles []string - if e.AGPLIDPSync.SiteRoleField != "" { + if e.SiteRoleField != "" { var err error // TODO: Smoke test this error for org and site - claimRoles, err = e.AGPLIDPSync.RolesFromClaim(e.AGPLIDPSync.SiteRoleField, mergedClaims) + claimRoles, err = e.RolesFromClaim(e.SiteRoleField, mergedClaims) if err != nil { - rawType := mergedClaims[e.AGPLIDPSync.SiteRoleField] + rawType := mergedClaims[e.SiteRoleField] e.Logger.Error(ctx, "oidc claims user roles field was an unknown type", slog.F("type", fmt.Sprintf("%T", rawType)), - slog.F("field", e.AGPLIDPSync.SiteRoleField), + slog.F("field", e.SiteRoleField), slog.F("raw_value", rawType), slog.Error(err), ) diff --git a/enterprise/coderd/groups_test.go b/enterprise/coderd/groups_test.go index 946bc30cd55..5a39c99b351 100644 --- a/enterprise/coderd/groups_test.go +++ b/enterprise/coderd/groups_test.go @@ -1128,7 +1128,7 @@ func TestGroups(t *testing.T) { if g.ID == everyoneGroup.ID || g.ID == group2.ID { // Only expect the 1 member, themselves. require.Len(t, g.Members, 1) - require.Equal(t, user5.ReducedUser.ID, g.Members[0].MinimalUser.ID) + require.Equal(t, user5.ID, g.Members[0].ID) continue } diff --git a/enterprise/coderd/license/license.go b/enterprise/coderd/license/license.go index 13fc7afb1b0..71a7860118b 100644 --- a/enterprise/coderd/license/license.go +++ b/enterprise/coderd/license/license.go @@ -1227,7 +1227,7 @@ func validateClaims(tok *jwt.Token) (*Claims, error) { } yearsHardLimit := time.Now().Add(5 /* years */ * 365 * 24 * time.Hour) - if claims.LicenseExpires == nil || claims.LicenseExpires.Time.After(yearsHardLimit) { + if claims.LicenseExpires == nil || claims.LicenseExpires.After(yearsHardLimit) { return nil, ErrMissingLicenseExpires } if claims.ExpiresAt == nil { diff --git a/enterprise/coderd/notifications_test.go b/enterprise/coderd/notifications_test.go index 571ed4ced00..37deb17c318 100644 --- a/enterprise/coderd/notifications_test.go +++ b/enterprise/coderd/notifications_test.go @@ -76,7 +76,7 @@ func TestUpdateNotificationTemplateMethod(t *testing.T) { require.Error(t, err) require.ErrorAsf(t, err, &sdkError, "error should be of type *codersdk.Error") require.Equal(t, http.StatusNotFound, sdkError.StatusCode()) - require.Equal(t, "Resource not found or you do not have access to this resource", sdkError.Response.Message) + require.Equal(t, "Resource not found or you do not have access to this resource", sdkError.Message) }) t.Run("Invalid notification method", func(t *testing.T) { @@ -98,8 +98,8 @@ func TestUpdateNotificationTemplateMethod(t *testing.T) { require.Error(t, err) require.ErrorAsf(t, err, &sdkError, "error should be of type *codersdk.Error") require.Equal(t, http.StatusBadRequest, sdkError.StatusCode()) - require.Equal(t, "Invalid request to update notification template method", sdkError.Response.Message) - require.Len(t, sdkError.Response.Validations, 1) + require.Equal(t, "Invalid request to update notification template method", sdkError.Message) + require.Len(t, sdkError.Validations, 1) require.Equal(t, "method", sdkError.Response.Validations[0].Field) require.Equal(t, fmt.Sprintf("%q is not a valid method; smtp, webhook, inbox are the available options", method), sdkError.Response.Validations[0].Detail) }) diff --git a/enterprise/coderd/provisionerdaemons_test.go b/enterprise/coderd/provisionerdaemons_test.go index a1f3f7f38e0..7c75c4ef74c 100644 --- a/enterprise/coderd/provisionerdaemons_test.go +++ b/enterprise/coderd/provisionerdaemons_test.go @@ -1389,7 +1389,7 @@ func (s *deleteKeyOnReadStore) GetProvisionerKeyByID(ctx context.Context, id uui if target := s.keyID.Load(); target != nil && *target == id { s.once.Do(func() { //nolint:gocritic // The test deletes the key outside the request actor. - _ = s.Store.DeleteProvisionerKey(dbauthz.AsSystemRestricted(context.Background()), id) + _ = s.DeleteProvisionerKey(dbauthz.AsSystemRestricted(context.Background()), id) s.deleted.Store(true) }) } diff --git a/enterprise/coderd/templates.go b/enterprise/coderd/templates.go index 9ef07271fcd..bf04a4b6c07 100644 --- a/enterprise/coderd/templates.go +++ b/enterprise/coderd/templates.go @@ -172,7 +172,7 @@ func (api *API) templateACL(rw http.ResponseWriter, r *http.Request) { // We should probably at least return more truncated user data here. // nolint:gocritic members, err = api.Database.GetGroupMembersByGroupID(dbauthz.AsSystemRestricted(ctx), database.GetGroupMembersByGroupIDParams{ - GroupID: group.Group.ID, + GroupID: group.ID, IncludeSystem: false, }) if err != nil { @@ -181,7 +181,7 @@ func (api *API) templateACL(rw http.ResponseWriter, r *http.Request) { } // nolint:gocritic memberCount, err := api.Database.GetGroupMembersCountByGroupID(dbauthz.AsSystemRestricted(ctx), database.GetGroupMembersCountByGroupIDParams{ - GroupID: group.Group.ID, + GroupID: group.ID, IncludeSystem: false, }) if err != nil { @@ -325,7 +325,7 @@ func convertTemplateUsers(tus []database.TemplateUser, orgIDsByUserIDs map[uuid. for _, tu := range tus { users = append(users, codersdk.TemplateUser{ - User: db2sdk.User(tu.User, orgIDsByUserIDs[tu.User.ID]), + User: db2sdk.User(tu.User, orgIDsByUserIDs[tu.ID]), Role: convertToTemplateRole(tu.Actions), }) } diff --git a/enterprise/coderd/templates_test.go b/enterprise/coderd/templates_test.go index 79cbacd49b7..d7585fbd846 100644 --- a/enterprise/coderd/templates_test.go +++ b/enterprise/coderd/templates_test.go @@ -188,7 +188,7 @@ func TestTemplates(t *testing.T) { // OK: setting the same level is a no-op under the new PATCH semantics // (304 Not Modified) but must not be a server error. - var level codersdk.WorkspaceAgentPortShareLevel = codersdk.WorkspaceAgentPortShareLevelPublic + level := codersdk.WorkspaceAgentPortShareLevelPublic _, err = client.UpdateTemplateMeta(ctx, template.ID, codersdk.UpdateTemplateMeta{ MaxPortShareLevel: &level, }) diff --git a/enterprise/coderd/usage/publisher.go b/enterprise/coderd/usage/publisher.go index 3fb9e022ee8..ccb2e14d3af 100644 --- a/enterprise/coderd/usage/publisher.go +++ b/enterprise/coderd/usage/publisher.go @@ -372,7 +372,7 @@ func (p *tallymanPublisher) getBestLicenseJWT(ctx context.Context) (string, erro // Otherwise, if it's issued more recently, it's the best license. // IssuedAt is verified to be non-nil in license.ParseClaims. - if bestLicense.Claims == nil || claims.IssuedAt.Time.After(bestLicense.Claims.IssuedAt.Time) { + if bestLicense.Claims == nil || claims.IssuedAt.After(bestLicense.Claims.IssuedAt.Time) { bestLicense = licenseJWTWithClaims{ Claims: claims, Raw: dbLicense.JWT, diff --git a/enterprise/coderd/workspaceproxy.go b/enterprise/coderd/workspaceproxy.go index d5440c5edb3..6746f5938a9 100644 --- a/enterprise/coderd/workspaceproxy.go +++ b/enterprise/coderd/workspaceproxy.go @@ -405,7 +405,7 @@ func validateProxyURL(u string) error { if p.Scheme != "http" && p.Scheme != "https" { return xerrors.New("scheme must be http or https") } - if !(p.Path == "/" || p.Path == "") { + if p.Path != "/" && p.Path != "" { return xerrors.New("path must be empty or /") } return nil @@ -623,7 +623,7 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request) } } - startingRegionID, _ := getProxyDERPStartingRegionID(api.Options.BaseDERPMap) + startingRegionID, _ := getProxyDERPStartingRegionID(api.BaseDERPMap) // #nosec G115 - Safe conversion as DERP region IDs are small integers expected to be within int32 range regionID := int32(startingRegionID) + proxy.RegionID diff --git a/enterprise/coderd/workspaceproxy_test.go b/enterprise/coderd/workspaceproxy_test.go index 144fbfde1ad..b958fe84fd0 100644 --- a/enterprise/coderd/workspaceproxy_test.go +++ b/enterprise/coderd/workspaceproxy_test.go @@ -867,7 +867,7 @@ func TestReconnectingPTYSignedToken(t *testing.T) { var sdkErr *codersdk.Error require.ErrorAs(t, err, &sdkErr) require.Equal(t, http.StatusBadRequest, sdkErr.StatusCode()) - require.Contains(t, sdkErr.Response.Message, "Invalid URL") + require.Contains(t, sdkErr.Message, "Invalid URL") }) t.Run("BadURL", func(t *testing.T) { @@ -886,8 +886,8 @@ func TestReconnectingPTYSignedToken(t *testing.T) { var sdkErr *codersdk.Error require.ErrorAs(t, err, &sdkErr) require.Equal(t, http.StatusBadRequest, sdkErr.StatusCode()) - require.Contains(t, sdkErr.Response.Message, "Invalid URL") - require.Contains(t, sdkErr.Response.Detail, "scheme") + require.Contains(t, sdkErr.Message, "Invalid URL") + require.Contains(t, sdkErr.Detail, "scheme") }) t.Run("BadURLPath", func(t *testing.T) { @@ -906,8 +906,8 @@ func TestReconnectingPTYSignedToken(t *testing.T) { var sdkErr *codersdk.Error require.ErrorAs(t, err, &sdkErr) require.Equal(t, http.StatusBadRequest, sdkErr.StatusCode()) - require.Contains(t, sdkErr.Response.Message, "Invalid URL") - require.Contains(t, sdkErr.Response.Detail, "The provided URL is not a valid reconnecting PTY endpoint URL") + require.Contains(t, sdkErr.Message, "Invalid URL") + require.Contains(t, sdkErr.Detail, "The provided URL is not a valid reconnecting PTY endpoint URL") }) t.Run("BadHostname", func(t *testing.T) { @@ -926,7 +926,7 @@ func TestReconnectingPTYSignedToken(t *testing.T) { var sdkErr *codersdk.Error require.ErrorAs(t, err, &sdkErr) require.Equal(t, http.StatusBadRequest, sdkErr.StatusCode()) - require.Contains(t, sdkErr.Response.Message, "Invalid hostname in URL") + require.Contains(t, sdkErr.Message, "Invalid hostname in URL") }) t.Run("NoToken", func(t *testing.T) { diff --git a/enterprise/coderd/workspaces_test.go b/enterprise/coderd/workspaces_test.go index ea764ae2174..ec7457c0df2 100644 --- a/enterprise/coderd/workspaces_test.go +++ b/enterprise/coderd/workspaces_test.go @@ -2961,7 +2961,7 @@ func TestPrebuildUpdateLifecycleParams(t *testing.T) { var apiErr *codersdk.Error require.ErrorAs(t, err, &apiErr) require.Equal(t, http.StatusConflict, apiErr.StatusCode()) - require.Equal(t, tc.apiErrorMsg, apiErr.Response.Message) + require.Equal(t, tc.apiErrorMsg, apiErr.Message) // Given: the prebuilt workspace is claimed by a user user, err := client.User(ctx, "testUser") @@ -4834,9 +4834,10 @@ func TestWorkspacesSharedWith(t *testing.T) { // Find actors in response var userActor, groupActor *codersdk.SharedWorkspaceActor for i := range sharedWith { - if sharedWith[i].ActorType == codersdk.SharedWorkspaceActorTypeUser { + switch sharedWith[i].ActorType { + case codersdk.SharedWorkspaceActorTypeUser: userActor = &sharedWith[i] - } else if sharedWith[i].ActorType == codersdk.SharedWorkspaceActorTypeGroup { + case codersdk.SharedWorkspaceActorTypeGroup: groupActor = &sharedWith[i] } } @@ -4921,9 +4922,10 @@ func TestWorkspacesSharedWith(t *testing.T) { // Find actors in response var userActor, groupActor *codersdk.SharedWorkspaceActor for i := range sharedWith { - if sharedWith[i].ActorType == codersdk.SharedWorkspaceActorTypeUser { + switch sharedWith[i].ActorType { + case codersdk.SharedWorkspaceActorTypeUser: userActor = &sharedWith[i] - } else if sharedWith[i].ActorType == codersdk.SharedWorkspaceActorTypeGroup { + case codersdk.SharedWorkspaceActorTypeGroup: groupActor = &sharedWith[i] } } diff --git a/enterprise/wsproxy/wsproxy_test.go b/enterprise/wsproxy/wsproxy_test.go index ec6ecc01d3d..c8c4b3c52b4 100644 --- a/enterprise/wsproxy/wsproxy_test.go +++ b/enterprise/wsproxy/wsproxy_test.go @@ -90,7 +90,7 @@ func TestDERPOnly(t *testing.T) { regions, err := client.Regions(ctx) require.NoError(t, err) require.Len(t, regions, 1) - require.Equal(t, api.Options.AccessURL.String(), regions[0].PathAppURL) + require.Equal(t, api.AccessURL.String(), regions[0].PathAppURL) } func TestDERP(t *testing.T) { diff --git a/mise.lock b/mise.lock index 02442a453fb..e6b1a785f5c 100644 --- a/mise.lock +++ b/mise.lock @@ -496,9 +496,9 @@ backend = "go:github.com/coder/whichtests" version = "v4.19.0" backend = "go:github.com/golang-migrate/migrate/v4/cmd/migrate" -[[tools."go:github.com/golangci/golangci-lint/cmd/golangci-lint"]] -version = "1.64.8" -backend = "go:github.com/golangci/golangci-lint/cmd/golangci-lint" +[[tools."go:github.com/golangci/golangci-lint/v2/cmd/golangci-lint"]] +version = "2.0.2" +backend = "go:github.com/golangci/golangci-lint/v2/cmd/golangci-lint" [[tools."go:github.com/goreleaser/nfpm/v2/cmd/nfpm"]] version = "v2.35.1" @@ -707,7 +707,6 @@ url = "https://nodejs.org/dist/v22.19.0/node-v22.19.0-linux-arm64.tar.gz" [tools.node."platforms.linux-arm64-musl"] checksum = "sha256:4cea680423f98abc6a2a5ca127fb34c5f6586c24217f57749be6ea886c9be9a6" url = "https://nodejs.org/dist/v22.19.0/node-v22.19.0.tar.gz" -install = "source" [tools.node."platforms.linux-x64"] checksum = "sha256:d36e56998220085782c0ca965f9d51b7726335aed2f5fc7321c6c0ad233aa96d" diff --git a/mise.toml b/mise.toml index efac2ca4c12..a44a5b1e17e 100644 --- a/mise.toml +++ b/mise.toml @@ -22,11 +22,12 @@ protoc-gen-go = "1.30.0" # Go development tools. "go:github.com/coder/paralleltestctx/cmd/paralleltestctx" = "v0.0.2" "go:github.com/coder/whichtests" = "377b8dbf1cccae3b04b48bc8cfc2410813491414" -# Keep golangci-lint on the Go backend while pinned to v1. The upstream -# precompiled v1 binary is built with an older Go toolchain and cannot lint -# this module's Go version. Upgrading to v2 should let us use the native -# golangci-lint mise/aqua backend and GitHub release binaries. -"go:github.com/golangci/golangci-lint/cmd/golangci-lint" = "v1.64.8" +# Keep golangci-lint on the Go backend until we upgrade to a more recent +# version. The upstream precompiled binaries may be built with older Go versions +# (and older included versions of packages like go/ast) that can result in them +# being unable to lint code for our Go version. Upgrading to a new enough +# version should let us use the native mise backend and GitHub release binaries. +"go:github.com/golangci/golangci-lint/v2/cmd/golangci-lint" = "v2.0.2" "go:github.com/golang-migrate/migrate/v4/cmd/migrate" = "v4.19.0" "go:github.com/goreleaser/nfpm/v2/cmd/nfpm" = "v2.35.1" "go:github.com/slsyy/mtimehash/cmd/mtimehash" = "v1.0.0" diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index 6b9b0b1c91a..0bdfc968169 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -343,35 +343,35 @@ func (r *Responses) Valid() error { for _, parse := range r.Parse { ty := parse.Type - if !(isParse(ty) || isLog(ty)) { + if !isParse(ty) && !isLog(ty) { return xerrors.Errorf("invalid parse response type: %T", ty) } } for _, init := range r.ProvisionInit { ty := init.Type - if !(isInit(ty) || isLog(ty) || isChunkPiece(ty) || isDataUpload(ty)) { + if !isInit(ty) && !isLog(ty) && !isChunkPiece(ty) && !isDataUpload(ty) { return xerrors.Errorf("invalid init response type: %T", ty) } } for _, plan := range r.ProvisionPlan { ty := plan.Type - if !(isPlan(ty) || isLog(ty)) { + if !isPlan(ty) && !isLog(ty) { return xerrors.Errorf("invalid plan response type: %T", ty) } } for _, apply := range r.ProvisionApply { ty := apply.Type - if !(isApply(ty) || isLog(ty)) { + if !isApply(ty) && !isLog(ty) { return xerrors.Errorf("invalid apply response type: %T", ty) } } for _, graph := range r.ProvisionGraph { ty := graph.Type - if !(isGraph(ty) || isLog(ty)) { + if !isGraph(ty) && !isLog(ty) { return xerrors.Errorf("invalid graph response type: %T", ty) } } diff --git a/provisioner/terraform/install.go b/provisioner/terraform/install.go index 48c8ea8a095..3eadfe79295 100644 --- a/provisioner/terraform/install.go +++ b/provisioner/terraform/install.go @@ -34,7 +34,7 @@ var ( // operation. // //nolint:revive // verbose is a control flag that controls the verbosity of the log output. -func Install(ctx context.Context, log slog.Logger, verbose bool, dir string, wantVersion *version.Version, baseUrl string) (string, error) { +func Install(ctx context.Context, log slog.Logger, verbose bool, dir string, wantVersion *version.Version, baseURL string) (string, error) { err := os.MkdirAll(dir, 0o750) if err != nil { return "", err @@ -68,8 +68,8 @@ func Install(ctx context.Context, log slog.Logger, verbose bool, dir string, wan Version: TerraformVersion, } installer.SetLogger(slog.Stdlib(ctx, log, slog.LevelDebug)) - if baseUrl != "" { - installer.ApiBaseURL = baseUrl + if baseURL != "" { + installer.ApiBaseURL = baseURL } logInstall := log.Debug diff --git a/provisioner/terraform/parse.go b/provisioner/terraform/parse.go index 2f5a8c7f5c3..33412fd62e8 100644 --- a/provisioner/terraform/parse.go +++ b/provisioner/terraform/parse.go @@ -54,10 +54,10 @@ func formatDiagnostics(baseDir string, diags tfconfig.Diagnostics) string { for _, d := range diags { // Convert severity. severity := "UNKNOWN SEVERITY" - switch { - case d.Severity == tfconfig.DiagError: + switch d.Severity { + case tfconfig.DiagError: severity = "ERROR" - case d.Severity == tfconfig.DiagWarning: + case tfconfig.DiagWarning: severity = "WARN" } diff --git a/provisioner/terraform/timings.go b/provisioner/terraform/timings.go index 05b4e0cf8bb..628a5333a61 100644 --- a/provisioner/terraform/timings.go +++ b/provisioner/terraform/timings.go @@ -192,15 +192,15 @@ func (t *timingAggregator) startStage(stage database.ProvisionerJobTimingStage) action: "terraform", provider: "coder", } - endTs := ts + endTS := ts t.ingest(dbtime.Now(), &ts) return func(err error) { - endTs.kind = timingStageEnd + endTS.kind = timingStageEnd if err != nil { - endTs.kind = timingStageError + endTS.kind = timingStageError } - t.ingest(dbtime.Now(), &endTs) + t.ingest(dbtime.Now(), &endTS) } } diff --git a/scaletest/dashboard/config.go b/scaletest/dashboard/config.go index 44ee41ae4a3..d749bc6139c 100644 --- a/scaletest/dashboard/config.go +++ b/scaletest/dashboard/config.go @@ -34,11 +34,11 @@ type Config struct { } func (c Config) Validate() error { - if !(c.Interval > 0) { + if c.Interval <= 0 { return xerrors.Errorf("validate interval: must be greater than zero") } - if !(c.Jitter < c.Interval) { + if c.Jitter >= c.Interval { return xerrors.Errorf("validate jitter: must be less than interval") } diff --git a/tailnet/configmaps.go b/tailnet/configmaps.go index 7d61610368b..92d123cea2d 100644 --- a/tailnet/configmaps.go +++ b/tailnet/configmaps.go @@ -152,7 +152,7 @@ func (c *configMaps) configLoop() { c.Broadcast() }() for { - for !(c.closing || c.netmapDirty || c.filterDirty || c.derpMapDirty) { + for !c.closing && !c.netmapDirty && !c.filterDirty && !c.derpMapDirty { c.phase = idle c.Wait() } diff --git a/tailnet/controllers.go b/tailnet/controllers.go index 6d5b55af605..0eba6735bef 100644 --- a/tailnet/controllers.go +++ b/tailnet/controllers.go @@ -420,7 +420,7 @@ func NewTunnelSrcCoordController( func (c *TunnelSrcCoordController) New(client CoordinatorClient) CloserWaiter { c.mu.Lock() defer c.mu.Unlock() - b := c.BasicCoordinationController.NewCoordination(client) + b := c.NewCoordination(client) c.coordination = b // resync destinations on reconnect for dest := range c.dests { diff --git a/tailnet/node.go b/tailnet/node.go index bb193dc2728..07584845928 100644 --- a/tailnet/node.go +++ b/tailnet/node.go @@ -49,7 +49,7 @@ func (u *nodeUpdater) updateLoop() { u.Broadcast() }() for { - for !(u.closing || u.dirty) { + for !u.closing && !u.dirty { u.phase = idle u.Wait() } diff --git a/tailnet/tailnettest/tailnettest.go b/tailnet/tailnettest/tailnettest.go index c2b2bff6311..75d02dd5ced 100644 --- a/tailnet/tailnettest/tailnettest.go +++ b/tailnet/tailnettest/tailnettest.go @@ -115,7 +115,7 @@ func RunDERPOnlyWebSockets(t *testing.T) *tailcfg.DERPMap { } if r.Header.Get("Upgrade") != "websocket" { w.WriteHeader(http.StatusBadRequest) - _, _ = w.Write([]byte(fmt.Sprintf(`Invalid "Upgrade" header: %s`, html.EscapeString(r.Header.Get("Upgrade"))))) + _, _ = fmt.Fprintf(w, `Invalid "Upgrade" header: %s`, html.EscapeString(r.Header.Get("Upgrade"))) return } handler.ServeHTTP(w, r) diff --git a/testutil/pty.go b/testutil/pty.go index c967835e82a..4067d545318 100644 --- a/testutil/pty.go +++ b/testutil/pty.go @@ -62,7 +62,7 @@ func (tr *TerminalReader) ReadUntil(ctx context.Context, matcher func(line strin gotTrimmed := strings.Join(lines, "\n") tr.t.Logf("Terminal contents:\n%s", gotTrimmed) // EOF is expected when matcher == nil - if retErr != nil && !(xerrors.Is(retErr, io.EOF) && matcher == nil) { + if retErr != nil && (!xerrors.Is(retErr, io.EOF) || matcher != nil) { tr.t.Logf("Bytes Read: %q", string(readBytes)) } }() diff --git a/testutil/retry.go b/testutil/retry.go index 1555464bad7..dac5edabc12 100644 --- a/testutil/retry.go +++ b/testutil/retry.go @@ -138,43 +138,43 @@ func (t *fakeT) Context() context.Context { // Error implements testing.TB. Error is equivalent to Log followed by Fail. func (t *fakeT) Error(args ...any) { - t.T.Helper() - t.T.Log(args...) + t.Helper() + t.Log(args...) t.Fail() } // Errorf implements testing.TB. Errorf is equivalent to Logf followed by Fail. func (t *fakeT) Errorf(format string, args ...any) { - t.T.Helper() - t.T.Logf(format, args...) + t.Helper() + t.Logf(format, args...) t.Fail() } // Fail implements testing.TB. Fail marks the function as having failed but // continues execution. func (t *fakeT) Fail() { - t.T.Helper() + t.Helper() t.mu.Lock() defer t.mu.Unlock() t.failed = true - t.T.Log("testutil.RunRetry: t.Fail called in testutil.RunRetry closure") + t.Log("testutil.RunRetry: t.Fail called in testutil.RunRetry closure") } // FailNow implements testing.TB. FailNow marks the function as having failed // and stops its execution by calling runtime.Goexit (which then runs all the // deferred calls in the current goroutine). func (t *fakeT) FailNow() { - t.T.Helper() + t.Helper() t.mu.Lock() defer t.mu.Unlock() t.failed = true - t.T.Log("testutil.RunRetry: t.FailNow called in testutil.RunRetry closure") + t.Log("testutil.RunRetry: t.FailNow called in testutil.RunRetry closure") runtime.Goexit() } // Failed implements testing.TB. Failed reports whether the function has failed. func (t *fakeT) Failed() bool { - t.T.Helper() + t.Helper() t.mu.Lock() defer t.mu.Unlock() return t.failed @@ -182,16 +182,16 @@ func (t *fakeT) Failed() bool { // Fatal implements testing.TB. Fatal is equivalent to Log followed by FailNow. func (t *fakeT) Fatal(args ...any) { - t.T.Helper() - t.T.Log(args...) + t.Helper() + t.Log(args...) t.FailNow() } // Fatalf implements testing.TB. Fatalf is equivalent to Logf followed by // FailNow. func (t *fakeT) Fatalf(format string, args ...any) { - t.T.Helper() - t.T.Logf(format, args...) + t.Helper() + t.Logf(format, args...) t.FailNow() } diff --git a/testutil/wait_buffer_test.go b/testutil/wait_buffer_test.go index 13bbe2713f2..090984b45eb 100644 --- a/testutil/wait_buffer_test.go +++ b/testutil/wait_buffer_test.go @@ -121,7 +121,7 @@ func TestWaitBuffer_ConcurrentWrites(t *testing.T) { go func() { defer wg.Done() for j := range iterations { - _, _ = wb.Write([]byte(fmt.Sprintf("w%d-%d ", i, j))) + _, _ = fmt.Fprintf(wb, "w%d-%d ", i, j) } }() } diff --git a/vpn/speaker.go b/vpn/speaker.go index 9ba0899af30..84a18a8cfb9 100644 --- a/vpn/speaker.go +++ b/vpn/speaker.go @@ -295,7 +295,7 @@ func handshake( writeOK := false theirHeader := "" readOK := false - for !(readOK && writeOK) { + for !readOK || !writeOK { select { case <-ctx.Done(): _ = conn.Close() // ensure our read/write goroutines get a chance to clean up diff --git a/vpn/tunnel.go b/vpn/tunnel.go index 47a6c22893b..b8a6868b65b 100644 --- a/vpn/tunnel.go +++ b/vpn/tunnel.go @@ -102,7 +102,7 @@ func NewTunnel( func (t *Tunnel) requestLoop() { defer close(t.requestLoopDone) - for req := range t.speaker.requests { + for req := range t.requests { if req.msg.Rpc != nil && req.msg.Rpc.MsgId != 0 { t.handleRPC(req) if _, ok := req.msg.GetMsg().(*ManagerMessage_Stop); ok { @@ -124,7 +124,7 @@ func (t *Tunnel) handleRPC(req *request[*TunnelMessage, *ManagerMessage]) { resp.Rpc = &RPC{ResponseTo: req.msg.Rpc.MsgId} switch msg := req.msg.GetMsg().(type) { case *ManagerMessage_GetPeerUpdate: - err := t.updater.sendUpdateResponse(req) + err := t.sendUpdateResponse(req) if err != nil { t.logger.Error(t.ctx, "failed to send peer update", slog.Error(err)) } @@ -165,7 +165,7 @@ func (t *Tunnel) handleRPC(req *request[*TunnelMessage, *ManagerMessage]) { }, } case *ManagerMessage_Wake: - if t.updater.rebind() { + if t.rebind() { t.logger.Info(t.ctx, "handling system wake; rebinding") } else { t.logger.Debug(t.ctx, "ignoring system wake; tunnel is not running or a rebind happened recently") @@ -208,7 +208,7 @@ func WithClock(clock quartz.Clock) TunnelOption { // ApplyNetworkSettings sends a request to the manager to apply the given network settings func (t *Tunnel) ApplyNetworkSettings(ctx context.Context, ns *NetworkSettingsRequest) error { - msg, err := t.speaker.unaryRPC(ctx, &TunnelMessage{ + msg, err := t.unaryRPC(ctx, &TunnelMessage{ Msg: &TunnelMessage_NetworkSettings{ NetworkSettings: ns, }, @@ -286,7 +286,7 @@ func (t *Tunnel) start(req *StartRequest) error { return xerrors.Errorf("failed to start connection: %w", err) } - if ok := t.updater.setConn(conn); !ok { + if ok := t.setConn(conn); !ok { t.logger.Warn(t.ctx, "asked to start tunnel, but tunnel is already running") } return err