From 2d1ec03575012cfed3a898cf3e8ec90ebb87c2bd Mon Sep 17 00:00:00 2001 From: eileencodes Date: Mon, 1 Jun 2026 17:00:17 -0400 Subject: [PATCH] [Fast lane] Support strategy in deploy requests cli Adds a hidden strategy flag to the planetscale cli. It is gated behind a feature flag so it will do nothing if someone was to send it before we turn on the feature. Shipping this now, while hidden, will allow us to set up some scripted tests so we can do easily repeatable scenarios to ensure parallel deploys work properly. PlanetScale Go: https://github.com/planetscale/planetscale-go/pull/311 `cc` https://github.com/planetscale/surfaces/issues/3692 --- go.mod | 2 +- go.sum | 4 +- internal/cmd/deployrequest/deploy.go | 9 +++ internal/cmd/deployrequest/deploy_test.go | 89 +++++++++++++++++++++++ 4 files changed, 101 insertions(+), 3 deletions(-) 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) +}