From 8f9d7506dc71aaa55db74b80a7118bc18d6947f2 Mon Sep 17 00:00:00 2001 From: fuxiaohei Date: Tue, 15 Nov 2022 21:28:07 +0800 Subject: [PATCH] feat(cli): set interactive stages in register command --- cmd/cmd.go | 18 ------- cmd/daemon.go | 18 +++++++ cmd/register.go | 129 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 146 insertions(+), 19 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index cf12a46..e3fe23c 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -5,33 +5,15 @@ import ( "os" "strconv" - "gitea.com/gitea/act_runner/config" "gitea.com/gitea/act_runner/engine" "gitea.com/gitea/act_runner/runtime" - "github.com/mattn/go-isatty" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) const version = "0.1.5" -// 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 cfg.Debug { - log.SetLevel(log.DebugLevel) - } - if cfg.Trace { - log.SetLevel(log.TraceLevel) - } -} - func Execute(ctx context.Context) { task := runtime.NewTask("gitea", 0, nil, nil) diff --git a/cmd/daemon.go b/cmd/daemon.go index d240720..5216937 100644 --- a/cmd/daemon.go +++ b/cmd/daemon.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "os" "time" "gitea.com/gitea/act_runner/client" @@ -15,6 +16,7 @@ import ( "github.com/bufbuild/connect-go" "github.com/joho/godotenv" + "github.com/mattn/go-isatty" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" @@ -162,3 +164,19 @@ func runDaemon(ctx context.Context, envFile string) func(cmd *cobra.Command, arg 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 cfg.Debug { + log.SetLevel(log.DebugLevel) + } + if cfg.Trace { + log.SetLevel(log.TraceLevel) + } +} diff --git a/cmd/register.go b/cmd/register.go index fe54c26..0a96dd4 100644 --- a/cmd/register.go +++ b/cmd/register.go @@ -1,8 +1,14 @@ package cmd import ( + "bufio" "context" + "os" + "os/signal" + "runtime" + "strings" + "github.com/mattn/go-isatty" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -10,7 +16,35 @@ import ( // runRegister registers a runner to the server func runRegister(ctx context.Context, regArgs *registerArgs) func(*cobra.Command, []string) error { return func(cmd *cobra.Command, args []string) error { - log.Infoln("Starting register to gitea instance") + log.SetReportCaller(false) + isTerm := isatty.IsTerminal(os.Stdout.Fd()) + log.SetFormatter(&log.TextFormatter{ + DisableColors: !isTerm, + DisableTimestamp: true, + }) + + log.Infof("Registering runner, arch=%s, os=%s, version=%s.", + runtime.GOARCH, runtime.GOOS, version) + + // runner always needs root permission + if os.Getuid() != 0 { + // TODO: use a better way to check root permission + log.Warnf("Runner in user-mode.") + } + + go func() { + if err := registerInteractive(); err != nil { + // log.Errorln(err) + os.Exit(2) + return + } + os.Exit(0) + }() + + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + <-c + return nil } } @@ -21,3 +55,96 @@ type registerArgs struct { InstanceAddr string Token string } + +type registerStage int8 + +const ( + StageUnknown registerStage = -1 + StageInputInstance registerStage = iota + 1 + StageInputToken + StageInputRunnerName + StageInputCustomLabels + StageWaitingForRegistration +) + +type registerInputs struct { + InstanceAddr string + Token string + RunnerName string + CustomLabels []string +} + +func (r *registerInputs) assignToNext(stage registerStage, value string) registerStage { + + // must set instance address and token. + // if empty, keep current stage. + if stage == StageInputInstance || stage == StageInputToken { + if value == "" { + return stage + } + } + + // set hostname for runner name if empty + if stage == StageInputRunnerName && value == "" { + value, _ = os.Hostname() + } + + switch stage { + case StageInputInstance: + r.InstanceAddr = value + return StageInputToken + case StageInputToken: + r.Token = value + return StageInputRunnerName + case StageInputRunnerName: + r.RunnerName = value + return StageInputCustomLabels + case StageInputCustomLabels: + r.CustomLabels = strings.Split(value, ",") + return StageWaitingForRegistration + } + return StageUnknown +} + +func registerInteractive() error { + var ( + reader = bufio.NewReader(os.Stdin) + stage = StageInputInstance + inputs = new(registerInputs) + ) + + for { + printStageHelp(stage) + cmdString, err := reader.ReadString('\n') + if err != nil { + return err + } + stage = inputs.assignToNext(stage, strings.TrimSpace(cmdString)) + + if stage == StageWaitingForRegistration { + log.Infof("Registering runner, name=%s, instance=%s, labels=%v.", inputs.RunnerName, inputs.InstanceAddr, inputs.CustomLabels) + return nil + } + + if stage <= StageUnknown { + log.Errorf("Invalid input, please re-run act command.") + return nil + } + } +} + +func printStageHelp(stage registerStage) { + switch stage { + case StageInputInstance: + log.Infoln("Enter the Gitea instance URL (for example, https://gitea.com/):") + case StageInputToken: + log.Infoln("Enter the runner token:") + case StageInputRunnerName: + 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, label1,label2):") + case StageWaitingForRegistration: + log.Infoln("Waiting for registration...") + } +}