mirror of
https://gitea.com/gitea/runner.git
synced 2026-08-29 23:37:45 +00:00
enhance: add runner.tool_cache_mode and default it to none (#1171)
The current shared tools cache is not concurrency-safe, e.g. multiple jobs can write and corrupt it, for example `setup-go` with explicit go version under concurrency reliably corrupts the tool cache and fails all jobs. This adds a new `runner.tool_cache_mode` (and `--tool-cache-mode` exec option) option which defaults to unshared tools cache: - `none` mounts nothing, so a job uses what its image ships there and discards what it installs - `shared` keeps the single volume every job reuses, and warns when `runner.capacity` is above 1 Under `none` effective tool cache can only come from the image or host, which is the same as it is on GitHub Actions which ships many preinstalled tools in its fat VM images. Co-authored-by: bircni <bircni@icloud.com> Reviewed-on: https://gitea.com/gitea/runner/pulls/1171 Reviewed-by: bircni <bircni@icloud.com> Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -60,6 +61,7 @@ type Runner struct {
|
||||
ActionShallowClone *bool `yaml:"action_shallow_clone"` // ActionShallowClone fetches only the requested ref of an action repository at depth 1 instead of cloning every branch's full history. It is a pointer to distinguish between false and not set; if not set, it defaults to true.
|
||||
SetActEnv *bool `yaml:"set_act_env"` // SetActEnv controls whether the ACT=true environment variable is injected into jobs. It is a pointer to distinguish between false and not set; if not set, it defaults to true. Set it to false so workflows gated on `if: ${{ !env.ACT }}` behave like on GitHub.
|
||||
AllocatePTY bool `yaml:"allocate_pty"` // AllocatePTY allocates a pseudo-TTY for each step's process. Default is false, matching GitHub's actions/runner. Enable only for jobs that need an interactive terminal; tools like docker build emit redrawing progress frames into the captured log when a TTY is present. Applies to both host and docker backends.
|
||||
ToolCacheMode string `yaml:"tool_cache_mode"` // ToolCacheMode is what the runner mounts at RUNNER_TOOL_CACHE on both backends: ToolCacheModeNone or ToolCacheModeShared.
|
||||
PostTaskScript string `yaml:"post_task_script"` // PostTaskScript is the path to an executable script run on the host after each task's cleanup completes. Empty disables the hook. On Windows use .exe/.bat/.cmd; PowerShell (.ps1) is not supported yet as the configured path.
|
||||
PostTaskScriptTimeout time.Duration `yaml:"post_task_script_timeout"` // PostTaskScriptTimeout caps how long the post-task script may run. Default is 5m when post_task_script is set.
|
||||
Hooks RunnerHooks `yaml:"hooks"` // Hooks are scripts run inside the job environment around the job's steps.
|
||||
@@ -143,6 +145,14 @@ type Container struct {
|
||||
ServiceReadyTimeout time.Duration `yaml:"service_ready_timeout"` // ServiceReadyTimeout bounds how long a job waits for a service container that declares a healthcheck to report healthy. Negative disables waiting.
|
||||
}
|
||||
|
||||
// Values of Runner.ToolCacheMode: the runner mounts no tool cache, or one that every job reuses.
|
||||
const (
|
||||
ToolCacheModeNone = "none"
|
||||
ToolCacheModeShared = "shared"
|
||||
)
|
||||
|
||||
var ToolCacheModes = []string{ToolCacheModeNone, ToolCacheModeShared}
|
||||
|
||||
type ContainerNetworkCreateOptions struct {
|
||||
EnableIPv4 *bool `yaml:"enable_ipv4"` // Enable or disable IPv4 for the network (true for docker by default)
|
||||
EnableIPv6 *bool `yaml:"enable_ipv6"` // Enable or disable IPv6 for the network (false for docker by default)
|
||||
@@ -257,6 +267,12 @@ func LoadDefault(file string) (*Config, error) {
|
||||
if cfg.Container.WorkdirParent == "" {
|
||||
cfg.Container.WorkdirParent = "workspace"
|
||||
}
|
||||
if cfg.Runner.ToolCacheMode == "" {
|
||||
cfg.Runner.ToolCacheMode = ToolCacheModeNone
|
||||
}
|
||||
if !slices.Contains(ToolCacheModes, cfg.Runner.ToolCacheMode) {
|
||||
return nil, fmt.Errorf("invalid runner.tool_cache_mode %q: must be one of %q", cfg.Runner.ToolCacheMode, ToolCacheModes)
|
||||
}
|
||||
if cfg.Host.WorkdirParent == "" {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
@@ -314,6 +330,10 @@ func LoadDefault(file string) (*Config, error) {
|
||||
}
|
||||
|
||||
// Validate and fix invalid config combinations to prevent confusing behavior.
|
||||
if cfg.Runner.ToolCacheMode == ToolCacheModeShared && cfg.Runner.Capacity > 1 {
|
||||
log.Warnf("runner.tool_cache_mode %q with capacity %d: two jobs writing the same tool version at once corrupt it",
|
||||
ToolCacheModeShared, cfg.Runner.Capacity)
|
||||
}
|
||||
if cfg.Runner.FetchIntervalMax < cfg.Runner.FetchInterval {
|
||||
log.Warnf("fetch_interval_max (%v) is less than fetch_interval (%v), setting fetch_interval_max to fetch_interval",
|
||||
cfg.Runner.FetchIntervalMax, cfg.Runner.FetchInterval)
|
||||
|
||||
Reference in New Issue
Block a user