1
0
Fork 0
mirror of https://code.forgejo.org/forgejo/runner.git synced 2025-09-15 18:57:01 +00:00

[RDNF #21 updated] fix: make node tool non volatile (#2372) + added 'time import' (#168)

https://github.com/nektos/act/pull/2372

+ fix: make node tool non volatile
Currently downgrading node via setup-node can break later actions

+ fix it and lookup on startup

+ fix problems

Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Reviewed-on: https://code.forgejo.org/forgejo/act/pulls/168
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Andrii Chyrva <andrii.s.chyrva@hotmail.com>
Co-committed-by: Andrii Chyrva <andrii.s.chyrva@hotmail.com>
This commit is contained in:
Andrii Chyrva 2025-07-06 16:56:42 +00:00 committed by earl-warren
parent 3fe4f4fb7f
commit 6e1377c2b0
9 changed files with 68 additions and 24 deletions

View file

@ -183,8 +183,7 @@ func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction
if err := maybeCopyToActionDir(ctx, step, actionDir, actionPath, containerActionDir); err != nil { if err := maybeCopyToActionDir(ctx, step, actionDir, actionPath, containerActionDir); err != nil {
return err return err
} }
containerArgs := []string{rc.GetNodeToolFullPath(ctx), path.Join(containerActionDir, action.Runs.Main)}
containerArgs := []string{"node", path.Join(containerActionDir, action.Runs.Main)}
logger.Debugf("executing remote job container: %s", containerArgs) logger.Debugf("executing remote job container: %s", containerArgs)
rc.ApplyExtraPath(ctx, step.getEnv()) rc.ApplyExtraPath(ctx, step.getEnv())
@ -569,14 +568,7 @@ func runPreStep(step actionStep) common.Executor {
return err return err
} }
var containerArgs []string containerArgs := []string{rc.GetNodeToolFullPath(ctx), path.Join(containerActionDir, action.Runs.Pre)}
if action.Runs.Using == model.ActionRunsUsingSh {
rc.ActionPath = containerActionDir
containerArgs = []string{"sh", "-c", action.Runs.Pre}
} else {
containerArgs = []string{"node", path.Join(containerActionDir, action.Runs.Pre)}
}
logger.Debugf("executing remote job container: %s", containerArgs) logger.Debugf("executing remote job container: %s", containerArgs)
rc.ApplyExtraPath(ctx, step.getEnv()) rc.ApplyExtraPath(ctx, step.getEnv())
@ -707,8 +699,9 @@ func runPostStep(step actionStep) common.Executor {
case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20: case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20:
populateEnvsFromSavedState(step.getEnv(), step, rc) populateEnvsFromSavedState(step.getEnv(), step, rc)
populateEnvsFromInput(ctx, step.getEnv(), step.getActionModel(), rc)
containerArgs := []string{"node", path.Join(containerActionDir, action.Runs.Post)} containerArgs := []string{rc.GetNodeToolFullPath(ctx), path.Join(containerActionDir, action.Runs.Post)}
logger.Debugf("executing remote job container: %s", containerArgs) logger.Debugf("executing remote job container: %s", containerArgs)
rc.ApplyExtraPath(ctx, step.getEnv()) rc.ApplyExtraPath(ctx, step.getEnv())

View file

@ -74,6 +74,7 @@ func newCompositeRunContext(ctx context.Context, parent *RunContext, step action
ExtraPath: parent.ExtraPath, ExtraPath: parent.ExtraPath,
Parent: parent, Parent: parent,
EventJSON: parent.EventJSON, EventJSON: parent.EventJSON,
nodeToolFullPath: parent.nodeToolFullPath,
} }
compositerc.ExprEval = compositerc.NewExpressionEvaluator(ctx) compositerc.ExprEval = compositerc.NewExpressionEvaluator(ctx)

View file

@ -164,6 +164,7 @@ func TestActionRunner(t *testing.T) {
}, },
}, },
}, },
nodeToolFullPath: "node",
}, },
action: &model.Action{ action: &model.Action{
Inputs: map[string]model.Input{ Inputs: map[string]model.Input{
@ -208,6 +209,7 @@ func TestActionRunner(t *testing.T) {
"name": "state value", "name": "state value",
}, },
}, },
nodeToolFullPath: "node",
}, },
action: &model.Action{ action: &model.Action{
Runs: model.ActionRuns{ Runs: model.ActionRuns{

View file

@ -196,7 +196,7 @@ func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect.
Mode: 0o644, Mode: 0o644,
Body: hashfiles, Body: hashfiles,
}). }).
Then(rc.execJobContainer([]string{"node", path.Join(rc.JobContainer.GetActPath(), name)}, Then(rc.execJobContainer([]string{rc.GetNodeToolFullPath(ctx), path.Join(rc.JobContainer.GetActPath(), name)},
env, "", "")). env, "", "")).
Finally(func(context.Context) error { Finally(func(context.Context) error {
rc.JobContainer.ReplaceLogWriter(stdout, stderr) rc.JobContainer.ReplaceLogWriter(stdout, stderr)

View file

@ -141,6 +141,7 @@ func newJobExecutor(info jobInfo, sf stepFactory, rc *RunContext) common.Executo
}) })
pipeline := make([]common.Executor, 0) pipeline := make([]common.Executor, 0)
pipeline = append(pipeline, rc.InitializeNodeTool())
pipeline = append(pipeline, preSteps...) pipeline = append(pipeline, preSteps...)
pipeline = append(pipeline, steps...) pipeline = append(pipeline, steps...)

View file

@ -258,6 +258,7 @@ func TestNewJobExecutor(t *testing.T) {
}, },
}, },
Config: &Config{}, Config: &Config{},
nodeToolFullPath: "node",
} }
rc.ExprEval = rc.NewExpressionEvaluator(ctx) rc.ExprEval = rc.NewExpressionEvaluator(ctx)
executorOrder := make([]string, 0) executorOrder := make([]string, 0)

View file

@ -19,6 +19,7 @@ import (
"runtime" "runtime"
"strings" "strings"
"text/template" "text/template"
"time"
"github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/network"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
@ -52,6 +53,7 @@ type RunContext struct {
Masks []string Masks []string
cleanUpJobContainer common.Executor cleanUpJobContainer common.Executor
caller *caller // job calling this RunContext (reusable workflows) caller *caller // job calling this RunContext (reusable workflows)
nodeToolFullPath string
} }
func (rc *RunContext) AddMask(mask string) { func (rc *RunContext) AddMask(mask string) {
@ -592,6 +594,48 @@ func (rc *RunContext) execJobContainer(cmd []string, env map[string]string, user
} }
} }
func (rc *RunContext) InitializeNodeTool() common.Executor {
return func(ctx context.Context) error {
rc.GetNodeToolFullPath(ctx)
return nil
}
}
func (rc *RunContext) GetNodeToolFullPath(ctx context.Context) string {
if rc.nodeToolFullPath == "" {
timeed, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()
path := rc.JobContainer.GetPathVariableName()
cenv := map[string]string{}
var cpath string
if err := rc.JobContainer.UpdateFromImageEnv(&cenv)(ctx); err == nil {
if p, ok := cenv[path]; ok {
cpath = p
}
}
if len(cpath) == 0 {
cpath = rc.JobContainer.DefaultPathVariable()
}
cenv[path] = cpath
hout := &bytes.Buffer{}
herr := &bytes.Buffer{}
stdout, stderr := rc.JobContainer.ReplaceLogWriter(hout, herr)
err := rc.execJobContainer([]string{"node", "--no-warnings", "-e", "console.log(process.execPath)"},
cenv, "", "").
Finally(func(context.Context) error {
rc.JobContainer.ReplaceLogWriter(stdout, stderr)
return nil
})(timeed)
rawStr := strings.Trim(hout.String(), "\r\n")
if err == nil && !strings.ContainsAny(rawStr, "\r\n") {
rc.nodeToolFullPath = rawStr
} else {
rc.nodeToolFullPath = "node"
}
}
return rc.nodeToolFullPath
}
func (rc *RunContext) ApplyExtraPath(ctx context.Context, env *map[string]string) { func (rc *RunContext) ApplyExtraPath(ctx context.Context, env *map[string]string) {
if len(rc.ExtraPath) > 0 { if len(rc.ExtraPath) > 0 {
path := rc.JobContainer.GetPathVariableName() path := rc.JobContainer.GetPathVariableName()

View file

@ -250,6 +250,7 @@ func TestStepActionLocalPost(t *testing.T) {
}, },
}, },
StepResults: tt.initialStepResults, StepResults: tt.initialStepResults,
nodeToolFullPath: "node",
}, },
Step: tt.stepModel, Step: tt.stepModel,
action: tt.actionModel, action: tt.actionModel,

View file

@ -573,6 +573,7 @@ func TestStepActionRemotePost(t *testing.T) {
}, },
StepResults: tt.initialStepResults, StepResults: tt.initialStepResults,
IntraActionState: tt.IntraActionState, IntraActionState: tt.IntraActionState,
nodeToolFullPath: "node",
}, },
Step: tt.stepModel, Step: tt.stepModel,
action: tt.actionModel, action: tt.actionModel,