@forge/manifest 6.1.0 → 6.2.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @forge/manifest
2
2
 
3
+ ## 6.2.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 9307e05: Added endpoint validation for bitbucket:mergeCheck module
8
+
3
9
  ## 6.1.0
4
10
 
5
11
  ### Minor Changes
@@ -41,6 +41,10 @@ export declare const errors: {
41
41
  propertyNotAllowed: (moduleKey: string, propertyName: string) => string;
42
42
  typeMismatch: (moduleKey: string, propertyName: string, errorDetails: string) => string;
43
43
  };
44
+ bitbucket: {
45
+ endpointOnlySupportSystemToken: (moduleKey: string, endpointModuleKey: string) => string;
46
+ endpointNeedsRoute: (moduleKey: string, endpointModuleKey: string) => string;
47
+ };
44
48
  confluence: {
45
49
  multipleProperty: (property: string, moduleKey: string, keys: string[]) => string;
46
50
  propertyUniqueness: (property: string, moduleKey: string, keys: string[]) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/text/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/text/errors.ts"],"names":[],"mappings":"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"}
@@ -54,6 +54,10 @@ exports.errors = {
54
54
  propertyNotAllowed: (moduleKey, propertyName) => `Display conditions of the "${moduleKey}" module are invalid. "${propertyName}" property is not allowed.`,
55
55
  typeMismatch: (moduleKey, propertyName, errorDetails) => `Display conditions of the "${moduleKey}" module are invalid. "${propertyName}" property ${errorDetails}.`
56
56
  },
57
+ bitbucket: {
58
+ endpointOnlySupportSystemToken: (moduleKey, endpointModuleKey) => `Bitbucket module: '${moduleKey}' using remote endpoint: '${endpointModuleKey}' only supports appSystemToken. Update appUserToken to false.`,
59
+ endpointNeedsRoute: (moduleKey, endpointModuleKey) => `Bitbucket module: '${moduleKey}' using remote endpoint: '${endpointModuleKey}' requires 'route' parameter.`
60
+ },
57
61
  confluence: {
58
62
  multipleProperty: (property, moduleKey, keys) => `There can be only 1 ${moduleKey} module which designates "${property}": true. Modules containing designation: ${keys.join(', ')}`,
59
63
  propertyUniqueness: (property, moduleKey, keys) => `${property} should be unique across all ${moduleKey} modules. Found duplicates: ${keys.join(', ')}`,
@@ -1 +1 @@
1
- {"version":3,"file":"modules-validator.d.ts","sourceRoot":"","sources":["../../src/validators/modules-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EACd,wBAAwB,EAIzB,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,cAAc,EAAoB,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAU3D,qBAAa,gBACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;IAEzF,OAAO,CAAC,oBAAoB,CAA0C;IAEhE,QAAQ,CACZ,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;IA2OpD,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,uBAAuB;IAiB/B,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,mBAAmB;CA2E5B"}
1
+ {"version":3,"file":"modules-validator.d.ts","sourceRoot":"","sources":["../../src/validators/modules-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EACd,wBAAwB,EAIzB,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,cAAc,EAAoB,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAW3D,qBAAa,gBACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;IAEzF,OAAO,CAAC,oBAAoB,CAA0C;IAEhE,QAAQ,CACZ,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;IA8OpD,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,uBAAuB;IAiB/B,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,mBAAmB;CA2E5B"}
@@ -12,6 +12,7 @@ const validate_full_admin_page_1 = require("./modules-validators/jira/validate-f
12
12
  const validate_subpages_in_module_1 = require("./modules-validators/jira/validate-subpages-in-module");
13
13
  const remote_1 = require("./modules-validators/remote");
14
14
  const validateModuleScopes_1 = require("./modules-validators/validateModuleScopes");
15
+ const bitbucket_1 = require("./modules-validators/bitbucket");
15
16
  class ModulesValidator {
16
17
  constructor() {
17
18
  this.functionHandlerRegex = /^([a-zA-Z0-9-_]+)\.([a-zA-Z0-9-_]+)$/;
@@ -116,6 +117,7 @@ class ModulesValidator {
116
117
  });
117
118
  });
118
119
  validationErrors.push(...(0, confluence_1.validateConfluenceModules)(modules, yamlContentByLine));
120
+ validationErrors.push(...(0, bitbucket_1.validateBitbucketModules)(modules, yamlContentByLine));
119
121
  (_c = modules === null || modules === void 0 ? void 0 : modules.trigger) === null || _c === void 0 ? void 0 : _c.forEach((module) => {
120
122
  if (module.filter) {
121
123
  const onlyJiraEvents = module.events.every((e) => e.includes('jira'));
@@ -0,0 +1,4 @@
1
+ import { Modules } from '../../../schema/manifest';
2
+ import { ValidationError } from '../../../types';
3
+ export declare const validateBitbucketModules: (modules: Modules, yamlContentByLine?: string[]) => ValidationError[];
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/validators/modules-validators/bitbucket/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjD,eAAO,MAAM,wBAAwB,YAAa,OAAO,sBAAsB,MAAM,EAAE,KAAG,eAAe,EAExG,CAAC"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateBitbucketModules = void 0;
4
+ const validateBackendModuleEndpoints_1 = require("./validateBackendModuleEndpoints");
5
+ const validateBitbucketModules = (modules, yamlContentByLine) => {
6
+ return (0, validateBackendModuleEndpoints_1.validateBackendModuleEndpoints)(modules, yamlContentByLine);
7
+ };
8
+ exports.validateBitbucketModules = validateBitbucketModules;
@@ -0,0 +1,4 @@
1
+ import { Modules } from '../../../schema/manifest';
2
+ import { ValidationError } from '../../../types';
3
+ export declare const validateBackendModuleEndpoints: (modules: Modules, yamlContentByLine?: string[]) => ValidationError[];
4
+ //# sourceMappingURL=validateBackendModuleEndpoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateBackendModuleEndpoints.d.ts","sourceRoot":"","sources":["../../../../src/validators/modules-validators/bitbucket/validateBackendModuleEndpoints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAEnD,OAAO,EAAkB,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjE,eAAO,MAAM,8BAA8B,YAAa,OAAO,sBAAsB,MAAM,EAAE,KAAG,eAAe,EA6B9G,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateBackendModuleEndpoints = void 0;
4
+ const text_1 = require("../../../text");
5
+ const types_1 = require("../../../types");
6
+ const utils_1 = require("../../../utils");
7
+ const validateBackendModuleEndpoints = (modules, yamlContentByLine) => {
8
+ var _a, _b;
9
+ const endpoints = (_a = modules.endpoint) !== null && _a !== void 0 ? _a : [];
10
+ const validationErrors = [];
11
+ const backendModulesWithEndpoint = ((_b = modules[types_1.AllModuleTypes.BitbucketMergeCheck]) === null || _b === void 0 ? void 0 : _b.filter((module) => module.endpoint != null)) || [];
12
+ backendModulesWithEndpoint.forEach((module) => {
13
+ var _a, _b;
14
+ const endpointModule = endpoints === null || endpoints === void 0 ? void 0 : endpoints.find((remoteEndpoint) => remoteEndpoint.key === module.endpoint);
15
+ if (endpointModule) {
16
+ if ((_b = (_a = endpointModule.auth) === null || _a === void 0 ? void 0 : _a.appUserToken) === null || _b === void 0 ? void 0 : _b.enabled) {
17
+ validationErrors.push(Object.assign({ message: text_1.errors.modules.bitbucket.endpointOnlySupportSystemToken(module.key, endpointModule.key), reference: text_1.References.Modules, level: 'error' }, (0, utils_1.findPosition)(endpointModule.key, yamlContentByLine)));
18
+ }
19
+ if (!endpointModule.route) {
20
+ validationErrors.push(Object.assign({ message: text_1.errors.modules.bitbucket.endpointNeedsRoute(module.key, endpointModule.key), reference: text_1.References.Modules, level: 'error' }, (0, utils_1.findPosition)(endpointModule.key, yamlContentByLine)));
21
+ }
22
+ }
23
+ });
24
+ return validationErrors;
25
+ };
26
+ exports.validateBackendModuleEndpoints = validateBackendModuleEndpoints;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forge/manifest",
3
- "version": "6.1.0",
3
+ "version": "6.2.0-next.0",
4
4
  "description": "Definitions and validations of the Forge manifest",
5
5
  "main": "out/index.js",
6
6
  "scripts": {