From 183bb7af1b998411a196da15e191b86d380faf49 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Mon, 5 Jun 2023 09:07:17 +0000 Subject: [PATCH] Support for multiple default URLs for getting actions (#58) Partially resolve https://github.com/go-gitea/gitea/issues/24789. `act_runner` needs to be improved to parse `gitea_default_actions_url` after this PR merged (https://gitea.com/gitea/act_runner/pulls/200) Co-authored-by: Lunny Xiao Reviewed-on: https://gitea.com/gitea/act/pulls/58 Reviewed-by: Lunny Xiao Reviewed-by: Jason Song Co-authored-by: Zettat123 Co-committed-by: Zettat123 --- pkg/runner/runner.go | 3 ++- pkg/runner/step_action_remote.go | 34 +++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 27b332d..000d98c 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -63,7 +63,8 @@ type Config struct { ContainerNamePrefix string // the prefix of container name ContainerMaxLifetime time.Duration // the max lifetime of job containers ContainerNetworkMode docker_container.NetworkMode // the network mode of job containers (the value of --network) - DefaultActionInstance string // the default actions web site + DefaultActionInstance string // Deprecated: use DefaultActionsURLs instead. + DefaultActionsURLs []string // urls from gitea's `DEFAULT_ACTIONS_URL` config PlatformPicker func(labels []string) string // platform picker, it will take precedence over Platforms if isn't nil JobLoggerLevel *log.Level // the level of job logger Vars map[string]string // the list of variables set at the repository, environment, or organization levels. diff --git a/pkg/runner/step_action_remote.go b/pkg/runner/step_action_remote.go index 953a414..e86cca3 100644 --- a/pkg/runner/step_action_remote.go +++ b/pkg/runner/step_action_remote.go @@ -5,11 +5,13 @@ import ( "errors" "fmt" "io" + "net/http" "os" "path" "path/filepath" "regexp" "strings" + "time" gogit "github.com/go-git/go-git/v5" @@ -18,6 +20,8 @@ import ( "github.com/nektos/act/pkg/model" ) +var detectActionClient = http.Client{Timeout: 5 * time.Second} + type stepActionRemote struct { Step *model.Step RunContext *RunContext @@ -57,9 +61,14 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor { } } + cloneURL, err := sar.remoteAction.GetAvailableCloneURL(sar.RunContext.Config.DefaultActionsURLs) + if err != nil { + return fmt.Errorf("failed to get available clone url of [%s] action, error: %w", sar.Step.Uses, err) + } + actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), safeFilename(sar.Step.Uses)) gitClone := stepActionRemoteNewCloneExecutor(git.NewGitCloneExecutorInput{ - URL: sar.remoteAction.CloneURL(sar.RunContext.Config.DefaultActionInstance), + URL: cloneURL, Ref: sar.remoteAction.Ref, Dir: actionDir, Token: "", /* @@ -232,6 +241,29 @@ func (ra *remoteAction) IsCheckout() bool { return false } +func (ra *remoteAction) GetAvailableCloneURL(actionURLs []string) (string, error) { + for _, u := range actionURLs { + cloneURL := ra.CloneURL(u) + resp, err := detectActionClient.Get(cloneURL) + if err != nil { + return "", err + } + defer resp.Body.Close() + + switch resp.StatusCode { + case http.StatusOK: + return cloneURL, nil + case http.StatusNotFound: + continue + + default: + return "", fmt.Errorf("unexpected http status code: %d", resp.StatusCode) + } + } + + return "", fmt.Errorf("no available url found") +} + func newRemoteAction(action string) *remoteAction { // support http(s)://host/owner/repo@v3 for _, schema := range []string{"https://", "http://"} {