mirror of https://code.forgejo.org/forgejo/runner
feat: use specified labels
parent
5781e233c1
commit
2354f5bb18
|
@ -5,12 +5,6 @@ import (
|
|||
"code.gitea.io/bots-proto-go/runner/v1/runnerv1connect"
|
||||
)
|
||||
|
||||
type Filter struct {
|
||||
OS string `json:"os"`
|
||||
Arch string `json:"arch"`
|
||||
Labels []string `json:"labels"`
|
||||
}
|
||||
|
||||
// A Client manages communication with the runner.
|
||||
type Client interface {
|
||||
pingv1connect.PingServiceClient
|
||||
|
|
|
@ -52,6 +52,7 @@ func runDaemon(ctx context.Context, envFile string) func(cmd *cobra.Command, arg
|
|||
Machine: cfg.Runner.Name,
|
||||
ForgeInstance: cfg.Client.Address,
|
||||
Environ: cfg.Runner.Environ,
|
||||
Labels: cfg.Runner.Labels,
|
||||
}
|
||||
|
||||
poller := poller.New(
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"gitea.com/gitea/act_runner/client"
|
||||
"gitea.com/gitea/act_runner/config"
|
||||
"gitea.com/gitea/act_runner/register"
|
||||
"github.com/appleboy/com/file"
|
||||
|
||||
"github.com/bufbuild/connect-go"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/mattn/go-isatty"
|
||||
|
@ -148,12 +148,19 @@ func (r *registerInputs) assignToNext(stage registerStage, value string) registe
|
|||
r.RunnerName = value
|
||||
return StageInputCustomLabels
|
||||
case StageInputCustomLabels:
|
||||
if value == "" {
|
||||
return StageWaitingForRegistration
|
||||
if value != "" {
|
||||
r.CustomLabels = strings.Split(value, ",")
|
||||
} else {
|
||||
r.CustomLabels = []string{
|
||||
"ubuntu-latest:docker://node:16-bullseye",
|
||||
"ubuntu-22.04:docker://node:16-bullseye", // There's no node:16-bookworm yet
|
||||
"ubuntu-20.04:docker://node:16-bullseye",
|
||||
"ubuntu-18.04:docker://node:16-buster",
|
||||
}
|
||||
}
|
||||
r.CustomLabels = strings.Split(value, ",")
|
||||
|
||||
if validateLabels(r.CustomLabels) != nil {
|
||||
log.Infoln("Invalid labels, please input again (for example, ubuntu-latest:docker://node:16-buster)")
|
||||
log.Infoln("Invalid labels, please input again, leave blank to use the default labels (for example, ubuntu-20.04:docker://node:16-bullseye,ubuntu-18.04:docker://node:16-buster)")
|
||||
return StageInputCustomLabels
|
||||
}
|
||||
return StageWaitingForRegistration
|
||||
|
@ -171,7 +178,7 @@ func registerInteractive(envFile string) error {
|
|||
// check if overwrite local config
|
||||
_ = godotenv.Load(envFile)
|
||||
cfg, _ := config.FromEnviron()
|
||||
if file.IsFile(cfg.Runner.File) {
|
||||
if f, err := os.Stat(cfg.Runner.File); err == nil && !f.IsDir() {
|
||||
stage = StageOverwriteLocalConfig
|
||||
}
|
||||
|
||||
|
@ -217,7 +224,7 @@ func printStageHelp(stage registerStage) {
|
|||
hostname, _ := os.Hostname()
|
||||
log.Infof("Enter the runner name (if set empty, use hostname:%s ):\n", hostname)
|
||||
case StageInputCustomLabels:
|
||||
log.Infoln("Enter the runner custom labels (comma-separated, for example, ubuntu-latest:docker://node:16-buster,ubuntu-2204:docker://node:18-buster):")
|
||||
log.Infoln("Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-20.04:docker://node:16-bullseye,ubuntu-18.04:docker://node:16-buster):")
|
||||
case StageWaitingForRegistration:
|
||||
log.Infoln("Waiting for registration...")
|
||||
}
|
||||
|
@ -285,18 +292,10 @@ func doRegister(cfg *config.Config, inputs *registerInputs) error {
|
|||
}
|
||||
}
|
||||
|
||||
register := register.New(
|
||||
cli,
|
||||
&client.Filter{
|
||||
OS: cfg.Platform.OS,
|
||||
Arch: cfg.Platform.Arch,
|
||||
Labels: inputs.CustomLabels,
|
||||
},
|
||||
)
|
||||
cfg.Runner.Name = inputs.RunnerName
|
||||
cfg.Runner.Token = inputs.Token
|
||||
cfg.Runner.Labels = inputs.CustomLabels
|
||||
_, err := register.Register(ctx, cfg.Runner)
|
||||
_, err := register.New(cli).Register(ctx, cfg.Runner)
|
||||
if err != nil {
|
||||
log.WithError(err).Errorln("Cannot register the runner")
|
||||
return nil
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"runtime"
|
||||
|
||||
"gitea.com/gitea/act_runner/core"
|
||||
"github.com/appleboy/com/file"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/kelseyhightower/envconfig"
|
||||
)
|
||||
|
@ -54,7 +54,7 @@ func FromEnviron() (Config, error) {
|
|||
}
|
||||
|
||||
// check runner config exist
|
||||
if file.IsFile(cfg.Runner.File) {
|
||||
if f, err := os.Stat(cfg.Runner.File); err == nil && !f.IsDir() {
|
||||
jsonFile, _ := os.Open(cfg.Runner.File)
|
||||
defer jsonFile.Close()
|
||||
byteValue, _ := io.ReadAll(jsonFile)
|
||||
|
@ -68,6 +68,9 @@ func FromEnviron() (Config, error) {
|
|||
if runner.Token != "" {
|
||||
cfg.Runner.Token = runner.Token
|
||||
}
|
||||
if len(runner.Labels) != 0 {
|
||||
cfg.Runner.Labels = runner.Labels
|
||||
}
|
||||
if runner.Address != "" {
|
||||
cfg.Client.Address = runner.Address
|
||||
}
|
||||
|
|
1
go.mod
1
go.mod
|
@ -4,7 +4,6 @@ go 1.18
|
|||
|
||||
require (
|
||||
code.gitea.io/bots-proto-go v0.1.0
|
||||
github.com/appleboy/com v0.1.6
|
||||
github.com/avast/retry-go/v4 v4.1.0
|
||||
github.com/bufbuild/connect-go v1.1.0
|
||||
github.com/docker/docker v20.10.21+incompatible
|
||||
|
|
2
go.sum
2
go.sum
|
@ -87,8 +87,6 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C
|
|||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/appleboy/com v0.1.6 h1:vP9ryTIbSFaXSrZcFTU7RRcgPbrpGJ0Oy5wpgEkQ2m8=
|
||||
github.com/appleboy/com v0.1.6/go.mod h1:jnufjIC3opMlReyPPPye+8JqNvUzLm25o7h6SOy8nv0=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
|
|
|
@ -28,7 +28,6 @@ func New(cli client.Client, dispatch func(context.Context, *runnerv1.Task) error
|
|||
|
||||
type Poller struct {
|
||||
Client client.Client
|
||||
Filter *client.Filter
|
||||
Dispatch func(context.Context, *runnerv1.Task) error
|
||||
|
||||
sync.Mutex
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
runnerv1 "code.gitea.io/bots-proto-go/runner/v1"
|
||||
"gitea.com/gitea/act_runner/client"
|
||||
|
@ -14,27 +15,26 @@ import (
|
|||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var defaultLabels = []string{"self-hosted"}
|
||||
|
||||
func New(cli client.Client, filter *client.Filter) *Register {
|
||||
func New(cli client.Client) *Register {
|
||||
return &Register{
|
||||
Client: cli,
|
||||
Filter: filter,
|
||||
}
|
||||
}
|
||||
|
||||
type Register struct {
|
||||
Client client.Client
|
||||
Filter *client.Filter
|
||||
}
|
||||
|
||||
func (p *Register) Register(ctx context.Context, cfg config.Runner) (*core.Runner, error) {
|
||||
labels := make([]string, len(cfg.Labels))
|
||||
for i, v := range cfg.Labels {
|
||||
labels[i] = strings.SplitN(v, ":", 2)[0]
|
||||
}
|
||||
// register new runner.
|
||||
resp, err := p.Client.Register(ctx, connect.NewRequest(&runnerv1.RegisterRequest{
|
||||
Name: cfg.Name,
|
||||
Token: cfg.Token,
|
||||
AgentLabels: append(defaultLabels, []string{p.Filter.OS, p.Filter.Arch}...),
|
||||
CustomLabels: p.Filter.Labels,
|
||||
Name: cfg.Name,
|
||||
Token: cfg.Token,
|
||||
AgentLabels: labels,
|
||||
}))
|
||||
if err != nil {
|
||||
log.WithError(err).Error("poller: cannot register new runner")
|
||||
|
|
|
@ -2,6 +2,7 @@ package runtime
|
|||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
runnerv1 "code.gitea.io/bots-proto-go/runner/v1"
|
||||
"gitea.com/gitea/act_runner/client"
|
||||
|
@ -13,9 +14,45 @@ type Runner struct {
|
|||
ForgeInstance string
|
||||
Environ map[string]string
|
||||
Client client.Client
|
||||
Labels []string
|
||||
}
|
||||
|
||||
// Run runs the pipeline stage.
|
||||
func (s *Runner) Run(ctx context.Context, task *runnerv1.Task) error {
|
||||
return NewTask(s.ForgeInstance, task.Id, s.Client, s.Environ).Run(ctx, task)
|
||||
return NewTask(s.ForgeInstance, task.Id, s.Client, s.Environ, s.platformPicker).Run(ctx, task)
|
||||
}
|
||||
|
||||
func (s *Runner) platformPicker(labels []string) string {
|
||||
// "ubuntu-18.04:docker://node:16-buster"
|
||||
|
||||
platforms := make(map[string]string, len(labels))
|
||||
for _, l := range s.Labels {
|
||||
// "ubuntu-18.04:docker://node:16-buster"
|
||||
splits := strings.SplitN(l, ":", 2)
|
||||
// ["ubuntu-18.04", "docker://node:16-buster"]
|
||||
k, v := splits[0], splits[1]
|
||||
|
||||
if prefix := "docker://"; !strings.HasPrefix(v, prefix) {
|
||||
continue
|
||||
} else {
|
||||
v = strings.TrimPrefix(v, prefix)
|
||||
}
|
||||
// ubuntu-18.04 => node:16-buster
|
||||
platforms[k] = v
|
||||
}
|
||||
|
||||
for _, label := range labels {
|
||||
if v, ok := platforms[label]; ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: support multiple labels
|
||||
// like:
|
||||
// ["ubuntu-22.04"] => "ubuntu:22.04"
|
||||
// ["with-gpu"] => "linux:with-gpu"
|
||||
// ["ubuntu-22.04", "with-gpu"] => "ubuntu:22.04_with-gpu"
|
||||
|
||||
// return default
|
||||
return "node:16-bullseye"
|
||||
}
|
||||
|
|
|
@ -66,12 +66,13 @@ type Task struct {
|
|||
BuildID int64
|
||||
Input *TaskInput
|
||||
|
||||
client client.Client
|
||||
log *log.Entry
|
||||
client client.Client
|
||||
log *log.Entry
|
||||
platformPicker func([]string) string
|
||||
}
|
||||
|
||||
// NewTask creates a new task
|
||||
func NewTask(forgeInstance string, buildID int64, client client.Client, runnerEnvs map[string]string) *Task {
|
||||
func NewTask(forgeInstance string, buildID int64, client client.Client, runnerEnvs map[string]string, picker func([]string) string) *Task {
|
||||
task := &Task{
|
||||
Input: &TaskInput{
|
||||
envs: runnerEnvs,
|
||||
|
@ -79,8 +80,9 @@ func NewTask(forgeInstance string, buildID int64, client client.Client, runnerEn
|
|||
},
|
||||
BuildID: buildID,
|
||||
|
||||
client: client,
|
||||
log: log.WithField("buildID", buildID),
|
||||
client: client,
|
||||
log: log.WithField("buildID", buildID),
|
||||
platformPicker: picker,
|
||||
}
|
||||
task.Input.repoDirectory, _ = os.Getwd()
|
||||
return task
|
||||
|
@ -99,34 +101,6 @@ func getWorkflowsPath(dir string) (string, error) {
|
|||
return p, nil
|
||||
}
|
||||
|
||||
func platformPicker(labels []string) string {
|
||||
|
||||
// FIXME: read custom labels
|
||||
|
||||
preset := map[string]string{
|
||||
// FIXME: shouldn't be the same
|
||||
"ubuntu-latest": "node:16-buster",
|
||||
"ubuntu-22.04": "node:16-buster",
|
||||
"ubuntu-20.04": "node:16-buster",
|
||||
"ubuntu-18.04": "node:16-buster",
|
||||
}
|
||||
|
||||
for _, label := range labels {
|
||||
if v, ok := preset[label]; ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: support multiple labels
|
||||
// like:
|
||||
// ["ubuntu-22.04"] => "ubuntu:22.04"
|
||||
// ["with-gpu"] => "linux:with-gpu"
|
||||
// ["ubuntu-22.04", "with-gpu"] => "ubuntu:22.04_with-gpu"
|
||||
|
||||
// FIXME: shall we need to support default?
|
||||
return "node:16-buster"
|
||||
}
|
||||
|
||||
func getToken(task *runnerv1.Task) string {
|
||||
token := task.Secrets["GITHUB_TOKEN"]
|
||||
if task.Secrets["GITEA_TOKEN"] != "" {
|
||||
|
@ -247,7 +221,7 @@ func (t *Task) Run(ctx context.Context, task *runnerv1.Task) error {
|
|||
ContainerMaxLifetime: 3 * time.Hour, // maybe should be specified by Gitea server
|
||||
ContainerNetworkMode: input.containerNetworkMode,
|
||||
DefaultActionInstance: dataContext["gitea_default_bots_url"].GetStringValue(),
|
||||
PlatformPicker: platformPicker,
|
||||
PlatformPicker: t.platformPicker,
|
||||
}
|
||||
r, err := runner.New(config)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue