mirror of
https://gitea.com/gitea/runner.git
synced 2026-08-29 15:27:45 +00:00
feat: add log.job.dir (#1165)
`log.job.dir` makes the runner write a copy of every task's log to that directory, as `<start time>-task-<id>.log`: the rows exactly as Gitea received them, with the same masking and the job's result on the last line. Off by default, and what Gitea shows does not change. `log.job.retention` (default `168h`) and `log.job.max_size` (default `1GB`) bound the directory. Documented in the README. --------- Co-authored-by: silverwind <me@silverwind.io> Reviewed-on: https://gitea.com/gitea/runner/pulls/1165 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com>
This commit is contained in:
@@ -1,13 +1,20 @@
|
||||
# Every option with its default value, all commented out. Read this file, do not copy it.
|
||||
# `./gitea-runner config init` writes a config file to copy the lines you change into.
|
||||
|
||||
# Logging for the runner process itself (messages printed to stderr).
|
||||
# This does not control how workflow step output is streamed to the Gitea UI;
|
||||
# tune that with runner.log_report_* below.
|
||||
# Logging for the runner process itself (messages printed to stderr), plus the copy of
|
||||
# each task's log kept under log.job. Neither controls how workflow step output is streamed
|
||||
# to the Gitea UI; tune that with runner.log_report_* below.
|
||||
log:
|
||||
# logrus severity: trace, debug, info, warn, error, fatal, panic.
|
||||
# trace and debug turn on caller/file:line in log lines. Default if omitted: info.
|
||||
#level: info
|
||||
# Write a copy of each task's log to dir as <start time>-task-<id>.log, so a job's output
|
||||
# survives a failure to send it to Gitea. A path turns them on, empty turns them off.
|
||||
# retention is how long a log is kept (0s keeps all), max_size caps one log (0 is no limit).
|
||||
#job:
|
||||
# dir: ""
|
||||
# retention: 168h
|
||||
# max_size: 1GB
|
||||
|
||||
runner:
|
||||
# Where to store the registration result.
|
||||
|
||||
@@ -38,9 +38,17 @@ const Minimal = `# Minimal config file. Every option it does not set keeps its d
|
||||
# "gitea-runner config generate" prints all options, "config set <key> <value>" sets one here.
|
||||
`
|
||||
|
||||
// Log represents the configuration for logging.
|
||||
// Log represents the runner process's own logging, plus the copy of each task's log it keeps.
|
||||
type Log struct {
|
||||
Level string `yaml:"level"` // Level indicates the logging level.
|
||||
Job LogJob `yaml:"job"` // Job configures the copy of each task's log kept on the runner host.
|
||||
}
|
||||
|
||||
// LogJob represents the configuration for the copy of each task's log kept on the runner host.
|
||||
type LogJob struct {
|
||||
Dir string `yaml:"dir"` // Dir is the directory the runner writes each task's log to. Empty, the default, writes none.
|
||||
Retention time.Duration `yaml:"retention"` // Retention deletes a task's log directory once it is older than this. Default 168h, 0s keeps them regardless of age.
|
||||
MaxSize Size `yaml:"max_size"` // MaxSize caps one task's log file. Default 1GB, 0 is no limit.
|
||||
}
|
||||
|
||||
// Runner represents the configuration for the runner.
|
||||
@@ -202,7 +210,8 @@ type Config struct {
|
||||
// LoadDefault returns the default configuration.
|
||||
// If file is not empty, it will be used to load the configuration.
|
||||
func LoadDefault(file string) (*Config, error) {
|
||||
cfg := &Config{Cache: DefaultCache()}
|
||||
// Seeded before the file is read, so a written 0 can mean off.
|
||||
cfg := &Config{Cache: DefaultCache(), Log: Log{Job: LogJob{Retention: 7 * 24 * time.Hour, MaxSize: 1024 * 1024 * 1024}}}
|
||||
definedRunnerKeys := map[string]bool{}
|
||||
if file != "" {
|
||||
content, err := os.ReadFile(file)
|
||||
|
||||
@@ -186,14 +186,14 @@ runner:
|
||||
assert.Equal(t, 5*time.Minute, cfg.Runner.PostTaskScriptTimeout)
|
||||
}
|
||||
|
||||
func TestLoadDefault_LoadsCacheEviction(t *testing.T) {
|
||||
write := func(t *testing.T, body string) string {
|
||||
t.Helper()
|
||||
path := filepath.Join(t.TempDir(), "config.yaml")
|
||||
require.NoError(t, os.WriteFile(path, []byte(body), 0o600))
|
||||
return path
|
||||
}
|
||||
func write(t *testing.T, body string) string {
|
||||
t.Helper()
|
||||
path := filepath.Join(t.TempDir(), "config.yaml")
|
||||
require.NoError(t, os.WriteFile(path, []byte(body), 0o600))
|
||||
return path
|
||||
}
|
||||
|
||||
func TestLoadDefault_LoadsCacheEviction(t *testing.T) {
|
||||
t.Run("sizes accept any spelling of the unit", func(t *testing.T) {
|
||||
cfg, err := LoadDefault(write(t, "cache:\n retention: 336h\n repo_size_limit: 50gb\n size_limit: 1TiB\n sweep_interval: 15m\n"))
|
||||
require.NoError(t, err)
|
||||
@@ -217,6 +217,14 @@ func TestLoadDefault_LoadsCacheEviction(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestLoadDefault_LoadsJobLogs(t *testing.T) {
|
||||
cfg, err := LoadDefault(write(t, "log:\n job:\n dir: /var/log/jobs\n retention: 0s\n max_size: 100MB\n"))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "/var/log/jobs", cfg.Log.Job.Dir)
|
||||
assert.Zero(t, cfg.Log.Job.Retention, "zero keeps every task directory")
|
||||
assert.Equal(t, Size(100*1024*1024), cfg.Log.Job.MaxSize)
|
||||
}
|
||||
|
||||
func TestLoadDefault_LoadsJobHooks(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "config.yaml")
|
||||
|
||||
Reference in New Issue
Block a user