diff --git a/internal/temporalcli/commands.workflow.go b/internal/temporalcli/commands.workflow.go index a65fffbf6..d012188c5 100644 --- a/internal/temporalcli/commands.workflow.go +++ b/internal/temporalcli/commands.workflow.go @@ -112,7 +112,7 @@ func (c *TemporalWorkflowUpdateOptionsCommand) run(cctx *CommandContext, args [] } if c.VersioningOverrideBehavior.Value == "pinned" { - if c.VersioningOverrideDeploymentName == "" && c.VersioningOverrideBuildId == "" { + if c.VersioningOverrideDeploymentName == "" || c.VersioningOverrideBuildId == "" { return fmt.Errorf("missing deployment name and/or build id with 'pinned' behavior") } } diff --git a/internal/temporalcli/commands.workflow_reset_update_options_test.go b/internal/temporalcli/commands.workflow_reset_update_options_test.go index d031110fb..db762f858 100644 --- a/internal/temporalcli/commands.workflow_reset_update_options_test.go +++ b/internal/temporalcli/commands.workflow_reset_update_options_test.go @@ -6,10 +6,12 @@ import ( "time" "github.com/google/uuid" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.temporal.io/api/enums/v1" "go.temporal.io/api/workflowservice/v1" "go.temporal.io/sdk/client" + "go.temporal.io/sdk/worker" "go.temporal.io/sdk/workflow" ) @@ -104,13 +106,14 @@ func (s *SharedServerSuite) TestWorkflow_ResetWithWorkflowUpdateOptions_Single_P wfExecutions++ return "result", nil }) + testTaskQueue := s.Worker().Options.TaskQueue // Start the workflow searchAttr := "keyword-" + uuid.NewString() run, err := s.Client.ExecuteWorkflow( s.Context, client.StartWorkflowOptions{ - TaskQueue: s.Worker().Options.TaskQueue, + TaskQueue: testTaskQueue, SearchAttributes: map[string]any{"CustomKeywordField": searchAttr}, }, DevWorkflow, @@ -124,6 +127,34 @@ func (s *SharedServerSuite) TestWorkflow_ResetWithWorkflowUpdateOptions_Single_P // Reset with pinned versioning behavior and properly formatted version pinnedDeploymentName := "test-deployment" pinnedBuildId := "v1.0" + + // Start a versioned worker polling v1.0 to create the version + w1 := s.DevServer.StartDevWorker(s.Suite.T(), DevWorkerOptions{ + Worker: worker.Options{ + DeploymentOptions: worker.DeploymentOptions{ + UseVersioning: true, + Version: worker.WorkerDeploymentVersion{ + DeploymentName: pinnedDeploymentName, + BuildID: pinnedBuildId, + }, + DefaultVersioningBehavior: workflow.VersioningBehaviorPinned, + }, + }, + TaskQueue: testTaskQueue, + }) + defer w1.Stop() + + // Wait for the version to exist + s.EventuallyWithT(func(t *assert.CollectT) { + res := s.Execute( + "worker", "deployment", "describe-version", + "--address", s.Address(), + "--deployment-name", pinnedDeploymentName, + "--build-id", pinnedBuildId, + ) + assert.NoError(t, res.Err) + }, 30*time.Second, 100*time.Millisecond) + res := s.Execute( "workflow", "reset", "with-workflow-update-options", "--address", s.Address(), @@ -209,13 +240,14 @@ func (s *SharedServerSuite) TestWorkflow_ResetBatchWithWorkflowUpdateOptions_Pin wfExecutions++ return "result", nil }) + testTaskQueue := s.Worker().Options.TaskQueue // Start the workflow searchAttr := "keyword-" + uuid.NewString() run, err := s.Client.ExecuteWorkflow( s.Context, client.StartWorkflowOptions{ - TaskQueue: s.Worker().Options.TaskQueue, + TaskQueue: testTaskQueue, SearchAttributes: map[string]any{"CustomKeywordField": searchAttr}, }, DevWorkflow, @@ -229,6 +261,33 @@ func (s *SharedServerSuite) TestWorkflow_ResetBatchWithWorkflowUpdateOptions_Pin // Reset batch with pinned versioning behavior and properly formatted version pinnedDeploymentName := "batch-deployment" pinnedBuildId := "v1.0" + // Start a versioned worker polling v1.0 to create the version + w1 := s.DevServer.StartDevWorker(s.Suite.T(), DevWorkerOptions{ + Worker: worker.Options{ + DeploymentOptions: worker.DeploymentOptions{ + UseVersioning: true, + Version: worker.WorkerDeploymentVersion{ + DeploymentName: pinnedDeploymentName, + BuildID: pinnedBuildId, + }, + DefaultVersioningBehavior: workflow.VersioningBehaviorPinned, + }, + }, + TaskQueue: testTaskQueue, + }) + defer w1.Stop() + + // Wait for the version to exist + s.EventuallyWithT(func(t *assert.CollectT) { + res := s.Execute( + "worker", "deployment", "describe-version", + "--address", s.Address(), + "--deployment-name", pinnedDeploymentName, + "--build-id", pinnedBuildId, + ) + assert.NoError(t, res.Err) + }, 30*time.Second, 100*time.Millisecond) + s.CommandHarness.Stdin.WriteString("y\n") res := s.Execute( "workflow", "reset", "with-workflow-update-options", diff --git a/internal/temporalcli/commands.workflow_test.go b/internal/temporalcli/commands.workflow_test.go index 44119740f..5a11f3627 100644 --- a/internal/temporalcli/commands.workflow_test.go +++ b/internal/temporalcli/commands.workflow_test.go @@ -469,8 +469,9 @@ func (s *SharedServerSuite) TestWorkflow_Cancel_SingleWorkflowSuccess() { } func (s *SharedServerSuite) TestWorkflow_Batch_Update_Options_Versioning_Override() { - buildId1 := uuid.NewString() - buildId2 := "bid2-" + uuid.NewString() + buildId1 := "id1-" + uuid.NewString() + buildId2 := "id2-" + uuid.NewString() + testTaskQueue := uuid.NewString() deploymentName := uuid.NewString() version1 := worker.WorkerDeploymentVersion{ DeploymentName: deploymentName, @@ -485,7 +486,7 @@ func (s *SharedServerSuite) TestWorkflow_Batch_Update_Options_Versioning_Overrid ctx.Done().Receive(ctx, nil) return ctx.Err() } - w := s.DevServer.StartDevWorker(s.Suite.T(), DevWorkerOptions{ + w1 := s.DevServer.StartDevWorker(s.Suite.T(), DevWorkerOptions{ Worker: worker.Options{ DeploymentOptions: worker.DeploymentOptions{ UseVersioning: true, @@ -494,8 +495,22 @@ func (s *SharedServerSuite) TestWorkflow_Batch_Update_Options_Versioning_Overrid }, }, Workflows: []any{waitingWorkflow}, + TaskQueue: testTaskQueue, }) - defer w.Stop() + defer w1.Stop() + + w2 := s.DevServer.StartDevWorker(s.Suite.T(), DevWorkerOptions{ + Worker: worker.Options{ + DeploymentOptions: worker.DeploymentOptions{ + UseVersioning: true, + Version: version2, + DefaultVersioningBehavior: workflow.VersioningBehaviorPinned, + }, + }, + Workflows: []any{waitingWorkflow}, + TaskQueue: testTaskQueue, + }) + defer w2.Stop() s.EventuallyWithT(func(t *assert.CollectT) { res := s.Execute( @@ -516,6 +531,16 @@ func (s *SharedServerSuite) TestWorkflow_Batch_Update_Options_Versioning_Overrid assert.NoError(t, res.Err) }, 30*time.Second, 100*time.Millisecond) + s.EventuallyWithT(func(t *assert.CollectT) { + res := s.Execute( + "worker", "deployment", "describe-version", + "--address", s.Address(), + "--deployment-name", version2.DeploymentName, + "--build-id", version2.BuildID, + ) + assert.NoError(t, res.Err) + }, 30*time.Second, 100*time.Millisecond) + res := s.Execute( "worker", "deployment", "set-current-version", "--address", s.Address(), @@ -533,7 +558,7 @@ func (s *SharedServerSuite) TestWorkflow_Batch_Update_Options_Versioning_Overrid run, err := s.Client.ExecuteWorkflow( s.Context, client.StartWorkflowOptions{ - TaskQueue: w.Options.TaskQueue, + TaskQueue: w1.Options.TaskQueue, SearchAttributes: map[string]any{"CustomKeywordField": searchAttr}, }, waitingWorkflow, @@ -609,8 +634,9 @@ func (s *SharedServerSuite) TestWorkflow_Batch_Update_Options_Versioning_Overrid } func (s *SharedServerSuite) TestWorkflow_Update_Options_Versioning_Override() { - buildId1 := uuid.NewString() - buildId2 := uuid.NewString() + buildId1 := "id1-" + uuid.NewString() + buildId2 := "id2-" + uuid.NewString() + testTaskQueue := uuid.NewString() buildId3 := "id3-" + uuid.NewString() deploymentName := uuid.NewString() version1 := worker.WorkerDeploymentVersion{ @@ -627,7 +653,7 @@ func (s *SharedServerSuite) TestWorkflow_Update_Options_Versioning_Override() { ctx.Done().Receive(ctx, nil) return ctx.Err() } - w := s.DevServer.StartDevWorker(s.Suite.T(), DevWorkerOptions{ + w1 := s.DevServer.StartDevWorker(s.Suite.T(), DevWorkerOptions{ Worker: worker.Options{ DeploymentOptions: worker.DeploymentOptions{ UseVersioning: true, @@ -636,8 +662,22 @@ func (s *SharedServerSuite) TestWorkflow_Update_Options_Versioning_Override() { }, }, Workflows: []any{waitingWorkflow}, + TaskQueue: testTaskQueue, }) - defer w.Stop() + defer w1.Stop() + + w2 := s.DevServer.StartDevWorker(s.Suite.T(), DevWorkerOptions{ + Worker: worker.Options{ + DeploymentOptions: worker.DeploymentOptions{ + UseVersioning: true, + Version: version2, + DefaultVersioningBehavior: workflow.VersioningBehaviorPinned, + }, + }, + Workflows: []any{waitingWorkflow}, + TaskQueue: testTaskQueue, + }) + defer w2.Stop() s.EventuallyWithT(func(t *assert.CollectT) { res := s.Execute( @@ -658,6 +698,16 @@ func (s *SharedServerSuite) TestWorkflow_Update_Options_Versioning_Override() { assert.NoError(t, res.Err) }, 30*time.Second, 100*time.Millisecond) + s.EventuallyWithT(func(t *assert.CollectT) { + res := s.Execute( + "worker", "deployment", "describe-version", + "--address", s.Address(), + "--deployment-name", version2.DeploymentName, + "--build-id", version2.BuildID, + ) + assert.NoError(t, res.Err) + }, 30*time.Second, 100*time.Millisecond) + res := s.Execute( "worker", "deployment", "set-current-version", "--address", s.Address(), @@ -670,7 +720,7 @@ func (s *SharedServerSuite) TestWorkflow_Update_Options_Versioning_Override() { // Start the workflow and wait until the operation is started. run, err := s.Client.ExecuteWorkflow( s.Context, - client.StartWorkflowOptions{TaskQueue: w.Options.TaskQueue}, + client.StartWorkflowOptions{TaskQueue: w1.Options.TaskQueue}, waitingWorkflow, ) s.NoError(err) @@ -716,7 +766,7 @@ func (s *SharedServerSuite) TestWorkflow_Update_Options_Versioning_Override() { "--versioning-override-behavior", "pinned", "--versioning-override-build-id", buildId3, ) - s.NoError(res.Err) + s.ErrorContains(res.Err, "missing deployment name and/or build id with 'pinned' behavior") res = s.Execute( "workflow", "describe", @@ -726,7 +776,7 @@ func (s *SharedServerSuite) TestWorkflow_Update_Options_Versioning_Override() { s.NoError(res.Err) s.ContainsOnSameLine(res.Stdout.String(), "OverrideBehavior", "Pinned") - s.ContainsOnSameLine(res.Stdout.String(), "OverridePinnedVersionBuildId", buildId3) + s.ContainsOnSameLine(res.Stdout.String(), "OverridePinnedVersionBuildId", buildId2) // remove override res = s.Execute(