From 3dcfd6ea3d359577aaef8621e86caa7f78fb34d0 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Fri, 7 Jul 2023 08:28:54 +0000 Subject: [PATCH] Run as cache server (#275) This PR - adds the `cache-server` command so act_runner can run as a cache server. When running as a cache server, act_runner only processes the requests related to cache and does not run jobs. - adds the `external_server` configuration for cache. If specified, act_runner will use this URL as the ACTIONS_CACHE_URL instead of starting a cache server itself. Reviewed-on: https://gitea.com/gitea/act_runner/pulls/275 Co-authored-by: Zettat123 Co-committed-by: Zettat123 --- internal/app/cmd/cache-server.go | 69 +++++++++++++++++++++++++ internal/app/cmd/cmd.go | 13 +++++ internal/app/run/runner.go | 24 +++++---- internal/pkg/config/config.example.yaml | 4 ++ internal/pkg/config/config.go | 9 ++-- 5 files changed, 105 insertions(+), 14 deletions(-) create mode 100644 internal/app/cmd/cache-server.go diff --git a/internal/app/cmd/cache-server.go b/internal/app/cmd/cache-server.go new file mode 100644 index 0000000..21b3352 --- /dev/null +++ b/internal/app/cmd/cache-server.go @@ -0,0 +1,69 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package cmd + +import ( + "context" + "fmt" + "os" + "os/signal" + + "gitea.com/gitea/act_runner/internal/pkg/config" + + "github.com/nektos/act/pkg/artifactcache" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +type cacheServerArgs struct { + Dir string + Host string + Port uint16 +} + +func runCacheServer(ctx context.Context, configFile *string, cacheArgs *cacheServerArgs) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + cfg, err := config.LoadDefault(*configFile) + if err != nil { + return fmt.Errorf("invalid configuration: %w", err) + } + + initLogging(cfg) + + var ( + dir = cfg.Cache.Dir + host = cfg.Cache.Host + port = cfg.Cache.Port + ) + + // cacheArgs has higher priority + if cacheArgs.Dir != "" { + dir = cacheArgs.Dir + } + if cacheArgs.Host != "" { + host = cacheArgs.Host + } + if cacheArgs.Port != 0 { + port = cacheArgs.Port + } + + cacheHandler, err := artifactcache.StartHandler( + dir, + host, + port, + log.StandardLogger().WithField("module", "cache_request"), + ) + if err != nil { + return err + } + + log.Infof("cache server is listening on %v", cacheHandler.ExternalURL()) + + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + <-c + + return nil + } +} diff --git a/internal/app/cmd/cmd.go b/internal/app/cmd/cmd.go index f6d2bda..254e2f0 100644 --- a/internal/app/cmd/cmd.go +++ b/internal/app/cmd/cmd.go @@ -63,6 +63,19 @@ func Execute(ctx context.Context) { }, }) + // ./act_runner cache-server + var cacheArgs cacheServerArgs + cacheCmd := &cobra.Command{ + Use: "cache-server", + Short: "Start a cache server for the cache action", + Args: cobra.MaximumNArgs(0), + RunE: runCacheServer(ctx, &configFile, &cacheArgs), + } + cacheCmd.Flags().StringVarP(&cacheArgs.Dir, "dir", "d", "", "Cache directory") + cacheCmd.Flags().StringVarP(&cacheArgs.Host, "host", "s", "", "Host of the cache server") + cacheCmd.Flags().Uint16VarP(&cacheArgs.Port, "port", "p", 0, "Port of the cache server") + rootCmd.AddCommand(cacheCmd) + // hide completion command rootCmd.CompletionOptions.HiddenDefaultCmd = true diff --git a/internal/app/run/runner.go b/internal/app/run/runner.go index abbfd34..d6be102 100644 --- a/internal/app/run/runner.go +++ b/internal/app/run/runner.go @@ -53,17 +53,21 @@ func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client) envs[k] = v } if cfg.Cache.Enabled == nil || *cfg.Cache.Enabled { - cacheHandler, err := artifactcache.StartHandler( - cfg.Cache.Dir, - cfg.Cache.Host, - cfg.Cache.Port, - log.StandardLogger().WithField("module", "cache_request"), - ) - if err != nil { - log.Errorf("cannot init cache server, it will be disabled: %v", err) - // go on + if cfg.Cache.ExternalServer != "" { + envs["ACTIONS_CACHE_URL"] = cfg.Cache.ExternalServer } else { - envs["ACTIONS_CACHE_URL"] = cacheHandler.ExternalURL() + "/" + cacheHandler, err := artifactcache.StartHandler( + cfg.Cache.Dir, + cfg.Cache.Host, + cfg.Cache.Port, + log.StandardLogger().WithField("module", "cache_request"), + ) + if err != nil { + log.Errorf("cannot init cache server, it will be disabled: %v", err) + // go on + } else { + envs["ACTIONS_CACHE_URL"] = cacheHandler.ExternalURL() + "/" + } } } diff --git a/internal/pkg/config/config.example.yaml b/internal/pkg/config/config.example.yaml index 773fd20..596bdbc 100644 --- a/internal/pkg/config/config.example.yaml +++ b/internal/pkg/config/config.example.yaml @@ -45,6 +45,10 @@ cache: # The port of the cache server. # 0 means to use a random available port. port: 0 + # The external cache server URL. Valid only when enable is true. + # If it's specified, act_runner will use this URL as the ACTIONS_CACHE_URL rather than start a server by itself. + # The URL should generally end with "/". + external_server: "" container: # Specifies the network to which the container will connect. diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 8f81cc8..8bc3e0d 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -34,10 +34,11 @@ type Runner struct { // 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. + 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.