diff --git a/act/runner/action.go b/act/runner/action.go index e205c0b7..9e086415 100644 --- a/act/runner/action.go +++ b/act/runner/action.go @@ -183,8 +183,7 @@ func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction if err := maybeCopyToActionDir(ctx, step, actionDir, actionPath, containerActionDir); err != nil { return err } - - containerArgs := []string{"node", path.Join(containerActionDir, action.Runs.Main)} + containerArgs := []string{rc.GetNodeToolFullPath(ctx), path.Join(containerActionDir, action.Runs.Main)} logger.Debugf("executing remote job container: %s", containerArgs) rc.ApplyExtraPath(ctx, step.getEnv()) @@ -569,14 +568,7 @@ func runPreStep(step actionStep) common.Executor { return err } - var containerArgs []string - - 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)} - } + containerArgs := []string{rc.GetNodeToolFullPath(ctx), path.Join(containerActionDir, action.Runs.Pre)} logger.Debugf("executing remote job container: %s", containerArgs) rc.ApplyExtraPath(ctx, step.getEnv()) @@ -707,8 +699,9 @@ func runPostStep(step actionStep) common.Executor { case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20: 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) rc.ApplyExtraPath(ctx, step.getEnv()) diff --git a/act/runner/action_composite.go b/act/runner/action_composite.go index fc173de4..2839aa97 100644 --- a/act/runner/action_composite.go +++ b/act/runner/action_composite.go @@ -64,16 +64,17 @@ func newCompositeRunContext(ctx context.Context, parent *RunContext, step action }, }, }, - Config: &configCopy, - StepResults: map[string]*model.StepResult{}, - JobContainer: parent.JobContainer, - ActionPath: actionPath, - Env: env, - GlobalEnv: parent.GlobalEnv, - Masks: parent.Masks, - ExtraPath: parent.ExtraPath, - Parent: parent, - EventJSON: parent.EventJSON, + Config: &configCopy, + StepResults: map[string]*model.StepResult{}, + JobContainer: parent.JobContainer, + ActionPath: actionPath, + Env: env, + GlobalEnv: parent.GlobalEnv, + Masks: parent.Masks, + ExtraPath: parent.ExtraPath, + Parent: parent, + EventJSON: parent.EventJSON, + nodeToolFullPath: parent.nodeToolFullPath, } compositerc.ExprEval = compositerc.NewExpressionEvaluator(ctx) diff --git a/act/runner/action_test.go b/act/runner/action_test.go index 36ee14f7..52658432 100644 --- a/act/runner/action_test.go +++ b/act/runner/action_test.go @@ -164,6 +164,7 @@ func TestActionRunner(t *testing.T) { }, }, }, + nodeToolFullPath: "node", }, action: &model.Action{ Inputs: map[string]model.Input{ @@ -208,6 +209,7 @@ func TestActionRunner(t *testing.T) { "name": "state value", }, }, + nodeToolFullPath: "node", }, action: &model.Action{ Runs: model.ActionRuns{ diff --git a/act/runner/expression.go b/act/runner/expression.go index ef89fceb..41881328 100644 --- a/act/runner/expression.go +++ b/act/runner/expression.go @@ -196,7 +196,7 @@ func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect. Mode: 0o644, 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, "", "")). Finally(func(context.Context) error { rc.JobContainer.ReplaceLogWriter(stdout, stderr) diff --git a/act/runner/job_executor.go b/act/runner/job_executor.go index ed40563f..0907bac3 100644 --- a/act/runner/job_executor.go +++ b/act/runner/job_executor.go @@ -141,6 +141,7 @@ func newJobExecutor(info jobInfo, sf stepFactory, rc *RunContext) common.Executo }) pipeline := make([]common.Executor, 0) + pipeline = append(pipeline, rc.InitializeNodeTool()) pipeline = append(pipeline, preSteps...) pipeline = append(pipeline, steps...) diff --git a/act/runner/job_executor_test.go b/act/runner/job_executor_test.go index ac7725f6..6ba28d23 100644 --- a/act/runner/job_executor_test.go +++ b/act/runner/job_executor_test.go @@ -257,7 +257,8 @@ func TestNewJobExecutor(t *testing.T) { }, }, }, - Config: &Config{}, + Config: &Config{}, + nodeToolFullPath: "node", } rc.ExprEval = rc.NewExpressionEvaluator(ctx) executorOrder := make([]string, 0) diff --git a/act/runner/run_context.go b/act/runner/run_context.go index b9f296e3..1506a4a5 100644 --- a/act/runner/run_context.go +++ b/act/runner/run_context.go @@ -19,6 +19,7 @@ import ( "runtime" "strings" "text/template" + "time" "github.com/docker/docker/api/types/network" "github.com/docker/go-connections/nat" @@ -52,6 +53,7 @@ type RunContext struct { Masks []string cleanUpJobContainer common.Executor caller *caller // job calling this RunContext (reusable workflows) + nodeToolFullPath 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) { if len(rc.ExtraPath) > 0 { path := rc.JobContainer.GetPathVariableName() diff --git a/act/runner/step_action_local_test.go b/act/runner/step_action_local_test.go index c4b63459..e69959ee 100644 --- a/act/runner/step_action_local_test.go +++ b/act/runner/step_action_local_test.go @@ -249,7 +249,8 @@ func TestStepActionLocalPost(t *testing.T) { }, }, }, - StepResults: tt.initialStepResults, + StepResults: tt.initialStepResults, + nodeToolFullPath: "node", }, Step: tt.stepModel, action: tt.actionModel, diff --git a/act/runner/step_action_remote_test.go b/act/runner/step_action_remote_test.go index 9dcc3383..3f3a59f3 100644 --- a/act/runner/step_action_remote_test.go +++ b/act/runner/step_action_remote_test.go @@ -573,6 +573,7 @@ func TestStepActionRemotePost(t *testing.T) { }, StepResults: tt.initialStepResults, IntraActionState: tt.IntraActionState, + nodeToolFullPath: "node", }, Step: tt.stepModel, action: tt.actionModel,