diff --git a/internal/app/cmd/cmd.go b/internal/app/cmd/cmd.go index bd1f474..7c8e9a4 100644 --- a/internal/app/cmd/cmd.go +++ b/internal/app/cmd/cmd.go @@ -39,6 +39,7 @@ func Execute(ctx context.Context) { registerCmd.Flags().StringVar(®Args.Token, "token", "", "Runner token") registerCmd.Flags().StringVar(®Args.RunnerName, "name", "", "Runner name") registerCmd.Flags().StringVar(®Args.Labels, "labels", "", "Runner tags, comma separated") + registerCmd.Flags().BoolVar(®Args.Ephemeral, "ephemeral", false, "Configure the runner to be ephemeral and only ever be able to pick a single job (stricter than --once)") rootCmd.AddCommand(registerCmd) // ./act_runner daemon diff --git a/internal/app/cmd/daemon.go b/internal/app/cmd/daemon.go index 57d289c..9134526 100644 --- a/internal/app/cmd/daemon.go +++ b/internal/app/cmd/daemon.go @@ -122,7 +122,7 @@ func runDaemon(ctx context.Context, daemArgs *daemonArgs, configFile *string) fu poller := poll.New(cfg, cli, runner) - if daemArgs.Once { + if daemArgs.Once || reg.Ephemeral { done := make(chan struct{}) go func() { defer close(done) diff --git a/internal/app/cmd/register.go b/internal/app/cmd/register.go index ddd7c29..969529f 100644 --- a/internal/app/cmd/register.go +++ b/internal/app/cmd/register.go @@ -75,6 +75,7 @@ type registerArgs struct { Token string RunnerName string Labels string + Ephemeral bool } type registerStage int8 @@ -101,6 +102,7 @@ type registerInputs struct { Token string RunnerName string Labels []string + Ephemeral bool } func (r *registerInputs) validate() error { @@ -258,6 +260,7 @@ func registerNoInteractive(ctx context.Context, configFile string, regArgs *regi Token: regArgs.Token, RunnerName: regArgs.RunnerName, Labels: defaultLabels, + Ephemeral: regArgs.Ephemeral, } regArgs.Labels = strings.TrimSpace(regArgs.Labels) // command line flag. @@ -321,10 +324,11 @@ func doRegister(ctx context.Context, cfg *config.Config, inputs *registerInputs) } reg := &config.Registration{ - Name: inputs.RunnerName, - Token: inputs.Token, - Address: inputs.InstanceAddr, - Labels: inputs.Labels, + Name: inputs.RunnerName, + Token: inputs.Token, + Address: inputs.InstanceAddr, + Labels: inputs.Labels, + Ephemeral: inputs.Ephemeral, } ls := make([]string, len(reg.Labels)) @@ -339,6 +343,7 @@ func doRegister(ctx context.Context, cfg *config.Config, inputs *registerInputs) Version: ver.Version(), AgentLabels: ls, // Could be removed after Gitea 1.20 Labels: ls, + Ephemeral: reg.Ephemeral, })) if err != nil { log.WithError(err).Error("poller: cannot register new runner") @@ -350,6 +355,11 @@ func doRegister(ctx context.Context, cfg *config.Config, inputs *registerInputs) reg.Name = resp.Msg.Runner.Name reg.Token = resp.Msg.Runner.Token + if inputs.Ephemeral != resp.Msg.Runner.Ephemeral { + // TODO we cannot remove the configuration via runner api, if we return an error here we just fill the database + log.Error("poller: cannot register new runner as ephemeral upgrade Gitea to gain security, run-once will be used automatically") + } + if err := config.SaveRegistration(cfg.Runner.File, reg); err != nil { return fmt.Errorf("failed to save runner config: %w", err) } diff --git a/internal/pkg/config/registration.go b/internal/pkg/config/registration.go index be66b4f..414f44f 100644 --- a/internal/pkg/config/registration.go +++ b/internal/pkg/config/registration.go @@ -14,12 +14,13 @@ const registrationWarning = "This file is automatically generated by act-runner. type Registration struct { Warning string `json:"WARNING"` // Warning message to display, it's always the registrationWarning constant - ID int64 `json:"id"` - UUID string `json:"uuid"` - Name string `json:"name"` - Token string `json:"token"` - Address string `json:"address"` - Labels []string `json:"labels"` + ID int64 `json:"id"` + UUID string `json:"uuid"` + Name string `json:"name"` + Token string `json:"token"` + Address string `json:"address"` + Labels []string `json:"labels"` + Ephemeral bool `json:"ephemeral"` } func LoadRegistration(file string) (*Registration, error) {