33 *
44 * @module
55 */
6- import assert from 'assert' ;
76import { randomUUID } from 'crypto' ;
87import asyncRetry from 'async-retry' ;
98import { ExecutionContext } from 'ava' ;
109import { Client } from '@temporalio/client' ;
1110import { toCanonicalString , WorkerDeploymentVersion } from '@temporalio/common' ;
1211import { temporal } from '@temporalio/proto' ;
12+ import { WorkerOptions } from '@temporalio/worker' ;
1313import { Worker } from './helpers' ;
1414import { Context , helpers , makeTestFunction } from './helpers-integration' ;
1515import { unblockSignal , versionQuery } from './workflows' ;
1616
17+ type WorkerDeploymentOptions = NonNullable < WorkerOptions [ 'workerDeploymentOptions' ] > ;
18+
1719const test = makeTestFunction ( { workflowsPath : __filename } ) ;
1820
1921test ( 'Worker deployment based versioning' , async ( t ) => {
@@ -94,7 +96,7 @@ test('Worker deployment based versioning', async (t) => {
9496 workflowId : 'deployment-versioning-v1-' + randomUUID ( ) ,
9597 } ) ;
9698 const state1 = await wf1 . query ( versionQuery ) ;
97- assert . equal ( state1 , 'v1' ) ;
99+ t . is ( state1 , 'v1' ) ;
98100
99101 // Wait for worker 2 to be visible and set as current version
100102 const describeResp2 = await waitUntilWorkerDeploymentVisible ( client , w2DeploymentVersion ) ;
@@ -106,7 +108,7 @@ test('Worker deployment based versioning', async (t) => {
106108 workflowId : 'deployment-versioning-v2-' + randomUUID ( ) ,
107109 } ) ;
108110 const state2 = await wf2 . query ( versionQuery ) ;
109- assert . equal ( state2 , 'v2' ) ;
111+ t . is ( state2 , 'v2' ) ;
110112
111113 // Wait for worker 3 to be visible and set as current version
112114 const describeResp3 = await waitUntilWorkerDeploymentVisible ( client , w3DeploymentVersion ) ;
@@ -118,7 +120,7 @@ test('Worker deployment based versioning', async (t) => {
118120 workflowId : 'deployment-versioning-v3-' + randomUUID ( ) ,
119121 } ) ;
120122 const state3 = await wf3 . query ( versionQuery ) ;
121- assert . equal ( state3 , 'v3' ) ;
123+ t . is ( state3 , 'v3' ) ;
122124
123125 // Signal all workflows to finish
124126 await wf1 . signal ( unblockSignal ) ;
@@ -129,17 +131,16 @@ test('Worker deployment based versioning', async (t) => {
129131 const res2 = await wf2 . result ( ) ;
130132 const res3 = await wf3 . result ( ) ;
131133
132- assert . equal ( res1 , 'version-v3' ) ;
133- assert . equal ( res2 , 'version-v2' ) ;
134- assert . equal ( res3 , 'version-v3' ) ;
134+ t . is ( res1 , 'version-v3' ) ;
135+ t . is ( res2 , 'version-v2' ) ;
136+ t . is ( res3 , 'version-v3' ) ;
135137
136138 worker1 . shutdown ( ) ;
137139 worker2 . shutdown ( ) ;
138140 worker3 . shutdown ( ) ;
139141 await worker1Promise ;
140142 await worker2Promise ;
141143 await worker3Promise ;
142- t . pass ( ) ;
143144} ) ;
144145
145146test ( 'Worker deployment based versioning with ramping' , async ( t ) => {
@@ -205,7 +206,7 @@ test('Worker deployment based versioning with ramping', async (t) => {
205206 } ) ;
206207 await wf . signal ( unblockSignal ) ;
207208 const res = await wf . result ( ) ;
208- assert . equal ( res , 'version-v2' ) ;
209+ t . is ( res , 'version-v2' ) ;
209210 }
210211
211212 // Set ramp to 0, expecting workflows to run on v1
@@ -217,7 +218,7 @@ test('Worker deployment based versioning with ramping', async (t) => {
217218 } ) ;
218219 await wf . signal ( unblockSignal ) ;
219220 const res = await wf . result ( ) ;
220- assert . equal ( res , 'version-v1' ) ;
221+ t . is ( res , 'version-v1' ) ;
221222 }
222223
223224 // Set ramp to 50 and eventually verify workflows run on both versions
@@ -257,7 +258,7 @@ async function testWorkerDeploymentWithDynamicBehavior(
257258 expectedResult : string
258259) {
259260 if ( t . context . env . supportsTimeSkipping ) {
260- t . pass ( "Test Server doesn't support worker deployments" ) ;
261+ t . fail ( "Test Server doesn't support worker deployments" ) ;
261262 return ;
262263 }
263264
@@ -295,7 +296,7 @@ async function testWorkerDeploymentWithDynamicBehavior(
295296 } ) ;
296297
297298 const result = await wf . result ( ) ;
298- assert . equal ( result , expectedResult ) ;
299+ t . is ( result , expectedResult ) ;
299300
300301 const history = await wf . fetchHistory ( ) ;
301302 const hasPinnedVersioningBehavior = history . events ! . some (
@@ -304,11 +305,10 @@ async function testWorkerDeploymentWithDynamicBehavior(
304305 event . workflowTaskCompletedEventAttributes . versioningBehavior ===
305306 temporal . api . enums . v1 . VersioningBehavior . VERSIONING_BEHAVIOR_PINNED
306307 ) ;
307- assert . ok ( hasPinnedVersioningBehavior , 'Expected workflow to use pinned versioning behavior' ) ;
308+ t . true ( hasPinnedVersioningBehavior , 'Expected workflow to use pinned versioning behavior' ) ;
308309
309310 worker . shutdown ( ) ;
310311 await workerPromise ;
311- t . pass ( ) ;
312312}
313313
314314test ( 'Worker deployment with dynamic workflow static behavior' , async ( t ) => {
@@ -362,11 +362,10 @@ test('Workflows can use default versioning behavior', async (t) => {
362362 event . workflowTaskCompletedEventAttributes . versioningBehavior ===
363363 temporal . api . enums . v1 . VersioningBehavior . VERSIONING_BEHAVIOR_PINNED
364364 ) ;
365- assert . ok ( hasPinnedVersioningBehavior , 'Expected workflow to use pinned versioning behavior' ) ;
365+ t . true ( hasPinnedVersioningBehavior , 'Expected workflow to use pinned versioning behavior' ) ;
366366
367367 worker . shutdown ( ) ;
368368 await workerPromise ;
369- t . pass ( ) ;
370369} ) ;
371370
372371test ( 'Workflow versioningOverride overrides default versioning behavior' , async ( t ) => {
@@ -406,7 +405,7 @@ test('Workflow versioningOverride overrides default versioning behavior', async
406405 } ,
407406 } ) ;
408407 const statePinned = await wfPinned . query ( versionQuery ) ;
409- assert . equal ( statePinned , 'v1' ) ;
408+ t . is ( statePinned , 'v1' ) ;
410409
411410 await wfPinned . signal ( unblockSignal ) ;
412411
@@ -418,14 +417,13 @@ test('Workflow versioningOverride overrides default versioning behavior', async
418417 temporal . api . enums . v1 . VersioningBehavior . VERSIONING_BEHAVIOR_PINNED ||
419418 event . workflowExecutionStartedEventAttributes ?. versioningOverride ?. pinned != null
420419 ) ;
421- assert . ok ( hasPinnedVersioningBehavior , 'Expected workflow to use pinned versioning behavior' ) ;
420+ t . true ( hasPinnedVersioningBehavior , 'Expected workflow to use pinned versioning behavior' ) ;
422421
423422 const resPinned = await wfPinned . result ( ) ;
424- assert . equal ( resPinned , 'version-v1' ) ;
423+ t . is ( resPinned , 'version-v1' ) ;
425424
426425 worker1 . shutdown ( ) ;
427426 await worker1Promise ;
428- t . pass ( ) ;
429427} ) ;
430428
431429async function setRampingVersion (
@@ -474,3 +472,85 @@ async function setCurrentDeploymentVersion(
474472 conflictToken,
475473 } ) ;
476474}
475+
476+ ///////////////////////////////
477+
478+ /**
479+ * Type-level tests for WorkerDeploymentOptions.
480+ *
481+ * Ensures that:
482+ * - When useWorkerVersioning is true, defaultVersioningBehavior is required
483+ * - When useWorkerVersioning is false, defaultVersioningBehavior must be absent
484+ * - version is always required
485+ */
486+
487+ test ( 'Worker with deployment options and useWorkerVersioning false can run workflows' , async ( t ) => {
488+ const taskQueue = 'versioning-off-with-build-id-' + randomUUID ( ) ;
489+ const buildId = 'my-custom-build-id-1.0' ;
490+ const { client, nativeConnection } = t . context . env ;
491+
492+ const worker = await Worker . create ( {
493+ workflowsPath : require . resolve ( './workflows' ) ,
494+ taskQueue,
495+ workerDeploymentOptions : {
496+ useWorkerVersioning : false ,
497+ version : {
498+ buildId,
499+ deploymentName : 'deployment-' + randomUUID ( ) ,
500+ } ,
501+ } ,
502+ connection : nativeConnection ,
503+ } ) ;
504+
505+ const handle = await client . workflow . start ( 'successString' , {
506+ taskQueue,
507+ workflowId : 'versioning-off-build-id-' + randomUUID ( ) ,
508+ } ) ;
509+
510+ await worker . runUntil ( handle . result ( ) ) ;
511+ t . is ( await handle . result ( ) , 'success' ) ;
512+
513+ const history = await handle . fetchHistory ( ) ;
514+ const buildIdInHistory = history . events ! . some (
515+ ( event ) => event . workflowTaskCompletedEventAttributes ?. workerVersion ?. buildId === buildId
516+ ) ;
517+ t . true ( buildIdInHistory , 'Expected build ID to appear in workflow history' ) ;
518+ } ) ;
519+
520+ test ( 'WorkerDeploymentOptions with useWorkerVersioning true requires defaultVersioningBehavior' , ( t ) => {
521+ const valid : WorkerDeploymentOptions = {
522+ version : { buildId : '1.0' , deploymentName : 'my-deployment' } ,
523+ useWorkerVersioning : true ,
524+ defaultVersioningBehavior : 'AUTO_UPGRADE' ,
525+ } ;
526+
527+ const validPinned : WorkerDeploymentOptions = {
528+ version : { buildId : '1.0' , deploymentName : 'my-deployment' } ,
529+ useWorkerVersioning : true ,
530+ defaultVersioningBehavior : 'PINNED' ,
531+ } ;
532+
533+ // @ts -expect-error defaultVersioningBehavior is required when useWorkerVersioning is true
534+ const missingBehavior : WorkerDeploymentOptions = {
535+ version : { buildId : '1.0' , deploymentName : 'my-deployment' } ,
536+ useWorkerVersioning : true ,
537+ } ;
538+
539+ t . pass ( ) ;
540+ } ) ;
541+
542+ test ( 'WorkerDeploymentOptions with useWorkerVersioning false does not allow defaultVersioningBehavior' , ( t ) => {
543+ const _validNoVersioning : WorkerDeploymentOptions = {
544+ version : { buildId : '1.0' , deploymentName : 'my-deployment' } ,
545+ useWorkerVersioning : false ,
546+ } ;
547+
548+ const invalidWithBehavior : WorkerDeploymentOptions = {
549+ version : { buildId : '1.0' , deploymentName : 'my-deployment' } ,
550+ useWorkerVersioning : false ,
551+ // @ts -expect-error defaultVersioningBehavior must not be specified when useWorkerVersioning is false
552+ defaultVersioningBehavior : 'AUTO_UPGRADE' ,
553+ } ;
554+
555+ t . pass ( ) ;
556+ } ) ;
0 commit comments