refactor(cmd): use factories instead of global cobra command structs (#238)

This enables us to create new commands for e2e tests.
This commit is contained in:
Julian Tölle 2025-08-24 16:44:05 +02:00 committed by GitHub
parent 5b5b29c0b5
commit e6503da93a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 128 additions and 111 deletions

View file

@ -7,21 +7,23 @@ import (
"os/signal"
"runtime/debug"
"syscall"
"time"
"github.com/lmittmann/tint"
"github.com/spf13/cobra"
)
var logger *slog.Logger
var rootCmd = &cobra.Command{
func NewRootCmd() *cobra.Command {
var cmd = &cobra.Command{
Use: "rp",
Short: "",
Long: ``,
Version: version(),
SilenceUsage: true, // Makes it harder to find the actual error
SilenceErrors: true, // We log manually with slog
}
cmd.AddCommand(newRunCommand())
return cmd
}
func version() string {
@ -66,24 +68,13 @@ func Execute() {
// Make sure to stop listening on signals after receiving the first signal to hand control of the signal back
// to the runtime. The Go runtime implements a "force shutdown" if the signal is received again.
<-ctx.Done()
logger.InfoContext(ctx, "Received shutdown signal, stopping...")
slog.InfoContext(ctx, "Received shutdown signal, stopping...")
stop()
}()
err := rootCmd.ExecuteContext(ctx)
err := NewRootCmd().ExecuteContext(ctx)
if err != nil {
logger.ErrorContext(ctx, err.Error())
slog.ErrorContext(ctx, err.Error())
os.Exit(1)
}
}
func init() {
logger = slog.New(
tint.NewHandler(os.Stderr, &tint.Options{
Level: slog.LevelDebug,
TimeFormat: time.RFC3339,
}),
)
slog.SetDefault(logger)
}

View file

@ -2,6 +2,7 @@ package cmd
import (
"fmt"
"log/slog"
"slices"
"strings"
@ -12,36 +13,26 @@ import (
"github.com/apricote/releaser-pleaser/internal/forge"
"github.com/apricote/releaser-pleaser/internal/forge/github"
"github.com/apricote/releaser-pleaser/internal/forge/gitlab"
"github.com/apricote/releaser-pleaser/internal/log"
"github.com/apricote/releaser-pleaser/internal/updater"
"github.com/apricote/releaser-pleaser/internal/versioning"
)
var runCmd = &cobra.Command{
Use: "run",
RunE: run,
}
var (
func newRunCommand() *cobra.Command {
var (
flagForge string
flagBranch string
flagOwner string
flagRepo string
flagExtraFiles string
flagUpdaters []string
)
)
func init() {
rootCmd.AddCommand(runCmd)
runCmd.PersistentFlags().StringVar(&flagForge, "forge", "", "")
runCmd.PersistentFlags().StringVar(&flagBranch, "branch", "main", "")
runCmd.PersistentFlags().StringVar(&flagOwner, "owner", "", "")
runCmd.PersistentFlags().StringVar(&flagRepo, "repo", "", "")
runCmd.PersistentFlags().StringVar(&flagExtraFiles, "extra-files", "", "")
runCmd.PersistentFlags().StringSliceVar(&flagUpdaters, "updaters", []string{}, "")
}
func run(cmd *cobra.Command, _ []string) error {
var cmd = &cobra.Command{
Use: "run",
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
logger := log.GetLogger(cmd.ErrOrStderr())
var err error
@ -67,7 +58,7 @@ func run(cmd *cobra.Command, _ []string) error {
Path: fmt.Sprintf("%s/%s", flagOwner, flagRepo),
})
if err != nil {
logger.ErrorContext(ctx, "failed to create client", "err", err)
slog.ErrorContext(ctx, "failed to create client", "err", err)
return fmt.Errorf("failed to create gitlab client: %w", err)
}
case "github":
@ -109,6 +100,17 @@ func run(cmd *cobra.Command, _ []string) error {
)
return releaserPleaser.Run(ctx)
},
}
cmd.PersistentFlags().StringVar(&flagForge, "forge", "", "")
cmd.PersistentFlags().StringVar(&flagBranch, "branch", "main", "")
cmd.PersistentFlags().StringVar(&flagOwner, "owner", "", "")
cmd.PersistentFlags().StringVar(&flagRepo, "repo", "", "")
cmd.PersistentFlags().StringVar(&flagExtraFiles, "extra-files", "", "")
cmd.PersistentFlags().StringSliceVar(&flagUpdaters, "updaters", []string{}, "")
return cmd
}
func parseExtraFiles(input string) []string {

View file

@ -2,6 +2,7 @@ package main
import (
"github.com/apricote/releaser-pleaser/cmd/rp/cmd"
_ "github.com/apricote/releaser-pleaser/internal/log"
)
func main() {

23
internal/log/log.go Normal file
View file

@ -0,0 +1,23 @@
package log
import (
"io"
"log/slog"
"os"
"time"
"github.com/lmittmann/tint"
)
func GetLogger(w io.Writer) *slog.Logger {
return slog.New(
tint.NewHandler(w, &tint.Options{
Level: slog.LevelDebug,
TimeFormat: time.RFC3339,
}),
)
}
func init() {
slog.SetDefault(GetLogger(os.Stderr))
}