fix: allow relocating the tool cache and mounting over runner paths (#1122)

1. Docker rejects two mounts on one target, so a `container.volumes:` or `--volume` aimed at `/opt/hostedtoolcache` failed the job with `Duplicate mount point`. Job and service volumes now displace the mount on the same path, and `name:/target:ro` no longer mounts read-write at the literal path `/target:ro`.
1. Setting `RUNNER_TOOL_CACHE` only changed what the variable said, the cache stayed where it was, so tools writing to it landed outside the mount and `${{ runner.tool_cache }}` disagreed with the variable. It now relocates the cache. Leaving it unset behaves as before.
1. Unknown `config.yaml` keys now warn instead of being dropped without a trace.

Fixes https://gitea.com/gitea/runner/issues/813

---------

Co-authored-by: bircni <bircni@icloud.com>
Reviewed-on: https://gitea.com/gitea/runner/pulls/1122
Reviewed-by: bircni <bircni@icloud.com>
Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
silverwind
2026-07-29 21:32:28 +00:00
committed by silverwind
parent e6c7ba3a15
commit 0192861155
10 changed files with 210 additions and 72 deletions

View File

@@ -4,6 +4,7 @@
package config
import (
"bytes"
"errors"
"fmt"
"maps"
@@ -143,6 +144,7 @@ func LoadDefault(file string) (*Config, error) {
if err := yaml.Unmarshal(content, cfg); err != nil {
return nil, fmt.Errorf("parse config file %q: %w", file, err)
}
warnUnknownKeys(file, content)
definedRunnerKeys, err = definedRunnerConfigKeys(content)
if err != nil {
return nil, fmt.Errorf("parse config file %q for defaults metadata: %w", file, err)
@@ -288,6 +290,21 @@ func LoadDefault(file string) (*Config, error) {
return cfg, nil
}
// warnUnknownKeys reports keys the config does not define, which are otherwise ignored
// without a trace. It only warns, so a config carrying keys from another runner version
// still loads.
func warnUnknownKeys(file string, content []byte) {
decoder := yaml.NewDecoder(bytes.NewReader(content))
decoder.KnownFields(true)
var typeErr *yaml.TypeError
if err := decoder.Decode(&Config{}); errors.As(err, &typeErr) {
for _, message := range typeErr.Errors {
log.Warnf("config file %q: %s, it will be ignored", file, message)
}
}
}
func definedRunnerConfigKeys(content []byte) (map[string]bool, error) {
var root yaml.Node
if err := yaml.Unmarshal(content, &root); err != nil {