summaryrefslogtreecommitdiffstats
path: root/internal/pkg/config/config.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/pkg/config/config.go')
-rw-r--r--internal/pkg/config/config.go166
1 files changed, 166 insertions, 0 deletions
diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go
new file mode 100644
index 0000000..a1536b3
--- /dev/null
+++ b/internal/pkg/config/config.go
@@ -0,0 +1,166 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package config
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/joho/godotenv"
+ log "github.com/sirupsen/logrus"
+ "gopkg.in/yaml.v3"
+)
+
+// Log represents the configuration for logging.
+type Log struct {
+ Level string `yaml:"level"` // Level indicates the logging level.
+}
+
+// Runner represents the configuration for the runner.
+type Runner struct {
+ File string `yaml:"file"` // File specifies the file path for the runner.
+ Capacity int `yaml:"capacity"` // Capacity specifies the capacity of the runner.
+ Envs map[string]string `yaml:"envs"` // Envs stores environment variables for the runner.
+ EnvFile string `yaml:"env_file"` // EnvFile specifies the path to the file containing environment variables for the runner.
+ Timeout time.Duration `yaml:"timeout"` // Timeout specifies the duration for runner timeout.
+ ShutdownTimeout time.Duration `yaml:"shutdown_timeout"` // ShutdownTimeout specifies the duration to wait for running jobs to complete during a shutdown of the runner.
+ Insecure bool `yaml:"insecure"` // Insecure indicates whether the runner operates in an insecure mode.
+ FetchTimeout time.Duration `yaml:"fetch_timeout"` // FetchTimeout specifies the timeout duration for fetching resources.
+ FetchInterval time.Duration `yaml:"fetch_interval"` // FetchInterval specifies the interval duration for fetching resources.
+ ReportInterval time.Duration `yaml:"report_interval"` // ReportInterval specifies the interval duration for reporting status and logs of a running job.
+ Labels []string `yaml:"labels"` // Labels specify the labels of the runner. Labels are declared on each startup
+}
+
+// Cache represents the configuration for caching.
+type Cache struct {
+ Enabled *bool `yaml:"enabled"` // Enabled indicates whether caching is enabled. It is a pointer to distinguish between false and not set. If not set, it will be true.
+ Dir string `yaml:"dir"` // Dir specifies the directory path for caching.
+ Host string `yaml:"host"` // Host specifies the caching host.
+ Port uint16 `yaml:"port"` // Port specifies the caching port.
+ ExternalServer string `yaml:"external_server"` // ExternalServer specifies the URL of external cache server
+}
+
+// Container represents the configuration for the container.
+type Container struct {
+ Network string `yaml:"network"` // Network specifies the network for the container.
+ NetworkMode string `yaml:"network_mode"` // Deprecated: use Network instead. Could be removed after Gitea 1.20
+ EnableIPv6 bool `yaml:"enable_ipv6"` // EnableIPv6 indicates whether the network is created with IPv6 enabled.
+ Privileged bool `yaml:"privileged"` // Privileged indicates whether the container runs in privileged mode.
+ Options string `yaml:"options"` // Options specifies additional options for the container.
+ WorkdirParent string `yaml:"workdir_parent"` // WorkdirParent specifies the parent directory for the container's working directory.
+ ValidVolumes []string `yaml:"valid_volumes"` // ValidVolumes specifies the volumes (including bind mounts) can be mounted to containers.
+ DockerHost string `yaml:"docker_host"` // DockerHost specifies the Docker host. It overrides the value specified in environment variable DOCKER_HOST.
+ ForcePull bool `yaml:"force_pull"` // Pull docker image(s) even if already present
+}
+
+// Host represents the configuration for the host.
+type Host struct {
+ WorkdirParent string `yaml:"workdir_parent"` // WorkdirParent specifies the parent directory for the host's working directory.
+}
+
+// Config represents the overall configuration.
+type Config struct {
+ Log Log `yaml:"log"` // Log represents the configuration for logging.
+ Runner Runner `yaml:"runner"` // Runner represents the configuration for the runner.
+ Cache Cache `yaml:"cache"` // Cache represents the configuration for caching.
+ Container Container `yaml:"container"` // Container represents the configuration for the container.
+ Host Host `yaml:"host"` // Host represents the configuration for the host.
+}
+
+// Tune the config settings accordingly to the Forgejo instance that will be used.
+func (c *Config) Tune(instanceURL string) {
+ if instanceURL == "https://codeberg.org" {
+ if c.Runner.FetchInterval < 30*time.Second {
+ log.Info("The runner is configured to be used by a public instance, fetch interval is set to 30 seconds.")
+ c.Runner.FetchInterval = 30 * time.Second
+ }
+ }
+}
+
+// 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{}
+ if file != "" {
+ content, err := os.ReadFile(file)
+ if err != nil {
+ return nil, fmt.Errorf("open config file %q: %w", file, err)
+ }
+ if err := yaml.Unmarshal(content, cfg); err != nil {
+ return nil, fmt.Errorf("parse config file %q: %w", file, err)
+ }
+ }
+ compatibleWithOldEnvs(file != "", cfg)
+
+ if cfg.Runner.EnvFile != "" {
+ if stat, err := os.Stat(cfg.Runner.EnvFile); err == nil && !stat.IsDir() {
+ envs, err := godotenv.Read(cfg.Runner.EnvFile)
+ if err != nil {
+ return nil, fmt.Errorf("read env file %q: %w", cfg.Runner.EnvFile, err)
+ }
+ if cfg.Runner.Envs == nil {
+ cfg.Runner.Envs = map[string]string{}
+ }
+ for k, v := range envs {
+ cfg.Runner.Envs[k] = v
+ }
+ }
+ }
+
+ if cfg.Log.Level == "" {
+ cfg.Log.Level = "info"
+ }
+ if cfg.Runner.File == "" {
+ cfg.Runner.File = ".runner"
+ }
+ if cfg.Runner.Capacity <= 0 {
+ cfg.Runner.Capacity = 1
+ }
+ if cfg.Runner.Timeout <= 0 {
+ cfg.Runner.Timeout = 3 * time.Hour
+ }
+ if cfg.Cache.Enabled == nil {
+ b := true
+ cfg.Cache.Enabled = &b
+ }
+ if *cfg.Cache.Enabled {
+ if cfg.Cache.Dir == "" {
+ home, _ := os.UserHomeDir()
+ cfg.Cache.Dir = filepath.Join(home, ".cache", "actcache")
+ }
+ }
+ if cfg.Container.WorkdirParent == "" {
+ cfg.Container.WorkdirParent = "workspace"
+ }
+ if cfg.Host.WorkdirParent == "" {
+ home, _ := os.UserHomeDir()
+ cfg.Host.WorkdirParent = filepath.Join(home, ".cache", "act")
+ }
+ if cfg.Runner.FetchTimeout <= 0 {
+ cfg.Runner.FetchTimeout = 5 * time.Second
+ }
+ if cfg.Runner.FetchInterval <= 0 {
+ cfg.Runner.FetchInterval = 2 * time.Second
+ }
+ if cfg.Runner.ReportInterval <= 0 {
+ cfg.Runner.ReportInterval = time.Second
+ }
+
+ // although `container.network_mode` will be deprecated, but we have to be compatible with it for now.
+ if cfg.Container.NetworkMode != "" && cfg.Container.Network == "" {
+ log.Warn("You are trying to use deprecated configuration item of `container.network_mode`, please use `container.network` instead.")
+ if cfg.Container.NetworkMode == "bridge" {
+ // Previously, if the value of `container.network_mode` is `bridge`, we will create a new network for job.
+ // But “bridge” is easily confused with the bridge network created by Docker by default.
+ // So we set the value of `container.network` to empty string to make `act_runner` automatically create a new network for job.
+ cfg.Container.Network = ""
+ } else {
+ cfg.Container.Network = cfg.Container.NetworkMode
+ }
+ }
+
+ return cfg, nil
+}