refactor: remove dead code and consolidate tests (#1335)

Removes dead code and redundant logic and consolidates tests, so there is less to read and maintain. No behavior change.

1. **act/runner**: inline single-use wrappers, compile regexes once instead of per call, embed the trampoline as a string, drop the unused legacy result of `parseActionCommand`
2. **act/container**: `sanitizeConfig` and `mergeContainerConfigs` stop returning the configs they already mutate in place, drop never-set option fields and the unused `user` parameter of `ExecWithCmdLine`
3. **act/common and cache server**: drop the unused `Trace`/`Tracef` loggers and the short SHA of `FindGitRevision`, `RegisterJob` releases through `RevokeJob`
4. **daemon, poller and reporter**: one shutdown wait for both poll modes, drop an unreachable fetch timeout branch, guard the reporter's last report time with its existing lock instead of an atomic
5. **build**: drop unused Makefile and release workflow variables, collapse the goreleaser ignore list to the same build targets
6. **tests**: fold near-duplicate tests into tables with shared setup

Throughout, hand-rolled logic gives way to `cmp.Or`, `strings.Cut`, `slices` and `min`/`max`.

Reviewed-on: https://gitea.com/gitea/runner/pulls/1335
Reviewed-by: bircni <[email protected]>
Co-authored-by: silverwind <[email protected]>
This commit is contained in:
silverwind authored and silverwind committed 2026-10-22 19:41:10 +00:00
1 parent 923a0bfb59
commit d882311ec6
107 files changed
+2408 -6500

No files matched your search

+71 -105
View File
@@ -85,71 +85,61 @@ func TestEvaluateRunContext(t *testing.T) {
ee := rc.NewExpressionEvaluator(t.Context())
tables := []struct {
in string
out any
errMesg string
in string
out any
}{
{" 1 ", 1.0, ""},
// {"1 + 3", "4", ""},
// {"(1 + 3) * -2", "-8", ""},
{"'my text'", "my text", ""},
{"contains('my text', 'te')", true, ""},
{"contains('my TEXT', 'te')", true, ""},
{"contains(fromJSON('[\"my text\"]'), 'te')", false, ""},
{"contains(fromJSON('[\"foo\",\"bar\"]'), 'bar')", true, ""},
{"startsWith('hello world', 'He')", true, ""},
{"endsWith('hello world', 'ld')", true, ""},
{"format('0:{0} 2:{2} 1:{1}', 'zero', 'one', 'two')", "0:zero 2:two 1:one", ""},
{"join(fromJSON('[\"hello\"]'),'octocat')", "hello", ""},
{"join(fromJSON('[\"hello\",\"mona\",\"the\"]'),'octocat')", "hellooctocatmonaoctocatthe", ""},
{"join('hello','mona')", "hello", ""},
{"toJSON(env)", "{\n \"ACT\": \"true\",\n \"ACT_SKIP_CHECKOUT\": \"true\",\n \"key\": \"value\"\n}", ""},
{"toJson(env)", "{\n \"ACT\": \"true\",\n \"ACT_SKIP_CHECKOUT\": \"true\",\n \"key\": \"value\"\n}", ""},
{"(fromJSON('{\"foo\":\"bar\"}')).foo", "bar", ""},
{"(fromJson('{\"foo\":\"bar\"}')).foo", "bar", ""},
{"(fromJson('[\"foo\",\"bar\"]'))[1]", "bar", ""},
// github does return an empty string for non-existent files
{"hashFiles('**/non-extant-files')", "", ""},
{"hashFiles('**/non-extant-files', '**/more-non-extant-files')", "", ""},
{"hashFiles('**/non.extant.files')", "", ""},
{"hashFiles('**/non''extant''files')", "", ""},
{"success()", true, ""},
{"failure()", false, ""},
{"always()", true, ""},
{"cancelled()", false, ""},
{"github.workflow", "test-workflow", ""},
{"github.actor", "nektos/act", ""},
{"github.run_id", "1", ""},
{"github.run_number", "1", ""},
{"job.status", "success", ""},
{"matrix.os", "Linux", ""},
{"matrix.foo", "bar", ""},
{"env.key", "value", ""},
{"secrets.CASE_INSENSITIVE_SECRET", "value", ""},
{"secrets.case_insensitive_secret", "value", ""},
{"vars.CASE_INSENSITIVE_VAR", "value", ""},
{"vars.case_insensitive_var", "value", ""},
{"format('{{0}}', 'test')", "{0}", ""},
{"format('{{{0}}}', 'test')", "{test}", ""},
{"format('}}')", "}", ""},
{"format('echo Hello {0} ${{Test}}', 'World')", "echo Hello World ${Test}", ""},
{"format('echo Hello {0} ${{Test}}', github.undefined_property)", "echo Hello ${Test}", ""},
{"format('echo Hello {0}{1} ${{Te{0}st}}', github.undefined_property, 'World')", "echo Hello World ${Test}", ""},
{"format('{0}', '{1}', 'World')", "{1}", ""},
{"format('{{{0}', '{1}', 'World')", "{{1}", ""},
{" 1 ", 1.0},
{"'my text'", "my text"},
{"contains('my text', 'te')", true},
{"contains('my TEXT', 'te')", true},
{"contains(fromJSON('[\"my text\"]'), 'te')", false},
{"contains(fromJSON('[\"foo\",\"bar\"]'), 'bar')", true},
{"startsWith('hello world', 'He')", true},
{"endsWith('hello world', 'ld')", true},
{"format('0:{0} 2:{2} 1:{1}', 'zero', 'one', 'two')", "0:zero 2:two 1:one"},
{"join(fromJSON('[\"hello\"]'),'octocat')", "hello"},
{"join(fromJSON('[\"hello\",\"mona\",\"the\"]'),'octocat')", "hellooctocatmonaoctocatthe"},
{"join('hello','mona')", "hello"},
{"toJSON(env)", "{\n \"ACT\": \"true\",\n \"ACT_SKIP_CHECKOUT\": \"true\",\n \"key\": \"value\"\n}"},
{"toJson(env)", "{\n \"ACT\": \"true\",\n \"ACT_SKIP_CHECKOUT\": \"true\",\n \"key\": \"value\"\n}"},
{"(fromJSON('{\"foo\":\"bar\"}')).foo", "bar"},
{"(fromJson('{\"foo\":\"bar\"}')).foo", "bar"},
{"(fromJson('[\"foo\",\"bar\"]'))[1]", "bar"},
{"hashFiles('**/non-extant-files')", ""},
{"hashFiles('**/non-extant-files', '**/more-non-extant-files')", ""},
{"hashFiles('**/non.extant.files')", ""},
{"hashFiles('**/non''extant''files')", ""},
{"success()", true},
{"failure()", false},
{"always()", true},
{"cancelled()", false},
{"github.workflow", "test-workflow"},
{"github.actor", "nektos/act"},
{"github.run_id", "1"},
{"github.run_number", "1"},
{"job.status", "success"},
{"matrix.os", "Linux"},
{"matrix.foo", "bar"},
{"env.key", "value"},
{"secrets.CASE_INSENSITIVE_SECRET", "value"},
{"secrets.case_insensitive_secret", "value"},
{"vars.CASE_INSENSITIVE_VAR", "value"},
{"vars.case_insensitive_var", "value"},
{"format('{{0}}', 'test')", "{0}"},
{"format('{{{0}}}', 'test')", "{test}"},
{"format('}}')", "}"},
{"format('echo Hello {0} ${{Test}}', 'World')", "echo Hello World ${Test}"},
{"format('echo Hello {0} ${{Test}}', github.undefined_property)", "echo Hello ${Test}"},
{"format('echo Hello {0}{1} ${{Te{0}st}}', github.undefined_property, 'World')", "echo Hello World ${Test}"},
{"format('{0}', '{1}', 'World')", "{1}"},
{"format('{{{0}', '{1}', 'World')", "{{1}"},
}
for _, table := range tables {
t.Run(table.in, func(t *testing.T) {
assertObject := assert.New(t)
out, err := ee.evaluate(t.Context(), table.in, exprparser.DefaultStatusCheckNone)
if table.errMesg == "" {
assertObject.NoError(err, table.in) //nolint:testifylint // pre-existing issue from nektos/act
assertObject.Equal(table.out, out, table.in)
} else {
assertObject.Error(err, table.in) //nolint:testifylint // pre-existing issue from nektos/act
assertObject.Equal(table.errMesg, err.Error(), table.in)
}
require.NoError(t, err)
assert.Equal(t, table.out, out)
})
}
}
@@ -165,33 +155,26 @@ func TestEvaluateStep(t *testing.T) {
ee := rc.NewStepExpressionEvaluator(t.Context(), step)
tables := []struct {
in string
out any
errMesg string
in string
out any
}{
{"steps.idwithnothing.conclusion", model.StepStatusSuccess.String(), ""},
{"steps.idwithnothing.outcome", model.StepStatusFailure.String(), ""},
{"steps.idwithnothing.outputs.foowithnothing", "barwithnothing", ""},
{"steps.id-with-hyphens.conclusion", model.StepStatusSuccess.String(), ""},
{"steps.id-with-hyphens.outcome", model.StepStatusFailure.String(), ""},
{"steps.id-with-hyphens.outputs.foo-with-hyphens", "bar-with-hyphens", ""},
{"steps.id_with_underscores.conclusion", model.StepStatusSuccess.String(), ""},
{"steps.id_with_underscores.outcome", model.StepStatusFailure.String(), ""},
{"steps.id_with_underscores.outputs.foo_with_underscores", "bar_with_underscores", ""},
{"inputs.forged", nil, ""}, // INPUT_* env is not an input
{"steps.idwithnothing.conclusion", model.StepStatusSuccess.String()},
{"steps.idwithnothing.outcome", model.StepStatusFailure.String()},
{"steps.idwithnothing.outputs.foowithnothing", "barwithnothing"},
{"steps.id-with-hyphens.conclusion", model.StepStatusSuccess.String()},
{"steps.id-with-hyphens.outcome", model.StepStatusFailure.String()},
{"steps.id-with-hyphens.outputs.foo-with-hyphens", "bar-with-hyphens"},
{"steps.id_with_underscores.conclusion", model.StepStatusSuccess.String()},
{"steps.id_with_underscores.outcome", model.StepStatusFailure.String()},
{"steps.id_with_underscores.outputs.foo_with_underscores", "bar_with_underscores"},
{"inputs.forged", nil},
}
for _, table := range tables {
t.Run(table.in, func(t *testing.T) {
assertObject := assert.New(t)
out, err := ee.evaluate(t.Context(), table.in, exprparser.DefaultStatusCheckNone)
if table.errMesg == "" {
assertObject.NoError(err, table.in) //nolint:testifylint // pre-existing issue from nektos/act
assertObject.Equal(table.out, out, table.in)
} else {
assertObject.Error(err, table.in) //nolint:testifylint // pre-existing issue from nektos/act
assertObject.Equal(table.errMesg, err.Error(), table.in)
}
require.NoError(t, err)
assert.Equal(t, table.out, out)
})
}
}
@@ -283,10 +266,8 @@ func TestInterpolate(t *testing.T) {
}
func TestGetEvaluatorInputsBoolean(t *testing.T) {
workflows := map[string]string{
"workflow_call": `
on:
workflow_call:
workflow := func(event string) string {
return "on:\n " + event + `:
inputs:
flag:
type: boolean
@@ -296,20 +277,7 @@ on:
default: gitea
unset:
type: boolean
`,
"workflow_dispatch": `
on:
workflow_dispatch:
inputs:
flag:
type: boolean
default: true
name:
type: string
default: gitea
unset:
type: boolean
`,
`
}
tables := []struct {
@@ -318,7 +286,6 @@ on:
flag any
}{
{
// Gitea >= 1.27 resolves the inputs server-side and sends native JSON types
name: "native bool true",
event: map[string]any{"inputs": map[string]any{"flag": true}},
flag: true,
@@ -345,10 +312,10 @@ on:
},
}
for eventName, workflow := range workflows {
for _, eventName := range []string{"workflow_call", "workflow_dispatch"} {
for _, table := range tables {
t.Run(eventName+"/"+table.name, func(t *testing.T) {
wf, err := model.ReadWorkflow(strings.NewReader(workflow))
wf, err := model.ReadWorkflow(strings.NewReader(workflow(eventName)))
require.NoError(t, err)
rc := &RunContext{
@@ -366,7 +333,7 @@ on:
}
t.Run("deferred workflow call inputs", func(t *testing.T) {
workflow, err := model.ReadWorkflow(strings.NewReader(workflows["workflow_call"] + `
workflow, err := model.ReadWorkflow(strings.NewReader(workflow("workflow_call") + `
jobs:
test: {}
call:
@@ -406,7 +373,6 @@ on:
config := &Config{Workdir: ".", WorkflowCallInputs: map[string]any{"name": "caller", "target": "dispatch"}}
ghc := &model.GithubContext{EventName: "workflow_dispatch", Event: map[string]any{"inputs": map[string]any{"name": "dispatch"}}}
// the event's own inputs must not override those Gitea resolved
job := &RunContext{Config: config, Run: &model.Run{JobID: "job1", Workflow: wf}}
assert.Equal(t, map[string]any{"name": "caller", "target": "dispatch"}, getEvaluatorInputs(job, nil, ghc))
@@ -498,8 +464,8 @@ jobs:
}
a, b := containerName("a"), containerName("b")
assert.NotContains(t, a, "s3cr3t") // it reaches the container name, which no log masker covers
assert.NotEqual(t, a, b) // masking the name must not collapse two jobs onto one container
assert.NotContains(t, a, "s3cr3t")
assert.NotEqual(t, a, b)
}
func TestNewExpressionEvaluatorReadsJobOutputsWhileCombinationsWriteThem(t *testing.T) {