From e804e181344fe85a9a1846b60a9127131a967094 Mon Sep 17 00:00:00 2001 From: Leslie Qi Wang Date: Fri, 15 Aug 2025 16:36:05 -0700 Subject: [PATCH] upgrade golangci-lint tool and enable more tools Also fixed another 21 issues identified Signed-off-by: Leslie Qi Wang --- .github/workflows/lint.yml | 2 +- .golangci.yml | 198 +++++++++++---------- actionsdotnetactcompat/act_runner.go | 3 +- actionsdotnetactcompat/act_worker.go | 40 +++-- actionsrunner/logger.go | 3 +- actionsrunner/runner.go | 8 +- actionsrunner/worker_runner_environment.go | 4 +- common/io.go | 2 +- main.go | 24 ++- protocol/connection.go | 6 +- protocol/misc.go | 6 +- protocol/results/service.go | 6 +- protocol/session.go | 3 +- protocol/task_agent.go | 2 +- protocol/template_token.go | 6 +- protocol/timeline.go | 3 +- runnerconfiguration/add.go | 4 +- runnerconfiguration/common.go | 4 +- runnerconfiguration/remove.go | 2 +- 19 files changed, 179 insertions(+), 147 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c4151e2..6b1e398 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -34,7 +34,7 @@ jobs: run: go mod download - name: Run golangci-lint - uses: golangci/golangci-lint-action@v4 + uses: golangci/golangci-lint-action@v8 with: version: latest args: --timeout=5m diff --git a/.golangci.yml b/.golangci.yml index 48fdb11..81bb31a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,115 +1,131 @@ +version: "2" run: - timeout: 5m - go: '1.21' - -linters-settings: - govet: - enable: - - shadow - revive: - min-confidence: 0.8 - gocyclo: - min-complexity: 15 - dupl: - threshold: 100 - goconst: - min-len: 2 - min-occurrences: 2 - misspell: - locale: US - lll: - line-length: 140 - goimports: - local-prefixes: github.com/ChristopherHX/github-act-runner - gocritic: - enabled-tags: - - diagnostic - - experimental - - opinionated - - performance - - style - disabled-checks: - - dupImport # https://github.com/go-critic/go-critic/issues/845 - - ifElseChain - - octalLiteral - - whyNoLint - - wrapperFunc - + go: "1.21" linters: enable: + - asciicheck + - bidichk - bodyclose - # - depguard # Disabled for now as it's too restrictive + - copyloopvar - dogsled - dupl - - errcheck - - copyloopvar # replaces exportloopref for Go 1.22+ + - durationcheck + - errname + - errorlint - exhaustive + - gocheckcompilerdirectives - goconst - gocritic - - gofmt - - goimports - - revive # replaces golint - - mnd # replaces gomnd - goprintffuncname - gosec - - gosimple - - govet - - ineffassign + - importas - lll + - makezero - misspell + - mnd - nakedret + - nilerr - noctx - nolintlint + - prealloc + - revive - rowserrcheck - staticcheck - - stylecheck - - typecheck + - tparallel - unconvert - unparam - - unused + - usestdlibvars - whitespace - + settings: + dupl: + threshold: 100 + goconst: + min-len: 2 + min-occurrences: 2 + gocritic: + disabled-checks: + - dupImport + - ifElseChain + - octalLiteral + - whyNoLint + - wrapperFunc + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + gocyclo: + min-complexity: 15 + govet: + enable: + - shadow + lll: + line-length: 140 + misspell: + locale: US + revive: + confidence: 0.8 + exclusions: + generated: lax + rules: + - linters: + - gocritic + - gosec + - mnd + path: _test\.go + - linters: + - mnd + path: main\.go + - linters: + - revive + path: protocol/ + - linters: + - gosec + text: weak cryptographic primitive + - linters: + - gosec + text: Use of weak random number generator + - linters: + - staticcheck + text: at least one file in a package should have a package comment + - linters: + - staticcheck + text: should have a package comment + - linters: + - revive + text: 'package-comments: should have a package comment' + - linters: + - revive + text: exported function .* should have comment or be unexported + - linters: + - revive + text: exported method .* should have comment or be unexported + - linters: + - revive + text: exported type .* should have comment or be unexported + - linters: + - revive + text: exported var .* should have comment or be unexported + paths: + - third_party$ + - builtin$ + - examples$ issues: - exclude-rules: - - path: _test\.go - linters: - - mnd - - gocritic - - gosec - - path: main\.go - linters: - - mnd - - path: protocol/ - linters: - - revive # Protocol has many generated-like structs - - text: "weak cryptographic primitive" - linters: - - gosec - - text: "Use of weak random number generator" - linters: - - gosec - - text: "at least one file in a package should have a package comment" - linters: - - stylecheck - - text: "should have a package comment" - linters: - - stylecheck - - text: "package-comments: should have a package comment" - linters: - - revive - - text: "exported function .* should have comment or be unexported" - linters: - - revive - - text: "exported method .* should have comment or be unexported" - linters: - - revive - - text: "exported type .* should have comment or be unexported" - linters: - - revive - - text: "exported var .* should have comment or be unexported" - linters: - - revive - - exclude-use-default: false max-issues-per-linter: 0 max-same-issues: 0 +formatters: + enable: + - gofmt + - gofumpt + - goimports + settings: + goimports: + local-prefixes: + - github.com/ChristopherHX/github-act-runner + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/actionsdotnetactcompat/act_runner.go b/actionsdotnetactcompat/act_runner.go index 8f00b06..ac781f3 100644 --- a/actionsdotnetactcompat/act_runner.go +++ b/actionsdotnetactcompat/act_runner.go @@ -10,7 +10,8 @@ type ActRunner struct { } func (arunner *ActRunner) ExecWorker(run *actionsrunner.RunRunner, wc actionsrunner.WorkerContext, - jobreq *protocol.AgentJobRequestMessage, src []byte) error { + jobreq *protocol.AgentJobRequestMessage, src []byte, +) error { if len(arunner.WorkerArgs) == 0 { ExecWorker(jobreq, wc) return nil diff --git a/actionsdotnetactcompat/act_worker.go b/actionsdotnetactcompat/act_worker.go index 70f0525..a0a9de6 100644 --- a/actionsdotnetactcompat/act_worker.go +++ b/actionsdotnetactcompat/act_worker.go @@ -38,9 +38,15 @@ const ( maxRedirects = 10 jobTimeout = 5 * time.Minute // File permissions - directoryPermissions = 0777 + directoryPermissions = 0o777 // Stage constants mainStage = "Main" + // Log prefix constants + debugPrefix = "##[debug]" + warnPrefix = "##[warn]" + errorPrefix = "##[error]" + panicPrefix = "##[panic]" + fatalPrefix = "##[fatal]" ) type ghaFormatter struct { @@ -54,11 +60,14 @@ type ghaFormatter struct { } func flushInternal(rec *protocol.TimelineRecord, res *model.StepResult) { - if res.Conclusion == model.StepStatusSuccess { + switch res.Conclusion { + case model.StepStatusSuccess: rec.Complete("Succeeded") - } else if res.Conclusion == model.StepStatusSkipped { + case model.StepStatusSkipped: rec.Complete("Skipped") - } else { + case model.StepStatusFailure: + rec.Complete("Failed") + default: rec.Complete("Failed") } } @@ -176,12 +185,21 @@ func (f *ghaFormatter) Format(entry *logrus.Entry) ([]byte, error) { } prefix := entry.Time.UTC().Format(protocol.TimestampOutputFormat) + " " - if entry.Level == logrus.DebugLevel { - prefix += "##[debug]" - } else if entry.Level == logrus.WarnLevel { - prefix += "##[warning]" - } else if entry.Level == logrus.ErrorLevel { - prefix += "##[error]" + switch entry.Level { + case logrus.DebugLevel: + prefix += debugPrefix + case logrus.WarnLevel: + prefix += warnPrefix + case logrus.ErrorLevel: + prefix += errorPrefix + case logrus.PanicLevel: + prefix += panicPrefix + case logrus.FatalLevel: + prefix += fatalPrefix + case logrus.InfoLevel: + // No special prefix for info level + case logrus.TraceLevel: + prefix += debugPrefix } entry.Message = f.linefeedregex.ReplaceAllString(prefix+strings.Trim(entry.Message, "\r\n"), "\n"+prefix) @@ -639,7 +657,7 @@ func downloadAndExtractAction( if contextLogger != nil { contextLogger.Infof("Downloading action %v/%v (sha:%v) from %v", owner, name, resolvedSha, tarURL) } - req, err := http.NewRequestWithContext(ctx, "GET", tarURL, http.NoBody) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, tarURL, http.NoBody) if err != nil { return err } diff --git a/actionsrunner/logger.go b/actionsrunner/logger.go index 1ce7a6d..7686f01 100644 --- a/actionsrunner/logger.go +++ b/actionsrunner/logger.go @@ -8,8 +8,7 @@ type BasicLogger interface { Printf(format string, a ...interface{}) } -type ConsoleLogger struct { -} +type ConsoleLogger struct{} func (*ConsoleLogger) Printf(format string, a ...interface{}) { fmt.Printf(format, a...) diff --git a/actionsrunner/runner.go b/actionsrunner/runner.go index 45eee25..c98e511 100644 --- a/actionsrunner/runner.go +++ b/actionsrunner/runner.go @@ -61,7 +61,6 @@ type RunnerEnvironment interface { ExecWorker(run *RunRunner, wc WorkerContext, jobreq *protocol.AgentJobRequestMessage, src []byte) error } -//nolint:revive // context-as-argument: API compatibility requirement - cannot change parameter order func (run *RunRunner) Run(runnerenv RunnerEnvironment, listenerctx, corectx context.Context) error { settings := run.Settings for i := 0; i < len(settings.Instances); i++ { @@ -448,17 +447,16 @@ type RunnerJobRequestRef struct { RunServiceURL string `json:"run_service_url"` } -type plainTextFormatter struct { -} +type plainTextFormatter struct{} func (f *plainTextFormatter) Format(entry *logrus.Entry) ([]byte, error) { return []byte(entry.Time.UTC().Format(protocol.TimestampOutputFormat) + " " + entry.Message + "\n"), nil } -//nolint:revive // context-as-argument: Legacy function signature for compatibility func runJob(runnerenv RunnerEnvironment, joblock *sync.Mutex, vssConnection *protocol.VssConnection, run *RunRunner, cancel context.CancelFunc, cancelJob context.CancelFunc, finishJob context.CancelFunc, jobExecCtx context.Context, jobctx context.Context, - session *protocol.AgentMessageConnection, message protocol.TaskAgentMessage, instance *runnerconfiguration.RunnerInstance) { + session *protocol.AgentMessageConnection, message protocol.TaskAgentMessage, instance *runnerconfiguration.RunnerInstance, +) { go func() { plogger := &PrefixConsoleLogger{ Parent: runnerenv, diff --git a/actionsrunner/worker_runner_environment.go b/actionsrunner/worker_runner_environment.go index bedb3ff..97058d2 100644 --- a/actionsrunner/worker_runner_environment.go +++ b/actionsrunner/worker_runner_environment.go @@ -16,7 +16,7 @@ const ( messageIDSize = 4 cancelRequestCmd = 2 // File permissions - filePermissions = 0664 + filePermissions = 0o664 ) type WorkerRunnerEnvironment struct { @@ -57,7 +57,7 @@ func (arunner *WorkerRunnerEnvironment) ExecWorker( return fmt.Errorf("missing WorkerArgs to execute an external worker") } //nolint:gosec // WorkerArgs are configured by the administrator, not user input - worker := exec.Command(arunner.WorkerArgs[0], arunner.WorkerArgs[1:]...) + worker := exec.CommandContext(jobExecCtx, arunner.WorkerArgs[0], arunner.WorkerArgs[1:]...) in, err := worker.StdinPipe() if err != nil { return err diff --git a/common/io.go b/common/io.go index a784566..5ccc0ad 100644 --- a/common/io.go +++ b/common/io.go @@ -7,7 +7,7 @@ import ( const ( // File permissions - filePermissions = 0664 + filePermissions = 0o664 ) func WriteJSON(path string, value interface{}) error { diff --git a/main.go b/main.go index ac3ed43..299e745 100644 --- a/main.go +++ b/main.go @@ -33,7 +33,7 @@ const ( // Binary protocol constants bufferSize = 4 // File permissions - logFilePermissions = 0777 + logFilePermissions = 0o777 ) type RunRunner struct { @@ -178,15 +178,16 @@ func (run *RunRunner) RunWithContext(listenerctx, ctx context.Context) int { var version = "0.8.x-dev" -type interactive struct { -} +type interactive struct{} func (i *interactive) GetInput(prompt, def string) string { return GetInput(prompt, def) } + func (i *interactive) GetSelectInput(_ string, options []string, def string) string { return RunnerGroupSurvey(def, options) } + func (i *interactive) GetMultiSelectInput(prompt string, options []string) []string { return GetMultiSelectInput(prompt, options) } @@ -251,7 +252,7 @@ func main() { remove := &runnerconfiguration.RemoveRunner{} printJITConfig := false saveActionsRunnerConfig := false - var cmdConfigure = &cobra.Command{ + cmdConfigure := &cobra.Command{ Use: "configure", Short: "Configure your self-hosted runner", Args: cobra.MaximumNArgs(0), @@ -318,7 +319,7 @@ func main() { "use the format of actions/runner to save the configuration") cmdConfigure.Flags().StringVar(&config.WorkFolder, "work", "_work", "actions/runner work folder (has no effect)") - var cmdRun = &cobra.Command{ + cmdRun := &cobra.Command{ Use: "run", Short: "Run your self-hosted runner", Args: cobra.MaximumNArgs(0), @@ -335,7 +336,7 @@ func main() { "read the runner configuration from the jitconfig") var jitConfig string local, _ := common.LookupEnvBool("ACTIONS_RUNNER_INPUT_LOCAL") - var cmdRemove = &cobra.Command{ + cmdRemove := &cobra.Command{ Use: "remove", Short: "Remove your self-hosted runner", Args: cobra.MaximumNArgs(0), @@ -392,7 +393,7 @@ func main() { "read the runner configuration from the jitconfig, this doesn't replace token/pat") cmdRemove.Flags().BoolVar(&local, "local", local, "only delete the configuration") - var cmdWorker = &cobra.Command{ + cmdWorker := &cobra.Command{ Use: "worker", Short: "Run as self-hosted runner worker, can be used to create ephemeral worker without exposing other job requests", Args: cobra.MaximumNArgs(0), @@ -447,7 +448,7 @@ func main() { <-ccontext.Done() }, } - var cmdSvc = &cobra.Command{ + cmdSvc := &cobra.Command{ Use: "svc", Short: "Manage the runner as a system service", } @@ -481,7 +482,6 @@ func main() { } svc, err := service.New(&RunRunnerSvc{}, getSvcConfig(wd, envFile)) - if err != nil { return err } @@ -494,7 +494,6 @@ func main() { Short: "Install the service may require admin privileges", RunE: func(_ *cobra.Command, _ []string) error { svc, err := service.New(&RunRunnerSvc{}, getSvcConfig(wd, envFile)) - if err != nil { return err } @@ -512,7 +511,6 @@ func main() { Short: "Uninstall the service may require admin privileges", RunE: func(_ *cobra.Command, _ []string) error { svc, err := service.New(&RunRunnerSvc{}, getSvcConfig(wd, envFile)) - if err != nil { return err } @@ -524,7 +522,6 @@ func main() { Short: "Start the service may require admin privileges", RunE: func(_ *cobra.Command, _ []string) error { svc, err := service.New(&RunRunnerSvc{}, getSvcConfig(wd, envFile)) - if err != nil { return err } @@ -536,7 +533,6 @@ func main() { Short: "Stop the service may require admin privileges", RunE: func(_ *cobra.Command, _ []string) error { svc, err := service.New(&RunRunnerSvc{}, getSvcConfig(wd, envFile)) - if err != nil { return err } @@ -545,7 +541,7 @@ func main() { } cmdSvc.AddCommand(svcInstall, svcStart, svcStop, svcRun, svcUninstall) - var rootCmd = &cobra.Command{ + rootCmd := &cobra.Command{ Use: "github-act-runner", Version: version, } diff --git a/protocol/connection.go b/protocol/connection.go index 5816a72..a9b4781 100644 --- a/protocol/connection.go +++ b/protocol/connection.go @@ -300,7 +300,7 @@ func (vssConnection *VssConnection) requestWithContextNoAuth( if failed { return response.StatusCode, fmt.Errorf("http failure: %v", traceMessage) } - if response.StatusCode == 204 && responseBody != nil { + if response.StatusCode == http.StatusNoContent && responseBody != nil { return response.StatusCode, io.EOF } return response.StatusCode, setResponseBody(responseReader, responseBody) @@ -332,6 +332,7 @@ func (vssConnection *VssConnection) GetAgentPools() (*TaskAgentPools, error) { } return _taskAgentPools, nil } + func (vssConnection *VssConnection) CreateSession(ctx context.Context) (*AgentMessageConnection, error) { session := &TaskAgentSession{} session.Agent = *vssConnection.TaskAgent @@ -417,7 +418,8 @@ func (vssConnection *VssConnection) FinishJob(e *JobEvent, plan *TaskOrchestrati } func (vssConnection *VssConnection) SendLogLines( - plan *TaskOrchestrationPlanReference, timelineID string, lines *TimelineRecordFeedLinesWrapper) error { + plan *TaskOrchestrationPlanReference, timelineID string, lines *TimelineRecordFeedLinesWrapper, +) error { return vssConnection.Request("858983e4-19bd-4c5e-864c-507b59b58b12", "5.1-preview", "POST", map[string]string{ "scopeIdentifier": plan.ScopeIdentifier, "planId": plan.PlanID, diff --git a/protocol/misc.go b/protocol/misc.go index 500921a..7438cb8 100644 --- a/protocol/misc.go +++ b/protocol/misc.go @@ -137,5 +137,7 @@ type VssOAuthTokenResponse struct { TokenType string `json:"token_type"` } -var TimestampInputFormat = "2006-01-02T15:04:05.9999999Z07:00" // allow to omit fractional seconds -var TimestampOutputFormat = "2006-01-02T15:04:05.0000000Z07:00" // dotnet "O" +var ( + TimestampInputFormat = "2006-01-02T15:04:05.9999999Z07:00" // allow to omit fractional seconds + TimestampOutputFormat = "2006-01-02T15:04:05.0000000Z07:00" // dotnet "O" +) diff --git a/protocol/results/service.go b/protocol/results/service.go index 0b94494..34dd061 100644 --- a/protocol/results/service.go +++ b/protocol/results/service.go @@ -16,7 +16,7 @@ type ResultsService struct { } func (rs *ResultsService) UploadBlockFileAsync(ctx context.Context, url, blobStorageType string, fileContent io.Reader) error { - request, err := http.NewRequestWithContext(ctx, "PUT", url, fileContent) + request, err := http.NewRequestWithContext(ctx, http.MethodPut, url, fileContent) if err != nil { return err } @@ -38,7 +38,7 @@ func (rs *ResultsService) UploadBlockFileAsync(ctx context.Context, url, blobSto } func (rs *ResultsService) CreateAppendFileAsync(ctx context.Context, url, blobStorageType string) error { - request, err := http.NewRequestWithContext(ctx, "PUT", url, bytes.NewBufferString("")) + request, err := http.NewRequestWithContext(ctx, http.MethodPut, url, bytes.NewBufferString("")) if err != nil { return err } @@ -66,7 +66,7 @@ func (rs *ResultsService) UploadAppendFileAsync( if finalize { comp = "&comp=appendblock&seal=true" } - request, err := http.NewRequestWithContext(ctx, "PUT", url+comp, fileContent) + request, err := http.NewRequestWithContext(ctx, http.MethodPut, url+comp, fileContent) if err != nil { return err } diff --git a/protocol/session.go b/protocol/session.go index ef0dce2..c63e361 100644 --- a/protocol/session.go +++ b/protocol/session.go @@ -6,8 +6,6 @@ import ( "crypto/cipher" "crypto/rand" "crypto/rsa" - "strings" - "crypto/sha1" "crypto/sha256" "encoding/base64" @@ -16,6 +14,7 @@ import ( "fmt" "hash" "io" + "strings" "time" ) diff --git a/protocol/task_agent.go b/protocol/task_agent.go index 1196b8c..400a9b4 100644 --- a/protocol/task_agent.go +++ b/protocol/task_agent.go @@ -83,7 +83,7 @@ func (taskAgent *TaskAgent) Authorize(c *http.Client, key interface{}) (*VssOAut data.Set("grant_type", "client_credentials") //nolint:noctx // Legacy function without context - would break API compatibility - poolsreq, err := http.NewRequest("POST", taskAgent.Authorization.AuthorizationURL, bytes.NewBufferString(data.Encode())) + poolsreq, err := http.NewRequest(http.MethodPost, taskAgent.Authorization.AuthorizationURL, bytes.NewBufferString(data.Encode())) if err != nil { return nil, errors.New(authFailurePrefix + err.Error()) } diff --git a/protocol/template_token.go b/protocol/template_token.go index 2f12515..db56190 100644 --- a/protocol/template_token.go +++ b/protocol/template_token.go @@ -390,8 +390,10 @@ func (converter *TemplateTokenConverter) ToYamlNode(token *TemplateToken) (ret * if !converter.AllowExpressions { return nil, fmt.Errorf("directives are not allowed: %s", *token.Expr) } - return &yaml.Node{Kind: yaml.ScalarNode, Style: yaml.DoubleQuotedStyle, - Value: templateOpenToken + *token.Directive + templateCloseToken}, nil + return &yaml.Node{ + Kind: yaml.ScalarNode, Style: yaml.DoubleQuotedStyle, + Value: templateOpenToken + *token.Directive + templateCloseToken, + }, nil case TokenTypeBool: val, _ := yaml.Marshal(token.Bool) return &yaml.Node{Kind: yaml.ScalarNode, Style: yaml.FlowStyle, Value: string(val[:len(val)-1])}, nil diff --git a/protocol/timeline.go b/protocol/timeline.go index 3a670b6..0832ee2 100644 --- a/protocol/timeline.go +++ b/protocol/timeline.go @@ -20,8 +20,7 @@ type Issue struct { Data map[string]string } -type TimelineAttempt struct { -} +type TimelineAttempt struct{} type TimelineRecord struct { ID string diff --git a/runnerconfiguration/add.go b/runnerconfiguration/add.go index 8d96268..0393ec4 100644 --- a/runnerconfiguration/add.go +++ b/runnerconfiguration/add.go @@ -82,7 +82,7 @@ func (config *ConfigureRunner) Configure( taskAgentPools := []string{} _taskAgentPools, err := vssConnection.GetAgentPools() if err != nil { - return nil, fmt.Errorf("failed to configure runner: %v", err) + return nil, fmt.Errorf("failed to configure runner: %w", err) } for _, val := range _taskAgentPools.Value { if !val.IsHosted { @@ -118,7 +118,7 @@ func (config *ConfigureRunner) Configure( ui := uint32(key.E) //nolint:gosec binary.BigEndian.PutUint32(bs, ui) expof := 0 - for ; expof < 3 && bs[expof] == 0; expof++ { //nolint:revive // empty-block: intentionally empty loop to find non-zero bytes + for ; expof < 3 && bs[expof] == 0; expof++ { // Skip leading zero bytes } taskAgent.Authorization.PublicKey = protocol.TaskAgentPublicKey{ diff --git a/runnerconfiguration/common.go b/runnerconfiguration/common.go index eb9b4f4..56c35b6 100644 --- a/runnerconfiguration/common.go +++ b/runnerconfiguration/common.go @@ -168,9 +168,8 @@ func gitHubAuth( URL: config.URL, RunnerEvent: runnerEvent, }, res) - if err != nil { - return nil, fmt.Errorf("failed to authenticate as Runner Admin: %v", err) + return nil, fmt.Errorf("failed to authenticate as Runner Admin: %w", err) } return res, nil } @@ -178,6 +177,7 @@ func gitHubAuth( func (config *ConfigureRunner) Authenticate(c *http.Client, survey Survey) (*protocol.GitHubAuthResult, error) { return gitHubAuth(&config.ConfigureRemoveRunner, c, "register", "registration-token", survey) } + func (config *RemoveRunner) Authenticate(c *http.Client, survey Survey) (*protocol.GitHubAuthResult, error) { return gitHubAuth(&config.ConfigureRemoveRunner, c, "remove", "remove-token", survey) } diff --git a/runnerconfiguration/remove.go b/runnerconfiguration/remove.go index 359ab67..1bded3d 100644 --- a/runnerconfiguration/remove.go +++ b/runnerconfiguration/remove.go @@ -83,7 +83,7 @@ func (config *RemoveRunner) Remove(settings *RunnerSettings, survey Survey, auth Trace: config.Trace, } if err := vssConnection.DeleteAgent(instance.Agent); err != nil { - return fmt.Errorf("failed to remove Runner from server: %v", err) + return fmt.Errorf("failed to remove Runner from server: %w", err) } return nil }()