fix: preserve symlinked Node action entrypoints (#1202)

Node resolves an ESM main to its realpath but leaves `process.argv[1]` as passed. `/var/run/act` reaches the action through the `/var/run` -> `/run` symlink most images ship, so the two disagree and actions comparing them skip their own `run()`. Passing `--preserve-symlinks-main` makes them match.

Trade-off: an action whose `runs.main` is a symlink now resolves dependencies from the link's directory rather than the target's.

Fixes https://gitea.com/gitea/runner/issues/1201
Co-authored-by: silverwind <me@silverwind.io>
Reviewed-on: https://gitea.com/gitea/runner/pulls/1202
Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com>
Co-authored-by: bircni <bircni@noreply.gitea.com>
This commit is contained in:
bircni
2026-08-31 13:06:49 +00:00
committed by silverwind
parent 6c77065295
commit b9018aca31
4 changed files with 43 additions and 7 deletions
+8 -3
View File
@@ -185,7 +185,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 := nodeActionCommand(path.Join(containerActionDir, action.Runs.Main))
logger.Debugf("executing remote job container: %s", containerArgs)
rc.ApplyExtraPath(ctx, step.getEnv())
@@ -232,6 +232,11 @@ func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction
}
}
// /var/run is a symlink, so without the flag node's import.meta.url differs from argv[1], which ESM actions compare.
func nodeActionCommand(script string) []string {
return []string{"node", "--preserve-symlinks-main", script}
}
// https://github.com/nektos/act/issues/228#issuecomment-629709055
// files in .gitignore are not copied in a Docker container
// this causes issues with actions that ignore other important resources
@@ -592,7 +597,7 @@ func runPreStep(step actionStep) common.Executor {
return err
}
containerArgs := []string{"node", path.Join(containerActionDir, action.Runs.Pre)}
containerArgs := nodeActionCommand(path.Join(containerActionDir, action.Runs.Pre))
logger.Debugf("executing remote job container: %s", containerArgs)
rc.ApplyExtraPath(ctx, step.getEnv())
@@ -693,7 +698,7 @@ func runPostStep(step actionStep) common.Executor {
populateEnvsFromSavedState(step.getEnv(), step, rc)
containerArgs := []string{"node", path.Join(containerActionDir, action.Runs.Post)}
containerArgs := nodeActionCommand(path.Join(containerActionDir, action.Runs.Post))
logger.Debugf("executing remote job container: %s", containerArgs)
rc.ApplyExtraPath(ctx, step.getEnv())