diff --git a/go.mod b/go.mod index 9732b8b6..79a72299 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/mattn/go-shellwords v1.0.12 github.com/mitchellh/go-homedir v1.1.0 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c - github.com/planetscale/planetscale-go v0.165.0 + github.com/planetscale/planetscale-go v0.166.0 github.com/planetscale/psdb v0.0.0-20250717190954-65c6661ab6e4 github.com/planetscale/psdbproxy v0.0.0-20250728082226-3f4ea3a74ec7 github.com/spf13/cobra v1.10.2 diff --git a/go.sum b/go.sum index cb08e6b5..c3251e47 100644 --- a/go.sum +++ b/go.sum @@ -176,8 +176,8 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjL github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/planetscale/noglog v0.2.1-0.20210421230640-bea75fcd2e8e h1:MZ8D+Z3m2vvqGZLvoQfpaGg/j1fNDr4j03s3PRz4rVY= github.com/planetscale/noglog v0.2.1-0.20210421230640-bea75fcd2e8e/go.mod h1:hwAsSPQdvPa3WcfKfzTXxtEq/HlqwLjQasfO6QbGo4Q= -github.com/planetscale/planetscale-go v0.165.0 h1:huSIreetdhlXwzSweuI1rB6hlAyYEWvZULjPmkCwTdg= -github.com/planetscale/planetscale-go v0.165.0/go.mod h1:paQCI5SgquuoewvMQM7R+r1XJO868bdP6/ihGidYRM0= +github.com/planetscale/planetscale-go v0.166.0 h1:Bnd9+VMYAuQgdAbiYUL6pFHU2gNCGae6JEFq2Whpox0= +github.com/planetscale/planetscale-go v0.166.0/go.mod h1:paQCI5SgquuoewvMQM7R+r1XJO868bdP6/ihGidYRM0= github.com/planetscale/psdb v0.0.0-20250717190954-65c6661ab6e4 h1:Xv5pj20Rhfty1Tv0OVcidg4ez4PvGrpKvb6rvUwQgDs= github.com/planetscale/psdb v0.0.0-20250717190954-65c6661ab6e4/go.mod h1:M52h5IWxAcbdQ1hSZrLAGQC4ZXslxEsK/Wh9nu3wdWs= github.com/planetscale/psdbproxy v0.0.0-20250728082226-3f4ea3a74ec7 h1:aRd6vdE1fyuSI4RVj7oCr8lFmgqXvpnPUmN85VbZCp8= diff --git a/internal/cmd/deployrequest/deploy.go b/internal/cmd/deployrequest/deploy.go index 653867d1..416bcfc4 100644 --- a/internal/cmd/deployrequest/deploy.go +++ b/internal/cmd/deployrequest/deploy.go @@ -19,6 +19,7 @@ func DeployCmd(ch *cmdutil.Helper) *cobra.Command { var flags struct { wait bool instant_ddl bool + strategy string } cmd := &cobra.Command{ @@ -51,11 +52,16 @@ func DeployCmd(ch *cmdutil.Helper) *cobra.Command { printer.BoldBlue(database), printer.BoldBlue(number)) } + if flags.strategy != "" && flags.strategy != "serial" && flags.strategy != "parallel" { + return fmt.Errorf("invalid --strategy %q: must be \"serial\" or \"parallel\"", flags.strategy) + } + dr, err := client.DeployRequests.Deploy(ctx, &planetscale.PerformDeployRequest{ Organization: ch.Config.Organization, Database: database, Number: number, InstantDDL: flags.instant_ddl, + Strategy: flags.strategy, }) if err != nil { @@ -112,6 +118,9 @@ func DeployCmd(ch *cmdutil.Helper) *cobra.Command { cmd.Flags().BoolVar(&flags.instant_ddl, "instant", false, "If enabled, the schema migrations from this deploy request will be applied using MySQL’s built-in ALGORITHM=INSTANT option. Deployment will be faster, but cannot be reverted.") // cmd.Flags().MarkHidden("instant") + cmd.Flags().StringVar(&flags.strategy, "strategy", "", "Deployment strategy: \"serial\" (default) or \"parallel\". Parallel deployments must be enabled for the database.") + _ = cmd.Flags().MarkHidden("strategy") + return cmd } diff --git a/internal/cmd/deployrequest/deploy_test.go b/internal/cmd/deployrequest/deploy_test.go index 96351ecc..2cef6cf9 100644 --- a/internal/cmd/deployrequest/deploy_test.go +++ b/internal/cmd/deployrequest/deploy_test.go @@ -116,3 +116,92 @@ func TestDeployRequest_DeployBranchName(t *testing.T) { res := &ps.DeployRequest{Number: number} c.Assert(buf.String(), qt.JSONEquals, res) } + +func TestDeployRequest_DeployStrategyFlag(t *testing.T) { + c := qt.New(t) + + var buf bytes.Buffer + format := printer.JSON + p := printer.NewPrinter(&format) + p.SetResourceOutput(&buf) + + org := "planetscale" + db := "planetscale" + var number uint64 = 10 + + svc := &mock.DeployRequestsService{ + DeployFn: func(ctx context.Context, req *ps.PerformDeployRequest) (*ps.DeployRequest, error) { + c.Assert(req.Strategy, qt.Equals, "parallel") + return &ps.DeployRequest{Number: number}, nil + }, + } + + ch := &cmdutil.Helper{ + Printer: p, + Config: &config.Config{ + Organization: org, + }, + Client: func() (*ps.Client, error) { + return &ps.Client{ + DeployRequests: svc, + }, nil + }, + } + + cmd := DeployCmd(ch) + cmd.SetArgs([]string{db, strconv.FormatUint(number, 10), "--strategy", "parallel"}) + err := cmd.Execute() + + c.Assert(err, qt.IsNil) + c.Assert(svc.DeployFnInvoked, qt.IsTrue) +} + +func TestDeployRequest_DeployStrategyFlagInvalid(t *testing.T) { + c := qt.New(t) + + var buf bytes.Buffer + format := printer.JSON + p := printer.NewPrinter(&format) + p.SetResourceOutput(&buf) + + org := "planetscale" + db := "planetscale" + var number uint64 = 10 + + svc := &mock.DeployRequestsService{ + DeployFn: func(ctx context.Context, req *ps.PerformDeployRequest) (*ps.DeployRequest, error) { + t.Fatal("Deploy should not be called when --strategy is invalid") + return nil, nil + }, + } + + ch := &cmdutil.Helper{ + Printer: p, + Config: &config.Config{ + Organization: org, + }, + Client: func() (*ps.Client, error) { + return &ps.Client{ + DeployRequests: svc, + }, nil + }, + } + + cmd := DeployCmd(ch) + cmd.SetArgs([]string{db, strconv.FormatUint(number, 10), "--strategy", "nope"}) + cmd.SetOut(&bytes.Buffer{}) + cmd.SetErr(&bytes.Buffer{}) + err := cmd.Execute() + + c.Assert(err, qt.ErrorMatches, `invalid --strategy "nope".*`) + c.Assert(svc.DeployFnInvoked, qt.IsFalse) +} + +func TestDeployRequest_DeployStrategyFlagHidden(t *testing.T) { + c := qt.New(t) + + cmd := DeployCmd(&cmdutil.Helper{}) + flag := cmd.Flags().Lookup("strategy") + c.Assert(flag, qt.IsNotNil) + c.Assert(flag.Hidden, qt.IsTrue) +}