auto adjust code

This commit is contained in:
Christopher Homberger
2026-02-22 20:58:46 +01:00
parent 949a40c7a5
commit d187ac2fc1
86 changed files with 617 additions and 617 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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)
})
}

View File

@@ -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]

View File

@@ -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")

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}
}

View File

@@ -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")

View File

@@ -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,

View File

@@ -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() {

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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)
})
}

View File

@@ -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

View File

@@ -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)
})
}

View File

@@ -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,

View File

@@ -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)
}

View File

@@ -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)
})
}
}

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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) {