diff --git a/act/artifactcache/handler.go b/act/artifactcache/handler.go index 71c00d52..62e8a097 100644 --- a/act/artifactcache/handler.go +++ b/act/artifactcache/handler.go @@ -234,7 +234,7 @@ func StartHandler(opts Options) (*Handler, error) { func (h *Handler) ExternalURL() string { // TODO: make the external url configurable if necessary - return fmt.Sprintf("http://%s:%d", h.outboundIP, h.port) + return "http://" + net.JoinHostPort(h.outboundIP, strconv.Itoa(h.port)) } func (h *Handler) baseURL(cred JobCredential) string { diff --git a/act/artifactcache/handler_test.go b/act/artifactcache/handler_test.go index 20ced3f6..e9364686 100644 --- a/act/artifactcache/handler_test.go +++ b/act/artifactcache/handler_test.go @@ -52,6 +52,10 @@ func signArtifactURL(h *Handler, id int64) string { return h.signedArtifactURL(JobCredential{}, uint64(id), time.Now().Add(artifactURLTTL)) } +func TestHandler_ExternalURL(t *testing.T) { + assert.Equal(t, "http://[2001:db8::1]:8080", (&Handler{outboundIP: "2001:db8::1", port: 8080}).ExternalURL()) +} + func TestHandler(t *testing.T) { dir := filepath.Join(t.TempDir(), "artifactcache") handler, err := StartHandler(Options{Dir: dir}) diff --git a/act/artifacts/server.go b/act/artifacts/server.go index df2cf1de..1d85fb3f 100644 --- a/act/artifacts/server.go +++ b/act/artifacts/server.go @@ -11,6 +11,7 @@ import ( "fmt" "io" "io/fs" + "net" "net/http" "os" "path/filepath" @@ -220,14 +221,14 @@ func Serve(ctx context.Context, artifactPath, addr, port string) context.CancelF downloads(router, artifactPath) server := &http.Server{ - Addr: fmt.Sprintf("%s:%s", addr, port), + Addr: net.JoinHostPort(addr, port), ReadHeaderTimeout: 2 * time.Second, Handler: router, } // run server go func() { - logger.Infof("Start server on http://%s:%s", addr, port) + logger.Infof("Start server on http://%s", server.Addr) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Fatal(err) } diff --git a/act/runner/run_context.go b/act/runner/run_context.go index 0f51a942..f8c51451 100644 --- a/act/runner/run_context.go +++ b/act/runner/run_context.go @@ -16,6 +16,7 @@ import ( "fmt" "io" maps0 "maps" + "net" "os" "path/filepath" "regexp" @@ -1646,7 +1647,7 @@ func imageOSFromImage(image string) string { func setActionRuntimeVars(rc *RunContext, env map[string]string) { actionsRuntimeURL := os.Getenv("ACTIONS_RUNTIME_URL") if actionsRuntimeURL == "" { - actionsRuntimeURL = fmt.Sprintf("http://%s:%s/", rc.Config.ArtifactServerAddr, rc.Config.ArtifactServerPort) + actionsRuntimeURL = "http://" + net.JoinHostPort(rc.Config.ArtifactServerAddr, rc.Config.ArtifactServerPort) + "/" } env["ACTIONS_RUNTIME_URL"] = actionsRuntimeURL diff --git a/act/runner/run_context_test.go b/act/runner/run_context_test.go index 89f30dcc..823543ac 100644 --- a/act/runner/run_context_test.go +++ b/act/runner/run_context_test.go @@ -1505,6 +1505,10 @@ func TestRunContextWithGithubEnvRunnerValues(t *testing.T) { rc := createRunsOnRunContext(t, "ubuntu-latest") rc.Config.RunnerName = "runner-1" rc.Config.Secrets = map[string]string{"ACTIONS_STEP_DEBUG": "true"} + t.Setenv("ACTIONS_RUNTIME_URL", "") + rc.Config.ArtifactServerPath = "artifacts" + rc.Config.ArtifactServerAddr = "2001:db8::1" + rc.Config.ArtifactServerPort = "8080" env := map[string]string{} rc.withGithubEnv(ctx, &model.GithubContext{Workspace: "/workspace/owner/repo"}, env) @@ -1513,4 +1517,5 @@ func TestRunContextWithGithubEnvRunnerValues(t *testing.T) { assert.Equal(t, "self-hosted", env["RUNNER_ENVIRONMENT"]) assert.Equal(t, "/workspace/owner", env["RUNNER_WORKSPACE"]) assert.Equal(t, "1", env["RUNNER_DEBUG"]) + assert.Equal(t, "http://[2001:db8::1]:8080/", env["ACTIONS_RUNTIME_URL"]) } diff --git a/e2e/gitea_fixture.go b/e2e/gitea_fixture.go index a0f71c66..a5d9b93c 100644 --- a/e2e/gitea_fixture.go +++ b/e2e/gitea_fixture.go @@ -160,7 +160,7 @@ func StartGitea(ctx context.Context, cli mobyclient.APIClient) (*GiteaFixture, e sharedNet, _ = selfNetwork(ctx, cli) ) if sharedNet != "" { - baseURL = fmt.Sprintf("http://%s:3000", name) + baseURL = "http://" + net.JoinHostPort(name, "3000") netConfig = &network.NetworkingConfig{ EndpointsConfig: map[string]*network.EndpointSettings{sharedNet: {}}, } @@ -170,7 +170,7 @@ func StartGitea(ctx context.Context, cli mobyclient.APIClient) (*GiteaFixture, e if err != nil { return nil, fmt.Errorf("find a free host port: %w", err) } - baseURL = fmt.Sprintf("http://%s:%d", host, port) + baseURL = "http://" + net.JoinHostPort(host.String(), strconv.Itoa(port)) hostConfig.PortBindings = network.PortMap{ containerPort: []network.PortBinding{{HostIP: host, HostPort: strconv.Itoa(port)}}, } diff --git a/internal/app/cmd/cache-server.go b/internal/app/cmd/cache-server.go index 72f86751..0ff68a34 100644 --- a/internal/app/cmd/cache-server.go +++ b/internal/app/cmd/cache-server.go @@ -6,8 +6,6 @@ package cmd import ( "errors" "fmt" - "os" - "os/signal" "gitea.com/gitea/runner/act/artifactcache" "gitea.com/gitea/runner/internal/app/run" @@ -67,10 +65,8 @@ func runCacheServer(configFile *string, cacheArgs *cacheServerArgs) func(cmd *co log.Infof("cache server is listening on %v", cacheHandler.ExternalURL()) - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) - <-c + <-cmd.Context().Done() - return nil + return cacheHandler.Close() } } diff --git a/internal/app/cmd/cmd.go b/internal/app/cmd/cmd.go index 4cb02420..e6fadd9b 100644 --- a/internal/app/cmd/cmd.go +++ b/internal/app/cmd/cmd.go @@ -82,7 +82,7 @@ func Execute(ctx context.Context) { // hide completion command rootCmd.CompletionOptions.HiddenDefaultCmd = true - if err := rootCmd.Execute(); err != nil { + if err := rootCmd.ExecuteContext(ctx); err != nil { os.Exit(1) } } diff --git a/internal/app/run/runner.go b/internal/app/run/runner.go index de71e153..2fc86715 100644 --- a/internal/app/run/runner.go +++ b/internal/app/run/runner.go @@ -281,10 +281,9 @@ func (r *Runner) SetCapabilitiesFromDeclare(resp *connect.Response[runnerv1.Decl } func (r *Runner) Run(ctx context.Context, task *runnerv1.Task) error { - if _, ok := r.runningTasks.Load(task.Id); ok { + if _, ok := r.runningTasks.LoadOrStore(task.Id, struct{}{}); ok { return fmt.Errorf("task %d is already running", task.Id) } - r.runningTasks.Store(task.Id, struct{}{}) defer r.runningTasks.Delete(task.Id) r.runningCount.Add(1)