From d187ac2fc12a5c5a86c5fa452f482bdf73107c55 Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sun, 22 Feb 2026 20:58:46 +0100 Subject: [PATCH] auto adjust code --- cmd/root.go | 34 ++++-- internal/app/run/runner.go | 5 +- internal/eval/functions/format.go | 4 +- internal/eval/v2/evaluation_result.go | 42 +++---- internal/eval/v2/evaluator.go | 18 +-- internal/eval/v2/evaluator_test.go | 4 +- internal/eval/v2/functions.go | 2 +- internal/expr/expression_parser.go | 2 +- internal/expr/lexer.go | 4 +- internal/expr/lexer_additional_test.go | 10 +- internal/expr/lexer_test.go | 4 +- internal/model/strategy_utils.go | 16 ++- internal/model/strategy_utils_test.go | 2 +- internal/model/workflow_state.go | 2 +- pkg/artifactcache/handler.go | 6 +- pkg/artifactcache/handler_test.go | 24 ++-- pkg/artifactcache/storage.go | 5 +- pkg/artifacts/artifacts_v4.go | 18 +-- pkg/artifacts/server_test.go | 26 ++-- pkg/common/auth.go | 5 +- pkg/common/auth_test.go | 16 +-- pkg/common/cartesian.go | 14 +-- pkg/common/cartesian_test.go | 10 +- pkg/common/draw.go | 7 +- pkg/common/executor.go | 12 +- pkg/common/executor_test.go | 24 ++-- pkg/common/git/git.go | 4 +- pkg/common/git/git_test.go | 2 +- pkg/container/docker_cli.go | 11 +- pkg/container/docker_cli_test.go | 4 +- pkg/container/docker_images_test.go | 28 ++--- pkg/container/docker_logger.go | 2 +- pkg/container/docker_pull_test.go | 8 +- pkg/container/docker_run.go | 2 +- pkg/container/docker_run_test.go | 6 +- pkg/container/docker_socket.go | 4 +- pkg/container/docker_socket_test.go | 28 ++--- pkg/container/executions_environment.go | 2 +- pkg/container/host_environment.go | 10 +- .../linux_container_environment_extensions.go | 4 +- ...x_container_environment_extensions_test.go | 4 +- pkg/exprparser/functions.go | 12 +- pkg/exprparser/interpreter.go | 30 ++--- pkg/exprparser/interpreter_test.go | 56 ++++----- pkg/filecollector/file_collector.go | 3 +- pkg/filecollector/file_collector_test.go | 2 +- pkg/model/action.go | 2 +- pkg/model/github_context.go | 80 ++++++------ pkg/model/github_context_test.go | 50 ++++---- pkg/model/planner.go | 15 +-- pkg/model/planner_test.go | 2 +- pkg/model/workflow.go | 60 +++++---- pkg/model/workflow_test.go | 115 +++++++++--------- pkg/runner/action.go | 16 +-- pkg/runner/action_composite.go | 11 +- pkg/runner/action_test.go | 4 +- pkg/runner/command.go | 4 +- pkg/runner/command_test.go | 2 +- pkg/runner/expression.go | 33 +++-- pkg/runner/expression_test.go | 17 ++- pkg/runner/job_executor.go | 5 +- pkg/runner/job_executor_test.go | 19 ++- pkg/runner/logger.go | 2 +- pkg/runner/reusable_workflow.go | 2 +- pkg/runner/run_context.go | 45 ++++--- pkg/runner/run_context_darwin.go | 3 +- pkg/runner/run_context_test.go | 36 +++--- pkg/runner/runner.go | 17 ++- pkg/runner/runner_test.go | 49 ++++---- pkg/runner/step.go | 5 +- pkg/runner/step_action_local.go | 2 +- pkg/runner/step_action_local_test.go | 8 +- pkg/runner/step_action_remote.go | 2 +- pkg/runner/step_action_remote_test.go | 8 +- pkg/runner/step_docker.go | 2 +- pkg/runner/step_docker_test.go | 6 +- pkg/runner/step_factory_test.go | 2 +- pkg/runner/step_run.go | 7 +- pkg/runner/step_run_test.go | 6 +- pkg/runner/step_test.go | 14 +-- pkg/schema/schema.go | 23 ++-- pkg/tart/environment_darwin.go | 6 +- pkg/tart/vm_darwin.go | 4 +- pkg/workflowpattern/trace_writer.go | 6 +- pkg/workflowpattern/workflow_pattern.go | 2 +- pkg/workflowpattern/workflow_pattern_test.go | 4 +- 86 files changed, 617 insertions(+), 617 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 7e27a6a6..56337200 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,12 +5,14 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "os" "path/filepath" "regexp" "runtime" "runtime/debug" + "strconv" "strings" "github.com/AlecAivazis/survey/v2" @@ -176,7 +178,7 @@ func bugReport(ctx context.Context, version string) error { report += sprintf("Variant:", "https://gitea.com/actions-oss/act-cli / https://github.com/actions-oss/act-cli") report += sprintf("GOOS:", runtime.GOOS) report += sprintf("GOARCH:", runtime.GOARCH) - report += sprintf("NumCPU:", fmt.Sprint(runtime.NumCPU())) + report += sprintf("NumCPU:", strconv.Itoa(runtime.NumCPU())) var dockerHost string var exists bool @@ -199,15 +201,21 @@ func bugReport(ctx context.Context, version string) error { } report += sprintf("Config files:", "") + var reportSb202 strings.Builder + var reportSb205 strings.Builder for _, c := range configLocations() { args := readArgsFile(c, false) if len(args) > 0 { - report += fmt.Sprintf("\t%s:\n", c) + fmt.Fprintf(&reportSb202, "\t%s:\n", c) + var reportSb206 strings.Builder for _, l := range args { - report += fmt.Sprintf("\t\t%s\n", l) + fmt.Fprintf(&reportSb206, "\t\t%s\n", l) } + reportSb205.WriteString(reportSb206.String()) } } + report += reportSb205.String() + report += reportSb202.String() vcs, ok := debug.ReadBuildInfo() if ok && vcs != nil { @@ -220,9 +228,11 @@ func bugReport(ctx context.Context, version string) error { report += sprintf("\tMain checksum:", vcs.Main.Sum) report += fmt.Sprintln("\tBuild settings:") + var reportSb223 strings.Builder for _, set := range vcs.Settings { - report += sprintf(fmt.Sprintf("\t\t%s:", set.Key), set.Value) + reportSb223.WriteString(sprintf(fmt.Sprintf("\t\t%s:", set.Key), set.Value)) } + report += reportSb223.String() } info, err := container.GetHostInfo(ctx) @@ -245,13 +255,15 @@ func bugReport(ctx context.Context, version string) error { report += sprintf("\tOS version:", info.OSVersion) report += sprintf("\tOS arch:", info.Architecture) report += sprintf("\tOS kernel:", info.KernelVersion) - report += sprintf("\tOS CPU:", fmt.Sprint(info.NCPU)) + report += sprintf("\tOS CPU:", strconv.Itoa(info.NCPU)) report += sprintf("\tOS memory:", fmt.Sprintf("%d MB", info.MemTotal/1024/1024)) report += fmt.Sprintln("\tSecurity options:") + var reportSb252 strings.Builder for _, secopt := range info.SecurityOptions { - report += fmt.Sprintf("\t\t%s\n", secopt) + fmt.Fprintf(&reportSb252, "\t\t%s\n", secopt) } + report += reportSb252.String() fmt.Println(report) return nil @@ -261,7 +273,7 @@ func generateManPage(cmd *cobra.Command) error { header := &doc.GenManHeader{ Title: "act", Section: "1", - Source: fmt.Sprintf("act %s", cmd.Version), + Source: "act " + cmd.Version, } buf := new(bytes.Buffer) cobra.CheckErr(doc.GenMan(cmd, header, buf)) @@ -575,7 +587,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str } if plan != nil { if len(plan.Stages) == 0 { - plannerErr = fmt.Errorf("could not find any stages to run. View the valid jobs with `act --list`. Use `act --help` to find how to filter by Job ID/Workflow/Event Name") + plannerErr = errors.New("could not find any stages to run. View the valid jobs with `act --list`. Use `act --help` to find how to filter by Job ID/Workflow/Event Name") } } if plan == nil && plannerErr != nil { @@ -611,7 +623,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str log.Warnf(deprecationWarning, "privileged", "--privileged") } if len(input.usernsMode) > 0 { - log.Warnf(deprecationWarning, "userns", fmt.Sprintf("--userns=%s", input.usernsMode)) + log.Warnf(deprecationWarning, "userns", "--userns="+input.usernsMode) } if len(input.containerCapAdd) > 0 { log.Warnf(deprecationWarning, "container-cap-add", fmt.Sprintf("--cap-add=%s", input.containerCapAdd)) @@ -699,9 +711,9 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str var r runner.Runner if eventName == "workflow_call" { // Do not use the totally broken code and instead craft a fake caller - convertedInputs := make(map[string]interface{}) + convertedInputs := make(map[string]any) for k, v := range inputs { - var raw interface{} + var raw any if err := yaml.Unmarshal([]byte(v), &raw); err != nil { return fmt.Errorf("failed to unmarshal input %s: %w", k, err) } diff --git a/internal/app/run/runner.go b/internal/app/run/runner.go index 696ccecc..c2d4d014 100644 --- a/internal/app/run/runner.go +++ b/internal/app/run/runner.go @@ -9,6 +9,7 @@ import ( "fmt" "maps" "path/filepath" + "strconv" "strings" "sync" @@ -145,7 +146,7 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report. var stepIds []string for i, v := range job.Steps { if v.ID == "" { - v.ID = fmt.Sprint(i) + v.ID = strconv.Itoa(i) } stepIds = append(stepIds, v.ID) } @@ -204,7 +205,7 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report. // maxLifetime = time.Until(deadline) // } - actCtx := map[string]interface{}{} + actCtx := map[string]any{} forgeCtx := task.Context.AsMap() actCtx["github"] = forgeCtx actCtx["gitea"] = forgeCtx diff --git a/internal/eval/functions/format.go b/internal/eval/functions/format.go index 429c786c..862980ed 100644 --- a/internal/eval/functions/format.go +++ b/internal/eval/functions/format.go @@ -10,7 +10,7 @@ import ( // It behaves like the C# implementation in the repository – // it supports escaped braces and numeric argument indices. // Format specifiers (e.g. :D) are recognised but currently ignored. -func Format(formatStr string, args ...interface{}) (string, error) { +func Format(formatStr string, args ...any) (string, error) { var sb strings.Builder i := 0 for i < len(formatStr) { @@ -47,7 +47,7 @@ func Format(formatStr string, args ...interface{}) (string, error) { } // append argument (format specifier is ignored here) arg := args[idx] - sb.WriteString(fmt.Sprintf("%v", arg)) + fmt.Fprintf(&sb, "%v", arg) if spec != "" { // placeholder for future specifier handling _ = spec diff --git a/internal/eval/v2/evaluation_result.go b/internal/eval/v2/evaluation_result.go index 54509626..86132245 100644 --- a/internal/eval/v2/evaluation_result.go +++ b/internal/eval/v2/evaluation_result.go @@ -93,14 +93,14 @@ func (o CaseSensitiveObject[T]) GetEnumerator() map[string]T { type EvaluationResult struct { context *EvaluationContext level int - value interface{} + value any kind ValueKind - raw interface{} + raw any omitTracing bool } // NewEvaluationResult creates a new EvaluationResult. -func NewEvaluationResult(context *EvaluationContext, level int, val interface{}, kind ValueKind, raw interface{}, omitTracing bool) *EvaluationResult { +func NewEvaluationResult(context *EvaluationContext, level int, val any, kind ValueKind, raw any, omitTracing bool) *EvaluationResult { er := &EvaluationResult{context: context, level: level, value: val, kind: kind, raw: raw, omitTracing: omitTracing} if !omitTracing { er.traceValue() @@ -112,10 +112,10 @@ func NewEvaluationResult(context *EvaluationContext, level int, val interface{}, func (er *EvaluationResult) Kind() ValueKind { return er.kind } // Raw returns the raw value that was passed to the constructor. -func (er *EvaluationResult) Raw() interface{} { return er.raw } +func (er *EvaluationResult) Raw() any { return er.raw } // Value returns the canonical value. -func (er *EvaluationResult) Value() interface{} { return er.value } +func (er *EvaluationResult) Value() any { return er.value } // IsFalsy implements the logic from the C# class. func (er *EvaluationResult) IsFalsy() bool { @@ -195,7 +195,7 @@ func (er *EvaluationResult) ConvertToString() string { } // TryGetCollectionInterface returns the underlying collection if the value is an array or object. -func (er *EvaluationResult) TryGetCollectionInterface() (interface{}, bool) { +func (er *EvaluationResult) TryGetCollectionInterface() (any, bool) { switch v := er.value.(type) { case ReadOnlyArray[any]: return v, true @@ -207,7 +207,7 @@ func (er *EvaluationResult) TryGetCollectionInterface() (interface{}, bool) { } // CreateIntermediateResult creates an EvaluationResult from an arbitrary object. -func CreateIntermediateResult(context *EvaluationContext, obj interface{}) *EvaluationResult { +func CreateIntermediateResult(context *EvaluationContext, obj any) *EvaluationResult { val, kind, raw := convertToCanonicalValue(obj) return NewEvaluationResult(context, 0, val, kind, raw, true) } @@ -226,7 +226,7 @@ var ExpressionConstants = struct { } // convertToCanonicalValue converts an arbitrary Go value to a canonical form. -func convertToCanonicalValue(obj interface{}) (interface{}, ValueKind, interface{}) { +func convertToCanonicalValue(obj any) (any, ValueKind, any) { switch v := obj.(type) { case nil: return nil, ValueKindNull, nil @@ -243,11 +243,11 @@ func convertToCanonicalValue(obj interface{}) (interface{}, ValueKind, interface return f, ValueKindNumber, f case string: return v, ValueKindString, v - case []interface{}: + case []any: return BasicArray[any](v), ValueKindArray, v case ReadOnlyArray[any]: return v, ValueKindArray, v - case map[string]interface{}: + case map[string]any: return CaseInsensitiveObject[any](v), ValueKindObject, v case ReadOnlyObject[any]: return v, ValueKindObject, v @@ -257,7 +257,7 @@ func convertToCanonicalValue(obj interface{}) (interface{}, ValueKind, interface } } -func toInt64(v interface{}) int64 { +func toInt64(v any) int64 { switch i := v.(type) { case int: return int64(i) @@ -274,7 +274,7 @@ func toInt64(v interface{}) int64 { } } -func toUint64(v interface{}) uint64 { +func toUint64(v any) uint64 { switch i := v.(type) { case uint: return uint64(i) @@ -291,7 +291,7 @@ func toUint64(v interface{}) uint64 { } } -func toFloat64(v interface{}) float64 { +func toFloat64(v any) float64 { switch f := v.(type) { case float32: return float64(f) @@ -304,7 +304,7 @@ func toFloat64(v interface{}) float64 { // coerceTypes implements the C# CoerceTypes logic. // It converts values to compatible types before comparison. -func coerceTypes(left, right interface{}) (interface{}, interface{}, ValueKind, ValueKind) { +func coerceTypes(left, right any) (any, any, ValueKind, ValueKind) { leftKind := getKind(left) rightKind := getKind(right) @@ -340,7 +340,7 @@ func coerceTypes(left, right interface{}) (interface{}, interface{}, ValueKind, } // abstractEqual uses coerceTypes before comparing. -func abstractEqual(left, right interface{}) bool { +func abstractEqual(left, right any) bool { left, right, leftKind, rightKind := coerceTypes(left, right) if leftKind != rightKind { return false @@ -367,7 +367,7 @@ func abstractEqual(left, right interface{}) bool { } // abstractGreaterThan uses coerceTypes before comparing. -func abstractGreaterThan(left, right interface{}) bool { +func abstractGreaterThan(left, right any) bool { left, right, leftKind, rightKind := coerceTypes(left, right) if leftKind != rightKind { return false @@ -389,7 +389,7 @@ func abstractGreaterThan(left, right interface{}) bool { } // abstractLessThan uses coerceTypes before comparing. -func abstractLessThan(left, right interface{}) bool { +func abstractLessThan(left, right any) bool { left, right, leftKind, rightKind := coerceTypes(left, right) if leftKind != rightKind { return false @@ -411,7 +411,7 @@ func abstractLessThan(left, right interface{}) bool { } // convertToNumber converts a value to a float64 following JavaScript rules. -func convertToNumber(v interface{}) float64 { +func convertToNumber(v any) float64 { switch val := v.(type) { case nil: return 0 @@ -447,7 +447,7 @@ func convertToNumber(v interface{}) float64 { } // getKind returns the ValueKind for a Go value. -func getKind(v interface{}) ValueKind { +func getKind(v any) ValueKind { switch v.(type) { case nil: return ValueKindNull @@ -457,9 +457,9 @@ func getKind(v interface{}) ValueKind { return ValueKindNumber case string: return ValueKindString - case []interface{}: + case []any: return ValueKindArray - case map[string]interface{}: + case map[string]any: return ValueKindObject default: return ValueKindObject diff --git a/internal/eval/v2/evaluator.go b/internal/eval/v2/evaluator.go index b7c7833b..92286e2e 100644 --- a/internal/eval/v2/evaluator.go +++ b/internal/eval/v2/evaluator.go @@ -56,11 +56,11 @@ func (e *Evaluator) EvaluateBoolean(expr string) (bool, error) { return result.IsTruthy(), nil } -func (e *Evaluator) ToRaw(result *EvaluationResult) (interface{}, error) { +func (e *Evaluator) ToRaw(result *EvaluationResult) (any, error) { if col, ok := result.TryGetCollectionInterface(); ok { switch node := col.(type) { case ReadOnlyObject[any]: - rawMap := map[string]interface{}{} + rawMap := map[string]any{} for k, v := range node.GetEnumerator() { rawRes, err := e.ToRaw(CreateIntermediateResult(e.Context(), v)) if err != nil { @@ -70,7 +70,7 @@ func (e *Evaluator) ToRaw(result *EvaluationResult) (interface{}, error) { } return rawMap, nil case ReadOnlyArray[any]: - rawArray := []interface{}{} + rawArray := []any{} for _, v := range node.GetEnumerator() { rawRes, err := e.ToRaw(CreateIntermediateResult(e.Context(), v)) if err != nil { @@ -85,7 +85,7 @@ func (e *Evaluator) ToRaw(result *EvaluationResult) (interface{}, error) { } // Evaluate parses and evaluates the expression, returning a boolean result. -func (e *Evaluator) EvaluateRaw(expr string) (interface{}, error) { +func (e *Evaluator) EvaluateRaw(expr string) (any, error) { root, err := exprparser.Parse(expr) if err != nil { return false, fmt.Errorf("parse error: %w", err) @@ -97,16 +97,16 @@ func (e *Evaluator) EvaluateRaw(expr string) (interface{}, error) { return e.ToRaw(result) } -type FilteredArray []interface{} +type FilteredArray []any -func (a FilteredArray) GetAt(i int64) interface{} { +func (a FilteredArray) GetAt(i int64) any { if int(i) > len(a) { return nil } return a[i] } -func (a FilteredArray) GetEnumerator() []interface{} { +func (a FilteredArray) GetEnumerator() []any { return a } @@ -244,7 +244,7 @@ func (e *Evaluator) evalUnaryNode(node *exprparser.UnaryNode) (*EvaluationResult } } -func processIndex(col interface{}, right *EvaluationResult) interface{} { +func processIndex(col any, right *EvaluationResult) any { if mapVal, ok := col.(ReadOnlyObject[any]); ok { key, ok := right.Value().(string) if !ok { @@ -264,7 +264,7 @@ func processIndex(col interface{}, right *EvaluationResult) interface{} { return nil } -func processStar(subcol interface{}, ret FilteredArray) FilteredArray { +func processStar(subcol any, ret FilteredArray) FilteredArray { if array, ok := subcol.(ReadOnlyArray[any]); ok { ret = append(ret, array.GetEnumerator()...) } else if obj, ok := subcol.(ReadOnlyObject[any]); ok { diff --git a/internal/eval/v2/evaluator_test.go b/internal/eval/v2/evaluator_test.go index 916cba3f..a2ba264b 100644 --- a/internal/eval/v2/evaluator_test.go +++ b/internal/eval/v2/evaluator_test.go @@ -6,7 +6,7 @@ import ( // Test boolean and comparison operations using the evaluator. func TestEvaluator_BooleanOps(t *testing.T) { - ctx := &EvaluationContext{Variables: CaseInsensitiveObject[any](map[string]interface{}{"a": 5, "b": 3})} + ctx := &EvaluationContext{Variables: CaseInsensitiveObject[any](map[string]any{"a": 5, "b": 3})} eval := NewEvaluator(ctx) tests := []struct { @@ -44,7 +44,7 @@ func TestEvaluator_Raw(t *testing.T) { tests := []struct { expr string - want interface{} + want any }{ {"a.b['x']", nil}, {"(a.b).c['x']", nil}, diff --git a/internal/eval/v2/functions.go b/internal/eval/v2/functions.go index c55fe169..ab2bab67 100644 --- a/internal/eval/v2/functions.go +++ b/internal/eval/v2/functions.go @@ -113,7 +113,7 @@ func (Format) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResu return nil, err } - sargs := []interface{}{} + sargs := []any{} for _, arg := range args[1:] { el, err := eval.Evaluate(arg) if err != nil { diff --git a/internal/expr/expression_parser.go b/internal/expr/expression_parser.go index 516edb25..a7dfbf89 100644 --- a/internal/expr/expression_parser.go +++ b/internal/expr/expression_parser.go @@ -20,7 +20,7 @@ type Node interface { type ValueNode struct { Kind TokenKind - Value interface{} + Value any } // FunctionNode represents a function call with arguments. diff --git a/internal/expr/lexer.go b/internal/expr/lexer.go index b6f1b764..423e3a03 100644 --- a/internal/expr/lexer.go +++ b/internal/expr/lexer.go @@ -51,7 +51,7 @@ const ( type Token struct { Kind TokenKind Raw string - Value interface{} + Value any Index int } @@ -256,7 +256,7 @@ func (l *Lexer) readNumber() *Token { } } // Try to parse as float64 - var val interface{} = raw + var val any = raw if f, err := strconv.ParseFloat(raw, 64); err == nil { val = f } diff --git a/internal/expr/lexer_additional_test.go b/internal/expr/lexer_additional_test.go index 27478f16..33e2b4ba 100644 --- a/internal/expr/lexer_additional_test.go +++ b/internal/expr/lexer_additional_test.go @@ -12,7 +12,7 @@ func TestLexerMultiple(t *testing.T) { cases := []struct { expr string expected []TokenKind - values []interface{} // optional, nil if not checking values + values []any // optional, nil if not checking values }{ { expr: "github.event_name == 'push'", @@ -67,12 +67,12 @@ func TestLexerMultiple(t *testing.T) { { expr: "true", expected: []TokenKind{TokenKindBoolean}, - values: []interface{}{true}, + values: []any{true}, }, { expr: "123", expected: []TokenKind{TokenKindNumber}, - values: []interface{}{123.0}, + values: []any{123.0}, }, { expr: "(a && b)", @@ -85,7 +85,7 @@ func TestLexerMultiple(t *testing.T) { { expr: "'Hello i''s escaped'", expected: []TokenKind{TokenKindString}, - values: []interface{}{"Hello i's escaped"}, + values: []any{"Hello i's escaped"}, }, } @@ -99,7 +99,7 @@ func TestLexerMultiple(t *testing.T) { } tokens = append(tokens, tok) } - assert.Equal(t, len(tc.expected), len(tokens), "expression: %s", tc.expr) + assert.Len(t, tokens, len(tc.expected), "expression: %s", tc.expr) for i, kind := range tc.expected { assert.Equal(t, kind, tokens[i].Kind, "expr %s token %d", tc.expr, i) } diff --git a/internal/expr/lexer_test.go b/internal/expr/lexer_test.go index 39ec1d67..a572504b 100644 --- a/internal/expr/lexer_test.go +++ b/internal/expr/lexer_test.go @@ -22,13 +22,13 @@ func TestLexer(t *testing.T) { for i, tok := range tokens { t.Logf("Token %d: Kind=%v, Value=%v", i, tok.Kind, tok.Value) } - assert.Equal(t, tokens[1].Kind, TokenKindDereference) + assert.Equal(t, TokenKindDereference, tokens[1].Kind) } func TestLexerNumbers(t *testing.T) { table := []struct { in string - out interface{} + out any }{ {"-Infinity", math.Inf(-1)}, {"Infinity", math.Inf(1)}, diff --git a/internal/model/strategy_utils.go b/internal/model/strategy_utils.go index edcb81eb..131012f8 100644 --- a/internal/model/strategy_utils.go +++ b/internal/model/strategy_utils.go @@ -2,7 +2,7 @@ package model import ( "errors" - "fmt" + "maps" "strings" "gopkg.in/yaml.v3" @@ -11,7 +11,7 @@ import ( // TraceWriter is an interface for logging trace information. // Implementations can write to console, file, or any other sink. type TraceWriter interface { - Info(format string, args ...interface{}) + Info(format string, args ...any) } // StrategyResult holds the result of expanding a strategy. @@ -46,14 +46,14 @@ func (strategyContext *strategyContext) handleInclude() error { if len(strategyContext.include) > 0 { for _, incNode := range strategyContext.include { if incNode.Kind != yaml.MappingNode { - return fmt.Errorf("include entry is not a mapping node") + return errors.New("include entry is not a mapping node") } incMap := make(map[string]yaml.Node) for i := 0; i < len(incNode.Content); i += 2 { keyNode := incNode.Content[i] valNode := incNode.Content[i+1] if keyNode.Kind != yaml.ScalarNode { - return fmt.Errorf("include key is not scalar") + return errors.New("include key is not scalar") } incMap[keyNode.Value] = *valNode } @@ -94,7 +94,7 @@ func (strategyContext *strategyContext) handleExclude() error { for _, exNode := range strategyContext.exclude { // exNode is expected to be a mapping node if exNode.Kind != yaml.MappingNode { - return fmt.Errorf("exclude entry is not a mapping node") + return errors.New("exclude entry is not a mapping node") } // Convert mapping to map[string]yaml.Node exMap := make(map[string]yaml.Node) @@ -102,7 +102,7 @@ func (strategyContext *strategyContext) handleExclude() error { keyNode := exNode.Content[i] valNode := exNode.Content[i+1] if keyNode.Kind != yaml.ScalarNode { - return fmt.Errorf("exclude key is not scalar") + return errors.New("exclude key is not scalar") } exMap[keyNode.Value] = *valNode } @@ -158,9 +158,7 @@ func ExpandStrategy(strategy *Strategy, jobTraceWriter TraceWriter) (*StrategyRe for _, row := range strategyContext.flatMatrix { for _, val := range values { newRow := make(map[string]yaml.Node) - for k, v := range row { - newRow[k] = v - } + maps.Copy(newRow, row) newRow[key] = val next = append(next, newRow) } diff --git a/internal/model/strategy_utils_test.go b/internal/model/strategy_utils_test.go index cb0c6ec3..5947b53d 100644 --- a/internal/model/strategy_utils_test.go +++ b/internal/model/strategy_utils_test.go @@ -10,7 +10,7 @@ import ( type EmptyTraceWriter struct { } -func (e *EmptyTraceWriter) Info(_ string, _ ...interface{}) { +func (e *EmptyTraceWriter) Info(_ string, _ ...any) { } func TestStrategy(t *testing.T) { diff --git a/internal/model/workflow_state.go b/internal/model/workflow_state.go index d5451448..664f9254 100644 --- a/internal/model/workflow_state.go +++ b/internal/model/workflow_state.go @@ -96,7 +96,7 @@ func (a *On) UnmarshalYAML(node *yaml.Node) error { return nil } -func (a *On) MarshalYAML() (interface{}, error) { +func (a *On) MarshalYAML() (any, error) { return a.Data, nil } diff --git a/pkg/artifactcache/handler.go b/pkg/artifactcache/handler.go index c8efa768..a756b7be 100644 --- a/pkg/artifactcache/handler.go +++ b/pkg/artifactcache/handler.go @@ -75,7 +75,7 @@ func StartHandler(dir, outboundIP string, port uint16, logger logrus.FieldLogger if outboundIP != "" { h.outboundIP = outboundIP } else if ip := common.GetOutboundIP(); ip == nil { - return nil, fmt.Errorf("unable to determine outbound IP address") + return nil, errors.New("unable to determine outbound IP address") } else { h.outboundIP = ip.String() } @@ -144,7 +144,7 @@ func CreateHandler(dir, externalAddress string, logger logrus.FieldLogger) (*Han if externalAddress != "" { h.externalAddress = externalAddress } else if ip := common.GetOutboundIP(); ip == nil { - return nil, nil, fmt.Errorf("unable to determine outbound IP address") + return nil, nil, errors.New("unable to determine outbound IP address") } else { h.outboundIP = ip.String() } @@ -420,7 +420,7 @@ func findCache(db *bolthold.Store, keys []string, version string) (*Cache, error } return cache, nil } - prefixPattern := fmt.Sprintf("^%s", regexp.QuoteMeta(prefix)) + prefixPattern := "^" + regexp.QuoteMeta(prefix) re, err := regexp.Compile(prefixPattern) if err != nil { continue diff --git a/pkg/artifactcache/handler_test.go b/pkg/artifactcache/handler_test.go index f6b92bd6..05737117 100644 --- a/pkg/artifactcache/handler_test.go +++ b/pkg/artifactcache/handler_test.go @@ -64,7 +64,7 @@ func TestHandler(t *testing.T) { }) t.Run("clean", func(t *testing.T) { - resp, err := http.Post(fmt.Sprintf("%s/clean", base), "", nil) + resp, err := http.Post(base+"/clean", "", nil) require.NoError(t, err) assert.Equal(t, 200, resp.StatusCode) }) @@ -72,7 +72,7 @@ func TestHandler(t *testing.T) { t.Run("reserve with bad request", func(t *testing.T) { body := []byte(`invalid json`) require.NoError(t, err) - resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body)) + resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) require.NoError(t, err) assert.Equal(t, 400, resp.StatusCode) }) @@ -90,7 +90,7 @@ func TestHandler(t *testing.T) { Size: 100, }) require.NoError(t, err) - resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body)) + resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) require.NoError(t, err) assert.Equal(t, 200, resp.StatusCode) @@ -104,7 +104,7 @@ func TestHandler(t *testing.T) { Size: 100, }) require.NoError(t, err) - resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body)) + resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) require.NoError(t, err) assert.Equal(t, 200, resp.StatusCode) @@ -117,7 +117,7 @@ func TestHandler(t *testing.T) { t.Run("upload with bad id", func(t *testing.T) { req, err := http.NewRequest(http.MethodPatch, - fmt.Sprintf("%s/caches/invalid_id", base), bytes.NewReader(nil)) + base+"/caches/invalid_id", bytes.NewReader(nil)) require.NoError(t, err) req.Header.Set("Content-Type", "application/octet-stream") req.Header.Set("Content-Range", "bytes 0-99/*") @@ -151,7 +151,7 @@ func TestHandler(t *testing.T) { Size: 100, }) require.NoError(t, err) - resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body)) + resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) require.NoError(t, err) assert.Equal(t, 200, resp.StatusCode) @@ -202,7 +202,7 @@ func TestHandler(t *testing.T) { Size: 100, }) require.NoError(t, err) - resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body)) + resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) require.NoError(t, err) assert.Equal(t, 200, resp.StatusCode) @@ -226,7 +226,7 @@ func TestHandler(t *testing.T) { t.Run("commit with bad id", func(t *testing.T) { { - resp, err := http.Post(fmt.Sprintf("%s/caches/invalid_id", base), "", nil) + resp, err := http.Post(base+"/caches/invalid_id", "", nil) require.NoError(t, err) assert.Equal(t, 400, resp.StatusCode) } @@ -254,7 +254,7 @@ func TestHandler(t *testing.T) { Size: 100, }) require.NoError(t, err) - resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body)) + resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) require.NoError(t, err) assert.Equal(t, 200, resp.StatusCode) @@ -300,7 +300,7 @@ func TestHandler(t *testing.T) { Size: 100, }) require.NoError(t, err) - resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body)) + resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) require.NoError(t, err) assert.Equal(t, 200, resp.StatusCode) @@ -328,7 +328,7 @@ func TestHandler(t *testing.T) { }) t.Run("get with bad id", func(t *testing.T) { - resp, err := http.Get(fmt.Sprintf("%s/artifacts/invalid_id", base)) + resp, err := http.Get(base + "/artifacts/invalid_id") require.NoError(t, err) require.Equal(t, 400, resp.StatusCode) }) @@ -537,7 +537,7 @@ func uploadCacheNormally(t *testing.T, base, key, version string, content []byte Size: int64(len(content)), }) require.NoError(t, err) - resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body)) + resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) require.NoError(t, err) assert.Equal(t, 200, resp.StatusCode) diff --git a/pkg/artifactcache/storage.go b/pkg/artifactcache/storage.go index 9a2609af..9ded1e4b 100644 --- a/pkg/artifactcache/storage.go +++ b/pkg/artifactcache/storage.go @@ -6,6 +6,7 @@ import ( "net/http" "os" "path/filepath" + "strconv" ) type Storage struct { @@ -103,11 +104,11 @@ func (s *Storage) Remove(id uint64) { } func (s *Storage) filename(id uint64) string { - return filepath.Join(s.rootDir, fmt.Sprintf("%02x", id%0xff), fmt.Sprint(id)) + return filepath.Join(s.rootDir, fmt.Sprintf("%02x", id%0xff), strconv.FormatUint(id, 10)) } func (s *Storage) tempDir(id uint64) string { - return filepath.Join(s.rootDir, "tmp", fmt.Sprint(id)) + return filepath.Join(s.rootDir, "tmp", strconv.FormatUint(id, 10)) } func (s *Storage) tempName(id uint64, offset int64) string { diff --git a/pkg/artifacts/artifacts_v4.go b/pkg/artifacts/artifacts_v4.go index d9967aef..cb6ee1d6 100644 --- a/pkg/artifacts/artifacts_v4.go +++ b/pkg/artifacts/artifacts_v4.go @@ -126,15 +126,15 @@ func artifactNameToID(s string) int64 { return int64(h.Sum32()) } -func (c ArtifactContext) Error(status int, _ ...interface{}) { +func (c ArtifactContext) Error(status int, _ ...any) { c.Resp.WriteHeader(status) } -func (c ArtifactContext) JSON(status int, _ ...interface{}) { +func (c ArtifactContext) JSON(status int, _ ...any) { c.Resp.WriteHeader(status) } -func validateRunIDV4(ctx *ArtifactContext, rawRunID string) (interface{}, int64, bool) { +func validateRunIDV4(ctx *ArtifactContext, rawRunID string) (any, int64, bool) { runID, err := strconv.ParseInt(rawRunID, 10, 64) if err != nil /* || task.Job.RunID != runID*/ { log.Error("Error runID not match") @@ -210,7 +210,7 @@ func (r artifactV4Routes) buildSignature(endp, expires, artifactName string, tas func (r artifactV4Routes) buildArtifactURL(endp, artifactName string, taskID int64) string { expires := time.Now().Add(60 * time.Minute).Format("2006-01-02 15:04:05.999999999 -0700 MST") uploadURL := "http://" + strings.TrimSuffix(r.AppURL, "/") + strings.TrimSuffix(r.prefix, "/") + - "/" + endp + "?sig=" + base64.URLEncoding.EncodeToString(r.buildSignature(endp, expires, artifactName, taskID)) + "&expires=" + url.QueryEscape(expires) + "&artifactName=" + url.QueryEscape(artifactName) + "&taskID=" + fmt.Sprint(taskID) + "/" + endp + "?sig=" + base64.URLEncoding.EncodeToString(r.buildSignature(endp, expires, artifactName, taskID)) + "&expires=" + url.QueryEscape(expires) + "&artifactName=" + url.QueryEscape(artifactName) + "&taskID=" + strconv.FormatInt(taskID, 10) return uploadURL } @@ -278,7 +278,7 @@ func (r *artifactV4Routes) createArtifact(ctx *ArtifactContext) { artifactName := req.Name - safeRunPath := safeResolve(r.baseDir, fmt.Sprint(runID)) + safeRunPath := safeResolve(r.baseDir, strconv.FormatInt(runID, 10)) safePath := safeResolve(safeRunPath, artifactName) safePath = safeResolve(safePath, artifactName+".zip") file, err := r.fs.OpenWritable(safePath) @@ -305,7 +305,7 @@ func (r *artifactV4Routes) uploadArtifact(ctx *ArtifactContext) { switch comp { case "block", "appendBlock": - safeRunPath := safeResolve(r.baseDir, fmt.Sprint(task)) + safeRunPath := safeResolve(r.baseDir, strconv.FormatInt(task, 10)) safePath := safeResolve(safeRunPath, artifactName) safePath = safeResolve(safePath, artifactName+".zip") @@ -365,7 +365,7 @@ func (r *artifactV4Routes) listArtifacts(ctx *ArtifactContext) { return } - safePath := safeResolve(r.baseDir, fmt.Sprint(runID)) + safePath := safeResolve(r.baseDir, strconv.FormatInt(runID, 10)) entries, err := fs.ReadDir(r.rfs, safePath) if err != nil { @@ -424,7 +424,7 @@ func (r *artifactV4Routes) downloadArtifact(ctx *ArtifactContext) { return } - safeRunPath := safeResolve(r.baseDir, fmt.Sprint(task)) + safeRunPath := safeResolve(r.baseDir, strconv.FormatInt(task, 10)) safePath := safeResolve(safeRunPath, artifactName) safePath = safeResolve(safePath, artifactName+".zip") @@ -443,7 +443,7 @@ func (r *artifactV4Routes) deleteArtifact(ctx *ArtifactContext) { if !ok { return } - safeRunPath := safeResolve(r.baseDir, fmt.Sprint(runID)) + safeRunPath := safeResolve(r.baseDir, strconv.FormatInt(runID, 10)) safePath := safeResolve(safeRunPath, req.Name) _ = os.RemoveAll(safePath) diff --git a/pkg/artifacts/server_test.go b/pkg/artifacts/server_test.go index e5e00c20..635da172 100644 --- a/pkg/artifacts/server_test.go +++ b/pkg/artifacts/server_test.go @@ -68,7 +68,7 @@ func TestNewArtifactUploadPrepare(t *testing.T) { router := httprouter.New() uploads(router, "artifact/server/path", writeMapFS{memfs}) - req, _ := http.NewRequest("POST", "http://localhost/_apis/pipelines/workflows/1/artifacts", nil) + req, _ := http.NewRequest(http.MethodPost, "http://localhost/_apis/pipelines/workflows/1/artifacts", nil) rr := httptest.NewRecorder() router.ServeHTTP(rr, req) @@ -94,7 +94,7 @@ func TestArtifactUploadBlob(t *testing.T) { router := httprouter.New() uploads(router, "artifact/server/path", writeMapFS{memfs}) - req, _ := http.NewRequest("PUT", "http://localhost/upload/1?itemPath=some/file", strings.NewReader("content")) + req, _ := http.NewRequest(http.MethodPut, "http://localhost/upload/1?itemPath=some/file", strings.NewReader("content")) rr := httptest.NewRecorder() router.ServeHTTP(rr, req) @@ -121,7 +121,7 @@ func TestFinalizeArtifactUpload(t *testing.T) { router := httprouter.New() uploads(router, "artifact/server/path", writeMapFS{memfs}) - req, _ := http.NewRequest("PATCH", "http://localhost/_apis/pipelines/workflows/1/artifacts", nil) + req, _ := http.NewRequest(http.MethodPatch, "http://localhost/_apis/pipelines/workflows/1/artifacts", nil) rr := httptest.NewRecorder() router.ServeHTTP(rr, req) @@ -151,7 +151,7 @@ func TestListArtifacts(t *testing.T) { router := httprouter.New() downloads(router, "artifact/server/path", memfs) - req, _ := http.NewRequest("GET", "http://localhost/_apis/pipelines/workflows/1/artifacts", nil) + req, _ := http.NewRequest(http.MethodGet, "http://localhost/_apis/pipelines/workflows/1/artifacts", nil) rr := httptest.NewRecorder() router.ServeHTTP(rr, req) @@ -183,7 +183,7 @@ func TestListArtifactContainer(t *testing.T) { router := httprouter.New() downloads(router, "artifact/server/path", memfs) - req, _ := http.NewRequest("GET", "http://localhost/download/1?itemPath=some/file", nil) + req, _ := http.NewRequest(http.MethodGet, "http://localhost/download/1?itemPath=some/file", nil) rr := httptest.NewRecorder() router.ServeHTTP(rr, req) @@ -198,7 +198,7 @@ func TestListArtifactContainer(t *testing.T) { panic(err) } - assert.Equal(1, len(response.Value)) + assert.Len(response.Value, 1) assert.Equal("some/file", response.Value[0].Path) assert.Equal("file", response.Value[0].ItemType) assert.Equal("http://localhost/artifact/1/some/file/.", response.Value[0].ContentLocation) @@ -216,7 +216,7 @@ func TestDownloadArtifactFile(t *testing.T) { router := httprouter.New() downloads(router, "artifact/server/path", memfs) - req, _ := http.NewRequest("GET", "http://localhost/artifact/1/some/file", nil) + req, _ := http.NewRequest(http.MethodGet, "http://localhost/artifact/1/some/file", nil) rr := httptest.NewRecorder() router.ServeHTTP(rr, req) @@ -283,7 +283,7 @@ func runTestJobFile(ctx context.Context, t *testing.T, tjfi TestJobFileInfo) { } workdir, err := filepath.Abs(tjfi.workdir) - assert.Nil(t, err, workdir) + assert.NoError(t, err, workdir) fullWorkflowPath := filepath.Join(workdir, tjfi.workflowPath) runnerConfig := &runner.Config{ Workdir: workdir, @@ -299,16 +299,16 @@ func runTestJobFile(ctx context.Context, t *testing.T, tjfi TestJobFileInfo) { } runner, err := runner.New(runnerConfig) - assert.Nil(t, err, tjfi.workflowPath) + assert.NoError(t, err, tjfi.workflowPath) planner, err := model.NewWorkflowPlanner(fullWorkflowPath, model.PlannerConfig{}) - assert.Nil(t, err, fullWorkflowPath) + assert.NoError(t, err, fullWorkflowPath) plan, err := planner.PlanEvent(tjfi.eventName) if err == nil { err = runner.NewPlanExecutor(plan)(ctx) if tjfi.errorMessage == "" { - assert.Nil(t, err, fullWorkflowPath) + assert.NoError(t, err, fullWorkflowPath) } else { assert.Error(t, err, tjfi.errorMessage) } @@ -356,7 +356,7 @@ func TestDownloadArtifactFileUnsafePath(t *testing.T) { router := httprouter.New() downloads(router, "artifact/server/path", memfs) - req, _ := http.NewRequest("GET", "http://localhost/artifact/2/../../some/file", nil) + req, _ := http.NewRequest(http.MethodGet, "http://localhost/artifact/2/../../some/file", nil) rr := httptest.NewRecorder() router.ServeHTTP(rr, req) @@ -378,7 +378,7 @@ func TestArtifactUploadBlobUnsafePath(t *testing.T) { router := httprouter.New() uploads(router, "artifact/server/path", writeMapFS{memfs}) - req, _ := http.NewRequest("PUT", "http://localhost/upload/1?itemPath=../../some/file", strings.NewReader("content")) + req, _ := http.NewRequest(http.MethodPut, "http://localhost/upload/1?itemPath=../../some/file", strings.NewReader("content")) rr := httptest.NewRecorder() router.ServeHTTP(rr, req) diff --git a/pkg/common/auth.go b/pkg/common/auth.go index 5faacf22..7e170a72 100644 --- a/pkg/common/auth.go +++ b/pkg/common/auth.go @@ -5,6 +5,7 @@ package common import ( "encoding/json" + "errors" "fmt" "net/http" "strings" @@ -78,7 +79,7 @@ func ParseAuthorizationToken(req *http.Request) (int64, error) { parts := strings.SplitN(h, " ", 2) if len(parts) != 2 { log.Errorf("split token failed: %s", h) - return 0, fmt.Errorf("split token failed") + return 0, errors.New("split token failed") } token, err := jwt.ParseWithClaims(parts[1], &actionsClaims{}, func(t *jwt.Token) (any, error) { @@ -93,7 +94,7 @@ func ParseAuthorizationToken(req *http.Request) (int64, error) { c, ok := token.Claims.(*actionsClaims) if !token.Valid || !ok { - return 0, fmt.Errorf("invalid token claim") + return 0, errors.New("invalid token claim") } return c.TaskID, nil diff --git a/pkg/common/auth_test.go b/pkg/common/auth_test.go index e6ee9670..87564c80 100644 --- a/pkg/common/auth_test.go +++ b/pkg/common/auth_test.go @@ -15,13 +15,13 @@ import ( func TestCreateAuthorizationToken(t *testing.T) { var taskID int64 = 23 token, err := CreateAuthorizationToken(taskID, 1, 2) - assert.Nil(t, err) - assert.NotEqual(t, "", token) + assert.NoError(t, err) + assert.NotEmpty(t, token) claims := jwt.MapClaims{} - _, err = jwt.ParseWithClaims(token, claims, func(_ *jwt.Token) (interface{}, error) { + _, err = jwt.ParseWithClaims(token, claims, func(_ *jwt.Token) (any, error) { return []byte{}, nil }) - assert.Nil(t, err) + assert.NoError(t, err) scp, ok := claims["scp"] assert.True(t, ok, "Has scp claim in jwt token") assert.Contains(t, scp, "Actions.Results:1:2") @@ -41,14 +41,14 @@ func TestCreateAuthorizationToken(t *testing.T) { func TestParseAuthorizationToken(t *testing.T) { var taskID int64 = 23 token, err := CreateAuthorizationToken(taskID, 1, 2) - assert.Nil(t, err) - assert.NotEqual(t, "", token) + assert.NoError(t, err) + assert.NotEmpty(t, token) headers := http.Header{} headers.Set("Authorization", "Bearer "+token) rTaskID, err := ParseAuthorizationToken(&http.Request{ Header: headers, }) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, taskID, rTaskID) } @@ -57,6 +57,6 @@ func TestParseAuthorizationTokenNoAuthHeader(t *testing.T) { rTaskID, err := ParseAuthorizationToken(&http.Request{ Header: headers, }) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, int64(0), rTaskID) } diff --git a/pkg/common/cartesian.go b/pkg/common/cartesian.go index 9cd60655..f7467c90 100644 --- a/pkg/common/cartesian.go +++ b/pkg/common/cartesian.go @@ -1,9 +1,9 @@ package common // CartesianProduct takes map of lists and returns list of unique tuples -func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interface{} { +func CartesianProduct(mapOfLists map[string][]any) []map[string]any { listNames := make([]string, 0) - lists := make([][]interface{}, 0) + lists := make([][]any, 0) for k, v := range mapOfLists { listNames = append(listNames, k) lists = append(lists, v) @@ -11,9 +11,9 @@ func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interfac listCart := cartN(lists...) - rtn := make([]map[string]interface{}, 0) + rtn := make([]map[string]any, 0) for _, list := range listCart { - vMap := make(map[string]interface{}) + vMap := make(map[string]any) for i, v := range list { vMap[listNames[i]] = v } @@ -22,7 +22,7 @@ func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interfac return rtn } -func cartN(a ...[]interface{}) [][]interface{} { +func cartN(a ...[]any) [][]any { c := 1 for _, a := range a { c *= len(a) @@ -30,8 +30,8 @@ func cartN(a ...[]interface{}) [][]interface{} { if c == 0 || len(a) == 0 { return nil } - p := make([][]interface{}, c) - b := make([]interface{}, c*len(a)) + p := make([][]any, c) + b := make([]any, c*len(a)) n := make([]int, len(a)) s := 0 for i := range p { diff --git a/pkg/common/cartesian_test.go b/pkg/common/cartesian_test.go index c49de06c..37b22eb3 100644 --- a/pkg/common/cartesian_test.go +++ b/pkg/common/cartesian_test.go @@ -8,7 +8,7 @@ import ( func TestCartesianProduct(t *testing.T) { assert := assert.New(t) - input := map[string][]interface{}{ + input := map[string][]any{ "foo": {1, 2, 3, 4}, "bar": {"a", "b", "c"}, "baz": {false, true}, @@ -25,15 +25,15 @@ func TestCartesianProduct(t *testing.T) { assert.Contains(v, "baz") } - input = map[string][]interface{}{ + input = map[string][]any{ "foo": {1, 2, 3, 4}, "bar": {}, "baz": {false, true}, } output = CartesianProduct(input) - assert.Len(output, 0) + assert.Empty(output) - input = map[string][]interface{}{} + input = map[string][]any{} output = CartesianProduct(input) - assert.Len(output, 0) + assert.Empty(output) } diff --git a/pkg/common/draw.go b/pkg/common/draw.go index b5b21fe9..d11fa9fb 100644 --- a/pkg/common/draw.go +++ b/pkg/common/draw.go @@ -125,11 +125,8 @@ func (p *Pen) DrawBoxes(labels ...string) *Drawing { // Draw to writer func (d *Drawing) Draw(writer io.Writer, centerOnWidth int) { - padSize := (centerOnWidth - d.GetWidth()) / 2 - if padSize < 0 { - padSize = 0 - } - for _, l := range strings.Split(d.buf.String(), "\n") { + padSize := max((centerOnWidth-d.GetWidth())/2, 0) + for l := range strings.SplitSeq(d.buf.String(), "\n") { if len(l) > 0 { padding := strings.Repeat(" ", padSize) fmt.Fprintf(writer, "%s%s\n", padding, l) diff --git a/pkg/common/executor.go b/pkg/common/executor.go index db36ab3b..0a6f4ade 100644 --- a/pkg/common/executor.go +++ b/pkg/common/executor.go @@ -19,7 +19,7 @@ func (w Warning) Error() string { } // Warningf create a warning -func Warningf(format string, args ...interface{}) Warning { +func Warningf(format string, args ...any) Warning { w := Warning{ Message: fmt.Sprintf(format, args...), } @@ -33,7 +33,7 @@ type Executor func(ctx context.Context) error type Conditional func(ctx context.Context) bool // NewInfoExecutor is an executor that logs messages -func NewInfoExecutor(format string, args ...interface{}) Executor { +func NewInfoExecutor(format string, args ...any) Executor { return func(ctx context.Context) error { logger := Logger(ctx) logger.Infof(format, args...) @@ -42,7 +42,7 @@ func NewInfoExecutor(format string, args ...interface{}) Executor { } // NewDebugExecutor is an executor that logs messages -func NewDebugExecutor(format string, args ...interface{}) Executor { +func NewDebugExecutor(format string, args ...any) Executor { return func(ctx context.Context) error { logger := Logger(ctx) logger.Debugf(format, args...) @@ -110,14 +110,14 @@ func NewParallelExecutor(parallel int, executors ...Executor) Executor { }(work, errs) } - for i := 0; i < len(executors); i++ { + for i := range executors { work <- executors[i] } close(work) // Executor waits all executors to cleanup these resources. var firstErr error - for i := 0; i < len(executors); i++ { + for range executors { err := <-errs if firstErr == nil { firstErr = err @@ -131,7 +131,7 @@ func NewParallelExecutor(parallel int, executors ...Executor) Executor { } } -func NewFieldExecutor(name string, value interface{}, exec Executor) Executor { +func NewFieldExecutor(name string, value any, exec Executor) Executor { return func(ctx context.Context) error { return exec(WithLogger(ctx, Logger(ctx).WithField(name, value))) } diff --git a/pkg/common/executor_test.go b/pkg/common/executor_test.go index baa03b6a..eb203d26 100644 --- a/pkg/common/executor_test.go +++ b/pkg/common/executor_test.go @@ -2,7 +2,7 @@ package common import ( "context" - "fmt" + "errors" "testing" "time" @@ -16,11 +16,11 @@ func TestNewWorkflow(t *testing.T) { // empty emptyWorkflow := NewPipelineExecutor() - assert.Nil(emptyWorkflow(ctx)) + assert.NoError(emptyWorkflow(ctx)) // error case - errorWorkflow := NewErrorExecutor(fmt.Errorf("test error")) - assert.NotNil(errorWorkflow(ctx)) + errorWorkflow := NewErrorExecutor(errors.New("test error")) + assert.Error(errorWorkflow(ctx)) // multiple success case runcount := 0 @@ -33,7 +33,7 @@ func TestNewWorkflow(t *testing.T) { runcount++ return nil }) - assert.Nil(successWorkflow(ctx)) + assert.NoError(successWorkflow(ctx)) assert.Equal(2, runcount) } @@ -55,7 +55,7 @@ func TestNewConditionalExecutor(t *testing.T) { return nil })(ctx) - assert.Nil(err) + assert.NoError(err) assert.Equal(0, trueCount) assert.Equal(1, falseCount) @@ -69,7 +69,7 @@ func TestNewConditionalExecutor(t *testing.T) { return nil })(ctx) - assert.Nil(err) + assert.NoError(err) assert.Equal(1, trueCount) assert.Equal(1, falseCount) } @@ -99,7 +99,7 @@ func TestNewParallelExecutor(t *testing.T) { assert.Equal(3, count, "should run all 3 executors") assert.Equal(2, maxCount, "should run at most 2 executors in parallel") - assert.Nil(err) + assert.NoError(err) // Reset to test running the executor with 0 parallelism count = 0 @@ -110,7 +110,7 @@ func TestNewParallelExecutor(t *testing.T) { assert.Equal(3, count, "should run all 3 executors") assert.Equal(1, maxCount, "should run at most 1 executors in parallel") - assert.Nil(errSingle) + assert.NoError(errSingle) } func TestNewParallelExecutorFailed(t *testing.T) { @@ -122,7 +122,7 @@ func TestNewParallelExecutorFailed(t *testing.T) { count := 0 errorWorkflow := NewPipelineExecutor(func(_ context.Context) error { count++ - return fmt.Errorf("fake error") + return errors.New("fake error") }) err := NewParallelExecutor(1, errorWorkflow)(ctx) assert.Equal(1, count) @@ -135,7 +135,7 @@ func TestNewParallelExecutorCanceled(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) cancel() - errExpected := fmt.Errorf("fake error") + errExpected := errors.New("fake error") count := 0 successWorkflow := NewPipelineExecutor(func(_ context.Context) error { @@ -148,5 +148,5 @@ func TestNewParallelExecutorCanceled(t *testing.T) { }) err := NewParallelExecutor(3, errorWorkflow, successWorkflow, successWorkflow)(ctx) assert.Equal(3, count) - assert.Error(errExpected, err) + assert.ErrorIs(errExpected, err) } diff --git a/pkg/common/git/git.go b/pkg/common/git/git.go index 654c038d..87f105e1 100644 --- a/pkg/common/git/git.go +++ b/pkg/common/git/git.go @@ -74,7 +74,7 @@ func FindGitRevision(ctx context.Context, file string) (shortSha string, sha str } if head.Hash().IsZero() { - return "", "", fmt.Errorf("head sha1 could not be resolved") + return "", "", errors.New("head sha1 could not be resolved") } hash := head.Hash().String() @@ -319,7 +319,7 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) common.Executor { cloneLock.Lock() defer cloneLock.Unlock() - refName := plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", input.Ref)) + refName := plumbing.ReferenceName("refs/heads/" + input.Ref) r, err := CloneIfRequired(ctx, refName, input, logger) if err != nil { return err diff --git a/pkg/common/git/git_test.go b/pkg/common/git/git_test.go index 0ade6635..f397a4a3 100644 --- a/pkg/common/git/git_test.go +++ b/pkg/common/git/git_test.go @@ -216,7 +216,7 @@ func TestGitCloneExecutor(t *testing.T) { assert.Error(t, err) assert.Equal(t, tt.Err, err) } else { - assert.Empty(t, err) + assert.NoError(t, err) } }) } diff --git a/pkg/container/docker_cli.go b/pkg/container/docker_cli.go index 4331d8e9..fc5a11a9 100644 --- a/pkg/container/docker_cli.go +++ b/pkg/container/docker_cli.go @@ -19,6 +19,7 @@ import ( "path/filepath" "reflect" "regexp" + "slices" "strconv" "strings" "time" @@ -559,7 +560,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con return nil, errors.Errorf("--health-retries cannot be negative") } if copts.healthStartPeriod < 0 { - return nil, fmt.Errorf("--health-start-period cannot be negative") + return nil, errors.New("--health-start-period cannot be negative") } healthConfig = &container.HealthConfig{ @@ -836,7 +837,7 @@ func convertToStandardNotation(ports []string) ([]string, error) { for _, publish := range ports { if strings.Contains(publish, "=") { params := map[string]string{"protocol": "tcp"} - for _, param := range strings.Split(publish, ",") { + for param := range strings.SplitSeq(publish, ",") { opt := strings.Split(param, "=") if len(opt) < 2 { return optsList, errors.Errorf("invalid publish opts format (should be name=value but got '%s')", param) @@ -1066,10 +1067,8 @@ func validateLinuxPath(val string, validator func(string) bool) (string, error) // validateAttach validates that the specified string is a valid attach option. func validateAttach(val string) (string, error) { s := strings.ToLower(val) - for _, str := range []string{"stdin", "stdout", "stderr"} { - if s == str { - return s, nil - } + if slices.Contains([]string{"stdin", "stdout", "stderr"}, s) { + return s, nil } return val, errors.Errorf("valid streams are STDIN, STDOUT and STDERR") } diff --git a/pkg/container/docker_cli_test.go b/pkg/container/docker_cli_test.go index cca08e24..d4336f49 100644 --- a/pkg/container/docker_cli_test.go +++ b/pkg/container/docker_cli_test.go @@ -339,7 +339,7 @@ func TestParseHostname(t *testing.T) { hostnameWithDomain := "--hostname=hostname.domainname" hostnameWithDomainTld := "--hostname=hostname.domainname.tld" for hostname, expectedHostname := range validHostnames { - if config, _, _ := mustParse(t, fmt.Sprintf("--hostname=%s", hostname)); config.Hostname != expectedHostname { + if config, _, _ := mustParse(t, "--hostname="+hostname); config.Hostname != expectedHostname { t.Fatalf("Expected the config to have 'hostname' as %q, got %q", expectedHostname, config.Hostname) } } @@ -677,7 +677,7 @@ func TestParseRestartPolicy(t *testing.T) { }, } for restart, expectedError := range invalids { - if _, _, _, err := parseRun([]string{fmt.Sprintf("--restart=%s", restart), "img", "cmd"}); err == nil || err.Error() != expectedError { + if _, _, _, err := parseRun([]string{"--restart=" + restart, "img", "cmd"}); err == nil || err.Error() != expectedError { t.Fatalf("Expected an error with message '%v' for %v, got %v", expectedError, restart, err) } } diff --git a/pkg/container/docker_images_test.go b/pkg/container/docker_images_test.go index 8d506f53..45fcd9f0 100644 --- a/pkg/container/docker_images_test.go +++ b/pkg/container/docker_images_test.go @@ -26,17 +26,17 @@ func TestImageExistsLocally(t *testing.T) { // Test if image exists with specific tag invalidImageTag, err := ImageExistsLocally(ctx, "library/alpine:this-random-tag-will-never-exist", "linux/amd64") - assert.Nil(t, err) - assert.Equal(t, false, invalidImageTag) + assert.NoError(t, err) + assert.False(t, invalidImageTag) // Test if image exists with specific architecture (image platform) invalidImagePlatform, err := ImageExistsLocally(ctx, "alpine:latest", "windows/amd64") - assert.Nil(t, err) - assert.Equal(t, false, invalidImagePlatform) + assert.NoError(t, err) + assert.False(t, invalidImagePlatform) // pull an image cli, err := client.NewClientWithOpts(client.FromEnv) - assert.Nil(t, err) + assert.NoError(t, err) cli.NegotiateAPIVersion(context.Background()) // Chose alpine latest because it's so small @@ -44,14 +44,14 @@ func TestImageExistsLocally(t *testing.T) { readerDefault, err := cli.ImagePull(ctx, "node:16-buster-slim", image.PullOptions{ Platform: "linux/amd64", }) - assert.Nil(t, err) + assert.NoError(t, err) defer readerDefault.Close() _, err = io.ReadAll(readerDefault) - assert.Nil(t, err) + assert.NoError(t, err) imageDefaultArchExists, err := ImageExistsLocally(ctx, "node:16-buster-slim", "linux/amd64") - assert.Nil(t, err) - assert.Equal(t, true, imageDefaultArchExists) + assert.NoError(t, err) + assert.True(t, imageDefaultArchExists) } func TestImageExistsLocallyQemu(t *testing.T) { @@ -66,19 +66,19 @@ func TestImageExistsLocallyQemu(t *testing.T) { // pull an image cli, err := client.NewClientWithOpts(client.FromEnv) - assert.Nil(t, err) + assert.NoError(t, err) cli.NegotiateAPIVersion(context.Background()) // Validate if another architecture platform can be pulled readerArm64, err := cli.ImagePull(ctx, "node:16-buster-slim", image.PullOptions{ Platform: "linux/arm64", }) - assert.Nil(t, err) + assert.NoError(t, err) defer readerArm64.Close() _, err = io.ReadAll(readerArm64) - assert.Nil(t, err) + assert.NoError(t, err) imageArm64Exists, err := ImageExistsLocally(ctx, "node:16-buster-slim", "linux/arm64") - assert.Nil(t, err) - assert.Equal(t, true, imageArm64Exists) + assert.NoError(t, err) + assert.True(t, imageArm64Exists) } diff --git a/pkg/container/docker_logger.go b/pkg/container/docker_logger.go index b9eb503e..549d8898 100644 --- a/pkg/container/docker_logger.go +++ b/pkg/container/docker_logger.go @@ -74,7 +74,7 @@ func logDockerResponse(logger logrus.FieldLogger, dockerResponse io.ReadCloser, return nil } -func writeLog(logger logrus.FieldLogger, isError bool, format string, args ...interface{}) { +func writeLog(logger logrus.FieldLogger, isError bool, format string, args ...any) { if isError { logger.Errorf(format, args...) } else { diff --git a/pkg/container/docker_pull_test.go b/pkg/container/docker_pull_test.go index bfbe89dd..0b7fc94a 100644 --- a/pkg/container/docker_pull_test.go +++ b/pkg/container/docker_pull_test.go @@ -40,15 +40,15 @@ func TestGetImagePullOptions(t *testing.T) { config.SetDir("/non-existent/docker") options, err := getImagePullOptions(ctx, NewDockerPullExecutorInput{}) - assert.Nil(t, err, "Failed to create ImagePullOptions") - assert.Equal(t, "", options.RegistryAuth, "RegistryAuth should be empty if no username or password is set") + assert.NoError(t, err, "Failed to create ImagePullOptions") + assert.Empty(t, options.RegistryAuth, "RegistryAuth should be empty if no username or password is set") options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{ Image: "", Username: "username", Password: "password", }) - assert.Nil(t, err, "Failed to create ImagePullOptions") + assert.NoError(t, err, "Failed to create ImagePullOptions") assert.Equal(t, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZCJ9", options.RegistryAuth, "Username and Password should be provided") config.SetDir("testdata/docker-pull-options") @@ -56,6 +56,6 @@ func TestGetImagePullOptions(t *testing.T) { options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{ Image: "nektos/act", }) - assert.Nil(t, err, "Failed to create ImagePullOptions") + assert.NoError(t, err, "Failed to create ImagePullOptions") assert.Equal(t, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZFxuIiwic2VydmVyYWRkcmVzcyI6Imh0dHBzOi8vaW5kZXguZG9ja2VyLmlvL3YxLyJ9", options.RegistryAuth, "RegistryAuth should be taken from local docker config") } diff --git a/pkg/container/docker_run.go b/pkg/container/docker_run.go index 33be46bd..1fabb76b 100644 --- a/pkg/container/docker_run.go +++ b/pkg/container/docker_run.go @@ -137,7 +137,7 @@ func (cr *containerReference) CopyDir(destPath string, srcPath string, useGitIgn func (cr *containerReference) GetContainerArchive(ctx context.Context, srcPath string) (io.ReadCloser, error) { if common.Dryrun(ctx) { - return nil, fmt.Errorf("dryrun is not supported in GetContainerArchive") + return nil, errors.New("dryrun is not supported in GetContainerArchive") } a, _, err := cr.cli.CopyFromContainer(ctx, cr.id, srcPath) return a, err diff --git a/pkg/container/docker_run_test.go b/pkg/container/docker_run_test.go index f4bfd6eb..40f8f228 100644 --- a/pkg/container/docker_run_test.go +++ b/pkg/container/docker_run_test.go @@ -4,7 +4,7 @@ import ( "bufio" "bytes" "context" - "fmt" + "errors" "io" "net" "strings" @@ -216,7 +216,7 @@ func TestDockerCopyTarStreamErrorInCopyFiles(t *testing.T) { conn := &mockConn{} - merr := fmt.Errorf("failure") + merr := errors.New("failure") client := &mockDockerClient{} client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("container.CopyToContainerOptions")).Return(merr) @@ -241,7 +241,7 @@ func TestDockerCopyTarStreamErrorInMkdir(t *testing.T) { conn := &mockConn{} - merr := fmt.Errorf("failure") + merr := errors.New("failure") client := &mockDockerClient{} client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("container.CopyToContainerOptions")).Return(nil) diff --git a/pkg/container/docker_socket.go b/pkg/container/docker_socket.go index c04ace96..52f940f8 100644 --- a/pkg/container/docker_socket.go +++ b/pkg/container/docker_socket.go @@ -43,8 +43,8 @@ func socketLocation() (string, bool) { // indicating that the `daemonPath` is a Docker host URI. If it doesn't, or if the "://" delimiter // is not found in the `daemonPath`, the function returns false. func isDockerHostURI(daemonPath string) bool { - if protoIndex := strings.Index(daemonPath, "://"); protoIndex != -1 { - scheme := daemonPath[:protoIndex] + if before, _, ok := strings.Cut(daemonPath, "://"); ok { + scheme := before if strings.IndexFunc(scheme, func(r rune) bool { return (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') }) == -1 { diff --git a/pkg/container/docker_socket_test.go b/pkg/container/docker_socket_test.go index 0915a937..346f3cc9 100644 --- a/pkg/container/docker_socket_test.go +++ b/pkg/container/docker_socket_test.go @@ -25,7 +25,7 @@ func TestGetSocketAndHostWithSocket(t *testing.T) { ret, err := GetSocketAndHost(socketURI) // Assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, SocketAndHost{socketURI, dockerHost}, ret) } @@ -38,7 +38,7 @@ func TestGetSocketAndHostNoSocket(t *testing.T) { ret, err := GetSocketAndHost("") // Assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, SocketAndHost{dockerHost, dockerHost}, ret) } @@ -54,7 +54,7 @@ func TestGetSocketAndHostOnlySocket(t *testing.T) { // Assert assert.NoError(t, err, "Expected no error from GetSocketAndHost") - assert.Equal(t, true, defaultSocketFound, "Expected to find default socket") + assert.True(t, defaultSocketFound, "Expected to find default socket") assert.Equal(t, socketURI, ret.Socket, "Expected socket to match common location") assert.Equal(t, defaultSocket, ret.Host, "Expected ret.Host to match default socket location") } @@ -69,7 +69,7 @@ func TestGetSocketAndHostDontMount(t *testing.T) { ret, err := GetSocketAndHost("-") // Assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, SocketAndHost{"-", dockerHost}, ret) } @@ -83,8 +83,8 @@ func TestGetSocketAndHostNoHostNoSocket(t *testing.T) { ret, err := GetSocketAndHost("") // Assert - assert.Equal(t, true, found, "Expected a default socket to be found") - assert.Nil(t, err, "Expected no error from GetSocketAndHost") + assert.True(t, found, "Expected a default socket to be found") + assert.NoError(t, err, "Expected no error from GetSocketAndHost") assert.Equal(t, SocketAndHost{defaultSocket, defaultSocket}, ret, "Expected to match default socket location") } @@ -93,7 +93,7 @@ func TestGetSocketAndHostNoHostNoSocket(t *testing.T) { // > This happens if neither DOCKER_HOST nor --container-daemon-socket has a value, but socketLocation() returns a URI func TestGetSocketAndHostNoHostNoSocketDefaultLocation(t *testing.T) { // Arrange - mySocketFile, tmpErr := os.CreateTemp("", "act-*.sock") + mySocketFile, tmpErr := os.CreateTemp(t.TempDir(), "act-*.sock") mySocket := mySocketFile.Name() unixSocket := "unix://" + mySocket defer os.RemoveAll(mySocket) @@ -108,8 +108,8 @@ func TestGetSocketAndHostNoHostNoSocketDefaultLocation(t *testing.T) { // Assert assert.Equal(t, unixSocket, defaultSocket, "Expected default socket to match common socket location") - assert.Equal(t, true, found, "Expected default socket to be found") - assert.Nil(t, err, "Expected no error from GetSocketAndHost") + assert.True(t, found, "Expected default socket to be found") + assert.NoError(t, err, "Expected no error from GetSocketAndHost") assert.Equal(t, SocketAndHost{unixSocket, unixSocket}, ret, "Expected to match default socket location") } @@ -124,8 +124,8 @@ func TestGetSocketAndHostNoHostInvalidSocket(t *testing.T) { ret, err := GetSocketAndHost(mySocket) // Assert - assert.Equal(t, false, found, "Expected no default socket to be found") - assert.Equal(t, "", defaultSocket, "Expected no default socket to be found") + assert.False(t, found, "Expected no default socket to be found") + assert.Empty(t, defaultSocket, "Expected no default socket to be found") assert.Equal(t, SocketAndHost{}, ret, "Expected to match default socket location") assert.Error(t, err, "Expected an error in invalid state") } @@ -142,9 +142,9 @@ func TestGetSocketAndHostOnlySocketValidButUnusualLocation(t *testing.T) { // Assert // Default socket locations - assert.Equal(t, "", defaultSocket, "Expect default socket location to be empty") - assert.Equal(t, false, found, "Expected no default socket to be found") + assert.Empty(t, defaultSocket, "Expect default socket location to be empty") + assert.False(t, found, "Expected no default socket to be found") // Sane default - assert.Nil(t, err, "Expect no error from GetSocketAndHost") + assert.NoError(t, err, "Expect no error from GetSocketAndHost") assert.Equal(t, socketURI, ret.Host, "Expect host to default to unusual socket") } diff --git a/pkg/container/executions_environment.go b/pkg/container/executions_environment.go index 41e3b57e..dfc1936e 100644 --- a/pkg/container/executions_environment.go +++ b/pkg/container/executions_environment.go @@ -9,7 +9,7 @@ type ExecutionsEnvironment interface { GetPathVariableName() string DefaultPathVariable() string JoinPathVariable(...string) string - GetRunnerContext(ctx context.Context) map[string]interface{} + GetRunnerContext(ctx context.Context) map[string]any // On windows PATH and Path are the same key IsEnvironmentCaseInsensitive() bool } diff --git a/pkg/container/host_environment.go b/pkg/container/host_environment.go index de514e66..ea6183e3 100644 --- a/pkg/container/host_environment.go +++ b/pkg/container/host_environment.go @@ -83,7 +83,7 @@ func (e *HostEnvironment) CopyTarStream(ctx context.Context, destPath string, ta continue } if ctx.Err() != nil { - return fmt.Errorf("copyTarStream has been cancelled") + return errors.New("copyTarStream has been cancelled") } if err := cp.WriteFile(ti.Name, ti.FileInfo(), ti.Linkname, tr); err != nil { return err @@ -224,7 +224,7 @@ func (l *localEnv) Getenv(name string) string { func lookupPathHost(cmd string, env map[string]string, writer io.Writer) (string, error) { f, err := lookpath.LookPath2(cmd, &localEnv{env: env}) if err != nil { - err := "Cannot find: " + fmt.Sprint(cmd) + " in PATH" + err := "Cannot find: " + cmd + " in PATH" if _, _err := writer.Write([]byte(err + "\n")); _err != nil { return "", fmt.Errorf("%v: %w", err, _err) } @@ -343,7 +343,7 @@ func (e *HostEnvironment) exec(ctx context.Context, command []string, cmdline st } if tty != nil { writer.AutoStop = true - if _, err := tty.Write([]byte("\x04")); err != nil { + if _, err := tty.WriteString("\x04"); err != nil { common.Logger(ctx).Debug("Failed to write EOT") } } @@ -451,8 +451,8 @@ func goOsToActionOs(os string) string { return os } -func (e *HostEnvironment) GetRunnerContext(_ context.Context) map[string]interface{} { - return map[string]interface{}{ +func (e *HostEnvironment) GetRunnerContext(_ context.Context) map[string]any { + return map[string]any{ "os": goOsToActionOs(runtime.GOOS), "arch": goArchToActionArch(runtime.GOARCH), "temp": e.TmpDir, diff --git a/pkg/container/linux_container_environment_extensions.go b/pkg/container/linux_container_environment_extensions.go index d6734511..667300a1 100644 --- a/pkg/container/linux_container_environment_extensions.go +++ b/pkg/container/linux_container_environment_extensions.go @@ -63,8 +63,8 @@ func (*LinuxContainerEnvironmentExtensions) JoinPathVariable(paths ...string) st return strings.Join(paths, ":") } -func (*LinuxContainerEnvironmentExtensions) GetRunnerContext(ctx context.Context) map[string]interface{} { - return map[string]interface{}{ +func (*LinuxContainerEnvironmentExtensions) GetRunnerContext(ctx context.Context) map[string]any { + return map[string]any{ "os": "Linux", "arch": RunnerArch(ctx), "temp": "/tmp", diff --git a/pkg/container/linux_container_environment_extensions_test.go b/pkg/container/linux_container_environment_extensions_test.go index 38111714..98d47eb6 100644 --- a/pkg/container/linux_container_environment_extensions_test.go +++ b/pkg/container/linux_container_environment_extensions_test.go @@ -31,8 +31,8 @@ func TestContainerPath(t *testing.T) { for _, v := range []containerPathJob{ {"/mnt/c/Users/act/go/src/github.com/nektos/act", "C:\\Users\\act\\go\\src\\github.com\\nektos\\act\\", ""}, {"/mnt/f/work/dir", `F:\work\dir`, ""}, - {"/mnt/c/windows/to/unix", "windows\\to\\unix", fmt.Sprintf("%s\\", rootDrive)}, - {fmt.Sprintf("/mnt/%v/act", rootDriveLetter), "act", fmt.Sprintf("%s\\", rootDrive)}, + {"/mnt/c/windows/to/unix", "windows\\to\\unix", rootDrive + "\\"}, + {fmt.Sprintf("/mnt/%v/act", rootDriveLetter), "act", rootDrive + "\\"}, } { if v.workDir != "" { if err := os.Chdir(v.workDir); err != nil { diff --git a/pkg/exprparser/functions.go b/pkg/exprparser/functions.go index 67435a9f..d66806d1 100644 --- a/pkg/exprparser/functions.go +++ b/pkg/exprparser/functions.go @@ -13,11 +13,11 @@ func (impl *interperterImpl) getNeedsTransitive(job *model.Job) []string { return needs } -func (impl *interperterImpl) always() (interface{}, error) { +func (impl *interperterImpl) always() (any, error) { return true, nil } -func (impl *interperterImpl) jobSuccess() (interface{}, error) { +func (impl *interperterImpl) jobSuccess() (any, error) { jobs := impl.config.Run.Workflow.Jobs jobNeeds := impl.getNeedsTransitive(impl.config.Run.Job()) @@ -30,11 +30,11 @@ func (impl *interperterImpl) jobSuccess() (interface{}, error) { return true, nil } -func (impl *interperterImpl) stepSuccess() (interface{}, error) { +func (impl *interperterImpl) stepSuccess() (any, error) { return impl.env.Job.Status == "success", nil } -func (impl *interperterImpl) jobFailure() (interface{}, error) { +func (impl *interperterImpl) jobFailure() (any, error) { jobs := impl.config.Run.Workflow.Jobs jobNeeds := impl.getNeedsTransitive(impl.config.Run.Job()) @@ -47,10 +47,10 @@ func (impl *interperterImpl) jobFailure() (interface{}, error) { return false, nil } -func (impl *interperterImpl) stepFailure() (interface{}, error) { +func (impl *interperterImpl) stepFailure() (any, error) { return impl.env.Job.Status == "failure", nil } -func (impl *interperterImpl) cancelled() (interface{}, error) { +func (impl *interperterImpl) cancelled() (any, error) { return impl.env.Job.Status == "cancelled", nil } diff --git a/pkg/exprparser/interpreter.go b/pkg/exprparser/interpreter.go index e8aba1c9..02bcca83 100644 --- a/pkg/exprparser/interpreter.go +++ b/pkg/exprparser/interpreter.go @@ -18,16 +18,16 @@ type EvaluationEnvironment struct { Job *model.JobContext Jobs *map[string]*model.WorkflowCallResult Steps map[string]*model.StepResult - Runner map[string]interface{} + Runner map[string]any Secrets map[string]string Vars map[string]string - Strategy map[string]interface{} - Matrix map[string]interface{} + Strategy map[string]any + Matrix map[string]any Needs map[string]Needs - Inputs map[string]interface{} - HashFiles func([]reflect.Value) (interface{}, error) + Inputs map[string]any + HashFiles func([]reflect.Value) (any, error) EnvCS bool - CtxData map[string]interface{} + CtxData map[string]any } type CaseSensitiveDict map[string]string @@ -69,7 +69,7 @@ func (dsc DefaultStatusCheck) String() string { } type Interpreter interface { - Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (interface{}, error) + Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (any, error) } type interperterImpl struct { @@ -151,7 +151,7 @@ func toRaw(left reflect.Value) any { // All values are evaluated as string, funcs that takes objects are implemented elsewhere type externalFunc struct { - f func([]reflect.Value) (interface{}, error) + f func([]reflect.Value) (any, error) } func (e externalFunc) Evaluate(ev *eval.Evaluator, args []exprparser.Node) (*eval.EvaluationResult, error) { @@ -170,7 +170,7 @@ func (e externalFunc) Evaluate(ev *eval.Evaluator, args []exprparser.Node) (*eva return eval.CreateIntermediateResult(ev.Context(), res), nil } -func (impl *interperterImpl) Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (interface{}, error) { +func (impl *interperterImpl) Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (any, error) { input = strings.TrimPrefix(input, "${{") input = strings.TrimSuffix(input, "}}") if defaultStatusCheck != DefaultStatusCheckNone && input == "" { @@ -226,10 +226,10 @@ func (impl *interperterImpl) GetFunctions() eval.CaseInsensitiveObject[eval.Func if impl.env.HashFiles != nil { functions["hashfiles"] = &externalFunc{impl.env.HashFiles} } - functions["always"] = &externalFunc{func(_ []reflect.Value) (interface{}, error) { + functions["always"] = &externalFunc{func(_ []reflect.Value) (any, error) { return impl.always() }} - functions["success"] = &externalFunc{func(_ []reflect.Value) (interface{}, error) { + functions["success"] = &externalFunc{func(_ []reflect.Value) (any, error) { if impl.config.Context == "job" { return impl.jobSuccess() } @@ -238,7 +238,7 @@ func (impl *interperterImpl) GetFunctions() eval.CaseInsensitiveObject[eval.Func } return nil, fmt.Errorf("context '%s' must be one of 'job' or 'step'", impl.config.Context) }} - functions["failure"] = &externalFunc{func(_ []reflect.Value) (interface{}, error) { + functions["failure"] = &externalFunc{func(_ []reflect.Value) (any, error) { if impl.config.Context == "job" { return impl.jobFailure() } @@ -247,7 +247,7 @@ func (impl *interperterImpl) GetFunctions() eval.CaseInsensitiveObject[eval.Func } return nil, fmt.Errorf("context '%s' must be one of 'job' or 'step'", impl.config.Context) }} - functions["cancelled"] = &externalFunc{func(_ []reflect.Value) (interface{}, error) { + functions["cancelled"] = &externalFunc{func(_ []reflect.Value) (any, error) { return impl.cancelled() }} return functions @@ -287,7 +287,7 @@ func (impl *interperterImpl) GetVariables() eval.ReadOnlyObject[any] { res := eval.CreateIntermediateResult(eval.NewEvaluationContext(), rawOtherCtx) if rOtherCd, ok := res.TryGetCollectionInterface(); ok { if otherCd, ok := rOtherCd.(eval.ReadOnlyObject[any]); ok { - if rawPayload, ok := cd.(map[string]interface{}); ok { + if rawPayload, ok := cd.(map[string]any); ok { for k, v := range rawPayload { // skip empty values, because github.workspace was set by Gitea Actions to an empty string if mk, _ := otherCd.GetKv(k); v != "" && v != nil { @@ -304,7 +304,7 @@ func (impl *interperterImpl) GetVariables() eval.ReadOnlyObject[any] { return vars } -func IsTruthy(input interface{}) bool { +func IsTruthy(input any) bool { value := reflect.ValueOf(input) switch value.Kind() { case reflect.Bool: diff --git a/pkg/exprparser/interpreter_test.go b/pkg/exprparser/interpreter_test.go index 7b1dbf53..72ee7722 100644 --- a/pkg/exprparser/interpreter_test.go +++ b/pkg/exprparser/interpreter_test.go @@ -11,7 +11,7 @@ import ( func TestLiterals(t *testing.T) { table := []struct { input string - expected interface{} + expected any name string }{ {"true", true, "true"}, @@ -30,7 +30,7 @@ func TestLiterals(t *testing.T) { for _, tt := range table { t.Run(tt.name, func(t *testing.T) { output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tt.expected, output) }) @@ -40,7 +40,7 @@ func TestLiterals(t *testing.T) { func TestOperators(t *testing.T) { table := []struct { input string - expected interface{} + expected any name string error string }{ @@ -69,7 +69,7 @@ func TestOperators(t *testing.T) { {`true && false`, false, "and", ""}, {`true || false`, true, "or", ""}, {`fromJSON('{}') && true`, true, "and-boolean-object", ""}, - {`fromJSON('{}') || false`, make(map[string]interface{}), "or-boolean-object", ""}, + {`fromJSON('{}') || false`, make(map[string]any), "or-boolean-object", ""}, {"github.event.commits[0].author.username != github.event.commits[1].author.username", true, "property-comparison1", ""}, {"github.event.commits[0].author.username1 != github.event.commits[1].author.username", true, "property-comparison2", ""}, {"github.event.commits[0].author.username != github.event.commits[1].author.username1", true, "property-comparison3", ""}, @@ -81,15 +81,15 @@ func TestOperators(t *testing.T) { env := &EvaluationEnvironment{ Github: &model.GithubContext{ Action: "push", - Event: map[string]interface{}{ - "commits": []interface{}{ - map[string]interface{}{ - "author": map[string]interface{}{ + Event: map[string]any{ + "commits": []any{ + map[string]any{ + "author": map[string]any{ "username": "someone", }, }, - map[string]interface{}{ - "author": map[string]interface{}{ + map[string]any{ + "author": map[string]any{ "username": "someone-else", }, }, @@ -102,10 +102,10 @@ func TestOperators(t *testing.T) { t.Run(tt.name, func(t *testing.T) { output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone) if tt.error != "" { - assert.NotNil(t, err) + assert.Error(t, err) assert.Equal(t, tt.error, err.Error()) } else { - assert.Nil(t, err) + assert.NoError(t, err) } assert.Equal(t, tt.expected, output) @@ -116,7 +116,7 @@ func TestOperators(t *testing.T) { func TestOperatorsCompare(t *testing.T) { table := []struct { input string - expected interface{} + expected any name string }{ {"!null", true, "not-null"}, @@ -154,7 +154,7 @@ func TestOperatorsCompare(t *testing.T) { for _, tt := range table { t.Run(tt.name, func(t *testing.T) { output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tt.expected, output) }) @@ -164,7 +164,7 @@ func TestOperatorsCompare(t *testing.T) { func TestOperatorsBooleanEvaluation(t *testing.T) { table := []struct { input string - expected interface{} + expected any name string }{ // true && @@ -517,7 +517,7 @@ func TestOperatorsBooleanEvaluation(t *testing.T) { for _, tt := range table { t.Run(tt.name, func(t *testing.T) { output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone) - assert.Nil(t, err) + assert.NoError(t, err) // Normalize int => float64 if i, ok := tt.expected.(int); ok { @@ -536,15 +536,15 @@ func TestOperatorsBooleanEvaluation(t *testing.T) { func TestContexts(t *testing.T) { table := []struct { input string - expected interface{} + expected any name string caseSensitiveEnv bool - ctxdata map[string]interface{} + ctxdata map[string]any }{ {input: "github.action", expected: "push", name: "github-context"}, - {input: "github.action", expected: "push", name: "github-context", ctxdata: map[string]interface{}{"github": map[string]interface{}{"ref": "refs/heads/test-data"}}}, - {input: "github.ref", expected: "refs/heads/test-data", name: "github-context", ctxdata: map[string]interface{}{"github": map[string]interface{}{"ref": "refs/heads/test-data"}}}, - {input: "github.custom-field", expected: "custom-value", name: "github-context", ctxdata: map[string]interface{}{"github": map[string]interface{}{"custom-field": "custom-value"}}}, + {input: "github.action", expected: "push", name: "github-context", ctxdata: map[string]any{"github": map[string]any{"ref": "refs/heads/test-data"}}}, + {input: "github.ref", expected: "refs/heads/test-data", name: "github-context", ctxdata: map[string]any{"github": map[string]any{"ref": "refs/heads/test-data"}}}, + {input: "github.custom-field", expected: "custom-value", name: "github-context", ctxdata: map[string]any{"github": map[string]any{"custom-field": "custom-value"}}}, {input: "github.event.commits[0].message", expected: nil, name: "github-context-noexist-prop"}, {input: "fromjson('{\"commits\":[]}').commits[0].message", expected: nil, name: "github-context-noexist-prop"}, {input: "github.event.pull_request.labels.*.name", expected: nil, name: "github-context-noexist-prop"}, @@ -581,8 +581,8 @@ func TestContexts(t *testing.T) { {input: "contains(needs.*.result, 'success')", expected: true, name: "needs-wildcard-context-contains-success"}, {input: "contains(needs.*.result, 'failure')", expected: false, name: "needs-wildcard-context-contains-failure"}, {input: "inputs.name", expected: "value", name: "inputs-context"}, - {input: "vars.MY_VAR", expected: "refs/heads/test-data", name: "vars-context", ctxdata: map[string]interface{}{"vars": map[string]interface{}{"MY_VAR": "refs/heads/test-data"}}}, - {input: "vars.MY_VAR", expected: "refs/heads/test-data", name: "vars-context", ctxdata: map[string]interface{}{"vars": map[string]interface{}{"my_var": "refs/heads/test-data"}}}, + {input: "vars.MY_VAR", expected: "refs/heads/test-data", name: "vars-context", ctxdata: map[string]any{"vars": map[string]any{"MY_VAR": "refs/heads/test-data"}}}, + {input: "vars.MY_VAR", expected: "refs/heads/test-data", name: "vars-context", ctxdata: map[string]any{"vars": map[string]any{"my_var": "refs/heads/test-data"}}}, } env := EvaluationEnvironment{ @@ -606,7 +606,7 @@ func TestContexts(t *testing.T) { Conclusion: model.StepStatusSkipped, }, }, - Runner: map[string]interface{}{ + Runner: map[string]any{ "os": "Linux", "temp": "/tmp", "tool_cache": "/opt/hostedtoolcache", @@ -617,10 +617,10 @@ func TestContexts(t *testing.T) { Vars: map[string]string{ "name": "value", }, - Strategy: map[string]interface{}{ + Strategy: map[string]any{ "fail-fast": true, }, - Matrix: map[string]interface{}{ + Matrix: map[string]any{ "os": "Linux", }, Needs: map[string]Needs{ @@ -637,7 +637,7 @@ func TestContexts(t *testing.T) { Result: "success", }, }, - Inputs: map[string]interface{}{ + Inputs: map[string]any{ "name": "value", }, } @@ -648,7 +648,7 @@ func TestContexts(t *testing.T) { tenv.EnvCS = tt.caseSensitiveEnv tenv.CtxData = tt.ctxdata output, err := NewInterpeter(&tenv, Config{}).Evaluate(tt.input, DefaultStatusCheckNone) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tt.expected, output) }) diff --git a/pkg/filecollector/file_collector.go b/pkg/filecollector/file_collector.go index c039926b..adb14459 100644 --- a/pkg/filecollector/file_collector.go +++ b/pkg/filecollector/file_collector.go @@ -3,6 +3,7 @@ package filecollector import ( "archive/tar" "context" + "errors" "fmt" "io" "io/fs" @@ -134,7 +135,7 @@ func (fc *FileCollector) CollectFiles(ctx context.Context, submodulePath []strin if ctx != nil { select { case <-ctx.Done(): - return fmt.Errorf("copy cancelled") + return errors.New("copy cancelled") default: } } diff --git a/pkg/filecollector/file_collector_test.go b/pkg/filecollector/file_collector_test.go index 45ec6594..f5726f2b 100644 --- a/pkg/filecollector/file_collector_test.go +++ b/pkg/filecollector/file_collector_test.go @@ -27,7 +27,7 @@ func (mfs *memoryFs) walk(root string, fn filepath.WalkFunc) error { if err != nil { return err } - for i := 0; i < len(dir); i++ { + for i := range dir { filename := filepath.Join(root, dir[i].Name()) err = fn(filename, dir[i], nil) if dir[i].IsDir() { diff --git a/pkg/model/action.go b/pkg/model/action.go index a7d8be2f..595716e6 100644 --- a/pkg/model/action.go +++ b/pkg/model/action.go @@ -12,7 +12,7 @@ import ( // ActionRunsUsing is the type of runner for the action type ActionRunsUsing string -func (a *ActionRunsUsing) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (a *ActionRunsUsing) UnmarshalYAML(unmarshal func(any) error) error { var using string if err := unmarshal(&using); err != nil { return err diff --git a/pkg/model/github_context.go b/pkg/model/github_context.go index 584cae82..135940c3 100644 --- a/pkg/model/github_context.go +++ b/pkg/model/github_context.go @@ -10,39 +10,39 @@ import ( ) type GithubContext struct { - Event map[string]interface{} `json:"event"` - EventPath string `json:"event_path"` - Workflow string `json:"workflow"` - RunAttempt string `json:"run_attempt"` - RunID string `json:"run_id"` - RunNumber string `json:"run_number"` - Actor string `json:"actor"` - Repository string `json:"repository"` - EventName string `json:"event_name"` - Sha string `json:"sha"` - Ref string `json:"ref"` - RefName string `json:"ref_name"` - RefType string `json:"ref_type"` - HeadRef string `json:"head_ref"` - BaseRef string `json:"base_ref"` - Token string `json:"token"` - Workspace string `json:"workspace"` - Action string `json:"action"` - ActionPath string `json:"action_path"` - ActionRef string `json:"action_ref"` - ActionRepository string `json:"action_repository"` - Job string `json:"job"` - JobName string `json:"job_name"` - RepositoryOwner string `json:"repository_owner"` - RetentionDays string `json:"retention_days"` - RunnerPerflog string `json:"runner_perflog"` - RunnerTrackingID string `json:"runner_tracking_id"` - ServerURL string `json:"server_url"` - APIURL string `json:"api_url"` - GraphQLURL string `json:"graphql_url"` + Event map[string]any `json:"event"` + EventPath string `json:"event_path"` + Workflow string `json:"workflow"` + RunAttempt string `json:"run_attempt"` + RunID string `json:"run_id"` + RunNumber string `json:"run_number"` + Actor string `json:"actor"` + Repository string `json:"repository"` + EventName string `json:"event_name"` + Sha string `json:"sha"` + Ref string `json:"ref"` + RefName string `json:"ref_name"` + RefType string `json:"ref_type"` + HeadRef string `json:"head_ref"` + BaseRef string `json:"base_ref"` + Token string `json:"token"` + Workspace string `json:"workspace"` + Action string `json:"action"` + ActionPath string `json:"action_path"` + ActionRef string `json:"action_ref"` + ActionRepository string `json:"action_repository"` + Job string `json:"job"` + JobName string `json:"job_name"` + RepositoryOwner string `json:"repository_owner"` + RetentionDays string `json:"retention_days"` + RunnerPerflog string `json:"runner_perflog"` + RunnerTrackingID string `json:"runner_tracking_id"` + ServerURL string `json:"server_url"` + APIURL string `json:"api_url"` + GraphQLURL string `json:"graphql_url"` } -func asString(v interface{}) string { +func asString(v any) string { if v == nil { return "" } else if s, ok := v.(string); ok { @@ -51,7 +51,7 @@ func asString(v interface{}) string { return "" } -func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{}) { +func nestedMapLookup(m map[string]any, ks ...string) (rval any) { var ok bool if len(ks) == 0 { // degenerate input @@ -61,20 +61,20 @@ func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{}) return nil } else if len(ks) == 1 { // we've reached the final key return rval - } else if m, ok = rval.(map[string]interface{}); !ok { + } else if m, ok = rval.(map[string]any); !ok { return nil } // 1+ more keys return nestedMapLookup(m, ks[1:]...) } -func withDefaultBranch(ctx context.Context, b string, event map[string]interface{}) map[string]interface{} { +func withDefaultBranch(ctx context.Context, b string, event map[string]any) map[string]any { repoI, ok := event["repository"] if !ok { - repoI = make(map[string]interface{}) + repoI = make(map[string]any) } - repo, ok := repoI.(map[string]interface{}) + repo, ok := repoI.(map[string]any) if !ok { common.Logger(ctx).Warnf("unable to set default branch to %v", b) return event @@ -101,19 +101,19 @@ func (ghc *GithubContext) SetRef(ctx context.Context, defaultBranch string, repo // https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads switch ghc.EventName { case "pull_request_target": - ghc.Ref = fmt.Sprintf("refs/heads/%s", ghc.BaseRef) + ghc.Ref = "refs/heads/" + ghc.BaseRef case "pull_request", "pull_request_review", "pull_request_review_comment": ghc.Ref = fmt.Sprintf("refs/pull/%.0f/merge", ghc.Event["number"]) case "deployment", "deployment_status": ghc.Ref = asString(nestedMapLookup(ghc.Event, "deployment", "ref")) case "release": - ghc.Ref = fmt.Sprintf("refs/tags/%s", asString(nestedMapLookup(ghc.Event, "release", "tag_name"))) + ghc.Ref = "refs/tags/" + asString(nestedMapLookup(ghc.Event, "release", "tag_name")) case "push", "create", "workflow_dispatch": ghc.Ref = asString(ghc.Event["ref"]) default: defaultBranch := asString(nestedMapLookup(ghc.Event, "repository", "default_branch")) if defaultBranch != "" { - ghc.Ref = fmt.Sprintf("refs/heads/%s", defaultBranch) + ghc.Ref = "refs/heads/" + defaultBranch } } @@ -134,7 +134,7 @@ func (ghc *GithubContext) SetRef(ctx context.Context, defaultBranch string, repo } if ghc.Ref == "" { - ghc.Ref = fmt.Sprintf("refs/heads/%s", asString(nestedMapLookup(ghc.Event, "repository", "default_branch"))) + ghc.Ref = "refs/heads/" + asString(nestedMapLookup(ghc.Event, "repository", "default_branch")) } } } diff --git a/pkg/model/github_context_test.go b/pkg/model/github_context_test.go index 2fe4603a..bbadbd3b 100644 --- a/pkg/model/github_context_test.go +++ b/pkg/model/github_context_test.go @@ -2,7 +2,7 @@ package model import ( "context" - "fmt" + "errors" "testing" log "github.com/sirupsen/logrus" @@ -27,19 +27,19 @@ func TestSetRef(t *testing.T) { tables := []struct { eventName string - event map[string]interface{} + event map[string]any ref string refName string }{ { eventName: "pull_request_target", - event: map[string]interface{}{}, + event: map[string]any{}, ref: "refs/heads/master", refName: "master", }, { eventName: "pull_request", - event: map[string]interface{}{ + event: map[string]any{ "number": 1234., }, ref: "refs/pull/1234/merge", @@ -47,8 +47,8 @@ func TestSetRef(t *testing.T) { }, { eventName: "deployment", - event: map[string]interface{}{ - "deployment": map[string]interface{}{ + event: map[string]any{ + "deployment": map[string]any{ "ref": "refs/heads/somebranch", }, }, @@ -57,8 +57,8 @@ func TestSetRef(t *testing.T) { }, { eventName: "release", - event: map[string]interface{}{ - "release": map[string]interface{}{ + event: map[string]any{ + "release": map[string]any{ "tag_name": "v1.0.0", }, }, @@ -67,7 +67,7 @@ func TestSetRef(t *testing.T) { }, { eventName: "push", - event: map[string]interface{}{ + event: map[string]any{ "ref": "refs/heads/somebranch", }, ref: "refs/heads/somebranch", @@ -75,8 +75,8 @@ func TestSetRef(t *testing.T) { }, { eventName: "unknown", - event: map[string]interface{}{ - "repository": map[string]interface{}{ + event: map[string]any{ + "repository": map[string]any{ "default_branch": "main", }, }, @@ -85,7 +85,7 @@ func TestSetRef(t *testing.T) { }, { eventName: "no-event", - event: map[string]interface{}{}, + event: map[string]any{}, ref: "refs/heads/master", refName: "master", }, @@ -109,12 +109,12 @@ func TestSetRef(t *testing.T) { t.Run("no-default-branch", func(t *testing.T) { findGitRef = func(_ context.Context, _ string) (string, error) { - return "", fmt.Errorf("no default branch") + return "", errors.New("no default branch") } ghc := &GithubContext{ EventName: "no-default-branch", - Event: map[string]interface{}{}, + Event: map[string]any{}, } ghc.SetRef(context.Background(), "", "/some/dir") @@ -141,14 +141,14 @@ func TestSetSha(t *testing.T) { tables := []struct { eventName string - event map[string]interface{} + event map[string]any sha string }{ { eventName: "pull_request_target", - event: map[string]interface{}{ - "pull_request": map[string]interface{}{ - "base": map[string]interface{}{ + event: map[string]any{ + "pull_request": map[string]any{ + "base": map[string]any{ "sha": "pr-base-sha", }, }, @@ -157,15 +157,15 @@ func TestSetSha(t *testing.T) { }, { eventName: "pull_request", - event: map[string]interface{}{ + event: map[string]any{ "number": 1234., }, sha: "1234fakesha", }, { eventName: "deployment", - event: map[string]interface{}{ - "deployment": map[string]interface{}{ + event: map[string]any{ + "deployment": map[string]any{ "sha": "deployment-sha", }, }, @@ -173,12 +173,12 @@ func TestSetSha(t *testing.T) { }, { eventName: "release", - event: map[string]interface{}{}, + event: map[string]any{}, sha: "1234fakesha", }, { eventName: "push", - event: map[string]interface{}{ + event: map[string]any{ "after": "push-sha", "deleted": false, }, @@ -186,12 +186,12 @@ func TestSetSha(t *testing.T) { }, { eventName: "unknown", - event: map[string]interface{}{}, + event: map[string]any{}, sha: "1234fakesha", }, { eventName: "no-event", - event: map[string]interface{}{}, + event: map[string]any{}, sha: "1234fakesha", }, } diff --git a/pkg/model/planner.go b/pkg/model/planner.go index a70497e4..d4327524 100644 --- a/pkg/model/planner.go +++ b/pkg/model/planner.go @@ -8,7 +8,7 @@ import ( "os" "path/filepath" "regexp" - "sort" + "slices" log "github.com/sirupsen/logrus" ) @@ -288,11 +288,8 @@ func (wp *workflowPlanner) GetEvents() []string { for _, w := range wp.workflows { found := false for _, e := range events { - for _, we := range w.On() { - if e == we { - found = true - break - } + if slices.Contains(w.On(), e) { + found = true } if found { break @@ -305,9 +302,7 @@ func (wp *workflowPlanner) GetEvents() []string { } // sort the list based on depth of dependencies - sort.Slice(events, func(i, j int) bool { - return events[i] < events[j] - }) + slices.Sort(events) return events } @@ -338,7 +333,7 @@ func (s *Stage) GetJobIDs() []string { // Merge stages with existing stages in plan func (p *Plan) mergeStages(stages []*Stage) { newStages := make([]*Stage, int(math.Max(float64(len(p.Stages)), float64(len(stages))))) - for i := 0; i < len(newStages); i++ { + for i := range newStages { newStages[i] = new(Stage) if i >= len(p.Stages) { newStages[i].Runs = append(newStages[i].Runs, stages[i].Runs...) diff --git a/pkg/model/planner_test.go b/pkg/model/planner_test.go index aab5c045..4e42195f 100644 --- a/pkg/model/planner_test.go +++ b/pkg/model/planner_test.go @@ -55,6 +55,6 @@ func TestWorkflow(t *testing.T) { // Check that a valid job id returns non-error result, err := createStages(&workflow, "valid_job") - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, result) } diff --git a/pkg/model/workflow.go b/pkg/model/workflow.go index 95bc12f7..346efcf5 100644 --- a/pkg/model/workflow.go +++ b/pkg/model/workflow.go @@ -4,8 +4,10 @@ import ( "errors" "fmt" "io" + "maps" "reflect" "regexp" + "slices" "strconv" "strings" @@ -61,7 +63,7 @@ func (w *Workflow) On() []string { } return val case yaml.MappingNode: - var val map[string]interface{} + var val map[string]any err := w.RawOn.Decode(&val) if err != nil { log.Fatal(err) @@ -75,9 +77,9 @@ func (w *Workflow) On() []string { return nil } -func (w *Workflow) OnEvent(event string) interface{} { +func (w *Workflow) OnEvent(event string) any { if w.RawOn.Kind == yaml.MappingNode { - var val map[string]interface{} + var val map[string]any if !decodeNode(w.RawOn, &val) { return nil } @@ -128,10 +130,8 @@ func (w *Workflow) WorkflowDispatchConfig() *WorkflowDispatch { if !decodeNode(w.RawOn, &val) { return nil } - for _, v := range val { - if v == "workflow_dispatch" { - return &WorkflowDispatch{} - } + if slices.Contains(val, "workflow_dispatch") { + return &WorkflowDispatch{} } case yaml.MappingNode: var val map[string]yaml.Node @@ -206,7 +206,7 @@ type Job struct { Defaults Defaults `yaml:"defaults"` Outputs map[string]string `yaml:"outputs"` Uses string `yaml:"uses"` - With map[string]interface{} `yaml:"with"` + With map[string]any `yaml:"with"` RawSecrets yaml.Node `yaml:"secrets"` Result string } @@ -384,9 +384,9 @@ func (j *Job) Environment() map[string]string { } // Matrix decodes RawMatrix YAML node -func (j *Job) Matrix() map[string][]interface{} { +func (j *Job) Matrix() map[string][]any { if j.Strategy.RawMatrix.Kind == yaml.MappingNode { - var val map[string][]interface{} + var val map[string][]any if !decodeNode(j.Strategy.RawMatrix, &val) { return nil } @@ -397,32 +397,32 @@ func (j *Job) Matrix() map[string][]interface{} { // GetMatrixes returns the matrix cross product // It skips includes and hard fails excludes for non-existing keys -func (j *Job) GetMatrixes() ([]map[string]interface{}, error) { - matrixes := make([]map[string]interface{}, 0) +func (j *Job) GetMatrixes() ([]map[string]any, error) { + matrixes := make([]map[string]any, 0) if j.Strategy != nil { j.Strategy.FailFast = j.Strategy.GetFailFast() j.Strategy.MaxParallel = j.Strategy.GetMaxParallel() if m := j.Matrix(); m != nil { - includes := make([]map[string]interface{}, 0) - extraIncludes := make([]map[string]interface{}, 0) + includes := make([]map[string]any, 0) + extraIncludes := make([]map[string]any, 0) for _, v := range m["include"] { switch t := v.(type) { - case []interface{}: + case []any: for _, i := range t { - i := i.(map[string]interface{}) + i := i.(map[string]any) includes = append(includes, i) } - case interface{}: - v := v.(map[string]interface{}) + case any: + v := v.(map[string]any) includes = append(includes, v) } } delete(m, "include") - excludes := make([]map[string]interface{}, 0) + excludes := make([]map[string]any, 0) for _, e := range m["exclude"] { - e := e.(map[string]interface{}) + e := e.(map[string]any) for k := range e { if _, ok := m[k]; ok { excludes = append(excludes, e) @@ -451,9 +451,7 @@ func (j *Job) GetMatrixes() ([]map[string]interface{}, error) { if commonKeysMatch2(matrix, include, m) { matched = true log.Debugf("Adding include values '%v' to existing entry", include) - for k, v := range include { - matrix[k] = v - } + maps.Copy(matrix, include) } } if !matched { @@ -465,19 +463,19 @@ func (j *Job) GetMatrixes() ([]map[string]interface{}, error) { matrixes = append(matrixes, include) } if len(matrixes) == 0 { - matrixes = append(matrixes, make(map[string]interface{})) + matrixes = append(matrixes, make(map[string]any)) } } else { - matrixes = append(matrixes, make(map[string]interface{})) + matrixes = append(matrixes, make(map[string]any)) } } else { - matrixes = append(matrixes, make(map[string]interface{})) + matrixes = append(matrixes, make(map[string]any)) log.Debugf("Empty Strategy, matrixes=%v", matrixes) } return matrixes, nil } -func commonKeysMatch(a map[string]interface{}, b map[string]interface{}) bool { +func commonKeysMatch(a map[string]any, b map[string]any) bool { for aKey, aVal := range a { if bVal, ok := b[aKey]; ok && !reflect.DeepEqual(aVal, bVal) { return false @@ -486,7 +484,7 @@ func commonKeysMatch(a map[string]interface{}, b map[string]interface{}) bool { return true } -func commonKeysMatch2(a map[string]interface{}, b map[string]interface{}, m map[string][]interface{}) bool { +func commonKeysMatch2(a map[string]any, b map[string]any, m map[string][]any) bool { for aKey, aVal := range a { _, useKey := m[aKey] if bVal, ok := b[aKey]; useKey && ok && !reflect.DeepEqual(aVal, bVal) { @@ -604,7 +602,7 @@ func (s *Step) GetEnv() map[string]string { for k, v := range s.With { envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(k), "_") - envKey = fmt.Sprintf("INPUT_%s", strings.ToUpper(envKey)) + envKey = "INPUT_" + strings.ToUpper(envKey) env[envKey] = v } return env @@ -752,11 +750,11 @@ func (w *Workflow) GetJobIDs() []string { return ids } -var OnDecodeNodeError = func(node yaml.Node, out interface{}, err error) { +var OnDecodeNodeError = func(node yaml.Node, out any, err error) { log.Fatalf("Failed to decode node %v into %T: %v", node, out, err) } -func decodeNode(node yaml.Node, out interface{}) bool { +func decodeNode(node yaml.Node, out any) bool { if err := node.Decode(out); err != nil { if OnDecodeNodeError != nil { OnDecodeNodeError(node, out, err) diff --git a/pkg/model/workflow_test.go b/pkg/model/workflow_test.go index 339a9e87..2d487016 100644 --- a/pkg/model/workflow_test.go +++ b/pkg/model/workflow_test.go @@ -87,7 +87,7 @@ jobs: workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{}) assert.NoError(t, err, "read workflow should succeed") - assert.Equal(t, workflow.Jobs["test"].RunsOn(), []string{"ubuntu-latest"}) + assert.Equal(t, []string{"ubuntu-latest"}, workflow.Jobs["test"].RunsOn()) } func TestReadWorkflow_RunsOnLabelsWithGroup(t *testing.T) { @@ -105,7 +105,7 @@ jobs: workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{}) assert.NoError(t, err, "read workflow should succeed") - assert.Equal(t, workflow.Jobs["test"].RunsOn(), []string{"ubuntu-latest", "linux"}) + assert.Equal(t, []string{"ubuntu-latest", "linux"}, workflow.Jobs["test"].RunsOn()) } func TestReadWorkflow_StringContainer(t *testing.T) { @@ -201,27 +201,27 @@ jobs: assert.Len(t, workflow.Jobs, 6) jobType, err := workflow.Jobs["default-job"].Type() - assert.Equal(t, nil, err) + assert.NoError(t, err) assert.Equal(t, JobTypeDefault, jobType) jobType, err = workflow.Jobs["remote-reusable-workflow-yml"].Type() - assert.Equal(t, nil, err) + assert.NoError(t, err) assert.Equal(t, JobTypeReusableWorkflowRemote, jobType) jobType, err = workflow.Jobs["remote-reusable-workflow-yaml"].Type() - assert.Equal(t, nil, err) + assert.NoError(t, err) assert.Equal(t, JobTypeReusableWorkflowRemote, jobType) jobType, err = workflow.Jobs["remote-reusable-workflow-custom-path"].Type() - assert.Equal(t, nil, err) + assert.NoError(t, err) assert.Equal(t, JobTypeReusableWorkflowRemote, jobType) jobType, err = workflow.Jobs["local-reusable-workflow-yml"].Type() - assert.Equal(t, nil, err) + assert.NoError(t, err) assert.Equal(t, JobTypeReusableWorkflowLocal, jobType) jobType, err = workflow.Jobs["local-reusable-workflow-yaml"].Type() - assert.Equal(t, nil, err) + assert.NoError(t, err) assert.Equal(t, JobTypeReusableWorkflowLocal, jobType) } @@ -246,19 +246,19 @@ jobs: jobType, err := workflow.Jobs["remote-reusable-workflow-missing-version"].Type() assert.Equal(t, JobTypeInvalid, jobType) - assert.NotEqual(t, nil, err) + assert.Error(t, err) jobType, err = workflow.Jobs["remote-reusable-workflow-bad-extension"].Type() assert.Equal(t, JobTypeInvalid, jobType) - assert.NotEqual(t, nil, err) + assert.Error(t, err) jobType, err = workflow.Jobs["local-reusable-workflow-bad-extension"].Type() assert.Equal(t, JobTypeInvalid, jobType) - assert.NotEqual(t, nil, err) + assert.Error(t, err) jobType, err = workflow.Jobs["local-reusable-workflow-bad-path"].Type() assert.Equal(t, JobTypeInvalid, jobType) - assert.NotEqual(t, nil, err) + assert.Error(t, err) } func TestReadWorkflow_StepsTypes(t *testing.T) { @@ -335,71 +335,69 @@ func TestReadWorkflow_Strategy(t *testing.T) { p, err := w.PlanJob("strategy-only-max-parallel") assert.NoError(t, err) - assert.Equal(t, len(p.Stages), 1) - assert.Equal(t, len(p.Stages[0].Runs), 1) + assert.Len(t, p.Stages, 1) + assert.Len(t, p.Stages[0].Runs, 1) wf := p.Stages[0].Runs[0].Workflow job := wf.Jobs["strategy-only-max-parallel"] matrixes, err := job.GetMatrixes() assert.NoError(t, err) - assert.Equal(t, matrixes, []map[string]interface{}{{}}) - assert.Equal(t, job.Matrix(), map[string][]interface{}(nil)) - assert.Equal(t, job.Strategy.MaxParallel, 2) - assert.Equal(t, job.Strategy.FailFast, true) + assert.Equal(t, []map[string]any{{}}, matrixes) + assert.Equal(t, job.Matrix(), map[string][]any(nil)) + assert.Equal(t, 2, job.Strategy.MaxParallel) + assert.True(t, job.Strategy.FailFast) job = wf.Jobs["strategy-only-fail-fast"] matrixes, err = job.GetMatrixes() assert.NoError(t, err) - assert.Equal(t, matrixes, []map[string]interface{}{{}}) - assert.Equal(t, job.Matrix(), map[string][]interface{}(nil)) - assert.Equal(t, job.Strategy.MaxParallel, 4) - assert.Equal(t, job.Strategy.FailFast, false) + assert.Equal(t, []map[string]any{{}}, matrixes) + assert.Equal(t, job.Matrix(), map[string][]any(nil)) + assert.Equal(t, 4, job.Strategy.MaxParallel) + assert.False(t, job.Strategy.FailFast) job = wf.Jobs["strategy-no-matrix"] matrixes, err = job.GetMatrixes() assert.NoError(t, err) - assert.Equal(t, matrixes, []map[string]interface{}{{}}) - assert.Equal(t, job.Matrix(), map[string][]interface{}(nil)) - assert.Equal(t, job.Strategy.MaxParallel, 2) - assert.Equal(t, job.Strategy.FailFast, false) + assert.Equal(t, []map[string]any{{}}, matrixes) + assert.Equal(t, job.Matrix(), map[string][]any(nil)) + assert.Equal(t, 2, job.Strategy.MaxParallel) + assert.False(t, job.Strategy.FailFast) job = wf.Jobs["strategy-all"] matrixes, err = job.GetMatrixes() assert.NoError(t, err) - assert.Equal(t, matrixes, - []map[string]interface{}{ - {"datacenter": "site-c", "node-version": "14.x", "site": "staging", "php-version": 5.4}, - {"datacenter": "site-c", "node-version": "16.x", "site": "staging", "php-version": 5.4}, - {"datacenter": "site-d", "node-version": "16.x", "site": "staging", "php-version": 5.4}, - {"datacenter": "site-a", "node-version": "10.x", "site": "prod"}, - {"datacenter": "site-b", "node-version": "12.x", "site": "dev"}, - }, + assert.Equal(t, []map[string]any{ + {"datacenter": "site-c", "node-version": "14.x", "site": "staging", "php-version": 5.4}, + {"datacenter": "site-c", "node-version": "16.x", "site": "staging", "php-version": 5.4}, + {"datacenter": "site-d", "node-version": "16.x", "site": "staging", "php-version": 5.4}, + {"datacenter": "site-a", "node-version": "10.x", "site": "prod"}, + {"datacenter": "site-b", "node-version": "12.x", "site": "dev"}, + }, matrixes, ) - assert.Equal(t, job.Matrix(), - map[string][]interface{}{ - "datacenter": {"site-c", "site-d"}, - "exclude": { - map[string]interface{}{"datacenter": "site-d", "node-version": "14.x", "site": "staging"}, - }, - "include": { - map[string]interface{}{"php-version": 5.4}, - map[string]interface{}{"datacenter": "site-a", "node-version": "10.x", "site": "prod"}, - map[string]interface{}{"datacenter": "site-b", "node-version": "12.x", "site": "dev"}, - }, - "node-version": {"14.x", "16.x"}, - "site": {"staging"}, + assert.Equal(t, map[string][]any{ + "datacenter": {"site-c", "site-d"}, + "exclude": { + map[string]any{"datacenter": "site-d", "node-version": "14.x", "site": "staging"}, }, + "include": { + map[string]any{"php-version": 5.4}, + map[string]any{"datacenter": "site-a", "node-version": "10.x", "site": "prod"}, + map[string]any{"datacenter": "site-b", "node-version": "12.x", "site": "dev"}, + }, + "node-version": {"14.x", "16.x"}, + "site": {"staging"}, + }, job.Matrix(), ) - assert.Equal(t, job.Strategy.MaxParallel, 2) - assert.Equal(t, job.Strategy.FailFast, false) + assert.Equal(t, 2, job.Strategy.MaxParallel) + assert.False(t, job.Strategy.FailFast) } func TestMatrixOnlyIncludes(t *testing.T) { - matrix := map[string][]interface{}{ - "include": []interface{}{ - map[string]interface{}{"a": "1", "b": "2"}, - map[string]interface{}{"a": "3", "b": "4"}, + matrix := map[string][]any{ + "include": []any{ + map[string]any{"a": "1", "b": "2"}, + map[string]any{"a": "3", "b": "4"}, }, } rN := yaml.Node{} @@ -413,11 +411,10 @@ func TestMatrixOnlyIncludes(t *testing.T) { assert.Equal(t, job.Matrix(), matrix) matrixes, err := job.GetMatrixes() require.NoError(t, err) - assert.Equal(t, matrixes, - []map[string]interface{}{ - {"a": "1", "b": "2"}, - {"a": "3", "b": "4"}, - }, + assert.Equal(t, []map[string]any{ + {"a": "1", "b": "2"}, + {"a": "3", "b": "4"}, + }, matrixes, ) } @@ -436,7 +433,7 @@ func TestStep_ShellCommand(t *testing.T) { for _, tt := range tests { t.Run(tt.shell, func(t *testing.T) { got := (&Step{Shell: tt.shell, WorkflowShell: tt.workflowShell}).ShellCommand() - assert.Equal(t, got, tt.want) + assert.Equal(t, tt.want, got) }) } } diff --git a/pkg/runner/action.go b/pkg/runner/action.go index 85af576f..f773fecb 100644 --- a/pkg/runner/action.go +++ b/pkg/runner/action.go @@ -154,14 +154,14 @@ func execAsDocker(ctx context.Context, step actionStep, actionName, subpath stri var prepImage common.Executor var image string forcePull := false - if strings.HasPrefix(action.Runs.Image, "docker://") { - image = strings.TrimPrefix(action.Runs.Image, "docker://") + if after, ok := strings.CutPrefix(action.Runs.Image, "docker://"); ok { + image = after // Apply forcePull only for prebuild docker images forcePull = rc.Config.ForcePull } else { // "-dockeraction" ensures that "./", "./test " won't get converted to "act-:latest", "act-test-:latest" which are invalid docker image names image = fmt.Sprintf("%s-dockeraction:%s", regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(actionName, "-"), "latest") - image = fmt.Sprintf("act-%s", strings.TrimLeft(image, "-")) + image = "act-" + strings.TrimLeft(image, "-") image = strings.ToLower(image) contextDir, fileName := path.Split(path.Join(subpath, action.Runs.Image)) @@ -298,7 +298,7 @@ func newStepContainer(ctx context.Context, step step, image string, cmd []string envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TEMP", "/tmp")) binds, mounts := rc.GetBindsAndMounts() - networkMode := fmt.Sprintf("container:%s", rc.jobContainerName()) + networkMode := "container:" + rc.jobContainerName() var workdir string if rc.IsHostEnv(ctx) { networkMode = "default" @@ -333,7 +333,7 @@ func populateEnvsFromSavedState(env *map[string]string, step actionStep, rc *Run state, ok := rc.IntraActionState[step.getStepModel().ID] if ok { for name, value := range state { - envName := fmt.Sprintf("STATE_%s", name) + envName := "STATE_" + name (*env)[envName] = value } } @@ -343,7 +343,7 @@ func populateEnvsFromInput(ctx context.Context, env *map[string]string, action * eval := rc.NewExpressionEvaluator(ctx) for inputID, input := range action.Inputs { envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(inputID), "_") - envKey = fmt.Sprintf("INPUT_%s", envKey) + envKey = "INPUT_" + envKey if _, ok := (*env)[envKey]; !ok { (*env)[envKey] = eval.Interpolate(ctx, input.Default) } @@ -429,7 +429,7 @@ func runPreStep(step actionStep) common.Executor { if steps := step.getCompositeSteps(); steps != nil && steps.pre != nil { return steps.pre(ctx) } - return fmt.Errorf("missing steps in composite action") + return errors.New("missing steps in composite action") default: return nil @@ -512,7 +512,7 @@ func runPostStep(step actionStep) common.Executor { if steps := step.getCompositeSteps(); steps != nil && steps.post != nil { return steps.post(ctx) } - return fmt.Errorf("missing steps in composite action") + return errors.New("missing steps in composite action") default: return nil diff --git a/pkg/runner/action_composite.go b/pkg/runner/action_composite.go index bb481ecd..fa3ae253 100644 --- a/pkg/runner/action_composite.go +++ b/pkg/runner/action_composite.go @@ -2,8 +2,9 @@ package runner import ( "context" - "fmt" + "errors" "regexp" + "strconv" "strings" "gitea.com/gitea/act_runner/pkg/common" @@ -25,7 +26,7 @@ func evaluateCompositeInputAndEnv(ctx context.Context, parent *RunContext, step for inputID, input := range step.getActionModel().Inputs { envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(inputID), "_") - envKey = fmt.Sprintf("INPUT_%s", strings.ToUpper(envKey)) + envKey = "INPUT_" + strings.ToUpper(envKey) // lookup if key is defined in the step but the already // evaluated value from the environment @@ -77,7 +78,7 @@ func newCompositeRunContext(ctx context.Context, parent *RunContext, step action nodeToolFullPath: parent.nodeToolFullPath, } if parent.ContextData != nil { - compositerc.ContextData = map[string]interface{}{} + compositerc.ContextData = map[string]any{} for k, v := range parent.ContextData { if !strings.EqualFold("inputs", k) { compositerc.ContextData[k] = v @@ -99,7 +100,7 @@ func execAsComposite(step actionStep) common.Executor { steps := step.getCompositeSteps() if steps == nil || steps.main == nil { - return fmt.Errorf("missing steps in composite action") + return errors.New("missing steps in composite action") } ctx = WithCompositeLogger(ctx, &compositeRC.Masks) @@ -147,7 +148,7 @@ func (rc *RunContext) compositeExecutor(action *model.Action) *compositeSteps { for i, step := range action.Runs.Steps { if step.ID == "" { - step.ID = fmt.Sprintf("%d", i) + step.ID = strconv.Itoa(i) } // create a copy of the step, since this composite action could diff --git a/pkg/runner/action_test.go b/pkg/runner/action_test.go index 8e9e907c..07e72f38 100644 --- a/pkg/runner/action_test.go +++ b/pkg/runner/action_test.go @@ -99,7 +99,7 @@ runs: action, err := readActionImpl(context.Background(), tt.step, readFile, model.ActionConfig{}) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tt.expected, action) closerMock.AssertExpectations(t) @@ -218,7 +218,7 @@ func TestActionRunner(t *testing.T) { err := runActionImpl(tt.step)(ctx) - assert.Nil(t, err) + assert.NoError(t, err) cm.AssertExpectations(t) }) } diff --git a/pkg/runner/command.go b/pkg/runner/command.go index 7a31c1e0..41a32fa5 100644 --- a/pkg/runner/command.go +++ b/pkg/runner/command.go @@ -133,8 +133,8 @@ func (rc *RunContext) addPath(ctx context.Context, arg string) { func parseKeyValuePairs(kvPairs string, separator string) map[string]string { rtn := make(map[string]string) - kvPairList := strings.Split(kvPairs, separator) - for _, kvPair := range kvPairList { + kvPairList := strings.SplitSeq(kvPairs, separator) + for kvPair := range kvPairList { kv := strings.Split(kvPair, "=") if len(kv) == 2 { rtn[kv[0]] = kv[1] diff --git a/pkg/runner/command_test.go b/pkg/runner/command_test.go index 314077fd..0288afc6 100644 --- a/pkg/runner/command_test.go +++ b/pkg/runner/command_test.go @@ -164,7 +164,7 @@ func TestAddmaskUsemask(t *testing.T) { re := captureOutput(t, func() { ctx := context.Background() - ctx = WithJobLogger(ctx, "0", "testjob", config, &rc.Masks, map[string]interface{}{}) + ctx = WithJobLogger(ctx, "0", "testjob", config, &rc.Masks, map[string]any{}) handler := rc.commandHandler(ctx) handler("::add-mask::secret\n") diff --git a/pkg/runner/expression.go b/pkg/runner/expression.go index 976e87dc..fe706125 100644 --- a/pkg/runner/expression.go +++ b/pkg/runner/expression.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "maps" "path" "reflect" "regexp" @@ -21,7 +22,7 @@ import ( // ExpressionEvaluator is the interface for evaluating expressions type ExpressionEvaluator interface { - evaluate(context.Context, string, exprparser.DefaultStatusCheck) (interface{}, error) + evaluate(context.Context, string, exprparser.DefaultStatusCheck) (any, error) EvaluateYamlNode(context.Context, *yaml.Node) error Interpolate(context.Context, string) string } @@ -36,7 +37,7 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map // todo: cleanup EvaluationEnvironment creation using := make(map[string]exprparser.Needs) - strategy := make(map[string]interface{}) + strategy := make(map[string]any) if rc.Run != nil { job := rc.Run.Job() if job != nil && job.Strategy != nil { @@ -64,9 +65,7 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map result := model.WorkflowCallResult{ Outputs: map[string]string{}, } - for k, v := range job.Outputs { - result.Outputs[k] = v - } + maps.Copy(result.Outputs, job.Outputs) workflowCallResult[jobName] = &result } } @@ -123,10 +122,10 @@ func (rc *RunContext) NewStepExpressionEvaluatorExt(ctx context.Context, step st return rc.newStepExpressionEvaluator(ctx, step, ghc, getEvaluatorInputs(ctx, rc, step, ghc)) } -func (rc *RunContext) newStepExpressionEvaluator(ctx context.Context, step step, _ *model.GithubContext, inputs map[string]interface{}) ExpressionEvaluator { +func (rc *RunContext) newStepExpressionEvaluator(ctx context.Context, step step, _ *model.GithubContext, inputs map[string]any) ExpressionEvaluator { // todo: cleanup EvaluationEnvironment creation job := rc.Run.Job() - strategy := make(map[string]interface{}) + strategy := make(map[string]any) if job.Strategy != nil { strategy["fail-fast"] = job.Strategy.FailFast strategy["max-parallel"] = job.Strategy.MaxParallel @@ -173,8 +172,8 @@ func (rc *RunContext) newStepExpressionEvaluator(ctx context.Context, step step, } } -func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect.Value) (interface{}, error) { - hashFiles := func(v []reflect.Value) (interface{}, error) { +func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect.Value) (any, error) { + hashFiles := func(v []reflect.Value) (any, error) { if rc.JobContainer != nil { timeed, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() @@ -198,9 +197,7 @@ func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect. patterns = append(patterns, s) } env := map[string]string{} - for k, v := range rc.Env { - env[k] = v - } + maps.Copy(env, rc.Env) env["patterns"] = strings.Join(patterns, "\n") if followSymlink { env["followSymbolicLinks"] = "true" @@ -238,7 +235,7 @@ type expressionEvaluator struct { interpreter exprparser.Interpreter } -func (ee expressionEvaluator) evaluate(ctx context.Context, in string, defaultStatusCheck exprparser.DefaultStatusCheck) (interface{}, error) { +func (ee expressionEvaluator) evaluate(ctx context.Context, in string, defaultStatusCheck exprparser.DefaultStatusCheck) (any, error) { logger := common.Logger(ctx) logger.Debugf("evaluating expression '%s'", in) evaluated, err := ee.interpreter.Evaluate(in, defaultStatusCheck) @@ -485,8 +482,8 @@ func rewriteSubExpression(ctx context.Context, in string, forceFormat bool) (str return out, nil } -func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *model.GithubContext) map[string]interface{} { - inputs := map[string]interface{}{} +func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *model.GithubContext) map[string]any { + inputs := map[string]any{} setupWorkflowInputs(ctx, &inputs, rc) @@ -498,8 +495,8 @@ func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *mod } for k, v := range env { - if strings.HasPrefix(k, "INPUT_") { - inputs[strings.ToLower(strings.TrimPrefix(k, "INPUT_"))] = v + if after, ok := strings.CutPrefix(k, "INPUT_"); ok { + inputs[strings.ToLower(after)] = v } } @@ -523,7 +520,7 @@ func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *mod return inputs } -func setupWorkflowInputs(ctx context.Context, inputs *map[string]interface{}, rc *RunContext) { +func setupWorkflowInputs(ctx context.Context, inputs *map[string]any, rc *RunContext) { if rc.caller != nil { config := rc.Run.Workflow.WorkflowCallConfig() diff --git a/pkg/runner/expression_test.go b/pkg/runner/expression_test.go index ec78f24f..dc33c323 100644 --- a/pkg/runner/expression_test.go +++ b/pkg/runner/expression_test.go @@ -6,6 +6,7 @@ import ( "os" "regexp" "sort" + "strings" "testing" "gitea.com/gitea/act_runner/pkg/exprparser" @@ -16,7 +17,7 @@ import ( func createRunContext(t *testing.T) *RunContext { var yml yaml.Node - err := yml.Encode(map[string][]interface{}{ + err := yml.Encode(map[string][]any{ "os": {"Linux", "Windows"}, "foo": {"bar", "baz"}, }) @@ -48,7 +49,7 @@ func createRunContext(t *testing.T) *RunContext { }, }, }, - Matrix: map[string]interface{}{ + Matrix: map[string]any{ "os": "Linux", "foo": "bar", }, @@ -84,7 +85,7 @@ func TestEvaluateRunContext(t *testing.T) { tables := []struct { in string - out interface{} + out any errMesg string }{ {" 1 ", 1, ""}, @@ -165,7 +166,7 @@ func TestEvaluateStep(t *testing.T) { tables := []struct { in string - out interface{} + out any errMesg string }{ {"steps.idwithnothing.conclusion", model.StepStatusSuccess.String(), ""}, @@ -281,9 +282,11 @@ func updateTestExpressionWorkflow(t *testing.T, tables []struct { keys = append(keys, k) } sort.Strings(keys) + var envsSb284 strings.Builder for _, k := range keys { - envs += fmt.Sprintf(" %s: %s\n", k, rc.Env[k]) + fmt.Fprintf(&envsSb284, " %s: %s\n", k, rc.Env[k]) } + envs += envsSb284.String() // editorconfig-checker-disable workflow := fmt.Sprintf(` @@ -299,6 +302,7 @@ jobs: steps: `, envs) // editorconfig-checker-enable + var workflowSb302 strings.Builder for _, table := range tables { expressionPattern := regexp.MustCompile(`\${{\s*(.+?)\s*}}`) @@ -307,8 +311,9 @@ jobs: }) name := fmt.Sprintf(`%s -> %s should be equal to %s`, expr, table.in, table.out) echo := `run: echo "Done "` - workflow += fmt.Sprintf("\n - name: %s\n %s\n", name, echo) + fmt.Fprintf(&workflowSb302, "\n - name: %s\n %s\n", name, echo) } + workflow += workflowSb302.String() file, err := os.Create("../../.github/workflows/test-expressions.yml") if err != nil { diff --git a/pkg/runner/job_executor.go b/pkg/runner/job_executor.go index 3752f553..c0086151 100644 --- a/pkg/runner/job_executor.go +++ b/pkg/runner/job_executor.go @@ -3,6 +3,7 @@ package runner import ( "context" "fmt" + "strconv" "time" "gitea.com/gitea/act_runner/pkg/common" @@ -10,7 +11,7 @@ import ( ) type jobInfo interface { - matrix() map[string]interface{} + matrix() map[string]any steps() []*model.Step startContainer() common.Executor stopContainer() common.Executor @@ -70,7 +71,7 @@ func newJobExecutor(info jobInfo, sf stepFactory, rc *RunContext) common.Executo } } if stepModel.ID == "" { - stepModel.ID = fmt.Sprintf("%d", i) + stepModel.ID = strconv.Itoa(i) } step, err := sf.newStep(stepModel, rc) diff --git a/pkg/runner/job_executor_test.go b/pkg/runner/job_executor_test.go index ce815d1c..21ffc3ec 100644 --- a/pkg/runner/job_executor_test.go +++ b/pkg/runner/job_executor_test.go @@ -2,8 +2,10 @@ package runner import ( "context" + "errors" "fmt" "io" + "slices" "testing" "gitea.com/gitea/act_runner/pkg/common" @@ -38,9 +40,9 @@ type jobInfoMock struct { mock.Mock } -func (jim *jobInfoMock) matrix() map[string]interface{} { +func (jim *jobInfoMock) matrix() map[string]any { args := jim.Called() - return args.Get(0).(map[string]interface{}) + return args.Get(0).(map[string]any) } func (jim *jobInfoMock) steps() []*model.Step { @@ -232,12 +234,7 @@ func TestNewJobExecutor(t *testing.T) { } contains := func(needle string, haystack []string) bool { - for _, item := range haystack { - if item == needle { - return true - } - } - return false + return slices.Contains(haystack, needle) } for _, tt := range table { @@ -287,7 +284,7 @@ func TestNewJobExecutor(t *testing.T) { sm.On("main").Return(func(_ context.Context) error { executorOrder = append(executorOrder, "step"+stepModel.ID) if tt.hasError { - return fmt.Errorf("error") + return errors.New("error") } return nil }) @@ -303,7 +300,7 @@ func TestNewJobExecutor(t *testing.T) { } if len(tt.steps) > 0 { - jim.On("matrix").Return(map[string]interface{}{}) + jim.On("matrix").Return(map[string]any{}) jim.On("interpolateOutputs").Return(func(_ context.Context) error { executorOrder = append(executorOrder, "interpolateOutputs") @@ -327,7 +324,7 @@ func TestNewJobExecutor(t *testing.T) { executor := newJobExecutor(jim, sfm, rc) err := executor(ctx) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tt.executedSteps, executorOrder) jim.AssertExpectations(t) diff --git a/pkg/runner/logger.go b/pkg/runner/logger.go index b27c2d1d..156a9bb9 100644 --- a/pkg/runner/logger.go +++ b/pkg/runner/logger.go @@ -70,7 +70,7 @@ func WithJobLoggerFactory(ctx context.Context, factory JobLoggerFactory) context } // WithJobLogger attaches a new logger to context that is aware of steps -func WithJobLogger(ctx context.Context, jobID string, jobName string, config *Config, masks *[]string, matrix map[string]interface{}) context.Context { +func WithJobLogger(ctx context.Context, jobID string, jobName string, config *Config, masks *[]string, matrix map[string]any) context.Context { ctx = WithMasks(ctx, masks) var logger *logrus.Logger diff --git a/pkg/runner/reusable_workflow.go b/pkg/runner/reusable_workflow.go index 8bbdfcfa..54865003 100644 --- a/pkg/runner/reusable_workflow.go +++ b/pkg/runner/reusable_workflow.go @@ -40,7 +40,7 @@ func newActionCacheReusableWorkflowExecutor(rc *RunContext, filename string, rem if err != nil { return err } - archive, err := cache.GetTarArchive(ctx, filename, sha, fmt.Sprintf(".github/workflows/%s", remoteReusableWorkflow.Filename)) + archive, err := cache.GetTarArchive(ctx, filename, sha, ".github/workflows/"+remoteReusableWorkflow.Filename) if err != nil { return err } diff --git a/pkg/runner/run_context.go b/pkg/runner/run_context.go index 5b7bec0e..11e330ce 100644 --- a/pkg/runner/run_context.go +++ b/pkg/runner/run_context.go @@ -12,6 +12,7 @@ import ( "errors" "fmt" "io" + maps0 "maps" "os" "path/filepath" "regexp" @@ -34,7 +35,7 @@ import ( type RunContext struct { Name string Config *Config - Matrix map[string]interface{} + Matrix map[string]any Run *model.Run EventJSON string Env map[string]string @@ -54,7 +55,7 @@ type RunContext struct { cleanUpJobContainer common.Executor caller *caller // job calling this RunContext (reusable workflows) Cancelled bool - ContextData map[string]interface{} + ContextData map[string]any nodeToolFullPath string } @@ -109,13 +110,13 @@ func (rc *RunContext) networkName() (string, bool) { } func getDockerDaemonSocketMountPath(daemonPath string) string { - if protoIndex := strings.Index(daemonPath, "://"); protoIndex != -1 { - scheme := daemonPath[:protoIndex] + if before, after, ok := strings.Cut(daemonPath, "://"); ok { + scheme := before if strings.EqualFold(scheme, "npipe") { // linux container mount on windows, use the default socket path of the VM / wsl2 return "/var/run/docker.sock" } else if strings.EqualFold(scheme, "unix") { - return daemonPath[protoIndex+3:] + return after } else if strings.IndexFunc(scheme, func(r rune) bool { return (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') }) == -1 { @@ -244,7 +245,7 @@ func (rc *RunContext) startHostEnvironment() common.Executor { }).Finally(rc.JobContainer.Remove()) for k, v := range rc.JobContainer.GetRunnerContext(ctx) { if v, ok := v.(string); ok { - rc.Env[fmt.Sprintf("RUNNER_%s", strings.ToUpper(k))] = v + rc.Env["RUNNER_"+strings.ToUpper(k)] = v } } for _, env := range os.Environ() { @@ -635,7 +636,7 @@ func (rc *RunContext) waitForServiceContainer(c container.ExecutionsEnvironment) if health == container.HealthHealthy { return nil } - return fmt.Errorf("service container failed to start") + return errors.New("service container failed to start") } } @@ -741,7 +742,7 @@ func (rc *RunContext) closeContainer() common.Executor { } } -func (rc *RunContext) matrix() map[string]interface{} { +func (rc *RunContext) matrix() map[string]any { return rc.Matrix } @@ -891,9 +892,7 @@ func (rc *RunContext) isEnabled(ctx context.Context) (bool, error) { func mergeMaps(maps ...map[string]string) map[string]string { rtnMap := make(map[string]string) for _, m := range maps { - for k, v := range m { - rtnMap[k] = v - } + maps0.Copy(rtnMap, m) } return rtnMap } @@ -945,7 +944,7 @@ func (rc *RunContext) getStepsContext() map[string]*model.StepResult { func (rc *RunContext) getGithubContext(ctx context.Context) *model.GithubContext { logger := common.Logger(ctx) ghc := &model.GithubContext{ - Event: make(map[string]interface{}), + Event: make(map[string]any), Workflow: rc.Run.Workflow.Name, RunAttempt: rc.Config.Env["GITHUB_RUN_ATTEMPT"], RunID: rc.Config.Env["GITHUB_RUN_ID"], @@ -1049,9 +1048,9 @@ func (rc *RunContext) getGithubContext(ctx context.Context) *model.GithubContext func (rc *RunContext) mergeGitHubContextWithContextData(ghc *model.GithubContext) { if rnout, ok := rc.ContextData["github"]; ok { - nout, ok := rnout.(map[string]interface{}) + nout, ok := rnout.(map[string]any) if ok { - var out map[string]interface{} + var out map[string]any content, _ := json.Marshal(ghc) _ = json.Unmarshal(content, &out) for k, v := range nout { @@ -1092,7 +1091,7 @@ func isLocalCheckout(ghc *model.GithubContext, step *model.Step) bool { return true } -func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{}) { +func nestedMapLookup(m map[string]any, ks ...string) (rval any) { var ok bool if len(ks) == 0 { // degenerate input @@ -1102,7 +1101,7 @@ func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{}) return nil } else if len(ks) == 1 { // we've reached the final key return rval - } else if m, ok = rval.(map[string]interface{}); !ok { + } else if m, ok = rval.(map[string]any); !ok { return nil } // 1+ more keys @@ -1200,22 +1199,22 @@ func (rc *RunContext) handleCredentials(ctx context.Context) (string, string, er } if container.Credentials != nil && len(container.Credentials) != 2 { - err := fmt.Errorf("invalid property count for key 'credentials:'") + err := errors.New("invalid property count for key 'credentials:'") return "", "", err } ee := rc.NewExpressionEvaluator(ctx) if username = ee.Interpolate(ctx, container.Credentials["username"]); username == "" { - err := fmt.Errorf("failed to interpolate container.credentials.username") + err := errors.New("failed to interpolate container.credentials.username") return "", "", err } if password = ee.Interpolate(ctx, container.Credentials["password"]); password == "" { - err := fmt.Errorf("failed to interpolate container.credentials.password") + err := errors.New("failed to interpolate container.credentials.password") return "", "", err } if container.Credentials["username"] == "" || container.Credentials["password"] == "" { - err := fmt.Errorf("container.credentials cannot be empty") + err := errors.New("container.credentials cannot be empty") return "", "", err } @@ -1227,18 +1226,18 @@ func (rc *RunContext) handleServiceCredentials(ctx context.Context, creds map[st return } if len(creds) != 2 { - err = fmt.Errorf("invalid property count for key 'credentials:'") + err = errors.New("invalid property count for key 'credentials:'") return } ee := rc.NewExpressionEvaluator(ctx) if username = ee.Interpolate(ctx, creds["username"]); username == "" { - err = fmt.Errorf("failed to interpolate credentials.username") + err = errors.New("failed to interpolate credentials.username") return } if password = ee.Interpolate(ctx, creds["password"]); password == "" { - err = fmt.Errorf("failed to interpolate credentials.password") + err = errors.New("failed to interpolate credentials.password") return } diff --git a/pkg/runner/run_context_darwin.go b/pkg/runner/run_context_darwin.go index 5b1072f8..34680c28 100644 --- a/pkg/runner/run_context_darwin.go +++ b/pkg/runner/run_context_darwin.go @@ -4,7 +4,6 @@ import ( "context" "crypto/rand" "encoding/hex" - "fmt" "net/url" "os" "path/filepath" @@ -85,7 +84,7 @@ func (rc *RunContext) startTartEnvironment() common.Executor { rc.cleanUpJobContainer = rc.JobContainer.Remove() for k, v := range rc.JobContainer.GetRunnerContext(ctx) { if v, ok := v.(string); ok { - rc.Env[fmt.Sprintf("RUNNER_%s", strings.ToUpper(k))] = v + rc.Env["RUNNER_"+strings.ToUpper(k)] = v } } diff --git a/pkg/runner/run_context_test.go b/pkg/runner/run_context_test.go index f66954b8..8cebf03a 100644 --- a/pkg/runner/run_context_test.go +++ b/pkg/runner/run_context_test.go @@ -21,7 +21,7 @@ import ( func TestRunContext_EvalBool(t *testing.T) { var yml yaml.Node - err := yml.Encode(map[string][]interface{}{ + err := yml.Encode(map[string][]any{ "os": {"Linux", "Windows"}, "foo": {"bar", "baz"}, }) @@ -49,7 +49,7 @@ func TestRunContext_EvalBool(t *testing.T) { }, }, }, - Matrix: map[string]interface{}{ + Matrix: map[string]any{ "os": "Linux", "foo": "bar", }, @@ -162,7 +162,7 @@ func TestRunContext_EvalBool(t *testing.T) { assertObject.Error(err) } - assertObject.Equal(table.out, b, fmt.Sprintf("Expected %s to be %v, was %v", table.in, table.out, b)) + assertObject.Equal(table.out, b, "Expected %s to be %v, was %v", table.in, table.out, b) }) } } @@ -178,9 +178,11 @@ func updateTestIfWorkflow(t *testing.T, tables []struct { keys = append(keys, k) } sort.Strings(keys) + var envsSb181 strings.Builder for _, k := range keys { - envs += fmt.Sprintf(" %s: %s\n", k, rc.Env[k]) + fmt.Fprintf(&envsSb181, " %s: %s\n", k, rc.Env[k]) } + envs += envsSb181.String() // editorconfig-checker-disable workflow := fmt.Sprintf(` name: "Test what expressions result in true and false on GitHub" @@ -196,6 +198,7 @@ jobs: `, envs) // editorconfig-checker-enable + var workflowSb199 strings.Builder for i, table := range tables { if table.wantErr || strings.HasPrefix(table.in, "github.actor") { continue @@ -211,11 +214,12 @@ jobs: echo = `run: echo OK` name = fmt.Sprintf(`"✅ I should run, expr: %s"`, expr) } - workflow += fmt.Sprintf("\n - name: %s\n id: step%d\n if: %s\n %s\n", name, i, table.in, echo) + fmt.Fprintf(&workflowSb199, "\n - name: %s\n id: step%d\n if: %s\n %s\n", name, i, table.in, echo) if table.out { - workflow += fmt.Sprintf("\n - name: \"Double checking expr: %s\"\n if: steps.step%d.conclusion == 'skipped'\n run: echo \"%s should have been true, but wasn't\"\n", expr, i, table.in) + fmt.Fprintf(&workflowSb199, "\n - name: \"Double checking expr: %s\"\n if: steps.step%d.conclusion == 'skipped'\n run: echo \"%s should have been true, but wasn't\"\n", expr, i, table.in) } } + workflow += workflowSb199.String() file, err := os.Create("../../.github/workflows/test-if.yml") if err != nil { @@ -281,7 +285,7 @@ func TestRunContext_GetBindsAndMounts(t *testing.T) { assert.Contains(t, gotbind, fullBind) } else { mountkey := testcase.rc.jobContainerName() - assert.EqualValues(t, testcase.wantmount, gotmount[mountkey]) + assert.Equal(t, testcase.wantmount, gotmount[mountkey]) } }) } @@ -341,7 +345,7 @@ func TestGetGitHubContext(t *testing.T) { log.SetLevel(log.DebugLevel) cwd, err := os.Getwd() - assert.Nil(t, err) + assert.NoError(t, err) rc := &RunContext{ Config: &Config{ @@ -355,7 +359,7 @@ func TestGetGitHubContext(t *testing.T) { }, Name: "GitHubContextTest", CurrentStep: "step", - Matrix: map[string]interface{}{}, + Matrix: map[string]any{}, Env: map[string]string{}, ExtraPath: []string{}, StepResults: map[string]*model.StepResult{}, @@ -397,7 +401,7 @@ func TestGetGitHubContextOverlay(t *testing.T) { log.SetLevel(log.DebugLevel) cwd, err := os.Getwd() - assert.Nil(t, err) + assert.NoError(t, err) rc := &RunContext{ Config: &Config{ @@ -411,13 +415,13 @@ func TestGetGitHubContextOverlay(t *testing.T) { }, Name: "GitHubContextTest", CurrentStep: "step", - Matrix: map[string]interface{}{}, + Matrix: map[string]any{}, Env: map[string]string{}, ExtraPath: []string{}, StepResults: map[string]*model.StepResult{}, OutputMappings: map[MappableOutput]MappableOutput{}, - ContextData: map[string]interface{}{ - "github": map[string]interface{}{ + ContextData: map[string]any{ + "github": map[string]any{ "actor": "me", "repository": "myowner/myrepo", "repository_owner": "myowner", @@ -721,7 +725,7 @@ func TestRunContextGetEnv(t *testing.T) { for _, test := range tests { t.Run(test.description, func(t *testing.T) { envMap := test.rc.GetEnv() - assert.EqualValues(t, test.want, envMap[test.targetEnv]) + assert.Equal(t, test.want, envMap[test.targetEnv]) }) } } @@ -744,7 +748,7 @@ func TestSetRuntimeVariables(t *testing.T) { tkn, _, err := jwt.NewParser().ParseUnverified(runtimeToken, jwt.MapClaims{}) assert.NotNil(t, tkn) - assert.Nil(t, err) + assert.NoError(t, err) } func TestSetRuntimeVariablesWithRunID(t *testing.T) { @@ -769,7 +773,7 @@ func TestSetRuntimeVariablesWithRunID(t *testing.T) { claims := jwt.MapClaims{} tkn, _, err := jwt.NewParser().ParseUnverified(runtimeToken, &claims) assert.NotNil(t, tkn) - assert.Nil(t, err) + assert.NoError(t, err) scp, ok := claims["scp"] assert.True(t, ok, "scp claim exists") assert.Equal(t, "Actions.Results:45:45", scp, "contains expected scp claim") diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index ec019fb4..9ba86df2 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -74,7 +74,7 @@ type Config struct { Planner model.PlannerConfig // Configuration for the workflow planner Action model.ActionConfig // Configuration for action reading MainContextNames []string // e.g. "github", "gitea", "forgejo" - ContextData map[string]interface{} + ContextData map[string]any EventJSON string } @@ -82,7 +82,7 @@ func (runnerConfig *Config) GetGitHubServerURL() string { if len(runnerConfig.GitHubServerURL) > 0 { return runnerConfig.GitHubServerURL } - return fmt.Sprintf("https://%s", runnerConfig.GitHubInstance) + return "https://" + runnerConfig.GitHubInstance } func (runnerConfig *Config) GetGitHubAPIServerURL() string { if len(runnerConfig.GitHubAPIServerURL) > 0 { @@ -203,7 +203,7 @@ func (runner *runnerImpl) NewPlanExecutor(plan *model.Plan) common.Executor { } } - var matrixes []map[string]interface{} + var matrixes []map[string]any if m, err := job.GetMatrixes(); err != nil { log.Errorf("error while get job's matrix: %v", err) } else { @@ -247,10 +247,7 @@ func (runner *runnerImpl) NewPlanExecutor(plan *model.Plan) common.Executor { if runner.config.Parallel != 0 { return common.NewParallelExecutor(len(pipeline), pipeline...)(ctx) } - ncpu := runtime.NumCPU() - if 1 > ncpu { - ncpu = 1 - } + ncpu := max(1, runtime.NumCPU()) log.Debugf("Detected CPUs: %d", ncpu) return common.NewParallelExecutor(ncpu, pipeline...)(ctx) }) @@ -272,8 +269,8 @@ func handleFailure(plan *model.Plan) common.Executor { } } -func selectMatrixes(originalMatrixes []map[string]interface{}, targetMatrixValues map[string]map[string]bool) []map[string]interface{} { - matrixes := make([]map[string]interface{}, 0) +func selectMatrixes(originalMatrixes []map[string]any, targetMatrixValues map[string]map[string]bool) []map[string]any { + matrixes := make([]map[string]any, 0) for _, original := range originalMatrixes { flag := true for key, val := range original { @@ -291,7 +288,7 @@ func selectMatrixes(originalMatrixes []map[string]interface{}, targetMatrixValue return matrixes } -func (runner *runnerImpl) newRunContext(ctx context.Context, run *model.Run, matrix map[string]interface{}) *RunContext { +func (runner *runnerImpl) newRunContext(ctx context.Context, run *model.Run, matrix map[string]any) *RunContext { rc := &RunContext{ Config: runner.config, Run: run, diff --git a/pkg/runner/runner_test.go b/pkg/runner/runner_test.go index 14f88cfe..27fd3c06 100644 --- a/pkg/runner/runner_test.go +++ b/pkg/runner/runner_test.go @@ -5,6 +5,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io" "os" @@ -87,7 +88,7 @@ func TestGraphMissingEvent(t *testing.T) { plan, err := planner.PlanEvent("push") assert.NoError(t, err) assert.NotNil(t, plan) - assert.Equal(t, 0, len(plan.Stages)) + assert.Empty(t, plan.Stages) assert.Contains(t, buf.String(), "no events found for workflow: no-event.yml") log.SetOutput(out) @@ -100,7 +101,7 @@ func TestGraphMissingFirst(t *testing.T) { plan, err := planner.PlanEvent("push") assert.EqualError(t, err, "unable to build dependency graph for no first (no-first.yml)") assert.NotNil(t, plan) - assert.Equal(t, 0, len(plan.Stages)) + assert.Empty(t, plan.Stages) } func TestGraphWithMissing(t *testing.T) { @@ -114,7 +115,7 @@ func TestGraphWithMissing(t *testing.T) { plan, err := planner.PlanEvent("push") assert.NotNil(t, plan) - assert.Equal(t, 0, len(plan.Stages)) + assert.Empty(t, plan.Stages) assert.EqualError(t, err, "unable to build dependency graph for missing (missing.yml)") assert.Contains(t, buf.String(), "unable to build dependency graph for missing (missing.yml)") log.SetOutput(out) @@ -134,7 +135,7 @@ func TestGraphWithSomeMissing(t *testing.T) { plan, err := planner.PlanAll() assert.Error(t, err, "unable to build dependency graph for no first (no-first.yml)") assert.NotNil(t, plan) - assert.Equal(t, 1, len(plan.Stages)) + assert.Len(t, plan.Stages, 1) assert.Contains(t, buf.String(), "unable to build dependency graph for missing (missing.yml)") assert.Contains(t, buf.String(), "unable to build dependency graph for no first (no-first.yml)") log.SetOutput(out) @@ -148,18 +149,18 @@ func TestGraphEvent(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, plan) assert.NotNil(t, plan.Stages) - assert.Equal(t, len(plan.Stages), 3, "stages") - assert.Equal(t, len(plan.Stages[0].Runs), 1, "stage0.runs") - assert.Equal(t, len(plan.Stages[1].Runs), 1, "stage1.runs") - assert.Equal(t, len(plan.Stages[2].Runs), 1, "stage2.runs") - assert.Equal(t, plan.Stages[0].Runs[0].JobID, "check", "jobid") - assert.Equal(t, plan.Stages[1].Runs[0].JobID, "build", "jobid") - assert.Equal(t, plan.Stages[2].Runs[0].JobID, "test", "jobid") + assert.Len(t, plan.Stages, 3, "stages") + assert.Len(t, plan.Stages[0].Runs, 1, "stage0.runs") + assert.Len(t, plan.Stages[1].Runs, 1, "stage1.runs") + assert.Len(t, plan.Stages[2].Runs, 1, "stage2.runs") + assert.Equal(t, "check", plan.Stages[0].Runs[0].JobID, "jobid") + assert.Equal(t, "build", plan.Stages[1].Runs[0].JobID, "jobid") + assert.Equal(t, "test", plan.Stages[2].Runs[0].JobID, "jobid") plan, err = planner.PlanEvent("release") assert.NoError(t, err) assert.NotNil(t, plan) - assert.Equal(t, 0, len(plan.Stages)) + assert.Empty(t, plan.Stages) } type TestJobFileInfo struct { @@ -177,7 +178,7 @@ func (j *TestJobFileInfo) runTest(ctx context.Context, t *testing.T, cfg *Config log.SetLevel(logLevel) workdir, err := filepath.Abs(j.workdir) - assert.Nil(t, err, workdir) + assert.NoError(t, err, workdir) fullWorkflowPath := filepath.Join(workdir, j.workflowPath) runnerConfig := &Config{ @@ -198,18 +199,18 @@ func (j *TestJobFileInfo) runTest(ctx context.Context, t *testing.T, cfg *Config } runner, err := New(runnerConfig) - assert.Nil(t, err, j.workflowPath) + assert.NoError(t, err, j.workflowPath) planner, err := model.NewWorkflowPlanner(fullWorkflowPath, model.PlannerConfig{}) if j.errorMessage != "" && err != nil { assert.Error(t, err, j.errorMessage) - } else if assert.Nil(t, err, fullWorkflowPath) { + } else if assert.NoError(t, err, fullWorkflowPath) { plan, err := planner.PlanEvent(j.eventName) - assert.True(t, (err == nil) != (plan == nil), "PlanEvent should return either a plan or an error") + assert.NotEqual(t, (err == nil), (plan == nil), "PlanEvent should return either a plan or an error") if err == nil && plan != nil { err = runner.NewPlanExecutor(plan)(ctx) if j.errorMessage == "" { - assert.Nil(t, err, fullWorkflowPath) + assert.NoError(t, err, fullWorkflowPath) } else { assert.Error(t, err, j.errorMessage) } @@ -434,7 +435,7 @@ func TestPullAndPostStepFailureIsJobFailure(t *testing.T) { var hasJobResult, hasStepResult bool for scan.Scan() { t.Log(scan.Text()) - entry := map[string]interface{}{} + entry := map[string]any{} if json.Unmarshal(scan.Bytes(), &entry) == nil { if val, ok := entry["jobResult"]; ok { assert.Equal(t, "failure", val) @@ -461,14 +462,14 @@ func (c mockCache) Fetch(ctx context.Context, cacheDir string, url string, ref s _ = url _ = ref _ = token - return "", fmt.Errorf("fetch failure") + return "", errors.New("fetch failure") } func (c mockCache) GetTarArchive(ctx context.Context, cacheDir string, sha string, includePrefix string) (io.ReadCloser, error) { _ = ctx _ = cacheDir _ = sha _ = includePrefix - return nil, fmt.Errorf("fetch failure") + return nil, errors.New("fetch failure") } func TestFetchFailureIsJobFailure(t *testing.T) { @@ -504,7 +505,7 @@ func TestFetchFailureIsJobFailure(t *testing.T) { var hasJobResult bool for scan.Scan() { t.Log(scan.Text()) - entry := map[string]interface{}{} + entry := map[string]any{} if json.Unmarshal(scan.Bytes(), &entry) == nil { if val, ok := entry["jobResult"]; ok { assert.Equal(t, "failure", val) @@ -735,11 +736,11 @@ func (f *maskJobLoggerFactory) WithJobLogger() *log.Logger { func TestMaskValues(t *testing.T) { assertNoSecret := func(text string, _ string) { - index := strings.Index(text, "composite secret") - if index > -1 { + found := strings.Contains(text, "composite secret") + if found { fmt.Printf("\nFound Secret in the given text:\n%s\n", text) } - assert.False(t, strings.Contains(text, "composite secret")) + assert.NotContains(t, text, "composite secret") } if testing.Short() { diff --git a/pkg/runner/step.go b/pkg/runner/step.go index 20ff1b3e..60b33b12 100644 --- a/pkg/runner/step.go +++ b/pkg/runner/step.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + maps0 "maps" "path" "strconv" "strings" @@ -336,9 +337,7 @@ func mergeIntoMap(step step, target *map[string]string, maps ...map[string]strin func mergeIntoMapCaseSensitive(target map[string]string, maps ...map[string]string) { for _, m := range maps { - for k, v := range m { - target[k] = v - } + maps0.Copy(target, m) } } diff --git a/pkg/runner/step_action_local.go b/pkg/runner/step_action_local.go index f70cdedd..2cf78fb8 100644 --- a/pkg/runner/step_action_local.go +++ b/pkg/runner/step_action_local.go @@ -43,7 +43,7 @@ func (sal *stepActionLocal) main() common.Executor { _, cpath := sal.getContainerActionPaths() return func(filename string) (io.Reader, io.Closer, error) { spath := path.Join(cpath, filename) - for i := 0; i < maxSymlinkDepth; i++ { + for range maxSymlinkDepth { tars, err := sal.RunContext.JobContainer.GetContainerArchive(ctx, spath) if errors.Is(err, fs.ErrNotExist) { return nil, nil, err diff --git a/pkg/runner/step_action_local_test.go b/pkg/runner/step_action_local_test.go index f5841255..40a7c590 100644 --- a/pkg/runner/step_action_local_test.go +++ b/pkg/runner/step_action_local_test.go @@ -92,10 +92,10 @@ func TestStepActionLocalTest(t *testing.T) { }) err := sal.pre()(ctx) - assert.Nil(t, err) + assert.NoError(t, err) err = sal.main()(ctx) - assert.Nil(t, err) + assert.NoError(t, err) cm.AssertExpectations(t) salm.AssertExpectations(t) @@ -258,7 +258,7 @@ func TestStepActionLocalPost(t *testing.T) { sal.RunContext.ExprEval = sal.RunContext.NewExpressionEvaluator(ctx) if tt.mocks.exec { - suffixMatcher := func(suffix string) interface{} { + suffixMatcher := func(suffix string) any { return mock.MatchedBy(func(array []string) bool { return strings.HasSuffix(array[1], suffix) }) @@ -288,7 +288,7 @@ func TestStepActionLocalPost(t *testing.T) { err := sal.post()(ctx) assert.Equal(t, tt.err, err) - assert.Equal(t, sal.RunContext.StepResults["post-step"], (*model.StepResult)(nil)) + assert.Equal(t, (*model.StepResult)(nil), sal.RunContext.StepResults["post-step"]) cm.AssertExpectations(t) }) } diff --git a/pkg/runner/step_action_remote.go b/pkg/runner/step_action_remote.go index 72f3930b..28303ce6 100644 --- a/pkg/runner/step_action_remote.go +++ b/pkg/runner/step_action_remote.go @@ -69,7 +69,7 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor { remoteReader := func(_ context.Context) actionYamlReader { return func(filename string) (io.Reader, io.Closer, error) { spath := path.Join(sar.remoteAction.Path, filename) - for i := 0; i < maxSymlinkDepth; i++ { + for range maxSymlinkDepth { tars, err := cache.GetTarArchive(ctx, sar.cacheDir, sar.resolvedSha, spath) if err != nil { return nil, nil, os.ErrNotExist diff --git a/pkg/runner/step_action_remote_test.go b/pkg/runner/step_action_remote_test.go index 926ba77b..41e4dcde 100644 --- a/pkg/runner/step_action_remote_test.go +++ b/pkg/runner/step_action_remote_test.go @@ -290,7 +290,7 @@ func TestStepActionRemotePre(t *testing.T) { err := sar.pre()(ctx) - assert.Nil(t, err) + assert.NoError(t, err) sarm.AssertExpectations(t) cacheMock.AssertExpectations(t) @@ -343,7 +343,7 @@ func TestStepActionRemotePreThroughAction(t *testing.T) { err := sar.pre()(ctx) - assert.Nil(t, err) + assert.NoError(t, err) sarm.AssertExpectations(t) cacheMock.AssertExpectations(t) @@ -397,7 +397,7 @@ func TestStepActionRemotePreThroughActionToken(t *testing.T) { err := sar.pre()(ctx) - assert.Nil(t, err) + assert.NoError(t, err) sarm.AssertExpectations(t) cacheMock.AssertExpectations(t) @@ -611,7 +611,7 @@ func TestStepActionRemotePost(t *testing.T) { } } // Ensure that StepResults is nil in this test - assert.Equal(t, sar.RunContext.StepResults["post-step"], (*model.StepResult)(nil)) + assert.Equal(t, (*model.StepResult)(nil), sar.RunContext.StepResults["post-step"]) cm.AssertExpectations(t) }) } diff --git a/pkg/runner/step_docker.go b/pkg/runner/step_docker.go index 2c3e0db1..70d773b1 100644 --- a/pkg/runner/step_docker.go +++ b/pkg/runner/step_docker.go @@ -123,7 +123,7 @@ func (sd *stepDocker) newStepContainer(ctx context.Context, image string, cmd [] Name: createContainerName(rc.jobContainerName(), step.ID), Env: envList, Mounts: mounts, - NetworkMode: fmt.Sprintf("container:%s", rc.jobContainerName()), + NetworkMode: "container:" + rc.jobContainerName(), Binds: binds, Stdout: logWriter, Stderr: logWriter, diff --git a/pkg/runner/step_docker_test.go b/pkg/runner/step_docker_test.go index 94fec3f8..2f3a36de 100644 --- a/pkg/runner/step_docker_test.go +++ b/pkg/runner/step_docker_test.go @@ -97,7 +97,7 @@ func TestStepDockerMain(t *testing.T) { cm.On("GetContainerArchive", ctx, "/var/run/act/workflow/pathcmd.txt").Return(io.NopCloser(&bytes.Buffer{}), nil) err := sd.main()(ctx) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "node:14", input.Image) @@ -109,8 +109,8 @@ func TestStepDockerPrePost(t *testing.T) { sd := &stepDocker{} err := sd.pre()(ctx) - assert.Nil(t, err) + assert.NoError(t, err) err = sd.post()(ctx) - assert.Nil(t, err) + assert.NoError(t, err) } diff --git a/pkg/runner/step_factory_test.go b/pkg/runner/step_factory_test.go index 1c6dacf6..c9ca3b5d 100644 --- a/pkg/runner/step_factory_test.go +++ b/pkg/runner/step_factory_test.go @@ -62,7 +62,7 @@ func TestStepFactoryNewStep(t *testing.T) { step, err := sf.newStep(tt.model, &RunContext{}) assert.True(t, tt.check((step))) - assert.Nil(t, err) + assert.NoError(t, err) }) } } diff --git a/pkg/runner/step_run.go b/pkg/runner/step_run.go index db060e26..2ef08039 100644 --- a/pkg/runner/step_run.go +++ b/pkg/runner/step_run.go @@ -3,6 +3,7 @@ package runner import ( "context" "fmt" + "maps" "runtime" "strings" @@ -90,7 +91,7 @@ func getScriptName(rc *RunContext, step *model.Step) string { for rcs := rc; rcs.Parent != nil; rcs = rcs.Parent { scriptName = fmt.Sprintf("%s-composite-%s", rcs.Parent.CurrentStep, scriptName) } - return fmt.Sprintf("workflow/%s", scriptName) + return "workflow/" + scriptName } // TODO: Currently we just ignore top level keys, BUT we should return proper error on them @@ -186,9 +187,7 @@ func (sr *stepRun) setupShell(ctx context.Context) { } step.Shell = shellWithFallback[0] lenv := &localEnv{env: map[string]string{}} - for k, v := range sr.env { - lenv.env[k] = v - } + maps.Copy(lenv.env, sr.env) sr.getRunContext().ApplyExtraPath(ctx, &lenv.env) _, err := lookpath.LookPath2(shellWithFallback[0], lenv) if err != nil { diff --git a/pkg/runner/step_run_test.go b/pkg/runner/step_run_test.go index a978f32b..bfbb11cd 100644 --- a/pkg/runner/step_run_test.go +++ b/pkg/runner/step_run_test.go @@ -78,7 +78,7 @@ func TestStepRun(t *testing.T) { cm.On("GetContainerArchive", ctx, "/var/run/act/workflow/pathcmd.txt").Return(io.NopCloser(&bytes.Buffer{}), nil) err := sr.main()(ctx) - assert.Nil(t, err) + assert.NoError(t, err) cm.AssertExpectations(t) } @@ -88,8 +88,8 @@ func TestStepRunPrePost(t *testing.T) { sr := &stepRun{} err := sr.pre()(ctx) - assert.Nil(t, err) + assert.NoError(t, err) err = sr.post()(ctx) - assert.Nil(t, err) + assert.NoError(t, err) } diff --git a/pkg/runner/step_test.go b/pkg/runner/step_test.go index c698b59c..087fc2d3 100644 --- a/pkg/runner/step_test.go +++ b/pkg/runner/step_test.go @@ -152,7 +152,7 @@ func TestSetupEnv(t *testing.T) { sm.On("getEnv").Return(&env) err := setupEnv(context.Background(), sm) - assert.Nil(t, err) + assert.NoError(t, err) // These are commit or system specific delete((env), "GITHUB_REF") @@ -313,37 +313,37 @@ func TestIsContinueOnError(t *testing.T) { step := createTestStep(t, "name: test") continueOnError, err := isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain) assertObject.False(continueOnError) - assertObject.Nil(err) + assertObject.NoError(err) // explicit true step = createTestStep(t, "continue-on-error: true") continueOnError, err = isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain) assertObject.True(continueOnError) - assertObject.Nil(err) + assertObject.NoError(err) // explicit false step = createTestStep(t, "continue-on-error: false") continueOnError, err = isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain) assertObject.False(continueOnError) - assertObject.Nil(err) + assertObject.NoError(err) // expression true step = createTestStep(t, "continue-on-error: ${{ 'test' == 'test' }}") continueOnError, err = isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain) assertObject.True(continueOnError) - assertObject.Nil(err) + assertObject.NoError(err) // expression false step = createTestStep(t, "continue-on-error: ${{ 'test' != 'test' }}") continueOnError, err = isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain) assertObject.False(continueOnError) - assertObject.Nil(err) + assertObject.NoError(err) // expression parse error step = createTestStep(t, "continue-on-error: ${{ 'test' != test }}") continueOnError, err = isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain) assertObject.False(continueOnError) - assertObject.NotNil(err) + assertObject.Error(err) } func TestSymlinkJoin(t *testing.T) { diff --git a/pkg/schema/schema.go b/pkg/schema/schema.go index 73f07cce..76a6abcf 100644 --- a/pkg/schema/schema.go +++ b/pkg/schema/schema.go @@ -7,6 +7,7 @@ import ( "fmt" "math" "regexp" + "slices" "strconv" "strings" @@ -53,7 +54,7 @@ type ValidationErrorCollection struct { } func indent(builder *strings.Builder, in string) { - for _, v := range strings.Split(in, "\n") { + for v := range strings.SplitSeq(in, "\n") { if v != "" { builder.WriteString(" ") builder.WriteString(v) @@ -242,7 +243,7 @@ func (s *Node) checkSingleExpression(exprNode exprparser.Node) error { case *exprparser.ValueNode: return nil default: - return fmt.Errorf("expressions are not allowed here") + return errors.New("expressions are not allowed here") } } @@ -290,8 +291,8 @@ func (s *Node) GetFunctions() []FunctionInfo { }, }) for _, v := range s.Context { - i := strings.Index(v, "(") - if i == -1 { + found := strings.Contains(v, "(") + if !found { continue } smatch := functions.FindStringSubmatch(v) @@ -348,7 +349,7 @@ func (s *Node) checkExpression(node *yaml.Node) (bool, error) { if parseErr != nil { err = errors.Join(err, ValidationError{ Location: toLocation(node), - Message: fmt.Sprintf("failed to parse: %s", parseErr.Error()), + Message: "failed to parse: " + parseErr.Error(), }) continue } @@ -409,10 +410,8 @@ func (s *Node) UnmarshalYAML(node *yaml.Node) error { return node.Decode(&b) } else if def.AllowedValues != nil { s := node.Value - for _, v := range *def.AllowedValues { - if s == v { - return nil - } + if slices.Contains(*def.AllowedValues, s) { + return nil } return ValidationError{ Location: toLocation(node), @@ -448,7 +447,7 @@ func (s *Node) checkString(node *yaml.Node, def Definition) error { if parseErr != nil { return ValidationError{ Location: toLocation(node), - Message: fmt.Sprintf("failed to parse: %s", parseErr.Error()), + Message: "failed to parse: " + parseErr.Error(), } } cerr := s.checkSingleExpression(exprNode) @@ -650,7 +649,7 @@ func (s *Node) checkMapping(node *yaml.Node, def Definition) error { if col := AsValidationErrorCollection(err); col != nil { allErrors.AddError(ValidationError{ Location: toLocation(node.Content[i+1]), - Message: fmt.Sprintf("error found in value of key %s", k.Value), + Message: "error found in value of key " + k.Value, }) allErrors.Collections = append(allErrors.Collections, *col) continue @@ -669,7 +668,7 @@ func (s *Node) checkMapping(node *yaml.Node, def Definition) error { allErrors.AddError(ValidationError{ Location: toLocation(node), Kind: ValidationKindMissingProperty, - Message: fmt.Sprintf("missing property %s", k), + Message: "missing property " + k, }) } } diff --git a/pkg/tart/environment_darwin.go b/pkg/tart/environment_darwin.go index 8184840e..c9b02f9e 100644 --- a/pkg/tart/environment_darwin.go +++ b/pkg/tart/environment_darwin.go @@ -161,9 +161,11 @@ func (e *Environment) exec(ctx context.Context, command []string, _ string, env wd = e.ToContainerPath(e.Path) } envs := "" + var envsSb164 strings.Builder for k, v := range env { - envs += shellquote.Join(k) + "=" + shellquote.Join(v) + " " + envsSb164.WriteString(shellquote.Join(k) + "=" + shellquote.Join(v) + " ") } + envs += envsSb164.String() return e.execRaw(ctx, "cd "+shellquote.Join(wd)+"\nenv "+envs+shellquote.Join(command...)+"\nexit $?") } @@ -224,7 +226,7 @@ func (e *Environment) GetContainerArchive(ctx context.Context, srcPath string) ( return e.HostEnvironment.GetContainerArchive(ctx, e.ToHostPath(srcPath)) } -func (e *Environment) GetRunnerContext(ctx context.Context) map[string]interface{} { +func (e *Environment) GetRunnerContext(ctx context.Context) map[string]any { rctx := e.HostEnvironment.GetRunnerContext(ctx) rctx["temp"] = e.ToContainerPath(e.TmpDir) rctx["tool_cache"] = e.ToContainerPath(e.ToolCache) diff --git a/pkg/tart/vm_darwin.go b/pkg/tart/vm_darwin.go index 54a1ad31..0a15520b 100644 --- a/pkg/tart/vm_darwin.go +++ b/pkg/tart/vm_darwin.go @@ -235,7 +235,7 @@ func ExecWithEnv( func firstNonEmptyLine(outputs ...string) string { for _, output := range outputs { - for _, line := range strings.Split(output, "\n") { + for line := range strings.SplitSeq(output, "\n") { if line != "" { return line } @@ -246,5 +246,5 @@ func firstNonEmptyLine(outputs ...string) string { } func (vm *VM) tartRunOutputPath() string { - return filepath.Join(os.TempDir(), fmt.Sprintf("%s-tart-run-output.log", vm.id)) + return filepath.Join(os.TempDir(), vm.id+"-tart-run-output.log") } diff --git a/pkg/workflowpattern/trace_writer.go b/pkg/workflowpattern/trace_writer.go index d5d990f6..675aa187 100644 --- a/pkg/workflowpattern/trace_writer.go +++ b/pkg/workflowpattern/trace_writer.go @@ -3,16 +3,16 @@ package workflowpattern import "fmt" type TraceWriter interface { - Info(string, ...interface{}) + Info(string, ...any) } type EmptyTraceWriter struct{} -func (*EmptyTraceWriter) Info(string, ...interface{}) { +func (*EmptyTraceWriter) Info(string, ...any) { } type StdOutTraceWriter struct{} -func (*StdOutTraceWriter) Info(format string, args ...interface{}) { +func (*StdOutTraceWriter) Info(format string, args ...any) { fmt.Printf(format+"\n", args...) } diff --git a/pkg/workflowpattern/workflow_pattern.go b/pkg/workflowpattern/workflow_pattern.go index cc03e405..2c696a5f 100644 --- a/pkg/workflowpattern/workflow_pattern.go +++ b/pkg/workflowpattern/workflow_pattern.go @@ -127,7 +127,7 @@ func PatternToRegex(pattern string) (string, error) { if errorMessage.Len() > 0 { errorMessage.WriteString(", ") } - errorMessage.WriteString(fmt.Sprintf("Position: %d Error: %s", position, err)) + fmt.Fprintf(&errorMessage, "Position: %d Error: %s", position, err) } return "", fmt.Errorf("invalid Pattern '%s': %s", pattern, errorMessage.String()) } diff --git a/pkg/workflowpattern/workflow_pattern_test.go b/pkg/workflowpattern/workflow_pattern_test.go index a62d529b..037b20ea 100644 --- a/pkg/workflowpattern/workflow_pattern_test.go +++ b/pkg/workflowpattern/workflow_pattern_test.go @@ -407,8 +407,8 @@ func TestMatchPattern(t *testing.T) { patterns, err := CompilePatterns(kase.patterns...) assert.NoError(t, err) - assert.EqualValues(t, kase.skipResult, Skip(patterns, kase.inputs, &StdOutTraceWriter{}), "skipResult") - assert.EqualValues(t, kase.filterResult, Filter(patterns, kase.inputs, &StdOutTraceWriter{}), "filterResult") + assert.Equal(t, kase.skipResult, Skip(patterns, kase.inputs, &StdOutTraceWriter{}), "skipResult") + assert.Equal(t, kase.filterResult, Filter(patterns, kase.inputs, &StdOutTraceWriter{}), "filterResult") }) } }