fix: keep a step's own with: values out of its inputs context (#1192)

A step's `if:`, its `continue-on-error:` and its `run:` script resolved `inputs.*` from the step's own `INPUT_*` env. A `with:` key colliding with a workflow input flipped conditions, and any `INPUT_`-shaped variable from `env:` or a `GITHUB_ENV` write forged an input that never existed.

GitHub evaluates all three in the enclosing scope: the workflow inputs, or for a composite action's steps that action's inputs. Action-input interpolation is the one place that legitimately sees a step's own `with:`, so it keeps its own evaluator.

Fixes https://gitea.com/gitea/runner/issues/1191, ports https://github.com/nektos/act/pull/2473 and extends it to the pre and post stages.

---------

Co-authored-by: silverwind <me@silverwind.io>
Reviewed-on: https://gitea.com/gitea/runner/pulls/1192
Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com>
Co-authored-by: ABiscuitttt <773542570@qq.com>
This commit is contained in:
ABiscuitttt
2026-08-26 14:45:05 +00:00
committed by silverwind
parent 0712b2a7a1
commit 212909db7b
10 changed files with 81 additions and 23 deletions
+14
View File
@@ -279,6 +279,13 @@ func TestIsStepEnabled(t *testing.T) {
Conclusion: model.StepStatusFailure,
}
assertObject.True(isStepEnabled(context.Background(), step.getStepModel().If.Value, step, stepStageMain))
// neither env nor the step's own with: values are inputs, at any stage
step = createTestStep(t, "if: inputs.forged")
step.getRunContext().Env["INPUT_FORGED"] = "leaked"
*step.getEnv() = map[string]string{"INPUT_FORGED": "leaked"}
assertObject.False(isStepEnabled(context.Background(), step.getStepModel().If.Value, step, stepStageMain))
assertObject.False(isStepEnabled(context.Background(), step.getStepModel().If.Value, step, stepStagePost))
}
func TestIsContinueOnError(t *testing.T) {
@@ -339,6 +346,13 @@ func TestIsContinueOnError(t *testing.T) {
assertObject.False(continueOnError)
assertObject.NoError(err) //nolint:testifylint // pre-existing issue from nektos/act
// the step's own with: values are not inputs
step = createTestStep(t, "continue-on-error: ${{ inputs.forged }}")
*step.getEnv() = map[string]string{"INPUT_FORGED": "true"}
continueOnError, err = isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain)
assertObject.False(continueOnError)
require.NoError(t, err)
// expression parse error
step = createTestStep(t, "continue-on-error: ${{ 'test' != test }}")
continueOnError, err = isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain)