diff --git a/index.js b/index.js index ae9a970..a682678 100644 --- a/index.js +++ b/index.js @@ -21,6 +21,7 @@ const camundaCloud10Rules = withConfig({ 'no-propagate-all-parent-variables': 'error', 'no-task-schedule': 'error', 'no-template': 'error', + 'no-version-tag': 'error', 'no-zeebe-properties': 'error', 'no-zeebe-user-task': 'error', 'sequence-flow-condition': 'error', @@ -83,7 +84,8 @@ const camundaCloud86Rules = withConfig({ 'inclusive-gateway', 'no-binding-type', 'no-execution-listeners', - 'no-priority-definition' + 'no-priority-definition', + 'no-version-tag' ]), 'duplicate-execution-listeners': 'error', 'execution-listener': 'error', @@ -143,6 +145,7 @@ const rules = { 'no-signal-event-sub-process': './rules/camunda-cloud/no-signal-event-sub-process', 'no-task-schedule': './rules/camunda-cloud/no-task-schedule', 'no-template': './rules/camunda-cloud/no-template', + 'no-version-tag': './rules/camunda-cloud/no-version-tag', 'no-zeebe-properties': './rules/camunda-cloud/no-zeebe-properties', 'no-zeebe-user-task': './rules/camunda-cloud/no-zeebe-user-task', 'priority-definition': './rules/camunda-cloud/priority-definition', diff --git a/rules/camunda-cloud/no-version-tag.js b/rules/camunda-cloud/no-version-tag.js new file mode 100644 index 0000000..5f7c27f --- /dev/null +++ b/rules/camunda-cloud/no-version-tag.js @@ -0,0 +1,63 @@ +const { is } = require('bpmnlint-utils'); + +const { hasProperties, findExtensionElement, hasNoExtensionElement } = require('../utils/element'); + +const { reportErrors } = require('../utils/reporter'); + +const { skipInNonExecutableProcess } = require('../utils/rule'); + +const allowedVersion = '8.6'; + +module.exports = skipInNonExecutableProcess(function() { + function check(node, reporter) { + if (is(node, 'bpmn:Process')) { + const errors = hasNoExtensionElement(node, 'zeebe:VersionTag', node, allowedVersion); + + if (errors && errors.length) { + reportErrors(node, reporter, errors); + } + + return; + } + + let extensionElement; + + if (is(node, 'bpmn:BusinessRuleTask')) { + extensionElement = findExtensionElement(node, 'zeebe:CalledDecision'); + } else if (is(node, 'bpmn:CallActivity')) { + extensionElement = findExtensionElement(node, 'zeebe:CalledElement'); + } else if (is(node, 'bpmn:UserTask')) { + extensionElement = findExtensionElement(node, 'zeebe:FormDefinition'); + } + + if (extensionElement) { + let errors = hasProperties(extensionElement, { + bindingType: { + allowed: (value) => value !== 'versionTag', + allowedVersion + } + }, node); + + if (errors && errors.length) { + reportErrors(node, reporter, errors); + + return; + } + + errors = hasProperties(extensionElement, { + versionTag: { + allowed: false, + allowedVersion + } + }, node); + + if (errors && errors.length) { + reportErrors(node, reporter, errors); + } + } + } + + return { + check + }; +}); \ No newline at end of file diff --git a/test/camunda-cloud/integration/no-version-tag-errors.bpmn b/test/camunda-cloud/integration/no-version-tag-errors.bpmn new file mode 100644 index 0000000..d2e71a7 --- /dev/null +++ b/test/camunda-cloud/integration/no-version-tag-errors.bpmn @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/camunda-cloud/integration/no-version-tag-spec.js b/test/camunda-cloud/integration/no-version-tag-spec.js new file mode 100644 index 0000000..73b30b6 --- /dev/null +++ b/test/camunda-cloud/integration/no-version-tag-spec.js @@ -0,0 +1,77 @@ +const { expect } = require('chai'); + +const Linter = require('bpmnlint/lib/linter'); + +const NodeResolver = require('bpmnlint/lib/resolver/node-resolver'); + +const { readModdle } = require('../../helper'); + +const versions = [ + '1.0', + '1.1', + '1.2', + '1.3', + '8.0', + '8.1', + '8.2', + '8.3', + '8.4', + '8.5' +]; + +describe('integration - no-version-tag', function() { + + versions.forEach(function(version) { + + let linter; + + beforeEach(function() { + linter = new Linter({ + config: { + extends: `plugin:camunda-compat/camunda-cloud-${ version.replace('.', '-') }` + }, + resolver: new NodeResolver() + }); + }); + + + describe(`Camunda Cloud ${ version }`, function() { + + describe('no errors', function() { + + it('should not have errors', async function() { + + // given + const { root } = await readModdle('test/camunda-cloud/integration/no-version-tag.bpmn'); + + // when + const reports = await linter.lint(root); + + // then + expect(reports[ 'camunda-compat/no-version-tag' ]).not.to.exist; + }); + + }); + + + describe('errors', function() { + + it('should have errors', async function() { + + // given + const { root } = await readModdle('test/camunda-cloud/integration/no-version-tag-errors.bpmn'); + + // when + const reports = await linter.lint(root); + + // then + expect(reports[ 'camunda-compat/no-version-tag' ]).to.exist; + }); + + }); + + }); + + }); + +}); \ No newline at end of file diff --git a/test/camunda-cloud/integration/no-version-tag.bpmn b/test/camunda-cloud/integration/no-version-tag.bpmn new file mode 100644 index 0000000..29a7f78 --- /dev/null +++ b/test/camunda-cloud/integration/no-version-tag.bpmn @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/camunda-cloud/no-version-tag.spec.js b/test/camunda-cloud/no-version-tag.spec.js new file mode 100644 index 0000000..584cca1 --- /dev/null +++ b/test/camunda-cloud/no-version-tag.spec.js @@ -0,0 +1,293 @@ +const RuleTester = require('bpmnlint/lib/testers/rule-tester'); + +const rule = require('../../rules/camunda-cloud/no-version-tag'); + +const { + createDefinitions, + createModdle, + createProcess +} = require('../helper'); + +const { ERROR_TYPES } = require('../../rules/utils/element'); + +const valid = [ + { + name: 'process', + config: { version: '8.5' }, + moddleElement: createModdle(createDefinitions(` + + `)) + }, + { + name: 'business rule task', + moddleElement: createModdle(createProcess(` + + + + + + `)) + }, + { + name: 'business rule task (version tag) (non-executable process)', + config: { version: '8.5' }, + moddleElement: createModdle(createDefinitions(` + + + + + + + + `)) + }, + { + name: 'call activity', + moddleElement: createModdle(createProcess(` + + + + + + `)) + }, + { + name: 'call activity (version tag) (non-executable process)', + config: { version: '8.5' }, + moddleElement: createModdle(createDefinitions(` + + + + + + + + `)) + }, + { + name: 'user task', + moddleElement: createModdle(createProcess(` + + + + + + `)) + }, + { + name: 'user task (version tag) (non-executable process)', + config: { version: '8.5' }, + moddleElement: createModdle(createDefinitions(` + + + + + + + + `)) + } +]; + +const invalid = [ + { + name: 'process (version tag)', + config: { version: '8.5' }, + moddleElement: createModdle(createDefinitions(` + + + + + + `)), + report: { + id: 'Process_1', + message: 'Extension element of type only allowed by Camunda 8.6', + path: [ + 'extensionElements', + 'values', + 0 + ], + data: { + type: ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED, + node: 'Process_1', + parentNode: null, + extensionElement: 'zeebe:VersionTag', + allowedVersion: '8.6' + } + } + }, + { + name: 'business rule task (binding type)', + config: { version: '8.5' }, + moddleElement: createModdle(createProcess(` + + + + + + `)), + report: { + id: 'BusinessRuleTask_1', + message: 'Property value of only allowed by Camunda 8.6 or newer', + path: [ + 'extensionElements', + 'values', + 0, + 'bindingType' + ], + data: { + type: ERROR_TYPES.PROPERTY_VALUE_NOT_ALLOWED, + node: 'zeebe:CalledDecision', + parentNode: 'BusinessRuleTask_1', + property: 'bindingType', + allowedVersion: '8.6' + } + } + }, + { + name: 'business rule task (version tag)', + config: { version: '8.5' }, + moddleElement: createModdle(createProcess(` + + + + + + `)), + report: { + id: 'BusinessRuleTask_1', + message: 'Property only allowed by Camunda 8.6 or newer', + path: [ + 'extensionElements', + 'values', + 0, + 'versionTag' + ], + data: { + type: ERROR_TYPES.PROPERTY_NOT_ALLOWED, + node: 'zeebe:CalledDecision', + parentNode: 'BusinessRuleTask_1', + property: 'versionTag', + allowedVersion: '8.6' + } + } + }, + { + name: 'call activity (binding type)', + config: { version: '8.5' }, + moddleElement: createModdle(createProcess(` + + + + + + `)), + report: { + id: 'CallActivity_1', + message: 'Property value of only allowed by Camunda 8.6 or newer', + path: [ + 'extensionElements', + 'values', + 0, + 'bindingType' + ], + data: { + type: ERROR_TYPES.PROPERTY_VALUE_NOT_ALLOWED, + node: 'zeebe:CalledElement', + parentNode: 'CallActivity_1', + property: 'bindingType', + allowedVersion: '8.6' + } + } + }, + { + name: 'call activity (version tag)', + config: { version: '8.5' }, + moddleElement: createModdle(createProcess(` + + + + + + `)), + report: { + id: 'CallActivity_1', + message: 'Property only allowed by Camunda 8.6 or newer', + path: [ + 'extensionElements', + 'values', + 0, + 'versionTag' + ], + data: { + type: ERROR_TYPES.PROPERTY_NOT_ALLOWED, + node: 'zeebe:CalledElement', + parentNode: 'CallActivity_1', + property: 'versionTag', + allowedVersion: '8.6' + } + } + }, + { + name: 'user task (binding type)', + config: { version: '8.5' }, + moddleElement: createModdle(createProcess(` + + + + + + `)), + report: { + id: 'UserTask_1', + message: 'Property value of only allowed by Camunda 8.6 or newer', + path: [ + 'extensionElements', + 'values', + 0, + 'bindingType' + ], + data: { + type: ERROR_TYPES.PROPERTY_VALUE_NOT_ALLOWED, + node: 'zeebe:FormDefinition', + parentNode: 'UserTask_1', + property: 'bindingType', + allowedVersion: '8.6' + } + } + }, + { + name: 'user task (version tag)', + config: { version: '8.5' }, + moddleElement: createModdle(createProcess(` + + + + + + `)), + report: { + id: 'UserTask_1', + message: 'Property only allowed by Camunda 8.6 or newer', + path: [ + 'extensionElements', + 'values', + 0, + 'versionTag' + ], + data: { + type: ERROR_TYPES.PROPERTY_NOT_ALLOWED, + node: 'zeebe:FormDefinition', + parentNode: 'UserTask_1', + property: 'versionTag', + allowedVersion: '8.6' + } + } + } +]; + +RuleTester.verify('no-version-tag', rule, { + valid, + invalid +}); \ No newline at end of file diff --git a/test/config/configs.spec.js b/test/config/configs.spec.js index f0e7e74..3b97228 100644 --- a/test/config/configs.spec.js +++ b/test/config/configs.spec.js @@ -22,10 +22,11 @@ describe('configs', function() { 'no-expression': [ 'error', { version: '1.0' } ], 'no-loop': [ 'error', { version: '1.0' } ], 'no-multiple-none-start-events' : [ 'error', { version: '1.0' } ], + 'no-priority-definition': [ 'error', { version: '1.0' } ], 'no-propagate-all-parent-variables' : [ 'error', { version: '1.0' } ], 'no-task-schedule': [ 'error', { version: '1.0' } ], - 'no-priority-definition': [ 'error', { version: '1.0' } ], 'no-template': [ 'error', { version: '1.0' } ], + 'no-version-tag': [ 'error', { version: '1.0' } ], 'no-zeebe-properties': [ 'error', { version: '1.0' } ], 'no-zeebe-user-task': [ 'error', { version: '1.0' } ], 'sequence-flow-condition': [ 'error', { version: '1.0' } ], @@ -55,10 +56,11 @@ describe('configs', function() { 'no-expression': [ 'error', { version: '1.1' } ], 'no-loop': [ 'error', { version: '1.1' } ], 'no-multiple-none-start-events' : [ 'error', { version: '1.1' } ], + 'no-priority-definition': [ 'error', { version: '1.1' } ], 'no-propagate-all-parent-variables' : [ 'error', { version: '1.1' } ], 'no-task-schedule': [ 'error', { version: '1.1' } ], - 'no-priority-definition': [ 'error', { version: '1.1' } ], 'no-template': [ 'error', { version: '1.1' } ], + 'no-version-tag': [ 'error', { version: '1.1' } ], 'no-zeebe-properties': [ 'error', { version: '1.1' } ], 'no-zeebe-user-task': [ 'error', { version: '1.1' } ], 'sequence-flow-condition': [ 'error', { version: '1.1' } ], @@ -88,10 +90,11 @@ describe('configs', function() { 'no-expression': [ 'error', { version: '1.2' } ], 'no-loop': [ 'error', { version: '1.2' } ], 'no-multiple-none-start-events' : [ 'error', { version: '1.2' } ], + 'no-priority-definition': [ 'error', { version: '1.2' } ], 'no-propagate-all-parent-variables' : [ 'error', { version: '1.2' } ], 'no-task-schedule': [ 'error', { version: '1.2' } ], - 'no-priority-definition': [ 'error', { version: '1.2' } ], 'no-template': [ 'error', { version: '1.2' } ], + 'no-version-tag': [ 'error', { version: '1.2' } ], 'no-zeebe-properties': [ 'error', { version: '1.2' } ], 'no-zeebe-user-task': [ 'error', { version: '1.2' } ], 'sequence-flow-condition': [ 'error', { version: '1.2' } ], @@ -121,10 +124,11 @@ describe('configs', function() { 'no-expression': [ 'error', { version: '1.3' } ], 'no-loop': [ 'error', { version: '1.3' } ], 'no-multiple-none-start-events' : [ 'error', { version: '1.3' } ], + 'no-priority-definition': [ 'error', { version: '1.3' } ], 'no-propagate-all-parent-variables' : [ 'error', { version: '1.3' } ], 'no-task-schedule': [ 'error', { version: '1.3' } ], - 'no-priority-definition': [ 'error', { version: '1.3' } ], 'no-template': [ 'error', { version: '1.3' } ], + 'no-version-tag': [ 'error', { version: '1.3' } ], 'no-zeebe-properties': [ 'error', { version: '1.3' } ], 'no-zeebe-user-task': [ 'error', { version: '1.3' } ], 'sequence-flow-condition': [ 'error', { version: '1.3' } ], @@ -155,9 +159,10 @@ describe('configs', function() { 'no-expression': [ 'error', { version: '8.0' } ], 'no-loop': [ 'error', { version: '8.0' } ], 'no-multiple-none-start-events' : [ 'error', { version: '8.0' } ], + 'no-priority-definition': [ 'error', { version: '8.0' } ], 'no-propagate-all-parent-variables' : [ 'error', { version: '8.0' } ], 'no-task-schedule': [ 'error', { version: '8.0' } ], - 'no-priority-definition': [ 'error', { version: '8.0' } ], + 'no-version-tag': [ 'error', { version: '8.0' } ], 'no-zeebe-properties': [ 'error', { version: '8.0' } ], 'no-zeebe-user-task': [ 'error', { version: '8.0' } ], 'sequence-flow-condition': [ 'error', { version: '8.0' } ], @@ -189,9 +194,10 @@ describe('configs', function() { 'no-expression': [ 'error', { version: '8.1' } ], 'no-loop': [ 'error', { version: '8.1' } ], 'no-multiple-none-start-events' : [ 'error', { version: '8.1' } ], + 'no-priority-definition': [ 'error', { version: '8.1' } ], 'no-propagate-all-parent-variables' : [ 'error', { version: '8.1' } ], 'no-task-schedule': [ 'error', { version: '8.1' } ], - 'no-priority-definition': [ 'error', { version: '8.1' } ], + 'no-version-tag': [ 'error', { version: '8.1' } ], 'no-zeebe-user-task': [ 'error', { version: '8.1' } ], 'sequence-flow-condition': [ 'error', { version: '8.1' } ], 'subscription': [ 'error', { version: '8.1' } ], @@ -224,8 +230,9 @@ describe('configs', function() { 'no-expression': [ 'error', { version: '8.2' } ], 'no-loop': [ 'error', { version: '8.2' } ], 'no-multiple-none-start-events' : [ 'error', { version: '8.2' } ], - 'no-signal-event-sub-process': [ 'error', { version: '8.2' } ], 'no-priority-definition': [ 'error', { version: '8.2' } ], + 'no-signal-event-sub-process': [ 'error', { version: '8.2' } ], + 'no-version-tag': [ 'error', { version: '8.2' } ], 'no-zeebe-user-task': [ 'error', { version: '8.2' } ], 'sequence-flow-condition': [ 'error', { version: '8.2' } ], 'subscription': [ 'error', { version: '8.2' } ], @@ -260,6 +267,7 @@ describe('configs', function() { 'no-loop': [ 'error', { version: '8.3' } ], 'no-multiple-none-start-events' : [ 'error', { version: '8.3' } ], 'no-priority-definition': [ 'error', { version: '8.3' } ], + 'no-version-tag': [ 'error', { version: '8.3' } ], 'no-zeebe-user-task': [ 'error', { version: '8.3' } ], 'secrets': [ 'warn', { version: '8.3' } ], 'sequence-flow-condition': [ 'error', { version: '8.3' } ], @@ -295,6 +303,7 @@ describe('configs', function() { 'no-loop': [ 'error', { version: '8.4' } ], 'no-multiple-none-start-events' : [ 'error', { version: '8.4' } ], 'no-priority-definition': [ 'error', { version: '8.4' } ], + 'no-version-tag': [ 'error', { version: '8.4' } ], 'no-zeebe-user-task': [ 'error', { version: '8.4' } ], 'secrets': [ 'warn', { version: '8.4' } ], 'sequence-flow-condition': [ 'error', { version: '8.4' } ], @@ -330,6 +339,7 @@ describe('configs', function() { 'no-loop': [ 'error', { version: '8.5' } ], 'no-multiple-none-start-events' : [ 'error', { version: '8.5' } ], 'no-priority-definition': [ 'error', { version: '8.5' } ], + 'no-version-tag': [ 'error', { version: '8.5' } ], 'secrets': [ 'warn', { version: '8.5' } ], 'sequence-flow-condition': [ 'error', { version: '8.5' } ], 'signal-reference': [ 'error', { version: '8.5' } ], @@ -427,6 +437,7 @@ describe('configs', function() { 'no-signal-event-sub-process': 'error', 'no-task-schedule': 'error', 'no-template': 'error', + 'no-version-tag': 'error', 'no-zeebe-properties': 'error', 'no-zeebe-user-task': 'error', 'priority-definition': 'error',