diff --git a/pkg/runner/action.go b/pkg/runner/action.go index 3809359..75b2a33 100644 --- a/pkg/runner/action.go +++ b/pkg/runner/action.go @@ -179,7 +179,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()) @@ -533,7 +533,7 @@ func runPreStep(step actionStep) common.Executor { return err } - 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()) @@ -627,7 +627,7 @@ func runPostStep(step actionStep) common.Executor { 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/pkg/runner/action_composite.go b/pkg/runner/action_composite.go index 1a47aff..fee7e32 100644 --- a/pkg/runner/action_composite.go +++ b/pkg/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/pkg/runner/action_test.go b/pkg/runner/action_test.go index 36ee14f..5265843 100644 --- a/pkg/runner/action_test.go +++ b/pkg/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/pkg/runner/expression.go b/pkg/runner/expression.go index dca3538..cfd5d42 100644 --- a/pkg/runner/expression.go +++ b/pkg/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/pkg/runner/job_executor.go b/pkg/runner/job_executor.go index 148c9ff..c5a87dc 100644 --- a/pkg/runner/job_executor.go +++ b/pkg/runner/job_executor.go @@ -116,6 +116,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/pkg/runner/job_executor_test.go b/pkg/runner/job_executor_test.go index ac7725f..6ba28d2 100644 --- a/pkg/runner/job_executor_test.go +++ b/pkg/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/pkg/runner/run_context.go b/pkg/runner/run_context.go index 2bed0f8..8abc435 100644 --- a/pkg/runner/run_context.go +++ b/pkg/runner/run_context.go @@ -3,6 +3,7 @@ package runner import ( "archive/tar" "bufio" + "bytes" "context" "crypto/rand" "crypto/sha256" @@ -50,6 +51,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) { @@ -432,6 +434,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 rc.ExtraPath != nil && len(rc.ExtraPath) > 0 { path := rc.JobContainer.GetPathVariableName() diff --git a/pkg/runner/step_action_local_test.go b/pkg/runner/step_action_local_test.go index c4b6345..e69959e 100644 --- a/pkg/runner/step_action_local_test.go +++ b/pkg/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/pkg/runner/step_action_remote_test.go b/pkg/runner/step_action_remote_test.go index ec1028a..253ad40 100644 --- a/pkg/runner/step_action_remote_test.go +++ b/pkg/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,