Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204package main
import ( "context" "fmt" "log/slog" "os" "strings" "text/tabwriter" "time"
"github.com/urfave/cli/v3" tlog "tangled.org/core/log" "tangled.org/core/spindle" "tangled.org/core/spindle/db" "tangled.org/core/spindle/mill")
func main() { cmd := &cli.Command{ Name: "spindle", Usage: "spindle continuous integration runner", Commands: []*cli.Command{ Command(), millCommand(), }, DefaultCommand: "run", }
logger := tlog.New("spindle") slog.SetDefault(logger)
ctx := context.Background() ctx = tlog.IntoContext(ctx, logger)
if err := cmd.Run(ctx, os.Args); err != nil { logger.Error(err.Error()) os.Exit(-1) }}
func Command() *cli.Command { return &cli.Command{ Name: "run", Usage: "run the spindle server", Action: func(ctx context.Context, cmd *cli.Command) error { return spindle.Run(ctx) }, }}
// for mill host administration and executor managementfunc millCommand() *cli.Command { dbFlag := &cli.StringFlag{ Name: "db", Usage: "path to the spindle sqlite db", Value: "spindle.db", Sources: cli.EnvVars("SPINDLE_SERVER_DB_PATH"), } openDB := func(ctx context.Context, cmd *cli.Command) (*db.DB, error) { return db.Make(ctx, cmd.String("db")) } return &cli.Command{ Name: "mill", Usage: "mill host administration", Commands: []*cli.Command{ { Name: "executor", Usage: "manage executors allowed to join this mill", Commands: []*cli.Command{ { Name: "add", Usage: "register an executor and print its token", ArgsUsage: "<name>", Flags: []cli.Flag{ dbFlag, &cli.DurationFlag{ Name: "ttl", Usage: "token lifetime (e.g. 720h); omit for no expiry", }, &cli.StringSliceFlag{ Name: "label", Usage: "authorized labels for this executor", }, }, Action: func(ctx context.Context, cmd *cli.Command) error { name := cmd.Args().First() if name == "" { return fmt.Errorf("usage: spindle mill executor add <name>") } d, err := openDB(ctx, cmd) if err != nil { return err } token, err := mill.GenerateToken() if err != nil { return err } var expiresAt *time.Time if ttl := cmd.Duration("ttl"); ttl > 0 { exp := time.Now().UTC().Add(ttl) expiresAt = &exp } labels := cmd.StringSlice("label") if err := d.AddExecutorToken(name, mill.HashToken(token), expiresAt, labels); err != nil { return fmt.Errorf("registering executor %q: %w", name, err) } fmt.Println(token) return nil }, }, { Name: "list", Usage: "list registered executors", Flags: []cli.Flag{dbFlag}, Action: func(ctx context.Context, cmd *cli.Command) error { d, err := openDB(ctx, cmd) if err != nil { return err } tokens, err := d.ListExecutorTokens() if err != nil { return err } w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0) fmt.Fprintln(w, "NAME\tCREATED\tEXPIRES\tLABELS\tQUARANTINE") for _, t := range tokens { expires := "never" if t.ExpiresAt != nil { expires = t.ExpiresAt.Format(time.RFC3339) if time.Now().After(*t.ExpiresAt) { expires += " (expired)" } } labels := strings.Join(t.Labels, ",") if labels == "" { labels = "-" } quarantine := "-" if t.QuarantineReason != nil { quarantine = *t.QuarantineReason if t.QuarantinedAt != nil { quarantine = *t.QuarantinedAt + ": " + quarantine } } fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", t.Name, t.CreatedAt, expires, labels, quarantine) } return w.Flush() }, }, { Name: "unquarantine", Usage: "allow a quarantined executor to reconnect", ArgsUsage: "<name>", Flags: []cli.Flag{dbFlag}, Action: func(ctx context.Context, cmd *cli.Command) error { name := cmd.Args().First() if name == "" { return fmt.Errorf("usage: spindle mill executor unquarantine <name>") } d, err := openDB(ctx, cmd) if err != nil { return err } ok, err := d.ClearExecutorQuarantine(name) if err != nil { return err } if !ok { return fmt.Errorf("no such executor identity %q", name) } return nil }, }, { Name: "revoke", Usage: "revoke an executor's token", ArgsUsage: "<name>", Flags: []cli.Flag{dbFlag}, Action: func(ctx context.Context, cmd *cli.Command) error { name := cmd.Args().First() if name == "" { return fmt.Errorf("usage: spindle mill executor revoke <name>") } d, err := openDB(ctx, cmd) if err != nil { return err } ok, err := d.RevokeExecutorToken(name) if err != nil { return err } if !ok { return fmt.Errorf("no such executor identity %q", name) } return nil }, }, }, }, }, }}