diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 76293726..b10d67af 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.43" + ".": "0.1.0-alpha.44" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 246eac41..f8afb0ab 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/stainless%2Fstainless-v0-e588492ce099ac1af79467a22ecac606b1fe8cf78a82fd37137bf8e30ac1a80e.yml -openapi_spec_hash: 7311d0d71ab64604d2b298e3c38b945f -config_hash: b4d273d7503424c98b7d284102d23fb1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/stainless%2Fstainless-v0-5c1008fd27f64bcde1a146a4158f1c3113b4e13437a4d880bd6811fb063cfcd6.yml +openapi_spec_hash: 9583f62164b5dc15b10051dad6a7fca4 +config_hash: e895f7992a607a15865ed026cbe5470d diff --git a/CHANGELOG.md b/CHANGELOG.md index a2702e4b..c7a6304d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## 0.1.0-alpha.44 (2025-09-22) + +Full Changelog: [v0.1.0-alpha.43...v0.1.0-alpha.44](https://github.com/stainless-api/stainless-api-cli/compare/v0.1.0-alpha.43...v0.1.0-alpha.44) + +### Features + +* **api:** docs ([f0762b0](https://github.com/stainless-api/stainless-api-cli/commit/f0762b08842d63a55f28afc18a77907c24f2513b)) +* improved formatting options for command outputs ([f5e6481](https://github.com/stainless-api/stainless-api-cli/commit/f5e6481706b882eaa0c84a3bf8aea2a088087402)) +* show full error message on fatal error ([00621a1](https://github.com/stainless-api/stainless-api-cli/commit/00621a1ba20a392670dc8a7bf991c1d0507efc12)) + + +### Bug Fixes + +* fix for issue with nil responses ([14f22bf](https://github.com/stainless-api/stainless-api-cli/commit/14f22bfbe6318e849a57b2243c958e3af869b18c)) +* fix go client version bump issues ([d59e6ea](https://github.com/stainless-api/stainless-api-cli/commit/d59e6ea0f8363c1ad7ace9c97e243ec972f75c24)) + + +### Chores + +* code cleanup for `interface{}` ([30cd6f1](https://github.com/stainless-api/stainless-api-cli/commit/30cd6f10ce33163f4f6b7f13085a259cf738ca49)) +* do not install brew dependencies in ./scripts/bootstrap by default ([ff84f98](https://github.com/stainless-api/stainless-api-cli/commit/ff84f986702f63a60e1f5343e180c305877f6171)) +* update go dependency ([22a15b8](https://github.com/stainless-api/stainless-api-cli/commit/22a15b85720596afe3dd95d3be4f2ce4ddf1341a)) + ## 0.1.0-alpha.43 (2025-09-16) Full Changelog: [v0.1.0-alpha.42...v0.1.0-alpha.43](https://github.com/stainless-api/stainless-api-cli/compare/v0.1.0-alpha.42...v0.1.0-alpha.43) diff --git a/README.md b/README.md index 53a4c853..0fe5ca33 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,8 @@ stl [resource] [command] [flags] ```sh stl builds create \ - --project project \ - --revision string + --project stainless \ + --revision main ``` For details about specific commands, use the `--help` flag. diff --git a/go.mod b/go.mod index a5f4c42e..26bb4340 100644 --- a/go.mod +++ b/go.mod @@ -16,8 +16,8 @@ require ( github.com/logrusorgru/aurora/v4 v4.0.0 github.com/muesli/reflow v0.3.0 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c - github.com/stainless-api/stainless-api-go v0.24.0 - github.com/tidwall/gjson v1.17.0 + github.com/stainless-api/stainless-api-go v0.25.0 + github.com/tidwall/gjson v1.18.0 github.com/tidwall/pretty v1.2.1 github.com/tidwall/sjson v1.2.5 github.com/urfave/cli-docs/v3 v3.0.0-alpha6 diff --git a/go.sum b/go.sum index 23d5b0aa..2c27d9b4 100644 --- a/go.sum +++ b/go.sum @@ -99,13 +99,13 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/stainless-api/stainless-api-go v0.24.0 h1:74rVOCsNiZFzp5WiNFZAF+0WPriyUdaQezUIDRzoqUo= -github.com/stainless-api/stainless-api-go v0.24.0/go.mod h1:9Q2t8xq6EFgw8HYOsVxqKEfSDVe9eqCoh1zC0HMRwTY= +github.com/stainless-api/stainless-api-go v0.25.0 h1:zcKI6oXjvw7kK3LoLOwmIxAGT+KzxBlWRyeZUCZ4s4E= +github.com/stainless-api/stainless-api-go v0.25.0/go.mod h1:apIvLQZziUlztAHBzTCLwf2TepwlPV0fg7dy/HIrKf8= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= -github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= diff --git a/pkg/cmd/build.go b/pkg/cmd/build.go index 0779c5ca..c76612e8 100644 --- a/pkg/cmd/build.go +++ b/pkg/cmd/build.go @@ -105,7 +105,7 @@ func processSingleTarget(target string) (string, string) { } // getBuildTargetInfo extracts completed targets from a build response -func getBuildTargetInfo(buildRes stainless.BuildObject) []BuildTargetInfo { +func getBuildTargetInfo(buildRes stainless.Build) []BuildTargetInfo { targets := []BuildTargetInfo{} // Check each target and add it to the list if it's completed or in postgen @@ -173,7 +173,7 @@ func isTargetCompleted(status stainless.BuildTargetStatus) bool { } // waitForBuildCompletion polls a build until completion and shows progress updates -func waitForBuildCompletion(ctx context.Context, client stainless.Client, build *stainless.BuildObject, waitGroup *Group) (*stainless.BuildObject, error) { +func waitForBuildCompletion(ctx context.Context, client stainless.Client, build *stainless.Build, waitGroup *Group) (*stainless.Build, error) { ticker := time.NewTicker(3 * time.Second) defer ticker.Stop() @@ -225,7 +225,7 @@ func waitForBuildCompletion(ctx context.Context, client stainless.Client, build var buildsCreate = cli.Command{ Name: "create", - Usage: "Create a new build", + Usage: "Create a build, on top of a project branch, against a given input revision.", Flags: []cli.Flag{ &jsonflag.JSONStringFlag{ Name: "project", @@ -310,7 +310,7 @@ var buildsCreate = cli.Command{ var buildsRetrieve = cli.Command{ Name: "retrieve", - Usage: "Retrieve a build by ID", + Usage: "Retrieve a build by its ID.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "build-id", @@ -322,7 +322,7 @@ var buildsRetrieve = cli.Command{ var buildsList = cli.Command{ Name: "list", - Usage: "List builds for a project", + Usage: "List user-triggered builds for a given project.", Flags: []cli.Flag{ &jsonflag.JSONStringFlag{ Name: "project", @@ -366,7 +366,7 @@ var buildsList = cli.Command{ var buildsCompare = cli.Command{ Name: "compare", - Usage: "Creates two builds whose outputs can be compared directly", + Usage: "Create two builds whose outputs can be directly compared with each other.", Flags: []cli.Flag{ &jsonflag.JSONStringFlag{ Name: "base.branch", @@ -489,21 +489,23 @@ func handleBuildsCreate(ctx context.Context, cmd *cli.Command) error { func handleBuildsRetrieve(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) - res, err := cc.client.Builds.Get( + var res []byte + _, err := cc.client.Builds.Get( context.TODO(), cmd.Value("build-id").(string), option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("builds retrieve", res.RawJSON(), format) + return ShowJSON("builds retrieve", string(res), format) } // pullBuildOutputs pulls the outputs for a completed build -func pullBuildOutputs(ctx context.Context, client stainless.Client, res stainless.BuildObject, targetPaths map[string]string, pullGroup *Group) error { +func pullBuildOutputs(ctx context.Context, client stainless.Client, res stainless.Build, targetPaths map[string]string, pullGroup *Group) error { // Get all targets allTargets := getBuildTargetInfo(res) @@ -572,8 +574,8 @@ func pullBuildOutputs(ctx context.Context, client stainless.Client, res stainles } // hasFailedCommitStep checks if a target has a fatal commit conclusion -func hasFailedCommitStep(build stainless.BuildObject, target stainless.Target) bool { - buildObj := NewBuildObject(&build) +func hasFailedCommitStep(build stainless.Build, target stainless.Target) bool { + buildObj := NewBuild(&build) buildTarget := buildObj.BuildTarget(target) if buildTarget == nil { return false @@ -774,31 +776,35 @@ func pullOutput(output, url, ref, targetDir string, targetGroup *Group) error { func handleBuildsList(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) params := stainless.BuildListParams{} - res, err := cc.client.Builds.List( + var res []byte + _, err := cc.client.Builds.List( context.TODO(), params, option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("builds list", res.RawJSON(), format) + return ShowJSON("builds list", string(res), format) } func handleBuildsCompare(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) params := stainless.BuildCompareParams{} - res, err := cc.client.Builds.Compare( + var res []byte + _, err := cc.client.Builds.Compare( context.TODO(), params, option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("builds compare", res.RawJSON(), format) + return ShowJSON("builds compare", string(res), format) } diff --git a/pkg/cmd/builddiagnostic.go b/pkg/cmd/builddiagnostic.go index bf347cd2..34e22f62 100644 --- a/pkg/cmd/builddiagnostic.go +++ b/pkg/cmd/builddiagnostic.go @@ -13,7 +13,7 @@ import ( var buildsDiagnosticsList = cli.Command{ Name: "list", - Usage: "Get diagnostics for a build", + Usage: "Get the list of diagnostics for a given build.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "build-id", @@ -61,16 +61,18 @@ var buildsDiagnosticsList = cli.Command{ func handleBuildsDiagnosticsList(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) params := stainless.BuildDiagnosticListParams{} - res, err := cc.client.Builds.Diagnostics.List( + var res []byte + _, err := cc.client.Builds.Diagnostics.List( context.TODO(), cmd.Value("build-id").(string), params, option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("builds:diagnostics list", res.RawJSON(), format) + return ShowJSON("builds:diagnostics list", string(res), format) } diff --git a/pkg/cmd/buildtargetoutput.go b/pkg/cmd/buildtargetoutput.go index 79ceed4a..fed4e519 100644 --- a/pkg/cmd/buildtargetoutput.go +++ b/pkg/cmd/buildtargetoutput.go @@ -14,7 +14,7 @@ import ( var buildsTargetOutputsRetrieve = cli.Command{ Name: "retrieve", - Usage: "Download the output of a build target", + Usage: "Retrieve a method to download an output for a given build target.", Flags: []cli.Flag{ &cli.BoolFlag{ Name: "pull", @@ -85,7 +85,9 @@ func handleBuildsTargetOutputsRetrieve(ctx context.Context, cmd *cli.Command) er } format := cmd.Root().String("format") - fmt.Printf("%s\n", ShowJSON("builds:target_outputs retrieve", res.RawJSON(), format)) + if err := ShowJSON("builds:target_outputs retrieve", res.RawJSON(), format); err != nil { + return err + } group := Info("Downloading output") if cmd.Bool("pull") { @@ -95,7 +97,7 @@ func handleBuildsTargetOutputsRetrieve(ctx context.Context, cmd *cli.Command) er return nil } -func getLatestBuild(ctx context.Context, client stainless.Client, project, branch string) (*stainless.BuildObject, error) { +func getLatestBuild(ctx context.Context, client stainless.Client, project, branch string) (*stainless.Build, error) { if project == "" { return nil, fmt.Errorf("project is required when build-id is not provided") } diff --git a/pkg/cmd/dev.go b/pkg/cmd/dev.go index 4cbcd913..02969792 100644 --- a/pkg/cmd/dev.go +++ b/pkg/cmd/dev.go @@ -21,12 +21,12 @@ var ErrUserCancelled = errors.New("user cancelled") // BuildModel represents the bubbletea model for build monitoring type BuildModel struct { - start func() (*stainless.BuildObject, error) + start func() (*stainless.Build, error) started time.Time ended *time.Time - build *stainless.BuildObject + build *stainless.Build branch string - diagnostics []stainless.BuildDiagnosticListResponse + diagnostics []stainless.BuildDiagnostic downloads map[stainless.Target]struct { status string path string @@ -40,13 +40,13 @@ type BuildModel struct { } type tickMsg time.Time -type fetchBuildMsg *stainless.BuildObject -type fetchDiagnosticsMsg []stainless.BuildDiagnosticListResponse +type fetchBuildMsg *stainless.Build +type fetchDiagnosticsMsg []stainless.BuildDiagnostic type errorMsg error type downloadMsg stainless.Target type triggerNewBuildMsg struct{} -func NewBuildModel(cc *apiCommandContext, ctx context.Context, branch string, fn func() (*stainless.BuildObject, error)) BuildModel { +func NewBuildModel(cc *apiCommandContext, ctx context.Context, branch string, fn func() (*stainless.Build, error)) BuildModel { return BuildModel{ start: fn, started: time.Now(), @@ -117,7 +117,7 @@ func (m BuildModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } m.build = msg - buildObj := NewBuildObject(m.build) + buildObj := NewBuild(m.build) if !m.isCompleted { // Check if all commit steps are completed allCommitsCompleted := true @@ -206,7 +206,7 @@ func (m BuildModel) fetchDiagnostics() tea.Cmd { if m.build == nil { return errorMsg(fmt.Errorf("no current build to fetch diagnostics for")) } - diags := []stainless.BuildDiagnosticListResponse{} + diags := []stainless.BuildDiagnostic{} diagnostics := m.cc.client.Builds.Diagnostics.ListAutoPaging(m.ctx, m.build.ID, stainless.BuildDiagnosticListParams{ Limit: stainless.Float(100), }) @@ -225,7 +225,7 @@ func (m *BuildModel) getBuildDuration() time.Duration { return time.Since(m.started) } - buildObj := NewBuildObject(m.build) + buildObj := NewBuild(m.build) if buildObj.IsCompleted() { if m.ended == nil { now := time.Now() @@ -370,7 +370,7 @@ func runDevBuild(ctx context.Context, cc *apiCommandContext, cmd *cli.Command, b AllowEmpty: stainless.Bool(true), } - model := NewBuildModel(cc, ctx, branch, func() (*stainless.BuildObject, error) { + model := NewBuildModel(cc, ctx, branch, func() (*stainless.Build, error) { build, err := cc.client.Builds.New(ctx, buildReq, option.WithMiddleware(cc.AsMiddleware())) if err != nil { return nil, fmt.Errorf("failed to create build: %v", err) diff --git a/pkg/cmd/dev_view.go b/pkg/cmd/dev_view.go index 7f5d8b18..7a312539 100644 --- a/pkg/cmd/dev_view.go +++ b/pkg/cmd/dev_view.go @@ -133,7 +133,7 @@ var parts = []struct { view: func(m BuildModel, s *strings.Builder) { s.WriteString("\n") if m.build != nil { - buildObj := NewBuildObject(m.build) + buildObj := NewBuild(m.build) languages := buildObj.Languages() // Target rows with colors for _, target := range languages { @@ -173,11 +173,11 @@ var parts = []struct { }, } -func ViewBuildPipeline(build *stainless.BuildObject, target stainless.Target, downloads map[stainless.Target]struct { +func ViewBuildPipeline(build *stainless.Build, target stainless.Target, downloads map[stainless.Target]struct { status string path string }) string { - buildObj := NewBuildObject(build) + buildObj := NewBuild(build) buildTarget := buildObj.BuildTarget(target) if buildTarget == nil { return "" @@ -240,15 +240,15 @@ func ViewStepSymbol(status, conclusion string) string { } } -func ViewDiagnosticIcon(level stainless.BuildDiagnosticListResponseLevel) string { +func ViewDiagnosticIcon(level stainless.BuildDiagnosticLevel) string { switch level { - case stainless.BuildDiagnosticListResponseLevelFatal: + case stainless.BuildDiagnosticLevelFatal: return lipgloss.NewStyle().Foreground(lipgloss.Color("1")).Bold(true).Render("đź’€") - case stainless.BuildDiagnosticListResponseLevelError: + case stainless.BuildDiagnosticLevelError: return lipgloss.NewStyle().Foreground(lipgloss.Color("1")).Render("❌") - case stainless.BuildDiagnosticListResponseLevelWarning: + case stainless.BuildDiagnosticLevelWarning: return lipgloss.NewStyle().Foreground(lipgloss.Color("3")).Render("⚠️") - case stainless.BuildDiagnosticListResponseLevelNote: + case stainless.BuildDiagnosticLevelNote: return lipgloss.NewStyle().Foreground(lipgloss.Color("6")).Render("ℹ️") default: return lipgloss.NewStyle().Foreground(lipgloss.Color("8")).Render("•") @@ -309,23 +309,23 @@ func renderMarkdown(content string) string { return strings.Trim(rendered, "\n ") } -func countDiagnosticsBySeverity(diagnostics []stainless.BuildDiagnosticListResponse) (fatal, errors, warnings, notes int) { +func countDiagnosticsBySeverity(diagnostics []stainless.BuildDiagnostic) (fatal, errors, warnings, notes int) { for _, diag := range diagnostics { switch diag.Level { - case stainless.BuildDiagnosticListResponseLevelFatal: + case stainless.BuildDiagnosticLevelFatal: fatal++ - case stainless.BuildDiagnosticListResponseLevelError: + case stainless.BuildDiagnosticLevelError: errors++ - case stainless.BuildDiagnosticListResponseLevelWarning: + case stainless.BuildDiagnosticLevelWarning: warnings++ - case stainless.BuildDiagnosticListResponseLevelNote: + case stainless.BuildDiagnosticLevelNote: notes++ } } return } -func ViewDiagnosticsPrint(diagnostics []stainless.BuildDiagnosticListResponse) string { +func ViewDiagnosticsPrint(diagnostics []stainless.BuildDiagnostic) string { var s strings.Builder if len(diagnostics) > 0 { @@ -373,6 +373,15 @@ func ViewDiagnosticsPrint(diagnostics []stainless.BuildDiagnosticListResponse) s sub.WriteString(fmt.Sprintf("%s %s\n", levelIcon, codeStyle.Render(diag.Code))) sub.WriteString(fmt.Sprintf("%s\n", renderMarkdown(diag.Message))) + if diag.Code == "FatalError" { + switch more := diag.More.AsAny().(type) { + case stainless.BuildDiagnosticMoreMarkdown: + sub.WriteString(fmt.Sprintf("%s\n", renderMarkdown(more.Markdown))) + case stainless.BuildDiagnosticMoreRaw: + sub.WriteString(fmt.Sprintf("%s\n", more.Raw)) + } + } + // Show source references if available if diag.OasRef != "" { refStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("8")) diff --git a/pkg/cmd/init.go b/pkg/cmd/init.go index 0cc6ff3a..e7287e21 100644 --- a/pkg/cmd/init.go +++ b/pkg/cmd/init.go @@ -459,7 +459,7 @@ func configureTargets(slug string, selectedTargets []string, config *WorkspaceCo } // waitForLatestBuild waits for the latest build to complete -func waitForLatestBuild(ctx context.Context, client stainless.Client, slug string) (*stainless.BuildObject, error) { +func waitForLatestBuild(ctx context.Context, client stainless.Client, slug string) (*stainless.Build, error) { waitGroup := Info("Waiting for build to complete...") // Try to get the latest build for this project (which should have been created automatically) @@ -478,7 +478,7 @@ func waitForLatestBuild(ctx context.Context, client stainless.Client, slug strin } // pullConfiguredTargets pulls build outputs for configured targets -func pullConfiguredTargets(ctx context.Context, client stainless.Client, build stainless.BuildObject, config WorkspaceConfig) error { +func pullConfiguredTargets(ctx context.Context, client stainless.Client, build stainless.Build, config WorkspaceConfig) error { if config.Targets == nil || len(config.Targets) == 0 { return nil } diff --git a/pkg/cmd/org.go b/pkg/cmd/org.go index 5c7c72bf..363ff718 100644 --- a/pkg/cmd/org.go +++ b/pkg/cmd/org.go @@ -11,7 +11,7 @@ import ( var orgsRetrieve = cli.Command{ Name: "retrieve", - Usage: "Retrieve an organization by name", + Usage: "Retrieve an organization by name.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "org", @@ -23,7 +23,7 @@ var orgsRetrieve = cli.Command{ var orgsList = cli.Command{ Name: "list", - Usage: "List organizations the user has access to", + Usage: "List organizations accessible to the current authentication method.", Flags: []cli.Flag{}, Action: handleOrgsList, HideHelpCommand: true, @@ -31,26 +31,33 @@ var orgsList = cli.Command{ func handleOrgsRetrieve(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) - res, err := cc.client.Orgs.Get( + var res []byte + _, err := cc.client.Orgs.Get( context.TODO(), cmd.Value("org").(string), option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("orgs retrieve", res.RawJSON(), format) + return ShowJSON("orgs retrieve", string(res), format) } func handleOrgsList(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) - res, err := cc.client.Orgs.List(context.TODO(), option.WithMiddleware(cc.AsMiddleware())) + var res []byte + _, err := cc.client.Orgs.List( + context.TODO(), + option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), + ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("orgs list", res.RawJSON(), format) + return ShowJSON("orgs list", string(res), format) } diff --git a/pkg/cmd/project.go b/pkg/cmd/project.go index d3c46b14..158b2940 100644 --- a/pkg/cmd/project.go +++ b/pkg/cmd/project.go @@ -13,7 +13,7 @@ import ( var projectsCreate = cli.Command{ Name: "create", - Usage: "Create a new project", + Usage: "Create a new project.", Flags: []cli.Flag{ &jsonflag.JSONStringFlag{ Name: "display-name", @@ -57,7 +57,7 @@ var projectsCreate = cli.Command{ var projectsRetrieve = cli.Command{ Name: "retrieve", - Usage: "Retrieve a project by name", + Usage: "Retrieve a project by name.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "project", @@ -69,7 +69,7 @@ var projectsRetrieve = cli.Command{ var projectsUpdate = cli.Command{ Name: "update", - Usage: "Update a project's properties", + Usage: "Update a project's properties.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "project", @@ -88,7 +88,7 @@ var projectsUpdate = cli.Command{ var projectsList = cli.Command{ Name: "list", - Usage: "List projects in an organization, from oldest to newest", + Usage: "List projects in an organization, from oldest to newest.", Flags: []cli.Flag{ &jsonflag.JSONStringFlag{ Name: "cursor", @@ -119,17 +119,19 @@ var projectsList = cli.Command{ func handleProjectsCreate(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) params := stainless.ProjectNewParams{} - res, err := cc.client.Projects.New( + var res []byte + _, err := cc.client.Projects.New( context.TODO(), params, option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("projects create", res.RawJSON(), format) + return ShowJSON("projects create", string(res), format) } func handleProjectsRetrieve(ctx context.Context, cmd *cli.Command) error { @@ -138,17 +140,19 @@ func handleProjectsRetrieve(ctx context.Context, cmd *cli.Command) error { if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) } - res, err := cc.client.Projects.Get( + var res []byte + _, err := cc.client.Projects.Get( context.TODO(), params, option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("projects retrieve", res.RawJSON(), format) + return ShowJSON("projects retrieve", string(res), format) } func handleProjectsUpdate(ctx context.Context, cmd *cli.Command) error { @@ -157,31 +161,35 @@ func handleProjectsUpdate(ctx context.Context, cmd *cli.Command) error { if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) } - res, err := cc.client.Projects.Update( + var res []byte + _, err := cc.client.Projects.Update( context.TODO(), params, option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("projects update", res.RawJSON(), format) + return ShowJSON("projects update", string(res), format) } func handleProjectsList(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) params := stainless.ProjectListParams{} - res, err := cc.client.Projects.List( + var res []byte + _, err := cc.client.Projects.List( context.TODO(), params, option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("projects list", res.RawJSON(), format) + return ShowJSON("projects list", string(res), format) } diff --git a/pkg/cmd/projectbranch.go b/pkg/cmd/projectbranch.go index 5cf45a69..8c7c478e 100644 --- a/pkg/cmd/projectbranch.go +++ b/pkg/cmd/projectbranch.go @@ -13,7 +13,7 @@ import ( var projectsBranchesCreate = cli.Command{ Name: "create", - Usage: "Create a new branch for a project", + Usage: "Create a new branch for a project.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "project", @@ -47,7 +47,7 @@ var projectsBranchesCreate = cli.Command{ var projectsBranchesRetrieve = cli.Command{ Name: "retrieve", - Usage: "Retrieve a project branch", + Usage: "Retrieve a project branch by name.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "project", @@ -62,7 +62,7 @@ var projectsBranchesRetrieve = cli.Command{ var projectsBranchesList = cli.Command{ Name: "list", - Usage: "List project branches", + Usage: "Retrieve a project branch by name.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "project", @@ -88,7 +88,7 @@ var projectsBranchesList = cli.Command{ var projectsBranchesDelete = cli.Command{ Name: "delete", - Usage: "Delete a project branch", + Usage: "Delete a project branch by name.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "project", @@ -103,7 +103,7 @@ var projectsBranchesDelete = cli.Command{ var projectsBranchesRebase = cli.Command{ Name: "rebase", - Usage: "Rebase a project branch", + Usage: "Rebase a project branch.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "project", @@ -129,17 +129,19 @@ func handleProjectsBranchesCreate(ctx context.Context, cmd *cli.Command) error { if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) } - res, err := cc.client.Projects.Branches.New( + var res []byte + _, err := cc.client.Projects.Branches.New( context.TODO(), params, option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("projects:branches create", res.RawJSON(), format) + return ShowJSON("projects:branches create", string(res), format) } func handleProjectsBranchesRetrieve(ctx context.Context, cmd *cli.Command) error { @@ -148,18 +150,20 @@ func handleProjectsBranchesRetrieve(ctx context.Context, cmd *cli.Command) error if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) } - res, err := cc.client.Projects.Branches.Get( + var res []byte + _, err := cc.client.Projects.Branches.Get( context.TODO(), cmd.Value("branch").(string), params, option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("projects:branches retrieve", res.RawJSON(), format) + return ShowJSON("projects:branches retrieve", string(res), format) } func handleProjectsBranchesList(ctx context.Context, cmd *cli.Command) error { @@ -168,17 +172,19 @@ func handleProjectsBranchesList(ctx context.Context, cmd *cli.Command) error { if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) } - res, err := cc.client.Projects.Branches.List( + var res []byte + _, err := cc.client.Projects.Branches.List( context.TODO(), params, option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("projects:branches list", res.RawJSON(), format) + return ShowJSON("projects:branches list", string(res), format) } func handleProjectsBranchesDelete(ctx context.Context, cmd *cli.Command) error { @@ -187,7 +193,7 @@ func handleProjectsBranchesDelete(ctx context.Context, cmd *cli.Command) error { if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) } - res := []byte{} + var res []byte _, err := cc.client.Projects.Branches.Delete( context.TODO(), cmd.Value("branch").(string), @@ -209,16 +215,18 @@ func handleProjectsBranchesRebase(ctx context.Context, cmd *cli.Command) error { if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) } - res, err := cc.client.Projects.Branches.Rebase( + var res []byte + _, err := cc.client.Projects.Branches.Rebase( context.TODO(), cmd.Value("branch").(string), params, option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&res), ) if err != nil { return err } format := cmd.Root().String("format") - return ShowJSON("projects:branches rebase", res.RawJSON(), format) + return ShowJSON("projects:branches rebase", string(res), format) } diff --git a/pkg/cmd/projectconfig.go b/pkg/cmd/projectconfig.go index 51c9a64a..92bc50cb 100644 --- a/pkg/cmd/projectconfig.go +++ b/pkg/cmd/projectconfig.go @@ -13,7 +13,7 @@ import ( var projectsConfigsRetrieve = cli.Command{ Name: "retrieve", - Usage: "Retrieve configuration files for a project", + Usage: "Retrieve the configuration files for a given project.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "project", @@ -39,7 +39,7 @@ var projectsConfigsRetrieve = cli.Command{ var projectsConfigsGuess = cli.Command{ Name: "guess", - Usage: "Generate configuration suggestions based on an OpenAPI spec", + Usage: "Generate suggestions for changes to config files based on an OpenAPI spec.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "project", @@ -69,7 +69,7 @@ func handleProjectsConfigsRetrieve(ctx context.Context, cmd *cli.Command) error if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) } - res := []byte{} + var res []byte _, err := cc.client.Projects.Configs.Get( context.TODO(), params, @@ -90,7 +90,7 @@ func handleProjectsConfigsGuess(ctx context.Context, cmd *cli.Command) error { if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) } - res := []byte{} + var res []byte _, err := cc.client.Projects.Configs.Guess( context.TODO(), params, diff --git a/pkg/cmd/stainlessutils.go b/pkg/cmd/stainlessutils.go index d01dcc2e..3db3f73b 100644 --- a/pkg/cmd/stainlessutils.go +++ b/pkg/cmd/stainlessutils.go @@ -7,22 +7,22 @@ import ( "github.com/tidwall/gjson" ) -// BuildObject wraps stainless.BuildObject to provide convenience methods -type BuildObject struct { - *stainless.BuildObject +// Build wraps stainless.Build to provide convenience methods +type Build struct { + *stainless.Build } -// NewBuildObject creates a new BuildObject wrapper -func NewBuildObject(build *stainless.BuildObject) *BuildObject { +// NewBuild creates a new Build wrapper +func NewBuild(build *stainless.Build) *Build { if build == nil { return nil } - return &BuildObject{BuildObject: build} + return &Build{Build: build} } // BuildTarget returns the build target wrapper for a given target type, replacing getBuildTarget -func (b *BuildObject) BuildTarget(target stainless.Target) *BuildTarget { - if b.BuildObject == nil { +func (b *Build) BuildTarget(target stainless.Target) *BuildTarget { + if b.Build == nil { return nil } @@ -76,8 +76,8 @@ func (b *BuildObject) BuildTarget(target stainless.Target) *BuildTarget { } // Languages returns all available build languages/targets for this build -func (b *BuildObject) Languages() []stainless.Target { - if b.BuildObject == nil { +func (b *Build) Languages() []stainless.Target { + if b.Build == nil { return []stainless.Target{} } @@ -122,7 +122,7 @@ func (b *BuildObject) Languages() []stainless.Target { } // IsCompleted checks if the entire build is completed (all targets) -func (b *BuildObject) IsCompleted() bool { +func (b *Build) IsCompleted() bool { languages := b.Languages() for _, target := range languages { buildTarget := b.BuildTarget(target) diff --git a/pkg/cmd/version.go b/pkg/cmd/version.go index e1a3903e..5f9bfc8d 100644 --- a/pkg/cmd/version.go +++ b/pkg/cmd/version.go @@ -2,4 +2,4 @@ package cmd -const Version = "0.1.0-alpha.43" // x-release-please-version +const Version = "0.1.0-alpha.44" // x-release-please-version diff --git a/pkg/jsonflag/json_flag.go b/pkg/jsonflag/json_flag.go index 8e4060b6..605f883b 100644 --- a/pkg/jsonflag/json_flag.go +++ b/pkg/jsonflag/json_flag.go @@ -12,7 +12,7 @@ type JSONConfig struct { Kind MutationKind Path string // For boolean flags that set a specific value when present - SetValue interface{} + SetValue any } type JSONValueCreator[T any] struct{} @@ -63,11 +63,9 @@ func (v *jsonValue[T]) Set(val string) error { return nil } // For any flags with SetValue, register the configured value - if _, isAny := any(parsed).(interface{}); isAny { - globalRegistry.Mutate(v.config.Kind, v.config.Path, v.config.SetValue) - *v.destination = any(v.config.SetValue).(T) - return nil - } + globalRegistry.Mutate(v.config.Kind, v.config.Path, v.config.SetValue) + *v.destination = any(v.config.SetValue).(T) + return nil } switch any(parsed).(type) { @@ -114,8 +112,8 @@ func (v *jsonValue[T]) Set(val string) error { return fmt.Errorf("invalid datetime value %q: %w", val, parseErr) } parsed = any(timeVal).(T) - case interface{}: - // For interface{}, store the string value directly + case any: + // For `any`, store the string value directly parsed = any(val).(T) default: return fmt.Errorf("unsupported type for JSON flag") @@ -247,4 +245,4 @@ type JSONIntFlag = cli.FlagBase[int, JSONConfig, JSONValueCreator[int]] type JSONFloatFlag = cli.FlagBase[float64, JSONConfig, JSONValueCreator[float64]] type JSONDatetimeFlag = cli.FlagBase[time.Time, JSONConfig, JSONValueCreator[time.Time]] type JSONDateFlag = cli.FlagBase[time.Time, JSONConfig, JSONDateValueCreator] -type JSONAnyFlag = cli.FlagBase[interface{}, JSONConfig, JSONValueCreator[interface{}]] +type JSONAnyFlag = cli.FlagBase[any, JSONConfig, JSONValueCreator[any]] diff --git a/pkg/jsonflag/mutation.go b/pkg/jsonflag/mutation.go index d0eb78eb..46c115b9 100644 --- a/pkg/jsonflag/mutation.go +++ b/pkg/jsonflag/mutation.go @@ -20,7 +20,7 @@ const ( type Mutation struct { Kind MutationKind Path string - Value interface{} + Value any } type registry struct { @@ -29,7 +29,7 @@ type registry struct { var globalRegistry = ®istry{} -func (r *registry) Mutate(kind MutationKind, path string, value interface{}) { +func (r *registry) Mutate(kind MutationKind, path string, value any) { r.mutations = append(r.mutations, Mutation{ Kind: kind, Path: path, @@ -68,7 +68,7 @@ func (r *registry) List() []Mutation { } // Mutate adds a mutation that will be applied to the specified kind of data -func Mutate(kind MutationKind, path string, value interface{}) { +func Mutate(kind MutationKind, path string, value any) { globalRegistry.Mutate(kind, path, value) } @@ -87,11 +87,10 @@ func ListMutations() []Mutation { return globalRegistry.List() } -func jsonSet(json []byte, path string, value interface{}) ([]byte, error) { +func jsonSet(json []byte, path string, value any) ([]byte, error) { keys := strings.Split(path, ".") path = "" - for i := 0; i < len(keys); i++ { - key := keys[i] + for _, key := range keys { if key == "#" { key = strconv.Itoa(len(gjson.GetBytes(json, path).Array()) - 1) } diff --git a/scripts/bootstrap b/scripts/bootstrap index 99810d31..a73aff96 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,10 +4,18 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { - echo "==> Installing Homebrew dependencies…" - brew bundle + echo -n "==> Install Homebrew dependencies? (y/N): " + read -r response + case "$response" in + [yY][eE][sS]|[yY]) + brew bundle + ;; + *) + ;; + esac + echo } fi