@docupace/pipeline 1.0.39-matttest.24 → 1.0.39-matttest.26

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/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # Pipeline Shared Scripts
2
+
3
+ A collection of CLI tools for Docupace's CI/CD pipelines and deployment workflows.
4
+
5
+ ## Overview
6
+
7
+ This package provides a set of command-line interfaces (CLIs) to facilitate various DevOps operations in the Docupace ecosystem:
8
+
9
+ - `dp-next-cli`: Deployment and pipeline management for Next applications
10
+ - `dp-changeset-cli`: Versioning and changeset management
11
+ - `dp-auth0-cli`: Auth0 tenant configuration and management
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @docupace/pipeline
17
+ ```
18
+
19
+ Or with pnpm:
20
+
21
+ ```bash
22
+ pnpm add @docupace/pipeline
23
+ ```
24
+
25
+ ## Command Line Interfaces
26
+
27
+ ### dp-next-cli
28
+
29
+ Manages deployment, Docker image handling, and infrastructure configuration.
30
+
31
+ ```bash
32
+ dp-next-cli [command] [options]
33
+ ```
34
+
35
+ **Commands:**
36
+
37
+ - `pull <imageName>`: Pull a Docker image from the registry
38
+ - `sonar`: Run Sonar analysis
39
+ - `addApacheSite`: Add site to apache
40
+ - `connectClone`: Clone connect site
41
+ - `haproxySync`: Sync haproxy config
42
+ - `vaultAddSiteData`: Add m2m auth0 data to vault
43
+ - `-s, --site-name <siteName>`: Site name
44
+ - `-p, --site-config-remote-path <path>`: Site config remote path
45
+ - `publish`: Publish a Docker image
46
+ - `deploy-from-site`: Deploy an application for a specific site
47
+ - `-f, --from-env <fromEnv>`: Source environment
48
+ - `-t, --to-env <toEnv>`: Target environment
49
+ - `-F, --from-site <fromSite>`: Source site
50
+ - `-T, --to-site <toSite>`: Target site
51
+ - `-c, --deploy-core <deployCore>`: Deploy Core (default: "false")
52
+ - `-C, --deploy-connect <deployConnect>`: Deploy Connect (default: "false")
53
+ - `deploy-template`: Deploy an application for a specific site
54
+ - `deploy-app <application>`: Deploy an application for a specific site
55
+ - `deploy-core <env> <site>`: Deploy Core
56
+ - `-l, --liquibase <liquibase>`: Application name (default: "true")
57
+ - `-b, --branch <branch>`: Branch (default: "master")
58
+ - `deploy-connect <env> <site>`: Deploy Connect
59
+ - `-l, --liquibase <liquibase>`: Application name (default: "true")
60
+ - `-b, --branch <branch>`: Branch (default: "master")
61
+ - `deploy-core-pipeline <env> <site>`: Deploy Core via pipeline
62
+ - `-l, --liquibase <liquibase>`: Application name (default: "true")
63
+ - `-b, --branch <branch>`: Branch (default: "master")
64
+ - `copy`: Copy a Docker image between registries
65
+ - `-a, --application <application>`: Application name
66
+ - `-f, --from-env <fromEnv>`: Source environment
67
+ - `-t, --to-env <toEnv>`: Target environment
68
+ - `-g, --tag <tag>`: Image tag
69
+ - `run-pipeline`: Trigger a pipeline by name
70
+ - `-r, --repository <repository>`: Repository name
71
+ - `-p, --pipeline-name <pipelineName>`: Pipeline name
72
+ - `-b, --branch <branch>`: Branch name
73
+ - `-v, --variables <key=value>`: Pipeline variable as key=value pair
74
+ - `-w, --wait`: Wait for the pipeline to complete (default: false)
75
+
76
+ ### dp-changeset-cli
77
+
78
+ Manages versioning and changesets for mono-repos and single-package repos.
79
+
80
+ ```bash
81
+ dp-changeset-cli [command] [options]
82
+ ```
83
+
84
+ **Commands:**
85
+
86
+ - `validate`: Validate changesets for the provided PR
87
+ - `version`: Run Changeset versioning
88
+ - `commit-tag`: Commit and tag the new version
89
+ - `version-commit-tag`: Run versioning and commit-and-tag in sequence
90
+ - `close-version`: Close a version and create a release branch
91
+ - `create-changeset`: Create a changeset based on the current branch and Jira ticket information
92
+
93
+ ### dp-auth0-cli
94
+
95
+ Manages Auth0 tenant configuration across environments.
96
+
97
+ ```bash
98
+ dp-auth0-cli [command] [options]
99
+ ```
100
+
101
+ **Commands:**
102
+
103
+ - `configureFromSite <fromSite> <toSite> <fromEnv> <toEnv> <deployUI> <deployGraphQLServer> <useNewDomain> <useS3>`: Configure Auth0 tenants
104
+ - `getVaultSecrets <vaultPath>`: Get secrets from Vault
105
+ - `configureAlias <site> <env> <username> <password> <realm>`: Configure Core Alias for the given site
106
+ - `exportConf <site> <env>`: Export Auth0 configuration for the given site
107
+ - `getAuth0Metadata <site> <env>`: Get Auth0 metadata for the given site
108
+
109
+ ## Environment Configuration
110
+
111
+ The CLI tools look for environment configuration in the following locations:
112
+ - `.env.pipeline.local`
113
+ - `config/.env.pipeline.local`
114
+
115
+ ## Examples
116
+
117
+ ```bash
118
+ # Deploy from one site to another
119
+ dp-next-cli deploy-from-site --from-env dev --to-env dev --from-site financialdev --to-site template --deploy-core true
120
+
121
+ # Run a pipeline
122
+ dp-next-cli run-pipeline -r docupace-next-e2e -b master -p run-tests-qa
123
+
124
+ # Validate changesets
125
+ dp-changeset-cli validate
126
+
127
+ # Create a new changeset
128
+ dp-changeset-cli create-changeset
129
+
130
+ # Configure Auth0 for a site
131
+ dp-auth0-cli configureFromSite sourceSite targetSite dev prod true true true false
132
+ ```
133
+
134
+ ## License
135
+
136
+ ISC
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docupace/pipeline",
3
- "version": "1.0.39-matttest.24",
3
+ "version": "1.0.39-matttest.26",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -5,16 +5,16 @@ import crypto from 'crypto';
5
5
 
6
6
  import {
7
7
  cloneEnvRepository,
8
- readDeployConfig,
9
- pushDeployConfig,
10
8
  cloneRepository,
9
+ pushDeployConfig,
10
+ readDeployConfig,
11
11
  } from '../next/deploy.js';
12
12
 
13
13
  import { getVaultSecrets, updateVaultSecrets } from './vault.js';
14
14
  import {
15
- getVaultSecretsConfigs,
16
- environmentConfig,
17
15
  coreSiteEnvMap,
16
+ environmentConfig,
17
+ getVaultSecretsConfigs,
18
18
  } from '../next/config.js';
19
19
 
20
20
  async function ensureDirectoryExists(dirPath) {
@@ -1,11 +1,10 @@
1
1
  import fs from 'fs-extra';
2
2
  import axios from 'axios';
3
3
  import path from 'path';
4
- import { cloneRepository } from '../next/deploy.js';
4
+ import { cloneRepository, pushDeployConfig } from '../next/deploy.js';
5
5
  import { getAuth0AuthToken } from './configure.js';
6
6
  import { getVaultSecrets } from './vault.js';
7
7
  import { getVaultSecretsConfigs } from '../next/config.js';
8
- import { pushDeployConfig } from '../next/deploy.js';
9
8
 
10
9
  export async function getAuth0Metadata(site, env) {
11
10
  try {
@@ -3,10 +3,9 @@ import { Command } from 'commander';
3
3
  import { $ } from 'zx';
4
4
  import { validateChangesets } from './validate.js';
5
5
  import dotenv from 'dotenv';
6
- import { getChangedAppPackages, isMonoRepo, setGitInfo } from '../next/util.js';
6
+ import { isMonoRepo, setGitInfo } from '../next/util.js';
7
7
  import { updateJiraWithVersion, versionCommand } from './version.js';
8
8
  import { createChangeset } from './create.js';
9
- import { getPackage } from './util.js';
10
9
 
11
10
  dotenv.config({ path: ['.env.pipeline.local', 'config/.env.pipeline.local'] });
12
11
 
@@ -4,7 +4,7 @@ import z from 'zod';
4
4
  import { zodResponseFormat } from 'openai/helpers/zod';
5
5
  import fs from 'fs';
6
6
  import path from 'path';
7
- import { getAllAppPackages, isMonoRepo } from '../next/util.js';
7
+ import { getAllAppPackages, getAllPackages, isMonoRepo } from '../next/util.js';
8
8
  import inquirer from 'inquirer';
9
9
  import { getMainPackage, getPackage } from './util.js';
10
10
 
@@ -128,17 +128,17 @@ ${summary} [${jiraTicketId}]
128
128
 
129
129
  export async function createChangeset() {
130
130
  if (isMonoRepo()) {
131
- const appPackages = await getAllAppPackages();
131
+ const allPackages = await getAllPackages();
132
132
  const response = await inquirer.prompt([
133
133
  {
134
134
  type: 'list',
135
135
  name: 'package',
136
136
  message: 'Which package do you want to generate changesetfor?',
137
- choices: appPackages.map((appPackage) => appPackage.name),
137
+ choices: allPackages.map((appPackage) => appPackage.name),
138
138
  },
139
139
  ]);
140
140
 
141
- const selectedPackage = appPackages.find(
141
+ const selectedPackage = allPackages.find(
142
142
  (appPackage) => appPackage.name == response.package,
143
143
  );
144
144
 
@@ -4,20 +4,35 @@ import { $ } from 'zx';
4
4
 
5
5
  import { isMonoRepo, setGitInfo } from '../next/util.js';
6
6
  import { versionStatus } from './version.js';
7
- import { getAppReleases } from './cli.js';
8
7
 
9
8
  const CHANGESET_DIR = '.changeset';
10
9
 
10
+ function areArraysEqualIgnoringOrder(arr1, arr2) {
11
+ if (arr1.length !== arr2.length) return false;
12
+
13
+ const sortedA = [...arr1].sort();
14
+ const sortedB = [...arr2].sort();
15
+
16
+ return sortedA.every((element, index) => element === sortedB[index]);
17
+ }
18
+
11
19
  export async function validateChangesets() {
12
20
  if (isMonoRepo()) {
13
21
  await setGitInfo();
14
22
  const destBranch = process.env.BITBUCKET_PR_DESTINATION_BRANCH;
15
23
  await $`git fetch origin ${destBranch}:${destBranch}`;
16
- const releases = await versionStatus(destBranch);
17
- const appReleases = getAppReleases(releases);
18
- if (appReleases.length == 0) {
19
- throw new Error('Must have a changeset for at lease one app');
20
- }
24
+ await versionStatus(destBranch);
25
+ /*const changedPackages = await getChangedPackages();
26
+ const releaseNames = releases.map((release) => release.name);
27
+ const changedPackageNames = changedPackages.map(
28
+ (changedPackage) => changedPackage.name,
29
+ );
30
+
31
+ if (!areArraysEqualIgnoringOrder(releaseNames, changedPackageNames)) {
32
+ throw new Error(
33
+ 'Changesets must be created for all packages created and for those that have those changed as dependencies',
34
+ );
35
+ }*/
21
36
  } else {
22
37
  await validateChangesetPath(path.resolve(process.cwd(), CHANGESET_DIR));
23
38
  }
@@ -1,6 +1,5 @@
1
1
  import groovy.json.JsonSlurper
2
-
3
- import hudson.model.*;
2
+ import hudson.model.*
4
3
 
5
4
  def build = Thread.currentThread().executable
6
5
  def params = build.getEnvironment(listener)
@@ -1,40 +1,43 @@
1
1
  import { $ } from 'zx';
2
2
 
3
3
  export async function addApacheSite() {
4
- if (
5
- !process.env.ENVIRONMENT ||
6
- (process.env.ENVIRONMENT !== 'dev' && process.env.ENVIRONMENT !== 'qa')
7
- ) {
8
- log("Error: ENVIRONMENT must be either 'dev' or 'qa'.");
9
- process.exit(1);
10
- }
11
- if (!process.env.SITE) {
12
- log('Error: SITE cannot be empty.');
13
- process.exit(1);
14
- }
15
-
16
- // Save private key from base64
17
- const haproxyPrivateKey = process.env.HAPROXY_PRIVATE_KEY;
18
- if (!haproxyPrivateKey) {
19
- log('Error: HAPROXY_PRIVATE_KEY not set.');
20
- process.exit(1);
21
- }
22
-
23
- await fs.writeFile('private.key', Buffer.from(haproxyPrivateKey, 'base64'));
24
- await fs.chmod('private.key', 0o600);
25
-
26
-
27
- console.log("Running command");
28
- const sshCmd = (server,script) =>
29
- $`ssh -i private.key -o StrictHostKeyChecking=no root@${server} ${script}`;
30
-
31
- let server = `${process.env.ENVIRONMENT}-apalb01a.corp.docupace.com`;
32
- // The script is run twice in the Bash version
33
- await sshCmd(server, `/root/repo/iis-preprod/scripts/addsite/add_core_site.sh ${process.env.ENVIRONMENT} ${process.env.SITE}`);
34
-
35
- server = `${process.env.ENVIRONMENT}-apalb01b.corp.docupace.com`;
4
+ if (
5
+ !process.env.ENVIRONMENT ||
6
+ (process.env.ENVIRONMENT !== 'dev' && process.env.ENVIRONMENT !== 'qa')
7
+ ) {
8
+ log("Error: ENVIRONMENT must be either 'dev' or 'qa'.");
9
+ process.exit(1);
10
+ }
11
+ if (!process.env.SITE) {
12
+ log('Error: SITE cannot be empty.');
13
+ process.exit(1);
14
+ }
36
15
 
37
- await sshCmd(server,`/root/repo/iis-preprod/scripts/addsite/add_core_site.sh ${process.env.ENVIRONMENT} ${process.env.SITE}`);
16
+ // Save private key from base64
17
+ const haproxyPrivateKey = process.env.HAPROXY_PRIVATE_KEY;
18
+ if (!haproxyPrivateKey) {
19
+ log('Error: HAPROXY_PRIVATE_KEY not set.');
20
+ process.exit(1);
38
21
  }
39
-
40
-
22
+
23
+ await fs.writeFile('private.key', Buffer.from(haproxyPrivateKey, 'base64'));
24
+ await fs.chmod('private.key', 0o600);
25
+
26
+ console.log('Running command');
27
+ const sshCmd = (server, script) =>
28
+ $`ssh -i private.key -o StrictHostKeyChecking=no root@${server} ${script}`;
29
+
30
+ let server = `${process.env.ENVIRONMENT}-apalb01a.corp.docupace.com`;
31
+ // The script is run twice in the Bash version
32
+ await sshCmd(
33
+ server,
34
+ `/root/repo/iis-preprod/scripts/addsite/add_core_site.sh ${process.env.ENVIRONMENT} ${process.env.SITE}`,
35
+ );
36
+
37
+ server = `${process.env.ENVIRONMENT}-apalb01b.corp.docupace.com`;
38
+
39
+ await sshCmd(
40
+ server,
41
+ `/root/repo/iis-preprod/scripts/addsite/add_core_site.sh ${process.env.ENVIRONMENT} ${process.env.SITE}`,
42
+ );
43
+ }
package/src/next/cli.js CHANGED
@@ -7,26 +7,24 @@ import { publish } from './publish.js';
7
7
  import {
8
8
  deployAppWithTag,
9
9
  deployFromSite,
10
+ deployTemplate,
10
11
  getDefaultDeploySite,
11
12
  getDeployTag,
12
13
  } from './deploy.js';
13
- import { deployTemplate } from './deploy.js';
14
14
  import { copy } from './copy.js';
15
15
  import { vaultAddSiteData } from './vault.js';
16
16
  import { addApacheSite } from './apache.js';
17
17
  import { haproxySync } from './haproxy.js';
18
18
  import { connectClone } from './connect.js';
19
19
  import dotenv from 'dotenv';
20
+ import { $ } from 'zx';
21
+ import { deployConnect, deployCore } from './jenkins.js';
22
+ import { runPipeline } from './pipline.js';
20
23
 
21
24
  dotenv.config({ path: ['.env.pipeline.local', 'config/.env.pipeline.local'] });
22
25
 
23
26
  const program = new Command();
24
27
 
25
- import { $ } from 'zx';
26
- import { deployConnect, deployCore } from './jenkins.js';
27
- import { runPipeline } from './pipline.js';
28
- import { buildChangePackages } from './util.js';
29
-
30
28
  const GIT_SHA = (await $`git log --pretty=format:'%h' -n 1`).stdout.trim();
31
29
 
32
30
  program
@@ -165,13 +163,6 @@ program
165
163
  });
166
164
  });
167
165
 
168
- program
169
- .command('build-mono-repo')
170
- .description('Build Mono Repo')
171
- .action(async () => {
172
- await buildChangePackages();
173
- });
174
-
175
166
  program
176
167
  .command('copy')
177
168
  .description('Copy a Docker image between registries')
@@ -6,7 +6,7 @@ import lodash from 'lodash';
6
6
  import { appInfo, environmentConfig, getRepUrl } from './config.js';
7
7
  import { copy2 } from './copy.js';
8
8
  import axios from 'axios';
9
- import { deployCore, deployConnect } from './jenkins.js';
9
+ import { deployConnect, deployCore } from './jenkins.js';
10
10
 
11
11
  /**
12
12
  * Clone the repository, read the YAML file, and return the parsed data and file paths.
@@ -1,12 +1,11 @@
1
1
  import { $ } from 'zx';
2
2
 
3
-
4
3
  export async function haproxySync() {
5
- const repoPath = '/root/repo/docupace-ansible';
6
- const inventory = path.join(repoPath, 'inventories/preprod/inventory');
7
-
8
- // Create haproxy.sh
9
- const scriptContent = `
4
+ const repoPath = '/root/repo/docupace-ansible';
5
+ const inventory = path.join(repoPath, 'inventories/preprod/inventory');
6
+
7
+ // Create haproxy.sh
8
+ const scriptContent = `
10
9
  #!/bin/bash
11
10
 
12
11
  [[ ! -f ${inventory} ]] && ( echo "Alert: no inventory file: ${inventory}" ; exit 1 )
@@ -27,24 +26,24 @@ export async function haproxySync() {
27
26
  git commit -m "Sync haproxy"
28
27
  git push origin master
29
28
  `;
30
-
31
- await fs.writeFile('haproxy.sh', scriptContent);
32
-
33
- // Private key
34
- const haproxyPrivateKey = process.env.HAPROXY_PRIVATE_KEY;
35
- if (!haproxyPrivateKey) {
36
- log('Error: HAPROXY_PRIVATE_KEY not set.');
37
- process.exit(1);
38
- }
39
-
40
- await fs.writeFile('private.key', Buffer.from(haproxyPrivateKey, 'base64'));
41
- await fs.chmod('private.key', 0o600);
42
-
43
- await $`cat private.key`; // Just to mimic the script's behavior
44
-
45
- // Copy script to remote
46
- await $`scp -i private.key -o StrictHostKeyChecking=no haproxy.sh root@10.10.28.198:/tmp/haproxy.sh`;
47
-
48
- // Execute script on remote
49
- await $`ssh -i private.key -o StrictHostKeyChecking=no root@10.10.28.198 "bash /tmp/haproxy.sh"`;
29
+
30
+ await fs.writeFile('haproxy.sh', scriptContent);
31
+
32
+ // Private key
33
+ const haproxyPrivateKey = process.env.HAPROXY_PRIVATE_KEY;
34
+ if (!haproxyPrivateKey) {
35
+ log('Error: HAPROXY_PRIVATE_KEY not set.');
36
+ process.exit(1);
50
37
  }
38
+
39
+ await fs.writeFile('private.key', Buffer.from(haproxyPrivateKey, 'base64'));
40
+ await fs.chmod('private.key', 0o600);
41
+
42
+ await $`cat private.key`; // Just to mimic the script's behavior
43
+
44
+ // Copy script to remote
45
+ await $`scp -i private.key -o StrictHostKeyChecking=no haproxy.sh root@10.10.28.198:/tmp/haproxy.sh`;
46
+
47
+ // Execute script on remote
48
+ await $`ssh -i private.key -o StrictHostKeyChecking=no root@10.10.28.198 "bash /tmp/haproxy.sh"`;
49
+ }
package/src/next/util.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { existsSync } from 'fs';
2
- import { join } from 'path';
3
- import { $, nothrow } from 'zx';
4
- import path from 'path';
2
+ import path, { join } from 'path';
3
+ import { $ } from 'zx';
5
4
 
6
5
  export function isMonoRepo() {
7
6
  // Check for the presence of turbo.json which indicates a Turborepo monorepo
@@ -86,7 +85,9 @@ export async function getChangedAppPackages() {
86
85
  }
87
86
 
88
87
  export async function setGitInfo() {
89
- await $`git config --global user.email "gitops@docupace.com"`;
90
- await $`git config --global user.name "Gitops"`;
91
- await $`git remote set-url origin https://${process.env.THIS_REP_TOKEN}@bitbucket.org/${process.env.BITBUCKET_REPO_FULL_NAME}.git`;
88
+ if (!process.env.IS_DEV) {
89
+ await $`git config --global user.email "gitops@docupace.com"`;
90
+ await $`git config --global user.name "Gitops"`;
91
+ await $`git remote set-url origin https://${process.env.THIS_REP_TOKEN}@bitbucket.org/${process.env.BITBUCKET_REPO_FULL_NAME}.git`;
92
+ }
92
93
  }
package/src/next/vault.js CHANGED
@@ -3,8 +3,8 @@ import axios from 'axios';
3
3
  export async function vaultAddSiteData(SITE, SITE_CONFIG_REMOTE_PATH) {
4
4
  const AUTH0_CLIENT_ID = process.env.AUTH0_CLIENT_ID;
5
5
  const AUTH0_CLIENT_SECRET = process.env.AUTH0_CLIENT_SECRET;
6
- const VAULT_ADDR = process.env.VAULT_ADDR; // Vault host URL from environment variables
7
- const VAULT_TOKEN = process.env.VAULT_TOKEN; // Vault token from environment variables
6
+ const VAULT_ADDR = process.env.VAULT_ADDR; // Vault host URL from environment variables
7
+ const VAULT_TOKEN = process.env.VAULT_TOKEN; // Vault token from environment variables
8
8
 
9
9
  if (!VAULT_ADDR || !VAULT_TOKEN) {
10
10
  throw new Error('Missing VAULT_ADDR or VAULT_TOKEN environment variable.');
@@ -13,7 +13,6 @@ export async function vaultAddSiteData(SITE, SITE_CONFIG_REMOTE_PATH) {
13
13
  const vaultApiUrl = `${VAULT_ADDR}/v1/secret/data/${SITE}/common/config`;
14
14
 
15
15
  try {
16
-
17
16
  if (process.env.VAULT_SKIP_VERIFY === 'true') {
18
17
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
19
18
  }
@@ -32,12 +31,15 @@ export async function vaultAddSiteData(SITE, SITE_CONFIG_REMOTE_PATH) {
32
31
  'X-Vault-Token': VAULT_TOKEN,
33
32
  'Content-Type': 'application/json',
34
33
  },
35
- }
34
+ },
36
35
  );
37
36
 
38
37
  console.log('Data added to Vault successfully:', response.data);
39
38
  } catch (error) {
40
- console.error('Error adding data to Vault:', error.response?.data || error.message);
39
+ console.error(
40
+ 'Error adding data to Vault:',
41
+ error.response?.data || error.message,
42
+ );
41
43
  throw error;
42
44
  }
43
45
  }