diff --git a/act/container/container_types.go b/act/container/container_types.go index 4fa25896..70e6be2f 100644 --- a/act/container/container_types.go +++ b/act/container/container_types.go @@ -25,11 +25,7 @@ import ( var hostOS = runtime.GOOS // replaced in tests -// DrainGracePeriod bounds how long we wait for an output-copy goroutine to -// finish draining a container's output before returning, so that neither a -// cancellation (waitForCommand) nor a normal container exit (wait) truncates -// the tail of the log. It is a safety bound: in the common case the stream -// reaches EOF and the goroutine returns well before this elapses. +// DrainGracePeriod caps the wait for container output to drain so the log tail is not truncated const DrainGracePeriod = 2 * time.Second // ExitCodeError reports a non-zero process exit code from a container command. diff --git a/act/runner/run_context.go b/act/runner/run_context.go index 383e012c..b06964ef 100644 --- a/act/runner/run_context.go +++ b/act/runner/run_context.go @@ -380,7 +380,7 @@ func splitVolumes(specs []string) ([]string, map[string]string, map[string]bool) return binds, mounts, targets } -// Returns the binds and mounts for the container, resolving paths as appropriate, and the task workspace the runner binds +// Returns the container's binds, mounts and bound task workspace, resolving paths as appropriate func (rc *RunContext) GetBindsAndMounts(ctx context.Context) ([]string, map[string]string, string) { name := rc.jobContainerName() ext := container.LinuxContainerEnvironmentExtensions{} @@ -842,7 +842,7 @@ func (rc *RunContext) cleanupJobResources(networkName string, createAndDeleteNet } } -// exits 3 unless $1 is a mountpoint in mountinfo $2, at least two levels deep, with no mount below it for rm to cross into +// exits 3 unless workspace $1 is safe to empty per mountinfo $2 const emptyTaskWorkspaceScript = `case "$1" in /?*/?*) ;; *) exit 3 ;; esac mounted= while read -r _ _ _ _ point _; do @@ -851,9 +851,9 @@ done <"$2" [ "$mounted" ] || exit 3 rm -rf "$1"/* "$1"/.[!.]* "$1"/..?*` -var runnerCanRemoveJobFiles = runtime.GOOS != "linux" || os.Geteuid() == 0 // root, or a desktop VM mapping container files to the user, replaced in tests +var runnerCanRemoveJobFiles = runtime.GOOS != "linux" || os.Geteuid() == 0 // root, or a desktop VM mapping file ownership, replaced in tests -// empties the workspace as root, on root-owned PATH dirs only, for a runner that may not own what the job wrote, called workflows share it +// runs as root with root-owned PATH dirs only, skipped for called workflows sharing the workspace func (rc *RunContext) emptyTaskWorkspace(ctx context.Context) { if rc.taskWorkspace == "" || rc.caller != nil || runnerCanRemoveJobFiles { return diff --git a/docs/post-task-script.md b/docs/post-task-script.md index b40fb071..cca3f4bb 100644 --- a/docs/post-task-script.md +++ b/docs/post-task-script.md @@ -9,7 +9,7 @@ It is configured under `runner.post_task_script` in the runner YAML config (see For each task, execution order is: 1. Workflow runs (steps, actions, containers). -2. In-job cleanup (action `post:` steps, emptying a bind-mounted workspace from inside the job container when a non-root runner on Linux may not own its files, container stop/remove). +2. In-job cleanup (action `post:` steps, container stop/remove). 3. Job outputs are reported to Gitea. 4. Bind-workdir workspace removal, when `container.bind_workdir` is enabled. 5. **Post-task script** (this hook).