diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 8c43f3f7..b3797e85 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -20,8 +20,6 @@ jobs: - name: Install dependencies run: npm install - env: - GH_NPM_TOKEN: ${{ secrets.GH_NPM_TOKEN }} - name: Lint last commit message run: npx commitlint --from=${{ github.event.pull_request.base.sha }} --to=${{ github.event.pull_request.head.sha }} --verbose diff --git a/src/__tests__/testdata/MigrateProcess-Version-1.bpmn b/src/__tests__/testdata/MigrateProcess-Version-1.bpmn new file mode 100644 index 00000000..20204981 --- /dev/null +++ b/src/__tests__/testdata/MigrateProcess-Version-1.bpmn @@ -0,0 +1,91 @@ + + + + + Flow_167nn02 + + + + Flow_1r250pk + + + + + + + + + Flow_167nn02 + Flow_04fsyv6 + + + + + + + + + + + Flow_1igeic8 + Flow_1r250pk + + + + + + + Flow_04fsyv6 + Flow_1igeic8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/__tests__/testdata/MigrateProcess-Version-2.bpmn b/src/__tests__/testdata/MigrateProcess-Version-2.bpmn new file mode 100644 index 00000000..80e0c29e --- /dev/null +++ b/src/__tests__/testdata/MigrateProcess-Version-2.bpmn @@ -0,0 +1,91 @@ + + + + + Flow_167nn02 + + + + Flow_1r250pk + + + + + + + + + Flow_167nn02 + Flow_04fsyv6 + + + + + + + + + + + Flow_1igeic8 + Flow_1r250pk + + + + + + + Flow_04fsyv6 + Flow_1igeic8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/__tests__/zeebe/integration/Client-MigrateProcessInstance.spec.ts b/src/__tests__/zeebe/integration/Client-MigrateProcessInstance.spec.ts new file mode 100644 index 00000000..27d78adc --- /dev/null +++ b/src/__tests__/zeebe/integration/Client-MigrateProcessInstance.spec.ts @@ -0,0 +1,112 @@ +import { restoreZeebeLogging, suppressZeebeLogging } from 'lib' +import { DeployResourceResponse, ProcessDeployment } from 'zeebe/types' + +import { ZeebeGrpcClient } from '../../../zeebe/index' +import { cancelProcesses } from '../../../zeebe/lib/cancelProcesses' + +suppressZeebeLogging() + +let res: DeployResourceResponse | undefined +let res1: DeployResourceResponse | undefined + +afterAll(async () => { + restoreZeebeLogging() + await cancelProcesses( + res?.deployments[0].process.processDefinitionKey as string + ) + await cancelProcesses( + res1?.deployments[0].process.processDefinitionKey as string + ) +}) + +const zbc = new ZeebeGrpcClient() + +test('ZeebeGrpcClient can migrate a process instance', async () => { + expect(true).toBe(true) + // Deploy a process model + + res = await zbc.deployResource({ + processFilename: './src/__tests__/testdata/MigrateProcess-Version-1.bpmn', + }) + + // Create an instance of the process model + + const processInstance = await zbc.createProcessInstance({ + bpmnProcessId: 'migrant-work', + variables: {}, + }) + + let instanceKey = '' + let processVersion = 0 + + await new Promise((res) => { + const w = zbc.createWorker({ + taskType: 'migrant-worker-task-1', + taskHandler: async (job) => { + instanceKey = job.processInstanceKey + processVersion = job.customHeaders.ProcessVersion as number + return job.complete().then((outcome) => { + w.close() + res(null) + return outcome + }) + }, + }) + }) + + expect(instanceKey).toBe(processInstance.processInstanceKey) + expect(processVersion).toBe('1') + + // Deploy the updated process model + res1 = await zbc.deployResource({ + processFilename: './src/__tests__/testdata/MigrateProcess-Version-2.bpmn', + }) + + // Migrate the process instance to the updated process model + await zbc.migrateProcessInstance({ + processInstanceKey: processInstance.processInstanceKey, + migrationPlan: { + mappingInstructions: [ + { + sourceElementId: 'Activity_050vmrm', + targetElementId: 'Activity_050vmrm', + }, + ], + targetProcessDefinitionKey: + res1?.deployments[0].process.processDefinitionKey, + }, + }) + + // Complete the job in the process instance + + await new Promise((res) => { + const w = zbc.createWorker({ + taskType: 'migration-checkpoint', + taskHandler: async (job) => { + return job.complete().then((outcome) => { + w.close() + res(null) + return outcome + }) + }, + }) + }) + + await new Promise((res) => { + const w = zbc.createWorker({ + taskType: 'migrant-worker-task-2', + taskHandler: async (job) => { + instanceKey = job.processInstanceKey + processVersion = job.customHeaders.ProcessVersion as number + return job.complete().then((outcome) => { + w.close() + res(null) + return outcome + }) + }, + }) + }) + + expect(instanceKey).toBe(processInstance.processInstanceKey) + expect(processVersion).toBe('2') +}) diff --git a/src/zeebe/lib/interfaces-1.0.ts b/src/zeebe/lib/interfaces-1.0.ts index 8149e79b..685db16e 100644 --- a/src/zeebe/lib/interfaces-1.0.ts +++ b/src/zeebe/lib/interfaces-1.0.ts @@ -20,6 +20,8 @@ import { EvaluateDecisionRequest, EvaluateDecisionResponse, FailJobRequest, + MigrateProcessInstanceRequest, + MigrateProcessInstanceResponse, ModifyProcessInstanceRequest, ModifyProcessInstanceResponse, ProcessInstanceCreationStartInstruction, @@ -420,6 +422,9 @@ export interface ZBGrpc extends GrpcClient { cancelProcessInstanceSync(processInstanceKey: { processInstanceKey: string | number }): Promise + migrateProcessInstanceSync( + request: MigrateProcessInstanceRequest + ): Promise modifyProcessInstanceSync( request: ModifyProcessInstanceRequest ): Promise diff --git a/src/zeebe/lib/interfaces-grpc-1.0.ts b/src/zeebe/lib/interfaces-grpc-1.0.ts index f1154a0b..2d146df6 100644 --- a/src/zeebe/lib/interfaces-grpc-1.0.ts +++ b/src/zeebe/lib/interfaces-grpc-1.0.ts @@ -319,7 +319,7 @@ export interface DecisionMetadata { * the assigned decision key, which acts as a unique identifier for this * decision */ - decisionKey: number + decisionKey: string /** * the dmn ID of the decision requirements graph that this decision is part * of, as parsed during deployment @@ -329,7 +329,7 @@ export interface DecisionMetadata { * the assigned key of the decision requirements graph that this decision is * part of */ - decisionRequirementsKey: number + decisionRequirementsKey: string /** the tenant id of the deployed decision */ tenantId: string } @@ -348,7 +348,7 @@ export interface DecisionRequirementsMetadata { * the assigned decision requirements key, which acts as a unique identifier * for this decision requirements */ - decisionRequirementsKey: number + decisionRequirementsKey: string /** * the resource name (see: Resource.name) from which this decision * requirements was parsed @@ -367,7 +367,7 @@ export interface FormMetadata { /** the assigned form version */ readonly version: number /** the assigned key, which acts as a unique identifier for this form */ - readonly formKey: number + readonly formKey: string /** the resource name */ readonly resourceName: string /** the tenant id of the deployed form */ @@ -396,7 +396,7 @@ export type Deployment = export interface DeployResourceResponse { /** the unique key identifying the deployment */ - readonly key: number + readonly key: string /** a list of deployed resources, e.g. processes */ readonly deployments: T[] /** the tenant id of the deployed resources */ @@ -439,7 +439,7 @@ export interface PublishMessageRequest { export interface PublishMessageResponse { /** the unique ID of the message that was published */ - key: number + key: string /** the tenantId of the message */ tenantId: string } @@ -573,6 +573,29 @@ export interface ModifyProcessInstanceRequest { export type ModifyProcessInstanceResponse = Record +export interface MigrateProcessInstanceRequest { + // key of the process instance to migrate + processInstanceKey: string + // the migration plan that defines target process and element mappings + migrationPlan: MigrationPlan +} + +interface MigrationPlan { + // the key of process definition to migrate the process instance to + targetProcessDefinitionKey: string + // the mapping instructions describe how to map elements from the source process definition to the target process definition + mappingInstructions: MappingInstruction[] +} + +interface MappingInstruction { + // the element id to migrate from + sourceElementId: string + // the element id to migrate into + targetElementId: string +} + +export type MigrateProcessInstanceResponse = Record + export type EvaluateDecisionRequest = | { /** diff --git a/src/zeebe/zb/ZeebeGrpcClient.ts b/src/zeebe/zb/ZeebeGrpcClient.ts index 3cf206fd..35b0307f 100644 --- a/src/zeebe/zb/ZeebeGrpcClient.ts +++ b/src/zeebe/zb/ZeebeGrpcClient.ts @@ -897,6 +897,18 @@ export class ZeebeGrpcClient extends TypedEmitter< }) } + /** + * + * @since 8.5.0 + */ + public migrateProcessInstance( + migrateProcessInstanceRequest: Grpc.MigrateProcessInstanceRequest + ): Promise { + return this.executeOperation('migrateProcessInstance', () => + this.grpc.migrateProcessInstanceSync(migrateProcessInstanceRequest) + ) + } + /** * @description Publish a message to the broker for correlation with a workflow instance. See [this tutorial](https://docs.camunda.io/docs/guides/message-correlation/) for a detailed description of message correlation. * @example