-
Notifications
You must be signed in to change notification settings - Fork 9
refactor: evolve salt into raystack service framework #85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ravisuhag
wants to merge
30
commits into
main
Choose a base branch
from
refactor/salt-evolution
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 18 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
1dd6f5c
refactor: restructure packages and drop unused code
ravisuhag 6f8fc36
feat(server): add h2c server with health checks and timeouts
ravisuhag e7e41ef
feat(middleware): add Connect interceptors and HTTP middleware
ravisuhag 12a2c29
feat(app): add service bootstrap
ravisuhag 1f44bcf
feat(cli): add CLI bootstrap and rewrite printer
ravisuhag 15d6c36
refactor(config): upgrade deps and remove stdout printing
ravisuhag 5f97557
fix: upgrade golangci-lint to v2 and Go to 1.24
ravisuhag e2df2b3
docs: add README, migration guide, and GoDoc examples
ravisuhag a38dd1b
refactor(cli): replace cli.Execute with cli.Init decorator pattern
ravisuhag 6b941e9
test(cli): add tests for Init, Output, and Prompter
ravisuhag b3cfd31
test(app): add test for OnStart failure cleanup behavior
ravisuhag 8a66841
feat(cli): add ConfigCommand helper for config init/list
ravisuhag 0f6ef68
deps: upgrade cobra v1.8.1 → v1.10.2, pflag v1.0.5 → v1.0.9
ravisuhag 71c0949
deps: upgrade all direct dependencies to latest
ravisuhag 02cd603
feat(cli): support cobra GroupID and set error prefix
ravisuhag 4e0d8f7
refactor(version): unexport internal functions
ravisuhag 3239333
docs: update migration guide with GroupID, ConfigCommand, dep versions
ravisuhag 77c342a
feat(prompt): add Password method for masked secret input
ravisuhag eaafbde
feat(cli): add typed error handling, remove IsCommandErr
ravisuhag f560a14
docs: add error handling examples and migration guide
ravisuhag 71818f7
feat(cli): cache version checks and add TTY-aware table output
ravisuhag 3eb7605
feat(cli): add terminal width and separate stderr for status output
ravisuhag 8e152b6
refactor(cli): add Execute, unexport error types, modernize idioms
ravisuhag 65c5fdd
fix: address review feedback from CodeRabbit
ravisuhag 2eab3de
docs: add language tag to code block and note defaults.Set error
ravisuhag 4837a4f
feat(cli): add IOStreams for centralized I/O and testability
ravisuhag 866c776
refactor(terminal): remove functions superseded by IOStreams
ravisuhag 90a1347
feat(cli): add --json flag with field selection for structured output
ravisuhag 6a1eb85
fix: address review findings across packages
ravisuhag 05a493a
fix(cli): DX improvements and comprehensive integration tests
ravisuhag File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,21 @@ | ||
| output: | ||
| formats: | ||
| - format: line-number | ||
| version: "2" | ||
| formatters: | ||
| enable: | ||
| - goimports | ||
| - gofmt | ||
| linters: | ||
| enable-all: false | ||
| disable-all: true | ||
| disable: | ||
| - errcheck | ||
| enable: | ||
| - govet | ||
| - goimports | ||
| - thelper | ||
| - tparallel | ||
| - unconvert | ||
| - wastedassign | ||
| - revive | ||
| - unused | ||
| - gofmt | ||
| - whitespace | ||
| - misspell | ||
| linters-settings: | ||
| revive: | ||
| ignore-generated-header: true | ||
| severity: warning | ||
| severity: | ||
| default-severity: error | ||
| settings: | ||
| revive: | ||
| severity: warning |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,273 @@ | ||
| # Migration Guide | ||
|
|
||
| This guide covers migrating from the previous salt version to the new structure. | ||
|
|
||
| ## Go version | ||
|
|
||
| Update `go.mod` to require Go 1.24: | ||
|
|
||
| ``` | ||
| go 1.24 | ||
| ``` | ||
|
|
||
| ## Packages removed | ||
|
|
||
| | Removed | Replacement | | ||
| |---------|-------------| | ||
| | `observability/logger` | Use `*slog.Logger` from `log/slog` directly | | ||
| | `observability/otelgrpc` | Use `connectrpc.com/otelconnect` | | ||
| | `observability/otelhttpclient` | Use `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp` | | ||
| | `server/mux` | Use `github.com/raystack/salt/server` | | ||
| | `db` | Use your preferred DB library (sqlx, pgx, gorm) directly | | ||
| | `auth/oidc` | Planned as complete CLI auth solution (#86) | | ||
| | `auth/audit` | Planned with standardized schema (#87) | | ||
| | `testing/dockertestx` | Use `ory/dockertest/v3` directly | | ||
|
|
||
| ## Packages moved | ||
|
|
||
| | Old | New | | ||
| |-----|-----| | ||
| | `observability` | `telemetry` | | ||
| | `cli/terminator` | `cli/terminal` | | ||
| | `cli/prompter` | `cli/prompt` | | ||
| | `cli/releaser` | `cli/version` | | ||
|
|
||
| ## Logger | ||
|
|
||
| The custom `logger.Logger` interface and all backends (Zap, Logrus, Slog, Noop) are removed. Use `*slog.Logger` from the Go standard library directly. | ||
|
|
||
| ```go | ||
| // Before | ||
| import "github.com/raystack/salt/observability/logger" | ||
| l := logger.NewZap() | ||
| l := logger.NewLogrus() | ||
| l := logger.NewNoop() | ||
|
|
||
| // After | ||
| import "log/slog" | ||
| l := slog.Default() | ||
| l := slog.New(slog.NewJSONHandler(os.Stderr, nil)) | ||
| l := slog.New(slog.DiscardHandler) // noop | ||
| ``` | ||
|
|
||
| All salt packages that previously accepted `logger.Logger` now accept `*slog.Logger`. | ||
|
|
||
| ## Server | ||
|
|
||
| The dual-port `server/mux` package is replaced by a single-port `server` package with h2c support. | ||
|
|
||
| ```go | ||
| // Before | ||
| import "github.com/raystack/salt/server/mux" | ||
| mux.Serve(ctx, | ||
| mux.WithHTTPTarget(":8080", httpServer), | ||
| mux.WithGRPCTarget(":8081", grpcServer), | ||
| ) | ||
|
|
||
| // After | ||
| import "github.com/raystack/salt/server" | ||
| srv := server.New( | ||
| server.WithAddr(":8080"), | ||
| server.WithHandler("/api/", connectHandler), | ||
| ) | ||
| srv.Start(ctx) | ||
| ``` | ||
|
|
||
| H2C and health check (`/ping`) are enabled by default. Use `server.WithoutH2C()` or `server.WithHealthCheck("")` to disable. | ||
|
|
||
| ## App bootstrap | ||
|
|
||
| New `app.Run()` for service bootstrap: | ||
|
|
||
| ```go | ||
| import "github.com/raystack/salt/app" | ||
|
|
||
| app.Run( | ||
| app.WithConfig(&cfg, config.WithFile("config.yaml")), | ||
| app.WithLogger(slog.Default()), | ||
| app.WithHTTPMiddleware(middleware.DefaultHTTP(slog.Default())), | ||
| app.WithHandler("/api/", handler), | ||
| app.WithAddr(cfg.Addr), | ||
|
ravisuhag marked this conversation as resolved.
|
||
| ) | ||
| ``` | ||
|
|
||
| HTTP middleware is explicit — use `middleware.DefaultHTTP(logger)` for the standard chain or compose your own. Database connections are managed via `app.WithOnStart` / `app.WithOnStop` hooks. | ||
|
|
||
| ## CLI bootstrap | ||
|
|
||
| New `cli.Init()` enhances your root command with standard features: | ||
|
|
||
| ```go | ||
| // Before | ||
| rootCmd := &cobra.Command{Use: "frontier", Short: "identity management"} | ||
| mgr := commander.New(rootCmd, commander.WithTopics(topics)) | ||
| mgr.Init() | ||
| rootCmd.AddCommand(serverCmd, configCmd) | ||
| rootCmd.Execute() | ||
|
|
||
| // After | ||
| import "github.com/raystack/salt/cli" | ||
|
|
||
| rootCmd := &cobra.Command{Use: "frontier", Short: "identity management"} | ||
| rootCmd.PersistentFlags().StringP("host", "h", "", "API host") | ||
| rootCmd.AddCommand(serverCmd, configCmd) | ||
|
|
||
| cli.Init(rootCmd, | ||
| cli.Version("0.1.0", "raystack/frontier"), | ||
| cli.Topics(topics...), | ||
| ) | ||
|
|
||
| rootCmd.Execute() | ||
| ``` | ||
|
|
||
| Config command helper replaces boilerplate: | ||
|
|
||
| ```go | ||
| // Before (50 lines of config init/list commands) | ||
| cmd.AddCommand(configInitCommand()) | ||
| cmd.AddCommand(configListCommand()) | ||
|
|
||
| // After (1 line) | ||
| rootCmd.AddCommand(cli.ConfigCommand("frontier", &Config{})) | ||
| ``` | ||
|
|
||
| Command grouping uses cobra's native GroupID instead of annotations: | ||
|
|
||
| ```go | ||
| // Before | ||
| cmd.Annotations = map[string]string{"group": "core"} | ||
|
|
||
| // After | ||
| rootCmd.AddGroup(&cobra.Group{ID: "manage", Title: "Management:"}) | ||
| cmd.GroupID = "manage" | ||
| ``` | ||
|
|
||
| Access shared output and prompting in commands: | ||
|
|
||
| ```go | ||
| func newListCmd() *cobra.Command { | ||
| return &cobra.Command{ | ||
| Use: "list", | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| out := cli.Output(cmd) | ||
| out.Table(rows) | ||
| return nil | ||
| }, | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Printer | ||
|
|
||
| Package-level functions replaced by `Output` type: | ||
|
|
||
| ```go | ||
| // Before | ||
| printer.Success("done") | ||
| printer.Table(os.Stdout, rows) | ||
| printer.JSON(data) | ||
| spinner := printer.Spin("loading") | ||
|
|
||
| // After | ||
| out := printer.NewOutput(os.Stdout) | ||
| // or inside a command: out := cli.Output(cmd) | ||
|
|
||
| out.Success("done") | ||
| out.Table(rows) | ||
| out.JSON(data) | ||
| spinner := out.Spin("loading") | ||
| ``` | ||
|
|
||
| Color formatting functions remain as package-level helpers returning styled strings: | ||
|
|
||
| ```go | ||
| printer.Green("text") | ||
| printer.Greenf("count: %d", n) | ||
| printer.Icon("success") // ✔ | ||
| printer.Italic("note") | ||
| ``` | ||
|
|
||
| ## Telemetry | ||
|
|
||
| ```go | ||
| // Before | ||
| import "github.com/raystack/salt/observability" | ||
| observability.Init(ctx, cfg, logger) | ||
|
|
||
| // After | ||
| import "github.com/raystack/salt/telemetry" | ||
| telemetry.Init(ctx, cfg, slogLogger) | ||
| ``` | ||
|
|
||
| ## Middleware | ||
|
|
||
| New package for ConnectRPC and HTTP middleware: | ||
|
|
||
| ```go | ||
| import "github.com/raystack/salt/middleware" | ||
|
|
||
| // Connect interceptors for your handler | ||
| interceptors := middleware.Default(slog.Default()) | ||
| handler := myv1connect.NewServiceHandler(svc, connect.WithInterceptors(interceptors...)) | ||
|
|
||
| // HTTP middleware | ||
| httpMW := middleware.DefaultHTTP(slog.Default()) | ||
| ``` | ||
|
|
||
| ## Config | ||
|
|
||
| ```go | ||
| // Import path for validator changed | ||
| // Before: "github.com/go-playground/validator" | ||
| // After: "github.com/go-playground/validator/v10" | ||
|
|
||
| // If you imported go-defaults directly: | ||
| // Before: "github.com/mcuadros/go-defaults" | ||
| // After: "github.com/creasty/defaults" | ||
| // API change: defaults.SetDefaults(cfg) → defaults.Set(cfg) | ||
| ``` | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| The config package no longer prints warnings to stdout when a config file is missing. | ||
|
|
||
| ## Version package | ||
|
|
||
| `cli/version` now exports only `CheckForUpdate`. The functions `FetchInfo`, `CompareVersions`, and types `Info`, `Timeout`, `APIFormat` are no longer exported — they were internal implementation details. | ||
|
|
||
| ## Dependency changes | ||
|
|
||
| | Removed (direct) | Replacement | | ||
| |-------------------|-------------| | ||
| | `go.uber.org/zap` | `log/slog` (stdlib) | | ||
| | `sirupsen/logrus` | `log/slog` (stdlib) | | ||
| | `AlecAivazis/survey/v2` | `charmbracelet/huh` | | ||
| | `olekukonko/tablewriter` | `text/tabwriter` (stdlib) | | ||
| | `oklog/run` | Removed with `server/mux` | | ||
| | `cli/safeexec` | `exec.LookPath` (stdlib) | | ||
| | `pkg/errors` | `fmt.Errorf` with `%w` (stdlib) | | ||
| | `mcuadros/go-defaults` | `creasty/defaults` | | ||
| | `go-playground/validator` v9 | `go-playground/validator/v10` | | ||
| | `jmoiron/sqlx` | Use directly if needed | | ||
| | `golang-migrate` | Use directly if needed | | ||
| | `ory/dockertest` | Use directly if needed | | ||
|
|
||
| | Added | Purpose | | ||
| |-------|---------| | ||
| | `connectrpc.com/connect` | Middleware interceptors | | ||
| | `charmbracelet/huh` | Interactive prompts | | ||
| | `creasty/defaults` | Struct default values | | ||
|
|
||
| | Upgraded | From → To | | ||
| |----------|-----------| | ||
| | `spf13/cobra` | v1.8.1 → v1.10.2 | | ||
| | `spf13/pflag` | v1.0.5 → v1.0.10 | | ||
| | `spf13/viper` | v1.19.0 → v1.21.0 | | ||
| | `go-playground/validator` | v9 → v10 | | ||
| | `charmbracelet/glamour` | v0.3 → v1.0.0 | | ||
| | `muesli/termenv` | v0.11 → v0.16.0 | | ||
| | `briandowns/spinner` | v1.18 → v1.23.2 | | ||
| | `schollz/progressbar` | v3.8 → v3.19.0 | | ||
| | `mattn/go-isatty` | v0.0.19 → v0.0.21 | | ||
| | `opentelemetry/otel` | v1.31.0 → v1.43.0 | | ||
| | `google.golang.org/grpc` | v1.67.1 → v1.80.0 | | ||
| | `stretchr/testify` | v1.9.0 → v1.11.1 | | ||
| | `hashicorp/go-version` | v1.3.0 → v1.9.0 | | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.