Refactor to new framework #98
No files matched your search
+1
-1
@@ -58,7 +58,7 @@ builds:
|
|||||||
flags:
|
flags:
|
||||||
- -trimpath
|
- -trimpath
|
||||||
ldflags:
|
ldflags:
|
||||||
- -s -w -X gitea.com/gitea/act_runner/cmd.version={{ .Summary }}
|
- -s -w -X gitea.com/gitea/act_runner/internal/pkg/ver.version={{ .Summary }}
|
||||||
binary: >-
|
binary: >-
|
||||||
{{ .ProjectName }}-
|
{{ .ProjectName }}-
|
||||||
{{- .Version }}-
|
{{- .Version }}-
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
|
|||||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||||
XGO_VERSION := go-1.18.x
|
XGO_VERSION := go-1.18.x
|
||||||
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
|
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
|
||||||
RUNNER_CMD_PACKAGE_PATH := gitea.com/gitea/act_runner/cmd
|
|
||||||
|
|
||||||
LINUX_ARCHS ?= linux/amd64,linux/arm64
|
LINUX_ARCHS ?= linux/amd64,linux/arm64
|
||||||
DARWIN_ARCHS ?= darwin-12/amd64,darwin-12/arm64
|
DARWIN_ARCHS ?= darwin-12/amd64,darwin-12/arm64
|
||||||
@@ -63,7 +62,7 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
TAGS ?=
|
TAGS ?=
|
||||||
LDFLAGS ?= -X "$(RUNNER_CMD_PACKAGE_PATH).version=$(RELASE_VERSION)"
|
LDFLAGS ?= -X "gitea.com/gitea/act_runner/internal/pkg/ver.version=$(RELASE_VERSION)"
|
||||||
|
|
||||||
all: build
|
all: build
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
Inspired by:
|
|
||||||
https://github.com/sp-ricard-valverde/github-act-cache-server
|
|
||||||
|
|
||||||
TODO:
|
|
||||||
- Authorization
|
|
||||||
- [Restrictions for accessing a cache](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache)
|
|
||||||
- [Force deleting cache entries](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries)
|
|
||||||
-136
@@ -1,136 +0,0 @@
|
|||||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/mattn/go-isatty"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
|
|
||||||
"gitea.com/gitea/act_runner/artifactcache"
|
|
||||||
"gitea.com/gitea/act_runner/client"
|
|
||||||
"gitea.com/gitea/act_runner/config"
|
|
||||||
"gitea.com/gitea/act_runner/engine"
|
|
||||||
"gitea.com/gitea/act_runner/poller"
|
|
||||||
"gitea.com/gitea/act_runner/runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command, args []string) error {
|
|
||||||
return func(cmd *cobra.Command, args []string) error {
|
|
||||||
log.Infoln("Starting runner daemon")
|
|
||||||
|
|
||||||
cfg, err := config.LoadDefault(*configFile)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid configuration: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
initLogging(cfg)
|
|
||||||
|
|
||||||
reg, err := config.LoadRegistration(cfg.Runner.File)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
log.Error("registration file not found, please register the runner first")
|
|
||||||
return err
|
|
||||||
} else if err != nil {
|
|
||||||
return fmt.Errorf("failed to load registration file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// require docker if a runner label uses a docker backend
|
|
||||||
needsDocker := false
|
|
||||||
for _, l := range reg.Labels {
|
|
||||||
_, schema, _, _ := runtime.ParseLabel(l)
|
|
||||||
if schema == "docker" {
|
|
||||||
needsDocker = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if needsDocker {
|
|
||||||
// try to connect to docker daemon
|
|
||||||
// if failed, exit with error
|
|
||||||
if err := engine.Start(ctx); err != nil {
|
|
||||||
log.WithError(err).Fatalln("failed to connect docker daemon engine")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var g errgroup.Group
|
|
||||||
|
|
||||||
cli := client.New(
|
|
||||||
reg.Address,
|
|
||||||
cfg.Runner.Insecure,
|
|
||||||
reg.UUID,
|
|
||||||
reg.Token,
|
|
||||||
version,
|
|
||||||
)
|
|
||||||
|
|
||||||
runner := &runtime.Runner{
|
|
||||||
Client: cli,
|
|
||||||
Machine: reg.Name,
|
|
||||||
ForgeInstance: reg.Address,
|
|
||||||
Environ: cfg.Runner.Envs,
|
|
||||||
Labels: reg.Labels,
|
|
||||||
Network: cfg.Container.Network,
|
|
||||||
Version: version,
|
|
||||||
}
|
|
||||||
|
|
||||||
if *cfg.Cache.Enabled {
|
|
||||||
if handler, err := artifactcache.NewHandler(cfg.Cache.Dir, cfg.Cache.Host, cfg.Cache.Port); err != nil {
|
|
||||||
log.Errorf("cannot init cache server, it will be disabled: %v", err)
|
|
||||||
} else {
|
|
||||||
log.Infof("cache handler listens on: %v", handler.ExternalURL())
|
|
||||||
runner.CacheHandler = handler
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
poller := poller.New(
|
|
||||||
cli,
|
|
||||||
runner.Run,
|
|
||||||
cfg,
|
|
||||||
)
|
|
||||||
|
|
||||||
g.Go(func() error {
|
|
||||||
l := log.WithField("capacity", cfg.Runner.Capacity).
|
|
||||||
WithField("endpoint", reg.Address)
|
|
||||||
l.Infoln("polling the remote server")
|
|
||||||
|
|
||||||
if err := poller.Poll(ctx); err != nil {
|
|
||||||
l.Errorf("poller error: %v", err)
|
|
||||||
}
|
|
||||||
poller.Wait()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
err = g.Wait()
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).
|
|
||||||
Errorln("shutting down the server")
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// initLogging setup the global logrus logger.
|
|
||||||
func initLogging(cfg *config.Config) {
|
|
||||||
isTerm := isatty.IsTerminal(os.Stdout.Fd())
|
|
||||||
log.SetFormatter(&log.TextFormatter{
|
|
||||||
DisableColors: !isTerm,
|
|
||||||
FullTimestamp: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
if l := cfg.Log.Level; l != "" {
|
|
||||||
level, err := log.ParseLevel(l)
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).
|
|
||||||
Errorf("invalid log level: %q", l)
|
|
||||||
}
|
|
||||||
if log.GetLevel() != level {
|
|
||||||
log.Infof("log level changed to %v", level)
|
|
||||||
log.SetLevel(level)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package engine
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/docker/docker/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Docker struct {
|
|
||||||
client client.APIClient
|
|
||||||
hidePull bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(opts ...Option) (*Docker, error) {
|
|
||||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
srv := &Docker{
|
|
||||||
client: cli,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop through each option
|
|
||||||
for _, opt := range opts {
|
|
||||||
// Call the option giving the instantiated
|
|
||||||
opt.Apply(srv)
|
|
||||||
}
|
|
||||||
|
|
||||||
return srv, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ping pings the Docker daemon.
|
|
||||||
func (e *Docker) Ping(ctx context.Context) error {
|
|
||||||
_, err := e.client.Ping(ctx)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package engine
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Start start docker engine api loop
|
|
||||||
func Start(ctx context.Context) error {
|
|
||||||
engine, err := New()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
for {
|
|
||||||
err := engine.Ping(ctx)
|
|
||||||
if err == context.Canceled {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return ctx.Err()
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).
|
|
||||||
Errorln("cannot ping the docker daemon")
|
|
||||||
count++
|
|
||||||
if count == 5 {
|
|
||||||
return fmt.Errorf("retry connect to docker daemon failed: %d times", count)
|
|
||||||
}
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
} else {
|
|
||||||
log.Infoln("successfully ping the docker daemon")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package engine
|
|
||||||
|
|
||||||
import "github.com/docker/docker/client"
|
|
||||||
|
|
||||||
// An Option configures a mutex.
|
|
||||||
type Option interface {
|
|
||||||
Apply(*Docker)
|
|
||||||
}
|
|
||||||
|
|
||||||
// OptionFunc is a function that configure a value.
|
|
||||||
type OptionFunc func(*Docker)
|
|
||||||
|
|
||||||
// Apply calls f(option)
|
|
||||||
func (f OptionFunc) Apply(docker *Docker) {
|
|
||||||
f(docker)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithClient set custom client
|
|
||||||
func WithClient(c client.APIClient) Option {
|
|
||||||
return OptionFunc(func(q *Docker) {
|
|
||||||
q.client = c
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithHidePull hide pull event.
|
|
||||||
func WithHidePull(v bool) Option {
|
|
||||||
return OptionFunc(func(q *Docker) {
|
|
||||||
q.hidePull = v
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -15,10 +15,12 @@ require (
|
|||||||
github.com/nektos/act v0.0.0
|
github.com/nektos/act v0.0.0
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.0
|
||||||
github.com/spf13/cobra v1.6.1
|
github.com/spf13/cobra v1.6.1
|
||||||
golang.org/x/sync v0.1.0
|
github.com/stretchr/testify v1.8.1
|
||||||
golang.org/x/term v0.6.0
|
golang.org/x/term v0.6.0
|
||||||
|
golang.org/x/time v0.1.0
|
||||||
google.golang.org/protobuf v1.28.1
|
google.golang.org/protobuf v1.28.1
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
|
gotest.tools/v3 v3.4.0
|
||||||
modernc.org/sqlite v1.14.2
|
modernc.org/sqlite v1.14.2
|
||||||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978
|
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978
|
||||||
xorm.io/xorm v1.3.2
|
xorm.io/xorm v1.3.2
|
||||||
@@ -33,6 +35,7 @@ require (
|
|||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/containerd/containerd v1.6.18 // indirect
|
github.com/containerd/containerd v1.6.18 // indirect
|
||||||
github.com/creack/pty v1.1.18 // indirect
|
github.com/creack/pty v1.1.18 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/docker/cli v23.0.1+incompatible // indirect
|
github.com/docker/cli v23.0.1+incompatible // indirect
|
||||||
github.com/docker/distribution v2.8.1+incompatible // indirect
|
github.com/docker/distribution v2.8.1+incompatible // indirect
|
||||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||||
@@ -46,6 +49,7 @@ require (
|
|||||||
github.com/goccy/go-json v0.8.1 // indirect
|
github.com/goccy/go-json v0.8.1 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/imdario/mergo v0.3.13 // indirect
|
github.com/imdario/mergo v0.3.13 // indirect
|
||||||
@@ -72,6 +76,7 @@ require (
|
|||||||
github.com/opencontainers/runc v1.1.3 // indirect
|
github.com/opencontainers/runc v1.1.3 // indirect
|
||||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||||
github.com/rhysd/actionlint v1.6.23 // indirect
|
github.com/rhysd/actionlint v1.6.23 // indirect
|
||||||
github.com/rivo/uniseg v0.4.3 // indirect
|
github.com/rivo/uniseg v0.4.3 // indirect
|
||||||
@@ -86,6 +91,7 @@ require (
|
|||||||
golang.org/x/crypto v0.2.0 // indirect
|
golang.org/x/crypto v0.2.0 // indirect
|
||||||
golang.org/x/mod v0.4.2 // indirect
|
golang.org/x/mod v0.4.2 // indirect
|
||||||
golang.org/x/net v0.7.0 // indirect
|
golang.org/x/net v0.7.0 // indirect
|
||||||
|
golang.org/x/sync v0.1.0 // indirect
|
||||||
golang.org/x/sys v0.6.0 // indirect
|
golang.org/x/sys v0.6.0 // indirect
|
||||||
golang.org/x/tools v0.1.5 // indirect
|
golang.org/x/tools v0.1.5 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||||
@@ -655,6 +656,7 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -684,6 +686,7 @@ golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
|||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
|
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
|
||||||
|
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@@ -704,6 +707,7 @@ golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWc
|
|||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
|
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -770,6 +774,7 @@ gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||||
|
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
// Package artifactcache provides a cache handler for the runner.
|
||||||
|
//
|
||||||
|
// Inspired by https://github.com/sp-ricard-valverde/github-act-cache-server
|
||||||
|
//
|
||||||
|
// TODO: Authorization
|
||||||
|
// TODO: Restrictions for accessing a cache, see https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache
|
||||||
|
// TODO: Force deleting cache entries, see https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries
|
||||||
|
|
||||||
|
package artifactcache
|
||||||
@@ -42,7 +42,7 @@ type Handler struct {
|
|||||||
outboundIP string
|
outboundIP string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(dir, outboundIP string, port uint16) (*Handler, error) {
|
func StartHandler(dir, outboundIP string, port uint16) (*Handler, error) {
|
||||||
h := &Handler{}
|
h := &Handler{}
|
||||||
|
|
||||||
if dir == "" {
|
if dir == "" {
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -10,19 +10,17 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"gitea.com/gitea/act_runner/config"
|
"gitea.com/gitea/act_runner/internal/pkg/config"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/ver"
|
||||||
)
|
)
|
||||||
|
|
||||||
// the version of act_runner
|
|
||||||
var version = "develop"
|
|
||||||
|
|
||||||
func Execute(ctx context.Context) {
|
func Execute(ctx context.Context) {
|
||||||
// ./act_runner
|
// ./act_runner
|
||||||
rootCmd := &cobra.Command{
|
rootCmd := &cobra.Command{
|
||||||
Use: "act_runner [event name to run]\nIf no event name passed, will default to \"on: push\"",
|
Use: "act_runner [event name to run]\nIf no event name passed, will default to \"on: push\"",
|
||||||
Short: "Run GitHub actions locally by specifying the event name (e.g. `push`) or an action name directly.",
|
Short: "Run GitHub actions locally by specifying the event name (e.g. `push`) or an action name directly.",
|
||||||
Args: cobra.MaximumNArgs(1),
|
Args: cobra.MaximumNArgs(1),
|
||||||
Version: version,
|
Version: ver.Version(),
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
}
|
}
|
||||||
configFile := ""
|
configFile := ""
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/mattn/go-isatty"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/internal/app/poll"
|
||||||
|
"gitea.com/gitea/act_runner/internal/app/run"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/client"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/config"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/envcheck"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/labels"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/ver"
|
||||||
|
)
|
||||||
|
|
||||||
|
func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command, args []string) error {
|
||||||
|
return func(cmd *cobra.Command, args []string) error {
|
||||||
|
log.Infoln("Starting runner daemon")
|
||||||
|
|
||||||
|
cfg, err := config.LoadDefault(*configFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid configuration: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
initLogging(cfg)
|
||||||
|
|
||||||
|
reg, err := config.LoadRegistration(cfg.Runner.File)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
log.Error("registration file not found, please register the runner first")
|
||||||
|
return err
|
||||||
|
} else if err != nil {
|
||||||
|
return fmt.Errorf("failed to load registration file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ls := labels.Labels{}
|
||||||
|
for _, l := range reg.Labels {
|
||||||
|
label, err := labels.Parse(l)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Warnf("ignored invalid label %q", l)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ls = append(ls, label)
|
||||||
|
}
|
||||||
|
if len(ls) == 0 {
|
||||||
|
log.Warn("no labels configured, runner may not be able to pick up jobs")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ls.RequireDocker() {
|
||||||
|
if err := envcheck.CheckIfDockerRunning(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cli := client.New(
|
||||||
|
reg.Address,
|
||||||
|
cfg.Runner.Insecure,
|
||||||
|
reg.UUID,
|
||||||
|
reg.Token,
|
||||||
|
ver.Version(),
|
||||||
|
)
|
||||||
|
|
||||||
|
runner := run.NewRunner(cfg, reg, cli)
|
||||||
|
poller := poll.New(cfg, cli, runner)
|
||||||
|
|
||||||
|
poller.Poll(ctx)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// initLogging setup the global logrus logger.
|
||||||
|
func initLogging(cfg *config.Config) {
|
||||||
|
isTerm := isatty.IsTerminal(os.Stdout.Fd())
|
||||||
|
log.SetFormatter(&log.TextFormatter{
|
||||||
|
DisableColors: !isTerm,
|
||||||
|
FullTimestamp: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
if l := cfg.Log.Level; l != "" {
|
||||||
|
level, err := log.ParseLevel(l)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).
|
||||||
|
Errorf("invalid log level: %q", l)
|
||||||
|
}
|
||||||
|
if log.GetLevel() != level {
|
||||||
|
log.Infof("log level changed to %v", level)
|
||||||
|
log.SetLevel(level)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
|
|
||||||
"gitea.com/gitea/act_runner/artifactcache"
|
"gitea.com/gitea/act_runner/internal/app/artifactcache"
|
||||||
)
|
)
|
||||||
|
|
||||||
type executeArgs struct {
|
type executeArgs struct {
|
||||||
@@ -348,7 +348,7 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
// init a cache server
|
// init a cache server
|
||||||
handler, err := artifactcache.NewHandler("", "", 0)
|
handler, err := artifactcache.StartHandler("", "", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -20,9 +20,10 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"gitea.com/gitea/act_runner/client"
|
"gitea.com/gitea/act_runner/internal/pkg/client"
|
||||||
"gitea.com/gitea/act_runner/config"
|
"gitea.com/gitea/act_runner/internal/pkg/config"
|
||||||
"gitea.com/gitea/act_runner/runtime"
|
"gitea.com/gitea/act_runner/internal/pkg/labels"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/ver"
|
||||||
)
|
)
|
||||||
|
|
||||||
// runRegister registers a runner to the server
|
// runRegister registers a runner to the server
|
||||||
@@ -37,7 +38,7 @@ func runRegister(ctx context.Context, regArgs *registerArgs, configFile *string)
|
|||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
|
|
||||||
log.Infof("Registering runner, arch=%s, os=%s, version=%s.",
|
log.Infof("Registering runner, arch=%s, os=%s, version=%s.",
|
||||||
goruntime.GOARCH, goruntime.GOOS, version)
|
goruntime.GOARCH, goruntime.GOOS, ver.Version())
|
||||||
|
|
||||||
// runner always needs root permission
|
// runner always needs root permission
|
||||||
if os.Getuid() != 0 {
|
if os.Getuid() != 0 {
|
||||||
@@ -116,9 +117,9 @@ func (r *registerInputs) validate() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateLabels(labels []string) error {
|
func validateLabels(ls []string) error {
|
||||||
for _, label := range labels {
|
for _, label := range ls {
|
||||||
if _, _, _, err := runtime.ParseLabel(label); err != nil {
|
if _, err := labels.Parse(label); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,7 +273,7 @@ func doRegister(cfg *config.Config, inputs *registerInputs) error {
|
|||||||
cfg.Runner.Insecure,
|
cfg.Runner.Insecure,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
version,
|
ver.Version(),
|
||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -305,16 +306,16 @@ func doRegister(cfg *config.Config, inputs *registerInputs) error {
|
|||||||
Labels: inputs.CustomLabels,
|
Labels: inputs.CustomLabels,
|
||||||
}
|
}
|
||||||
|
|
||||||
labels := make([]string, len(reg.Labels))
|
ls := make([]string, len(reg.Labels))
|
||||||
for i, v := range reg.Labels {
|
for i, v := range reg.Labels {
|
||||||
l, _, _, _ := runtime.ParseLabel(v)
|
l, _ := labels.Parse(v)
|
||||||
labels[i] = l
|
ls[i] = l.Name
|
||||||
}
|
}
|
||||||
// register new runner.
|
// register new runner.
|
||||||
resp, err := cli.Register(ctx, connect.NewRequest(&runnerv1.RegisterRequest{
|
resp, err := cli.Register(ctx, connect.NewRequest(&runnerv1.RegisterRequest{
|
||||||
Name: reg.Name,
|
Name: reg.Name,
|
||||||
Token: reg.Token,
|
Token: reg.Token,
|
||||||
AgentLabels: labels,
|
AgentLabels: ls,
|
||||||
}))
|
}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("poller: cannot register new runner")
|
log.WithError(err).Error("poller: cannot register new runner")
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package poll
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||||
|
"github.com/bufbuild/connect-go"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/time/rate"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/internal/app/run"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/client"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Poller struct {
|
||||||
|
client client.Client
|
||||||
|
runner *run.Runner
|
||||||
|
capacity int
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(cfg *config.Config, client client.Client, runner *run.Runner) *Poller {
|
||||||
|
return &Poller{
|
||||||
|
client: client,
|
||||||
|
runner: runner,
|
||||||
|
capacity: cfg.Runner.Capacity,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Poller) Poll(ctx context.Context) {
|
||||||
|
limiter := rate.NewLimiter(rate.Every(2*time.Second), 1)
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
|
for i := 0; i < p.capacity; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go p.poll(ctx, wg, limiter)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Poller) poll(ctx context.Context, wg *sync.WaitGroup, limiter *rate.Limiter) {
|
||||||
|
defer wg.Done()
|
||||||
|
for {
|
||||||
|
if err := limiter.Wait(ctx); err != nil {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
log.WithError(err).Debug("limiter wait failed")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
task, ok := p.fetchTask(ctx)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := p.runner.Run(ctx, task); err != nil {
|
||||||
|
log.WithError(err).Error("failed to run task")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Poller) fetchTask(ctx context.Context) (*runnerv1.Task, bool) {
|
||||||
|
reqCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
resp, err := p.client.FetchTask(reqCtx, connect.NewRequest(&runnerv1.FetchTaskRequest{}))
|
||||||
|
if errors.Is(err, context.DeadlineExceeded) {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("failed to fetch task")
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Msg.Task == nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return resp.Msg.Task, true
|
||||||
|
}
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package run
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||||
|
"github.com/nektos/act/pkg/common"
|
||||||
|
"github.com/nektos/act/pkg/model"
|
||||||
|
"github.com/nektos/act/pkg/runner"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/internal/app/artifactcache"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/client"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/config"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/labels"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/report"
|
||||||
|
"gitea.com/gitea/act_runner/internal/pkg/ver"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Runner runs the pipeline.
|
||||||
|
type Runner struct {
|
||||||
|
name string
|
||||||
|
|
||||||
|
cfg *config.Config
|
||||||
|
|
||||||
|
client client.Client
|
||||||
|
labels labels.Labels
|
||||||
|
envs map[string]string
|
||||||
|
|
||||||
|
runningTasks sync.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client) *Runner {
|
||||||
|
ls := labels.Labels{}
|
||||||
|
for _, v := range reg.Labels {
|
||||||
|
if l, err := labels.Parse(v); err == nil {
|
||||||
|
ls = append(ls, l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
envs := make(map[string]string, len(cfg.Runner.Envs))
|
||||||
|
for k, v := range cfg.Runner.Envs {
|
||||||
|
envs[k] = v
|
||||||
|
}
|
||||||
|
if cfg.Cache.Enabled == nil || *cfg.Cache.Enabled {
|
||||||
|
cacheHandler, err := artifactcache.StartHandler(cfg.Cache.Dir, cfg.Cache.Host, cfg.Cache.Port)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("cannot init cache server, it will be disabled: %v", err)
|
||||||
|
// go on
|
||||||
|
} else {
|
||||||
|
envs["ACTIONS_CACHE_URL"] = cacheHandler.ExternalURL() + "/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Runner{
|
||||||
|
name: reg.Name,
|
||||||
|
cfg: cfg,
|
||||||
|
client: cli,
|
||||||
|
labels: ls,
|
||||||
|
envs: envs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runner) Run(ctx context.Context, task *runnerv1.Task) error {
|
||||||
|
if _, ok := r.runningTasks.Load(task.Id); ok {
|
||||||
|
return fmt.Errorf("task %d is already running", task.Id)
|
||||||
|
} else {
|
||||||
|
r.runningTasks.Store(task.Id, struct{}{})
|
||||||
|
defer r.runningTasks.Delete(task.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, r.cfg.Runner.Timeout)
|
||||||
|
defer cancel()
|
||||||
|
reporter := report.NewReporter(ctx, cancel, r.client, task)
|
||||||
|
var runErr error
|
||||||
|
defer func() {
|
||||||
|
lastWords := ""
|
||||||
|
if runErr != nil {
|
||||||
|
lastWords = runErr.Error()
|
||||||
|
}
|
||||||
|
_ = reporter.Close(lastWords)
|
||||||
|
}()
|
||||||
|
reporter.RunDaemon()
|
||||||
|
runErr = r.run(ctx, task, reporter)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.Reporter) (err error) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
err = fmt.Errorf("panic: %v", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
reporter.Logf("%s(version:%s) received task %v of job %v, be triggered by event: %s", r.name, ver.Version(), task.Id, task.Context.Fields["job"].GetStringValue(), task.Context.Fields["event_name"].GetStringValue())
|
||||||
|
|
||||||
|
workflow, err := model.ReadWorkflow(bytes.NewReader(task.WorkflowPayload))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
jobIDs := workflow.GetJobIDs()
|
||||||
|
if len(jobIDs) != 1 {
|
||||||
|
return fmt.Errorf("multiple jobs found: %v", jobIDs)
|
||||||
|
}
|
||||||
|
jobID := jobIDs[0]
|
||||||
|
plan, err := model.CombineWorkflowPlanner(workflow).PlanJob(jobID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
job := workflow.GetJob(jobID)
|
||||||
|
reporter.ResetSteps(len(job.Steps))
|
||||||
|
|
||||||
|
taskContext := task.Context.Fields
|
||||||
|
|
||||||
|
log.Infof("task %v repo is %v %v %v", task.Id, taskContext["repository"].GetStringValue(),
|
||||||
|
taskContext["gitea_default_actions_url"].GetStringValue(),
|
||||||
|
r.client.Address())
|
||||||
|
|
||||||
|
preset := &model.GithubContext{
|
||||||
|
Event: taskContext["event"].GetStructValue().AsMap(),
|
||||||
|
RunID: taskContext["run_id"].GetStringValue(),
|
||||||
|
RunNumber: taskContext["run_number"].GetStringValue(),
|
||||||
|
Actor: taskContext["actor"].GetStringValue(),
|
||||||
|
Repository: taskContext["repository"].GetStringValue(),
|
||||||
|
EventName: taskContext["event_name"].GetStringValue(),
|
||||||
|
Sha: taskContext["sha"].GetStringValue(),
|
||||||
|
Ref: taskContext["ref"].GetStringValue(),
|
||||||
|
RefName: taskContext["ref_name"].GetStringValue(),
|
||||||
|
RefType: taskContext["ref_type"].GetStringValue(),
|
||||||
|
HeadRef: taskContext["head_ref"].GetStringValue(),
|
||||||
|
BaseRef: taskContext["base_ref"].GetStringValue(),
|
||||||
|
Token: taskContext["token"].GetStringValue(),
|
||||||
|
RepositoryOwner: taskContext["repository_owner"].GetStringValue(),
|
||||||
|
RetentionDays: taskContext["retention_days"].GetStringValue(),
|
||||||
|
}
|
||||||
|
if t := task.Secrets["GITEA_TOKEN"]; t != "" {
|
||||||
|
preset.Token = t
|
||||||
|
} else if t := task.Secrets["GITHUB_TOKEN"]; t != "" {
|
||||||
|
preset.Token = t
|
||||||
|
}
|
||||||
|
|
||||||
|
eventJSON, err := json.Marshal(preset.Event)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
maxLifetime := 3 * time.Hour
|
||||||
|
if deadline, ok := ctx.Deadline(); ok {
|
||||||
|
maxLifetime = time.Until(deadline)
|
||||||
|
}
|
||||||
|
|
||||||
|
runnerConfig := &runner.Config{
|
||||||
|
// On Linux, Workdir will be like "/<owner>/<repo>"
|
||||||
|
// On Windows, Workdir will be like "\<owner>\<repo>"
|
||||||
|
Workdir: filepath.FromSlash(string(filepath.Separator) + preset.Repository),
|
||||||
|
BindWorkdir: false,
|
||||||
|
|
||||||
|
ReuseContainers: false,
|
||||||
|
ForcePull: false,
|
||||||
|
ForceRebuild: false,
|
||||||
|
LogOutput: true,
|
||||||
|
JSONLogger: false,
|
||||||
|
Env: r.envs,
|
||||||
|
Secrets: task.Secrets,
|
||||||
|
GitHubInstance: r.client.Address(),
|
||||||
|
AutoRemove: true,
|
||||||
|
NoSkipCheckout: true,
|
||||||
|
PresetGitHubContext: preset,
|
||||||
|
EventJSON: string(eventJSON),
|
||||||
|
ContainerNamePrefix: fmt.Sprintf("GITEA-ACTIONS-TASK-%d", task.Id),
|
||||||
|
ContainerMaxLifetime: maxLifetime,
|
||||||
|
ContainerNetworkMode: r.cfg.Container.NetworkMode,
|
||||||
|
DefaultActionInstance: taskContext["gitea_default_actions_url"].GetStringValue(),
|
||||||
|
PlatformPicker: r.labels.PickPlatform,
|
||||||
|
}
|
||||||
|
|
||||||
|
rr, err := runner.New(runnerConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
executor := rr.NewPlanExecutor(plan)
|
||||||
|
|
||||||
|
reporter.Logf("workflow prepared")
|
||||||
|
|
||||||
|
// add logger recorders
|
||||||
|
ctx = common.WithLoggerHook(ctx, reporter)
|
||||||
|
|
||||||
|
return executor(ctx)
|
||||||
|
}
|
||||||
File renamed without changes.
File renamed without changes.
@@ -28,7 +28,7 @@ func getHttpClient(endpoint string, insecure bool) *http.Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new runner client.
|
// New returns a new runner client.
|
||||||
func New(endpoint string, insecure bool, uuid, token, runnerVersion string, opts ...connect.ClientOption) *HTTPClient {
|
func New(endpoint string, insecure bool, uuid, token, version string, opts ...connect.ClientOption) *HTTPClient {
|
||||||
baseURL := strings.TrimRight(endpoint, "/") + "/api/actions"
|
baseURL := strings.TrimRight(endpoint, "/") + "/api/actions"
|
||||||
|
|
||||||
opts = append(opts, connect.WithInterceptors(connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc {
|
opts = append(opts, connect.WithInterceptors(connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc {
|
||||||
@@ -39,8 +39,8 @@ func New(endpoint string, insecure bool, uuid, token, runnerVersion string, opts
|
|||||||
if token != "" {
|
if token != "" {
|
||||||
req.Header().Set(TokenHeader, token)
|
req.Header().Set(TokenHeader, token)
|
||||||
}
|
}
|
||||||
if runnerVersion != "" {
|
if version != "" {
|
||||||
req.Header().Set(VersionHeader, runnerVersion)
|
req.Header().Set(VersionHeader, version)
|
||||||
}
|
}
|
||||||
return next(ctx, req)
|
return next(ctx, req)
|
||||||
}
|
}
|
||||||
@@ -38,5 +38,5 @@ cache:
|
|||||||
port: 0
|
port: 0
|
||||||
|
|
||||||
container:
|
container:
|
||||||
# Which network to use for the job containers.
|
# Which network to use for the job containers. Could be bridge, host, none, or the name of a custom network.
|
||||||
network: bridge
|
network_mode: bridge
|
||||||
@@ -32,7 +32,7 @@ type Config struct {
|
|||||||
Port uint16 `yaml:"port"`
|
Port uint16 `yaml:"port"`
|
||||||
} `yaml:"cache"`
|
} `yaml:"cache"`
|
||||||
Container struct {
|
Container struct {
|
||||||
Network string `yaml:"network"`
|
NetworkMode string `yaml:"network_mode"`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,8 +87,8 @@ func LoadDefault(file string) (*Config, error) {
|
|||||||
cfg.Cache.Dir = filepath.Join(home, ".cache", "actcache")
|
cfg.Cache.Dir = filepath.Join(home, ".cache", "actcache")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cfg.Container.Network == "" {
|
if cfg.Container.NetworkMode == "" {
|
||||||
cfg.Container.Network = "bridge"
|
cfg.Container.NetworkMode = "bridge"
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,5 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
// Package envcheck provides a simple way to check if the environment is ready to run jobs.
|
||||||
|
package envcheck
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package envcheck
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/docker/docker/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CheckIfDockerRunning(ctx context.Context) error {
|
||||||
|
// TODO: if runner support configures to use docker, we need config.Config to pass in
|
||||||
|
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
_, err = cli.Ping(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot ping the docker daemon, does it running? %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Loaded 30 of 42 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user