@docupace/pipeline 1.0.61 → 1.0.62

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.
@@ -0,0 +1,28 @@
1
+ clone:
2
+ depth: 2
3
+
4
+ pipelines:
5
+ pull-requests:
6
+ '**':
7
+ - step:
8
+ runs-on:
9
+ - linux.shell
10
+ - onprem
11
+ name: On Pull Request
12
+ script:
13
+ - pnpm config set //registry.npmjs.org/:_authToken $DOCUPACE_NPM_TOKEN
14
+ - pnpm install --frozen-lockfile
15
+ - >
16
+ npx eslint . --rule "no-unused-vars: warn" --rule "no-useless-escape: warn" --color
17
+ custom:
18
+ scheduled-tests:
19
+ - step:
20
+ runs-on:
21
+ - linux.shell
22
+ - onprem
23
+ name: Manual
24
+ script:
25
+ - pnpm config set //registry.npmjs.org/:_authToken $DOCUPACE_NPM_TOKEN
26
+ - pnpm install --frozen-lockfile
27
+ - >
28
+ npx eslint . --rule "no-unused-vars: warn" --rule "no-useless-escape: warn" --color
package/eslint.config.js CHANGED
@@ -2,6 +2,7 @@ import globals from 'globals';
2
2
  import pluginJs from '@eslint/js';
3
3
  import prettierConfig from 'eslint-config-prettier';
4
4
  import prettierPlugin from 'eslint-plugin-prettier';
5
+ import importPlugin from 'eslint-plugin-import';
5
6
 
6
7
  /** @type {import('eslint').Linter.Config[]} */
7
8
  export default [
@@ -10,17 +11,28 @@ export default [
10
11
  globals: {
11
12
  ...globals.browser,
12
13
  ...globals.node, // Add Node.js globals
13
- },g
14
+ },
14
15
  },
15
16
  },
16
17
  pluginJs.configs.recommended,
17
18
  {
18
19
  plugins: {
19
20
  prettier: prettierPlugin,
21
+ import: importPlugin,
22
+ },
23
+ settings: {
24
+ 'import/resolver': {
25
+ node: { extensions: ['.js', '.mjs', '.cjs'] },
26
+ typescript: {},
27
+ },
20
28
  },
21
29
  rules: {
22
30
  ...prettierConfig.rules,
23
31
  'prettier/prettier': 'error',
32
+ // Import-related rules
33
+ 'import/no-unresolved': 'error',
34
+ 'import/named': 'error',
35
+ 'import/no-extraneous-dependencies': 'error',
24
36
  },
25
37
  },
26
38
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docupace/pipeline",
3
- "version": "1.0.61",
3
+ "version": "1.0.62",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -16,29 +16,32 @@
16
16
  "license": "ISC",
17
17
  "dependencies": {
18
18
  "@changesets/cli": "^2.27.10",
19
- "@docupace/core-client": "^0.1.59",
19
+ "@docupace/core-client": "^0.1.94",
20
20
  "@docupace/pipeline": "^1.0.33-alpha-2",
21
21
  "auth0-deploy-cli": "^8.8.0",
22
22
  "axios": "^1.7.9",
23
23
  "commander": "^12.1.0",
24
24
  "dotenv": "^16.4.7",
25
+ "eslint-plugin-import": "^2.32.0",
25
26
  "fs-extra": "^11.3.0",
26
27
  "inquirer": "^12.6.1",
27
28
  "js-yaml": "^4.1.0",
28
29
  "lodash": "^4.17.21",
29
30
  "openai": "^4.76.3",
30
31
  "semver": "^7.7.2",
31
- "zod": "^3.24.1",
32
- "zx": "^8.3.0"
32
+ "zod": "^3.24.1"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@eslint/js": "^9.17.0",
36
36
  "esbuild": "^0.24.0",
37
- "eslint": "^9.17.0",
37
+ "eslint": "^9.34.0",
38
38
  "eslint-config-prettier": "^9.1.0",
39
+ "eslint-import-resolver-node": "^0.3.9",
40
+ "eslint-import-resolver-typescript": "^4.4.4",
39
41
  "eslint-plugin-prettier": "^5.2.1",
40
42
  "globals": "^15.14.0",
41
- "prettier": "^3.4.2"
43
+ "prettier": "^3.4.2",
44
+ "zx": "^8.8.1"
42
45
  },
43
46
  "scripts": {
44
47
  "test-deploy-core": "dp-next-cli deploy-core-pipeline dev template",
@@ -10,10 +10,7 @@ import {
10
10
  readDeployConfig,
11
11
  } from '../next/deploy.js';
12
12
 
13
- import {
14
- getVaultSecrets,
15
- updateVaultSecrets
16
- } from './vault.js';
13
+ import { getVaultSecrets, updateVaultSecrets } from './vault.js';
17
14
  import {
18
15
  coreSiteEnvMap,
19
16
  environmentConfig,
@@ -22,7 +19,7 @@ import {
22
19
 
23
20
  async function ensureDirectoryExists(dirPath) {
24
21
  try {
25
- await fs.promises.mkdir(dirPath, {recursive: true});
22
+ await fs.promises.mkdir(dirPath, { recursive: true });
26
23
  console.log(`Directory created or already exists: ${dirPath}`);
27
24
  } catch (err) {
28
25
  console.error(`Failed to create directory: ${err.message}`);
@@ -85,7 +82,7 @@ async function configureUI(
85
82
  const auth0Response = await axios.get(
86
83
  `https://${auth0Domain}/api/v2/clients`,
87
84
  {
88
- headers: {authorization: `Bearer ${auth0Token}`},
85
+ headers: { authorization: `Bearer ${auth0Token}` },
89
86
  },
90
87
  );
91
88
 
@@ -121,13 +118,14 @@ async function configureUI(
121
118
  console.log(`siteAWSSecretsPath => ${siteAWSSecretsPath}`);
122
119
  }
123
120
 
124
- const awsS3Vars = (useS3 === true || useS3 === 'true')
125
- ? `
121
+ const awsS3Vars =
122
+ useS3 === true || useS3 === 'true'
123
+ ? `
126
124
  AWS_ACCESS_KEY_ID: vault:secret/data/${site}/aws/config#AWS_ACCESS_KEY_ID
127
125
  AWS_BUCKET_NAME: vault:secret/data/${site}/aws/config#AWS_BUCKET_NAME
128
126
  AWS_SECRET_ACCESS_KEY: vault:secret/data/${site}/aws/config#AWS_SECRET_ACCESS_KEY
129
127
  AWS_REGION: vault:secret/data/${site}/aws/config#AWS_REGION`
130
- : '';
128
+ : '';
131
129
 
132
130
  // Prepare ui.app.yaml
133
131
  const uiAppYaml = `
@@ -151,13 +149,17 @@ uiMain:
151
149
  image:
152
150
  repository: registry.paperout.com/docupace-ui-main-${env}-docker-local/enterprise-ui-app
153
151
  tag: ${imageTag}
154
- ${useS3 === true || useS3 === 'true' ? `
152
+ ${
153
+ useS3 === true || useS3 === 'true'
154
+ ? `
155
155
  serviceAccount:
156
156
  create: true
157
157
  annotations:
158
158
  "helm.sh/hook": pre-install
159
159
  "helm.sh/hook-weight": "-10"
160
- eks.amazonaws.com/role-arn: arn:aws:iam::${siteAWSSecrets.AWS_ACCOUNT_ID}:role/eks-pod-identity-connect-next-${env}-${site}-bucket` : ''}
160
+ eks.amazonaws.com/role-arn: arn:aws:iam::${siteAWSSecrets.AWS_ACCOUNT_ID}:role/eks-pod-identity-connect-next-${env}-${site}-bucket`
161
+ : ''
162
+ }
161
163
  imagePullSecrets:
162
164
  - name: jf-artifactory
163
165
  ingress:
@@ -222,7 +224,9 @@ externalConnectService:
222
224
  if (err) {
223
225
  console.error('Failed to write the file:', err);
224
226
  } else {
225
- console.log(`File ${repoPath}/dp/${site}/ui.app.yaml written successfully.`);
227
+ console.log(
228
+ `File ${repoPath}/dp/${site}/ui.app.yaml written successfully.`,
229
+ );
226
230
  }
227
231
  },
228
232
  );
@@ -234,7 +238,9 @@ externalConnectService:
234
238
  if (err) {
235
239
  console.error('Failed to write the file:', err);
236
240
  } else {
237
- console.log(`File ${repoPath}/dp/${site}/ui.values.yaml written successfully.`);
241
+ console.log(
242
+ `File ${repoPath}/dp/${site}/ui.values.yaml written successfully.`,
243
+ );
238
244
  }
239
245
  },
240
246
  );
@@ -274,7 +280,7 @@ async function configureCCUI(
274
280
  const auth0Response = await axios.get(
275
281
  `https://${auth0Domain}/api/v2/clients`,
276
282
  {
277
- headers: {authorization: `Bearer ${auth0Token}`},
283
+ headers: { authorization: `Bearer ${auth0Token}` },
278
284
  },
279
285
  );
280
286
 
@@ -310,15 +316,20 @@ async function configureCCUI(
310
316
  console.log(`siteAWSSecretsPath => ${siteAWSSecretsPath}`);
311
317
  }
312
318
 
313
- const awsS3Vars = (useS3 === true || useS3 === 'true')
314
- ? `
319
+ const awsS3Vars =
320
+ useS3 === true || useS3 === 'true'
321
+ ? `
315
322
  AWS_ACCESS_KEY_ID: vault:secret/data/${site}/aws/config#AWS_ACCESS_KEY_ID
316
323
  AWS_BUCKET_NAME: vault:secret/data/${site}/aws/config#AWS_BUCKET_NAME
317
324
  AWS_SECRET_ACCESS_KEY: vault:secret/data/${site}/aws/config#AWS_SECRET_ACCESS_KEY
318
325
  AWS_REGION: vault:secret/data/${site}/aws/config#AWS_REGION`
319
- : '';
326
+ : '';
327
+
328
+ const uiCCAppYaml = `
329
+ repo: docupace-ui-main
330
+ revision: ${revision}
331
+ `.trim();
320
332
 
321
- // Prepare cc.app.yaml
322
333
  const uiCCValuesYaml = `
323
334
  uiMain:
324
335
  auth0BaseUrl: https://${ccUrl}
@@ -354,13 +365,17 @@ ingress:
354
365
  - hosts:
355
366
  - ${ccUrl}
356
367
  secretName: dp-cc-ui-cert
357
- ${useS3 === true || useS3 === 'true' ? `
368
+ ${
369
+ useS3 === true || useS3 === 'true'
370
+ ? `
358
371
  serviceAccount:
359
372
  create: true
360
373
  annotations:
361
374
  "helm.sh/hook": pre-install
362
375
  "helm.sh/hook-weight": "-10"
363
- eks.amazonaws.com/role-arn: arn:aws:iam::${siteAWSSecrets.AWS_ACCOUNT_ID}:role/eks-pod-identity-connect-next-${env}-${site}-bucket` : ''}
376
+ eks.amazonaws.com/role-arn: arn:aws:iam::${siteAWSSecrets.AWS_ACCOUNT_ID}:role/eks-pod-identity-connect-next-${env}-${site}-bucket`
377
+ : ''
378
+ }
364
379
  `.trim();
365
380
 
366
381
  console.log('Writing configuration files...');
@@ -371,9 +386,14 @@ serviceAccount:
371
386
  uiCCAppYaml,
372
387
  (err) => {
373
388
  if (err) {
374
- console.error(`Failed to write ${repoPath}/dp/${site}/cc.app.yaml file:`, err);
389
+ console.error(
390
+ `Failed to write ${repoPath}/dp/${site}/cc.app.yaml file:`,
391
+ err,
392
+ );
375
393
  } else {
376
- console.log(`File ${repoPath}/dp/${site}/cc.app.yaml written successfully.`);
394
+ console.log(
395
+ `File ${repoPath}/dp/${site}/cc.app.yaml written successfully.`,
396
+ );
377
397
  }
378
398
  },
379
399
  );
@@ -383,9 +403,14 @@ serviceAccount:
383
403
  uiCCValuesYaml,
384
404
  (err) => {
385
405
  if (err) {
386
- console.error(`Failed to write ${repoPath}/dp/${site}/cc.values.yaml file:`, err);
406
+ console.error(
407
+ `Failed to write ${repoPath}/dp/${site}/cc.values.yaml file:`,
408
+ err,
409
+ );
387
410
  } else {
388
- console.log(`File ${repoPath}/dp/${site}/cc.values.yaml written successfully.`);
411
+ console.log(
412
+ `File ${repoPath}/dp/${site}/cc.values.yaml written successfully.`,
413
+ );
389
414
  }
390
415
  },
391
416
  );
@@ -406,7 +431,10 @@ export async function cleanAndWritePropertiesFile(configPath, content) {
406
431
  await fs.writeFile(configPath, cleanedContent, 'utf8');
407
432
  console.log(`Cleaned and written file to: ${configPath}`);
408
433
  } catch (error) {
409
- console.error(`Error writing properties file to ${configPath}:`, error.message);
434
+ console.error(
435
+ `Error writing properties file to ${configPath}:`,
436
+ error.message,
437
+ );
410
438
  process.exit(1);
411
439
  }
412
440
  }
@@ -427,7 +455,12 @@ export async function updateCoreSiteConfig(site, env, useS3Ui, useS3Gq) {
427
455
 
428
456
  let siteAWSSecrets = null;
429
457
 
430
- if (useS3Ui === true || useS3Ui === 'true' || useS3Gq === true || useS3Gq === 'true') {
458
+ if (
459
+ useS3Ui === true ||
460
+ useS3Ui === 'true' ||
461
+ useS3Gq === true ||
462
+ useS3Gq === 'true'
463
+ ) {
431
464
  const siteAWSSecretsPath = getVaultSecretsConfigs(site).awsSecretsPath;
432
465
  siteAWSSecrets = await getVaultSecrets(siteAWSSecretsPath);
433
466
  console.log(`siteAWSSecretsPath => ${siteAWSSecretsPath}`);
@@ -435,11 +468,13 @@ export async function updateCoreSiteConfig(site, env, useS3Ui, useS3Gq) {
435
468
 
436
469
  const coreSiteConfig = `
437
470
  ${
438
- siteAWSSecrets
439
- ? `
471
+ siteAWSSecrets
472
+ ? `
440
473
  com.docupace.imports.files.FilesImportConfig.aws.accessKeyId=${siteAWSSecrets.AWS_ACCESS_KEY_ID}
441
474
  com.docupace.imports.files.FilesImportConfig.aws.accessKeySecret=${siteAWSSecrets.AWS_SECRET_ACCESS_KEY}
442
- com.docupace.imports.files.FilesImportConfig.aws.region=${siteAWSSecrets.AWS_REGION}`.trim() : ''}
475
+ com.docupace.imports.files.FilesImportConfig.aws.region=${siteAWSSecrets.AWS_REGION}`.trim()
476
+ : ''
477
+ }
443
478
  `;
444
479
 
445
480
  await fs.ensureDir(path.join(coreSiteConfigRepoPath, site.toUpperCase()));
@@ -482,7 +517,7 @@ async function configureGraphQLServer(
482
517
  const auth0Response = await axios.get(
483
518
  `https://${auth0Domain}/api/v2/clients`,
484
519
  {
485
- headers: {authorization: `Bearer ${auth0Token}`},
520
+ headers: { authorization: `Bearer ${auth0Token}` },
486
521
  },
487
522
  );
488
523
 
@@ -525,13 +560,14 @@ async function configureGraphQLServer(
525
560
  console.log(`siteAWSSecretsPath => ${siteAWSSecretsPath}`);
526
561
  }
527
562
 
528
- const awsS3Vars = (useS3 === true || useS3 === 'true')
529
- ? `
563
+ const awsS3Vars =
564
+ useS3 === true || useS3 === 'true'
565
+ ? `
530
566
  AWS_ACCESS_KEY_ID: vault:secret/data/${site}/aws/config#AWS_ACCESS_KEY_ID
531
567
  AWS_S3_BUCKET_NAME: vault:secret/data/${site}/aws/config#AWS_BUCKET_NAME
532
568
  AWS_SECRET_ACCESS_KEY: vault:secret/data/${site}/aws/config#AWS_SECRET_ACCESS_KEY
533
569
  AWS_REGION: vault:secret/data/${site}/aws/config#AWS_REGION`.trim()
534
- : '';
570
+ : '';
535
571
  // Prepare graphql-server.app.yaml
536
572
  const graphQLServerAppYaml = `
537
573
  repo: docupace-graphql-server
@@ -556,15 +592,16 @@ graphqlServer:
556
592
  AUTH0_CC_CLIENT_ID: vault:secret/data/${site}/graphql-server/config#AUTH0_CC_CLIENT_ID
557
593
  AUTH0_CC_CLIENT_SECRET: vault:secret/data/${site}/graphql-server/config#AUTH0_CC_CLIENT_SECRET${awsS3Vars ? '\n ' + awsS3Vars.trim() : ''}
558
594
  ${
559
- useS3 === true || useS3 === 'true'
560
- ? `
595
+ useS3 === true || useS3 === 'true'
596
+ ? `
561
597
  serviceAccount:
562
598
  create: true
563
599
  annotations:
564
600
  "helm.sh/hook": pre-install
565
601
  "helm.sh/hook-weight": "-10"
566
602
  eks.amazonaws.com/role-arn: arn:aws:iam::${siteAWSSecrets.AWS_ACCOUNT_ID}:role/eks-pod-identity-connect-next-${env}-${site}-bucket`.trim()
567
- : ''}
603
+ : ''
604
+ }
568
605
  image:
569
606
  repository: registry.paperout.com/docupace-graphql-server-${env}-docker-local/docupace-graphql-server
570
607
  tag: ${imageTag}
@@ -609,9 +646,14 @@ ingress:
609
646
  graphQLServerValuesYaml,
610
647
  (err) => {
611
648
  if (err) {
612
- console.error(`Failed to write ${repoPath}/dp/${site}/graphql-server.values.yaml file:`, err);
649
+ console.error(
650
+ `Failed to write ${repoPath}/dp/${site}/graphql-server.values.yaml file:`,
651
+ err,
652
+ );
613
653
  } else {
614
- console.log(`File ${repoPath}/dp/${site}/graphql-server.values.yaml written successfully.`);
654
+ console.log(
655
+ `File ${repoPath}/dp/${site}/graphql-server.values.yaml written successfully.`,
656
+ );
615
657
  }
616
658
  },
617
659
  );
@@ -686,13 +728,13 @@ export async function configureFromSite(
686
728
  let uiImageTag, uiRevision;
687
729
  if (deployUI === true || deployUI === 'true') {
688
730
  // Read deploy configs
689
- const {deployConfig: deployUIConfig} = await readDeployConfig(
731
+ const { deployConfig: deployUIConfig } = await readDeployConfig(
690
732
  'ui',
691
733
  fromEnv,
692
734
  fromSite,
693
735
  'values',
694
736
  );
695
- const {deployConfig: deployUiRevisionConfig} = await readDeployConfig(
737
+ const { deployConfig: deployUiRevisionConfig } = await readDeployConfig(
696
738
  'ui',
697
739
  fromEnv,
698
740
  fromSite,
@@ -707,14 +749,14 @@ export async function configureFromSite(
707
749
 
708
750
  let ccImageTag, ccRevision;
709
751
  if (deployCCUI === true || deployCCUI === 'true') {
710
- const {deployConfig: deployCCConfig} = await readDeployConfig(
752
+ const { deployConfig: deployCCConfig } = await readDeployConfig(
711
753
  'cc',
712
754
  fromEnv,
713
755
  fromSite,
714
756
  'values',
715
757
  );
716
758
 
717
- const {deployConfig: deployCCRevisionConfig} = await readDeployConfig(
759
+ const { deployConfig: deployCCRevisionConfig } = await readDeployConfig(
718
760
  'cc',
719
761
  fromEnv,
720
762
  fromSite,
@@ -727,19 +769,15 @@ export async function configureFromSite(
727
769
  console.log(`Copying Latest CC Revision: ${ccRevision}`);
728
770
  }
729
771
 
730
- const {deployConfig: deployGraphQLServerConfig} = await readDeployConfig(
772
+ const { deployConfig: deployGraphQLServerConfig } = await readDeployConfig(
731
773
  'graphql-server',
732
774
  fromEnv,
733
775
  fromSite,
734
776
  'values',
735
777
  );
736
778
 
737
- const {deployConfig: deployGraphQLServerRevisionConfig} = await readDeployConfig(
738
- 'graphql-server',
739
- fromEnv,
740
- fromSite,
741
- 'app',
742
- );
779
+ const { deployConfig: deployGraphQLServerRevisionConfig } =
780
+ await readDeployConfig('graphql-server', fromEnv, fromSite, 'app');
743
781
 
744
782
  const gqRevision = deployGraphQLServerRevisionConfig.revision;
745
783
 
@@ -767,11 +805,7 @@ export async function configureFromSite(
767
805
 
768
806
  const envConfig = environmentConfig[toEnv];
769
807
 
770
- let CORE_URL,
771
- SITE_HOST,
772
- CORE_API_CONTEXT,
773
- CONNECT_URL,
774
- DOCUPACE_HOST;
808
+ let CORE_URL, SITE_HOST, CORE_API_CONTEXT, CONNECT_URL, DOCUPACE_HOST;
775
809
  const newUrl = envConfig.newUrl(toSite);
776
810
  const ccUrl = envConfig.ccUrl(toSite);
777
811
 
@@ -34,10 +34,10 @@ export async function getPackage(mainModulePath) {
34
34
  * @returns {JIRA-TicketID|null}
35
35
  */
36
36
  export function findJiraTicketId(str) {
37
- if (!str) {
38
- return null;
39
- }
40
- const regex = /([A-Z]{2,}-\d+)/;
41
- const matches = str.match(regex);
42
- return matches ? matches[0] : null;
37
+ if (!str) {
38
+ return null;
39
+ }
40
+ const regex = /([A-Z]{2,}-\d+)/;
41
+ const matches = str.match(regex);
42
+ return matches ? matches[0] : null;
43
43
  }
@@ -17,31 +17,32 @@ function areArraysEqualIgnoringOrder(arr1, arr2) {
17
17
  }
18
18
 
19
19
  export async function validateChangesets() {
20
- await setGitInfo();
21
- const destBranch = process.env.BITBUCKET_PR_DESTINATION_BRANCH;
22
- await $`git fetch origin ${destBranch}:${destBranch}`;
23
- let releases;
24
-
25
- try {
26
- console.log('🔍 Validating changesets...');
27
- releases = await versionStatus(destBranch);
28
- }
29
- catch(e) {
30
- console.error(
31
- '❌ No changeset found. Please add a changeset to this PR. Please see more information at https://docupacellc.atlassian.net/wiki/spaces/PM/pages/1350893571/Creating+changesets+for+Docupace+Next',
32
- );
33
- process.exit(-1);
34
- }
35
-
36
- if(!['master', 'main'].includes(destBranch)) {
37
- if(releases.some(item => item.type !== 'patch')) {
38
- console.error('❌ A changeset must be a patch for change to a release branch');
39
- process.exit(-1);
40
- }
41
- }
20
+ await setGitInfo();
21
+ const destBranch = process.env.BITBUCKET_PR_DESTINATION_BRANCH;
22
+ await $`git fetch origin ${destBranch}:${destBranch}`;
23
+ let releases;
42
24
 
43
- console.log('✅ Changeset validation passed.');
25
+ try {
26
+ console.log('🔍 Validating changesets...');
27
+ releases = await versionStatus(destBranch);
28
+ } catch (e) {
29
+ console.error(
30
+ '❌ No changeset found. Please add a changeset to this PR. Please see more information at https://docupacellc.atlassian.net/wiki/spaces/PM/pages/1350893571/Creating+changesets+for+Docupace+Next',
31
+ e,
32
+ );
33
+ process.exit(-1);
34
+ }
35
+
36
+ if (!['master', 'main'].includes(destBranch)) {
37
+ if (releases.some((item) => item.type !== 'patch')) {
38
+ console.error(
39
+ '❌ A changeset must be a patch for change to a release branch',
40
+ );
41
+ process.exit(-1);
42
+ }
43
+ }
44
44
 
45
+ console.log('✅ Changeset validation passed.');
45
46
  }
46
47
 
47
48
  export async function validateChangesetPath(directoryPath) {
@@ -1,37 +1,55 @@
1
- import { $ } from '@docupace/pipeline/src/next/logger.js';
1
+ import { $ } from '../next/logger.js';
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
4
 
5
- export async function deployMicroservice(appName, helmPath, environment = 'dev', tag = null) {
5
+ export async function deployMicroservice(
6
+ appName,
7
+ helmPath,
8
+ environment = 'dev',
9
+ tag = null,
10
+ ) {
6
11
  if (!appName || !helmPath) {
7
- throw new Error('Missing required parameters. Usage: deployMicroservice(appName, helmPath, [environment], [tag])');
12
+ throw new Error(
13
+ 'Missing required parameters. Usage: deployMicroservice(appName, helmPath, [environment], [tag])',
14
+ );
8
15
  }
9
16
 
10
17
  let deployTag = tag;
11
18
  if (!deployTag) {
12
- deployTag = process.env.VERSION_TAG ||
13
- process.env.BITBUCKET_TAG ||
14
- (process.env.BITBUCKET_BUILD_NUMBER ? `build-${process.env.BITBUCKET_BUILD_NUMBER}` : null);
19
+ deployTag =
20
+ process.env.VERSION_TAG ||
21
+ process.env.BITBUCKET_TAG ||
22
+ (process.env.BITBUCKET_BUILD_NUMBER
23
+ ? `build-${process.env.BITBUCKET_BUILD_NUMBER}`
24
+ : null);
15
25
  }
16
26
 
17
27
  if (!deployTag) {
18
- throw new Error('No tag specified and no default tag available from environment variables');
28
+ throw new Error(
29
+ 'No tag specified and no default tag available from environment variables',
30
+ );
19
31
  }
20
32
 
21
33
  const repoName = `gitops-${environment}`;
22
34
  const filePath = `dp/${helmPath}/${appName}.values.yaml`;
23
-
24
- const gitopsBranch = (environment === 'dev' || environment === 'uat')
25
- ? (process.env.GITOPS_BRANCH || 'master')
26
- : (process.env.GITOPS_BRANCH || 'main');
35
+
36
+ const gitopsBranch =
37
+ environment === 'dev' || environment === 'uat'
38
+ ? process.env.GITOPS_BRANCH || 'master'
39
+ : process.env.GITOPS_BRANCH || 'main';
27
40
 
28
41
  let repoUrl;
29
42
  if (environment === 'dev' && process.env.GITOPS_REP_TOKEN) {
30
43
  repoUrl = `https://x-token-auth:${process.env.GITOPS_REP_TOKEN}@bitbucket.org/dp-cloud/${repoName}.git`;
31
- } else if (process.env.BITBUCKET_USERNAME && process.env.BITBUCKET_APP_PASSWORD) {
44
+ } else if (
45
+ process.env.BITBUCKET_USERNAME &&
46
+ process.env.BITBUCKET_APP_PASSWORD
47
+ ) {
32
48
  repoUrl = `https://${process.env.BITBUCKET_USERNAME}:${process.env.BITBUCKET_APP_PASSWORD}@bitbucket.org/dp-cloud/${repoName}.git`;
33
49
  } else {
34
- throw new Error('No authentication credentials found for GitOps repository');
50
+ throw new Error(
51
+ 'No authentication credentials found for GitOps repository',
52
+ );
35
53
  }
36
54
 
37
55
  console.log('=========================================');
@@ -48,58 +66,61 @@ export async function deployMicroservice(appName, helmPath, environment = 'dev',
48
66
  try {
49
67
  console.log('Cloning GitOps repository...');
50
68
  await $`git clone --depth 1 ${repoUrl} ${repoName}`;
51
-
69
+
52
70
  console.log('Checking if directory exists...');
53
71
  await $`ls -la ${repoName}`;
54
-
72
+
55
73
  console.log(`Changing to directory: ${repoName}`);
56
74
  const originalDir = process.cwd();
57
75
  process.chdir(repoName);
58
-
76
+
59
77
  console.log('Verifying directory change...');
60
78
  const newDir = process.cwd();
61
79
  console.log(`Original: ${originalDir}`);
62
80
  console.log(`New: ${newDir}`);
63
-
81
+
64
82
  await $`cd ${repoName} && git config user.email "pipeline@bitbucket.org"`;
65
83
  await $`cd ${repoName} && git config user.name "Bitbucket Pipeline"`;
66
-
84
+
67
85
  console.log(`Attempting to checkout branch: ${gitopsBranch}`);
68
86
  await $`cd ${repoName} && git checkout ${gitopsBranch}`;
69
-
87
+
70
88
  const fullFilePath = path.resolve(filePath);
71
89
  console.log(`Looking for file at: ${fullFilePath}`);
72
90
  if (!fs.existsSync(fullFilePath)) {
73
- throw new Error(`Values file ${filePath} does not exist in ${repoName} on branch ${gitopsBranch}`);
91
+ throw new Error(
92
+ `Values file ${filePath} does not exist in ${repoName} on branch ${gitopsBranch}`,
93
+ );
74
94
  }
75
-
95
+
76
96
  console.log(`Updating image tag to ${deployTag}...`);
77
-
97
+
78
98
  let fileContent = fs.readFileSync(fullFilePath, 'utf8');
79
-
80
- const tagRegex = /^ tag: .*/gm;
99
+
100
+ const tagRegex = /^ {2}tag: .*/gm;
81
101
  const newContent = fileContent.replace(tagRegex, ` tag: ${deployTag}`);
82
-
102
+
83
103
  if (fileContent === newContent) {
84
104
  console.log(`No changes detected - tag is already ${deployTag}`);
85
105
  return;
86
106
  }
87
-
107
+
88
108
  fs.writeFileSync(fullFilePath, newContent, 'utf8');
89
-
109
+
90
110
  console.log('Changes to be committed:');
91
111
  await $`cd ${repoName} && git diff ${filePath}`;
92
-
112
+
93
113
  await $`cd ${repoName} && git add ${filePath}`;
94
114
  await $`cd ${repoName} && git commit -m "Update ${appName} image tag to ${deployTag} in ${environment} environment"`;
95
-
115
+
96
116
  console.log('Pushing changes to GitOps repository...');
97
117
  await $`cd ${repoName} && git push origin ${gitopsBranch}`;
98
-
118
+
99
119
  console.log('=========================================');
100
- console.log(`✅ Successfully deployed ${appName}:${deployTag} to ${environment}`);
120
+ console.log(
121
+ `✅ Successfully deployed ${appName}:${deployTag} to ${environment}`,
122
+ );
101
123
  console.log('=========================================');
102
-
103
124
  } catch (error) {
104
125
  console.error('Error during microservice deployment:', error.message);
105
126
  throw error;
@@ -108,7 +129,10 @@ export async function deployMicroservice(appName, helmPath, environment = 'dev',
108
129
  process.chdir('..');
109
130
  await $`rm -rf ${repoName}`;
110
131
  } catch (cleanupError) {
111
- console.warn('Warning: Failed to clean up temporary directory:', cleanupError.message);
132
+ console.warn(
133
+ 'Warning: Failed to clean up temporary directory:',
134
+ cleanupError.message,
135
+ );
112
136
  }
113
137
  }
114
138
  }
@@ -1,4 +1,4 @@
1
- import { $ } from '@docupace/pipeline/src/next/logger.js';
1
+ import { $ } from '../next/logger.js';
2
2
 
3
3
  /**
4
4
  * Publish Docker images for microservices with flexible naming
@@ -14,18 +14,25 @@ import { $ } from '@docupace/pipeline/src/next/logger.js';
14
14
  export async function publishMicroservice(gitSha, options = {}) {
15
15
  // Use environment variables as defaults, but allow overrides
16
16
  const config = {
17
- imageName: options.imageName || process.env.IMAGE_NAME || process.env.APP_NAME,
17
+ imageName:
18
+ options.imageName || process.env.IMAGE_NAME || process.env.APP_NAME,
18
19
  registryUrl: options.registryUrl || process.env.JF_REGISTRY_URL,
19
20
  repoName: options.repoName || process.env.JF_REGISTRY_REPO_NAME,
20
21
  username: options.username || process.env.JF_REGISTRY_USER_DEV,
21
22
  password: options.password || process.env.JF_REGISTRY_PASSWORD_DEV,
22
23
  buildNumber: options.buildNumber || process.env.BITBUCKET_BUILD_NUMBER,
23
- tag: options.tag || process.env.TAG || process.env.BITBUCKET_TAG || process.env.VERSION_TAG
24
+ tag:
25
+ options.tag ||
26
+ process.env.TAG ||
27
+ process.env.BITBUCKET_TAG ||
28
+ process.env.VERSION_TAG,
24
29
  };
25
30
 
26
31
  // Validate required fields
27
32
  if (!config.imageName) {
28
- throw new Error('Image name is required. Set IMAGE_NAME or APP_NAME environment variable.');
33
+ throw new Error(
34
+ 'Image name is required. Set IMAGE_NAME or APP_NAME environment variable.',
35
+ );
29
36
  }
30
37
 
31
38
  console.log('=== Docker Image Publishing Configuration ===');
@@ -38,7 +45,7 @@ export async function publishMicroservice(gitSha, options = {}) {
38
45
 
39
46
  const registryPath = `${config.registryUrl}/${config.repoName}`;
40
47
  const SHA_IMAGE_NAME = `${config.imageName}:sha-${gitSha}`;
41
-
48
+
42
49
  // Docker login
43
50
  await $`echo ${config.password} | docker login --username ${config.username} --password-stdin ${config.registryUrl}`;
44
51
 
@@ -74,25 +81,25 @@ export async function publishMicroservice(gitSha, options = {}) {
74
81
  if (config.tag) {
75
82
  // Handle various tag formats
76
83
  let version = config.tag;
77
-
84
+
78
85
  // If tag contains @, extract version after it
79
86
  if (version.includes('@')) {
80
87
  version = 'v' + version.split('@')[1];
81
88
  }
82
-
89
+
83
90
  // Ensure version starts with 'v' if it's a semver without it
84
91
  if (/^\d+\.\d+\.\d+/.test(version) && !version.startsWith('v')) {
85
92
  version = 'v' + version;
86
93
  }
87
-
94
+
88
95
  const VERSION_IMAGE_NAME = `${config.imageName}:${version}`;
89
96
  const versionTag = `${registryPath}/${VERSION_IMAGE_NAME}`;
90
-
97
+
91
98
  console.log(`Tagging and pushing version: ${versionTag}`);
92
99
  await $`docker tag ${SHA_IMAGE_NAME} ${versionTag}`;
93
100
  await $`docker push ${versionTag}`;
94
101
  tagsToPush.push(VERSION_IMAGE_NAME);
95
-
102
+
96
103
  // Also push 'latest' tag when we have a version
97
104
  const LATEST_IMAGE_NAME = `${config.imageName}:latest`;
98
105
  const latestTag = `${registryPath}/${LATEST_IMAGE_NAME}`;
@@ -108,22 +115,22 @@ export async function publishMicroservice(gitSha, options = {}) {
108
115
  .trim()
109
116
  .split('\n')
110
117
  .filter(Boolean);
111
-
118
+
112
119
  if (gitTags.length > 0) {
113
120
  console.log(`Found git tags at HEAD: ${gitTags.join(', ')}`);
114
-
121
+
115
122
  for (const gitTag of gitTags) {
116
123
  // Skip if we already handled this tag above
117
124
  if (gitTag === config.tag) continue;
118
-
125
+
119
126
  let version = gitTag;
120
127
  if (version.includes('@')) {
121
128
  version = 'v' + version.split('@')[1];
122
129
  }
123
-
130
+
124
131
  const TAG_IMAGE_NAME = `${config.imageName}:${version}`;
125
132
  const gitTagPath = `${registryPath}/${TAG_IMAGE_NAME}`;
126
-
133
+
127
134
  console.log(`Tagging and pushing git tag: ${gitTagPath}`);
128
135
  await $`docker tag ${SHA_IMAGE_NAME} ${gitTagPath}`;
129
136
  await $`docker push ${gitTagPath}`;
@@ -131,17 +138,19 @@ export async function publishMicroservice(gitSha, options = {}) {
131
138
  }
132
139
  }
133
140
  } catch (e) {
134
- console.log('No git tags found at HEAD or error checking tags');
141
+ console.log('No git tags found at HEAD or error checking tags', e);
135
142
  }
136
143
 
137
144
  console.log('\n✅ Docker image published successfully!');
138
145
  console.log('=== Summary of pushed tags ===');
139
- tagsToPush.forEach(tag => console.log(` ✓ ${tag}`));
146
+ tagsToPush.forEach((tag) => console.log(` ✓ ${tag}`));
140
147
  console.log('==============================\n');
141
-
148
+
142
149
  // Verify the version tag if we expect one
143
150
  if (config.tag) {
144
- const version = config.tag.includes('@') ? 'v' + config.tag.split('@')[1] : config.tag;
151
+ const version = config.tag.includes('@')
152
+ ? 'v' + config.tag.split('@')[1]
153
+ : config.tag;
145
154
  const expectedTag = `${registryPath}/${config.imageName}:${version}`;
146
155
  console.log(`Verifying version tag exists: ${expectedTag}`);
147
156
  try {
@@ -149,10 +158,9 @@ export async function publishMicroservice(gitSha, options = {}) {
149
158
  console.log('✅ Version tag verified in registry!');
150
159
  } catch (e) {
151
160
  console.error('❌ WARNING: Could not verify version tag in registry!');
152
- console.error('ArgoCD may fail to pull this image.');
161
+ console.error('ArgoCD may fail to pull this image.', e);
153
162
  }
154
163
  }
155
-
156
164
  } catch (error) {
157
165
  console.error('Error during image publishing:', error);
158
166
  throw error;
@@ -177,4 +185,4 @@ async function checkLocalImage(imageName) {
177
185
  // Backward compatibility wrapper
178
186
  export async function publishWithDefaults(gitSha) {
179
187
  return publishMicroservice(gitSha);
180
- }
188
+ }
@@ -8,7 +8,7 @@ function log(msg) {
8
8
  export async function addApacheSite() {
9
9
  if (
10
10
  !process.env.ENVIRONMENT ||
11
- !['dev', 'qa', 'uat', 'stage','www3'].includes(process.env.ENVIRONMENT)
11
+ !['dev', 'qa', 'uat', 'stage', 'www3'].includes(process.env.ENVIRONMENT)
12
12
  ) {
13
13
  log('Error: wront ENVIRONMENT');
14
14
  process.exit(1);
@@ -69,7 +69,7 @@ export async function addApacheSite() {
69
69
  apacheEnvHostMap[process.env.ENVIRONMENT].host1,
70
70
  `/root/repo/${apacheEnvHostMap[process.env.ENVIRONMENT].repo}/scripts/addsite/add_core_site.sh ${process.env.ENVIRONMENT} ${process.env.SITE}`,
71
71
  );
72
-
72
+
73
73
  await sshCmd(
74
74
  apacheEnvHostMap[process.env.ENVIRONMENT].host2,
75
75
  `/root/tomcat_repo_sync.sh`,
package/src/next/cli.js CHANGED
@@ -4,7 +4,7 @@ import { Command } from 'commander';
4
4
  import { pull } from './pull.js';
5
5
  import { sonar } from './sonar.js';
6
6
  import { publish } from './publish.js';
7
- import { publishMicroservice } from './micro/publish-ms.js'; // Add this import
7
+ import { publishMicroservice } from '../micro/publish-ms.js';
8
8
  import {
9
9
  deployAppWithTag,
10
10
  deployFromSite,
@@ -132,7 +132,6 @@ program
132
132
  await deployTemplate(env, site, deployTag, 'siteConfigRemoteBranch');
133
133
  });
134
134
 
135
-
136
135
  program
137
136
  .command('deploy-app <application>')
138
137
  .description('Deploy an application for a specific site')
@@ -232,4 +231,4 @@ program
232
231
  }
233
232
  });
234
233
 
235
- program.parse(process.argv);
234
+ program.parse(process.argv);
@@ -20,7 +20,6 @@ const connectUIEnvMap = {
20
20
  prod: 'prod-www3',
21
21
  };
22
22
 
23
-
24
23
  const siteSettingsEnvMap = {
25
24
  dev: 'dev',
26
25
  preprod: 'preprod',
@@ -158,7 +157,7 @@ export async function connectClone() {
158
157
  try {
159
158
  // Execute the shell command
160
159
  const result =
161
- await $`cd ${cloneFrom} && bash dock.sh clone ${connectToEnv} ${process.env.BUILD_SITE} ${process.env.IMAGE_VERSION}`;
160
+ await $`cd ${cloneFrom} && bash dock.sh clone ${connectToEnv} ${process.env.BUILD_SITE} ${process.env.IMAGE_VERSION}`;
162
161
  await $`cd ${cloneTo} && git checkout master && git pull --ff-only`;
163
162
  await $`cd ${cloneTo} && git remote -v`;
164
163
  await $`cd ${cloneTo} && git branch`;