mirror of
https://gitea.com/gitea/act_runner
synced 2024-11-09 18:05:52 +01:00
feat: use specified labels
This commit is contained in:
parent
5781e233c1
commit
2354f5bb18
@ -5,12 +5,6 @@ import (
|
|||||||
"code.gitea.io/bots-proto-go/runner/v1/runnerv1connect"
|
"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.
|
// A Client manages communication with the runner.
|
||||||
type Client interface {
|
type Client interface {
|
||||||
pingv1connect.PingServiceClient
|
pingv1connect.PingServiceClient
|
||||||
|
@ -52,6 +52,7 @@ func runDaemon(ctx context.Context, envFile string) func(cmd *cobra.Command, arg
|
|||||||
Machine: cfg.Runner.Name,
|
Machine: cfg.Runner.Name,
|
||||||
ForgeInstance: cfg.Client.Address,
|
ForgeInstance: cfg.Client.Address,
|
||||||
Environ: cfg.Runner.Environ,
|
Environ: cfg.Runner.Environ,
|
||||||
|
Labels: cfg.Runner.Labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
poller := poller.New(
|
poller := poller.New(
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
"gitea.com/gitea/act_runner/client"
|
"gitea.com/gitea/act_runner/client"
|
||||||
"gitea.com/gitea/act_runner/config"
|
"gitea.com/gitea/act_runner/config"
|
||||||
"gitea.com/gitea/act_runner/register"
|
"gitea.com/gitea/act_runner/register"
|
||||||
"github.com/appleboy/com/file"
|
|
||||||
"github.com/bufbuild/connect-go"
|
"github.com/bufbuild/connect-go"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"github.com/mattn/go-isatty"
|
"github.com/mattn/go-isatty"
|
||||||
@ -148,12 +148,19 @@ func (r *registerInputs) assignToNext(stage registerStage, value string) registe
|
|||||||
r.RunnerName = value
|
r.RunnerName = value
|
||||||
return StageInputCustomLabels
|
return StageInputCustomLabels
|
||||||
case StageInputCustomLabels:
|
case StageInputCustomLabels:
|
||||||
if value == "" {
|
if value != "" {
|
||||||
return StageWaitingForRegistration
|
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 {
|
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 StageInputCustomLabels
|
||||||
}
|
}
|
||||||
return StageWaitingForRegistration
|
return StageWaitingForRegistration
|
||||||
@ -171,7 +178,7 @@ func registerInteractive(envFile string) error {
|
|||||||
// check if overwrite local config
|
// check if overwrite local config
|
||||||
_ = godotenv.Load(envFile)
|
_ = godotenv.Load(envFile)
|
||||||
cfg, _ := config.FromEnviron()
|
cfg, _ := config.FromEnviron()
|
||||||
if file.IsFile(cfg.Runner.File) {
|
if f, err := os.Stat(cfg.Runner.File); err == nil && !f.IsDir() {
|
||||||
stage = StageOverwriteLocalConfig
|
stage = StageOverwriteLocalConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +224,7 @@ func printStageHelp(stage registerStage) {
|
|||||||
hostname, _ := os.Hostname()
|
hostname, _ := os.Hostname()
|
||||||
log.Infof("Enter the runner name (if set empty, use hostname:%s ):\n", hostname)
|
log.Infof("Enter the runner name (if set empty, use hostname:%s ):\n", hostname)
|
||||||
case StageInputCustomLabels:
|
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:
|
case StageWaitingForRegistration:
|
||||||
log.Infoln("Waiting for registration...")
|
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.Name = inputs.RunnerName
|
||||||
cfg.Runner.Token = inputs.Token
|
cfg.Runner.Token = inputs.Token
|
||||||
cfg.Runner.Labels = inputs.CustomLabels
|
cfg.Runner.Labels = inputs.CustomLabels
|
||||||
_, err := register.Register(ctx, cfg.Runner)
|
_, err := register.New(cli).Register(ctx, cfg.Runner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Errorln("Cannot register the runner")
|
log.WithError(err).Errorln("Cannot register the runner")
|
||||||
return nil
|
return nil
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"gitea.com/gitea/act_runner/core"
|
"gitea.com/gitea/act_runner/core"
|
||||||
"github.com/appleboy/com/file"
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"github.com/kelseyhightower/envconfig"
|
"github.com/kelseyhightower/envconfig"
|
||||||
)
|
)
|
||||||
@ -54,7 +54,7 @@ func FromEnviron() (Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check runner config exist
|
// 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)
|
jsonFile, _ := os.Open(cfg.Runner.File)
|
||||||
defer jsonFile.Close()
|
defer jsonFile.Close()
|
||||||
byteValue, _ := io.ReadAll(jsonFile)
|
byteValue, _ := io.ReadAll(jsonFile)
|
||||||
@ -68,6 +68,9 @@ func FromEnviron() (Config, error) {
|
|||||||
if runner.Token != "" {
|
if runner.Token != "" {
|
||||||
cfg.Runner.Token = runner.Token
|
cfg.Runner.Token = runner.Token
|
||||||
}
|
}
|
||||||
|
if len(runner.Labels) != 0 {
|
||||||
|
cfg.Runner.Labels = runner.Labels
|
||||||
|
}
|
||||||
if runner.Address != "" {
|
if runner.Address != "" {
|
||||||
cfg.Client.Address = runner.Address
|
cfg.Client.Address = runner.Address
|
||||||
}
|
}
|
||||||
|
1
go.mod
1
go.mod
@ -4,7 +4,6 @@ go 1.18
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
code.gitea.io/bots-proto-go v0.1.0
|
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/avast/retry-go/v4 v4.1.0
|
||||||
github.com/bufbuild/connect-go v1.1.0
|
github.com/bufbuild/connect-go v1.1.0
|
||||||
github.com/docker/docker v20.10.21+incompatible
|
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 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
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/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/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 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
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 {
|
type Poller struct {
|
||||||
Client client.Client
|
Client client.Client
|
||||||
Filter *client.Filter
|
|
||||||
Dispatch func(context.Context, *runnerv1.Task) error
|
Dispatch func(context.Context, *runnerv1.Task) error
|
||||||
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
runnerv1 "code.gitea.io/bots-proto-go/runner/v1"
|
runnerv1 "code.gitea.io/bots-proto-go/runner/v1"
|
||||||
"gitea.com/gitea/act_runner/client"
|
"gitea.com/gitea/act_runner/client"
|
||||||
@ -14,27 +15,26 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultLabels = []string{"self-hosted"}
|
func New(cli client.Client) *Register {
|
||||||
|
|
||||||
func New(cli client.Client, filter *client.Filter) *Register {
|
|
||||||
return &Register{
|
return &Register{
|
||||||
Client: cli,
|
Client: cli,
|
||||||
Filter: filter,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Register struct {
|
type Register struct {
|
||||||
Client client.Client
|
Client client.Client
|
||||||
Filter *client.Filter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Register) Register(ctx context.Context, cfg config.Runner) (*core.Runner, error) {
|
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.
|
// register new runner.
|
||||||
resp, err := p.Client.Register(ctx, connect.NewRequest(&runnerv1.RegisterRequest{
|
resp, err := p.Client.Register(ctx, connect.NewRequest(&runnerv1.RegisterRequest{
|
||||||
Name: cfg.Name,
|
Name: cfg.Name,
|
||||||
Token: cfg.Token,
|
Token: cfg.Token,
|
||||||
AgentLabels: append(defaultLabels, []string{p.Filter.OS, p.Filter.Arch}...),
|
AgentLabels: labels,
|
||||||
CustomLabels: p.Filter.Labels,
|
|
||||||
}))
|
}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("poller: cannot register new runner")
|
log.WithError(err).Error("poller: cannot register new runner")
|
||||||
|
@ -2,6 +2,7 @@ package runtime
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
runnerv1 "code.gitea.io/bots-proto-go/runner/v1"
|
runnerv1 "code.gitea.io/bots-proto-go/runner/v1"
|
||||||
"gitea.com/gitea/act_runner/client"
|
"gitea.com/gitea/act_runner/client"
|
||||||
@ -13,9 +14,45 @@ type Runner struct {
|
|||||||
ForgeInstance string
|
ForgeInstance string
|
||||||
Environ map[string]string
|
Environ map[string]string
|
||||||
Client client.Client
|
Client client.Client
|
||||||
|
Labels []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the pipeline stage.
|
// Run runs the pipeline stage.
|
||||||
func (s *Runner) Run(ctx context.Context, task *runnerv1.Task) error {
|
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
|
BuildID int64
|
||||||
Input *TaskInput
|
Input *TaskInput
|
||||||
|
|
||||||
client client.Client
|
client client.Client
|
||||||
log *log.Entry
|
log *log.Entry
|
||||||
|
platformPicker func([]string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTask creates a new task
|
// 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{
|
task := &Task{
|
||||||
Input: &TaskInput{
|
Input: &TaskInput{
|
||||||
envs: runnerEnvs,
|
envs: runnerEnvs,
|
||||||
@ -79,8 +80,9 @@ func NewTask(forgeInstance string, buildID int64, client client.Client, runnerEn
|
|||||||
},
|
},
|
||||||
BuildID: buildID,
|
BuildID: buildID,
|
||||||
|
|
||||||
client: client,
|
client: client,
|
||||||
log: log.WithField("buildID", buildID),
|
log: log.WithField("buildID", buildID),
|
||||||
|
platformPicker: picker,
|
||||||
}
|
}
|
||||||
task.Input.repoDirectory, _ = os.Getwd()
|
task.Input.repoDirectory, _ = os.Getwd()
|
||||||
return task
|
return task
|
||||||
@ -99,34 +101,6 @@ func getWorkflowsPath(dir string) (string, error) {
|
|||||||
return p, nil
|
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 {
|
func getToken(task *runnerv1.Task) string {
|
||||||
token := task.Secrets["GITHUB_TOKEN"]
|
token := task.Secrets["GITHUB_TOKEN"]
|
||||||
if task.Secrets["GITEA_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
|
ContainerMaxLifetime: 3 * time.Hour, // maybe should be specified by Gitea server
|
||||||
ContainerNetworkMode: input.containerNetworkMode,
|
ContainerNetworkMode: input.containerNetworkMode,
|
||||||
DefaultActionInstance: dataContext["gitea_default_bots_url"].GetStringValue(),
|
DefaultActionInstance: dataContext["gitea_default_bots_url"].GetStringValue(),
|
||||||
PlatformPicker: platformPicker,
|
PlatformPicker: t.platformPicker,
|
||||||
}
|
}
|
||||||
r, err := runner.New(config)
|
r, err := runner.New(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user