@docupace/pipeline 1.0.1-2.ervinsUpdate2.6 → 1.0.2-3.tes1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docupace/pipeline",
3
- "version": "1.0.12.ervinsUpdate2.6",
3
+ "version": "1.0.23.tes1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -16,6 +16,7 @@
16
16
  "license": "ISC",
17
17
  "dependencies": {
18
18
  "@changesets/cli": "^2.27.10",
19
+ "@docupace/core-client": "^0.1.59",
19
20
  "auth0-deploy-cli": "^7.24.3",
20
21
  "axios": "^1.7.9",
21
22
  "commander": "^12.1.0",
@@ -0,0 +1,75 @@
1
+ import axios from 'axios';
2
+
3
+ import {
4
+ createAlias
5
+ } from '../next/alias.js';
6
+
7
+ import {getAuth0AuthToken} from './configure.js';
8
+
9
+ import {
10
+ getVaultSecrets,
11
+ } from './vault.js';
12
+
13
+ import {
14
+ getVaultSecretsConfigs,
15
+ } from '../next/config.js';
16
+
17
+ import {
18
+ cloneEnvRepository,
19
+ readDeployConfig,
20
+ } from '../next/deploy.js';
21
+
22
+ export async function getCCAlias ({application, auth0Domain, auth0AuthToken}){
23
+ console.log(`Forming alias name for application ${application}...`);
24
+
25
+ try {
26
+ const auth0Response = await axios.get(`https://${auth0Domain}/api/v2/clients`, {
27
+ headers: {authorization: `Bearer ${auth0AuthToken}`},
28
+ });
29
+
30
+ const appAuth0ClientIdData = auth0Response.data.find(client => client.name === `${application}`);
31
+ const appAuth0ClientId = appAuth0ClientIdData.client_id;
32
+
33
+ console.log(`Client Credentials Alias: ${appAuth0ClientId}@clients`);
34
+ return `${appAuth0ClientId}@clients`;
35
+ } catch (err) {
36
+ console.error(`Failed to form alias name for application: ${application}: ${err.message}`);
37
+ }
38
+ }
39
+
40
+ export async function configureAlias(site, env, username, password, realm) {
41
+
42
+ console.log(`Creating alias for site: ${site} in env: ${env}`);
43
+
44
+ const commonSecretsPath = getVaultSecretsConfigs(site).commonSecretsPath;
45
+ console.log(`commonSecretsPath => ${commonSecretsPath}`)
46
+ const commonSecrets = await getVaultSecrets(commonSecretsPath);
47
+
48
+ // Site Common Secrets
49
+ const siteCommonSecretsPath = getVaultSecretsConfigs(site).siteCommonSecretsPath;
50
+ console.log(`siteCommonSecretsPath => ${siteCommonSecretsPath}`)
51
+ const siteCommonSecrets = await getVaultSecrets(siteCommonSecretsPath);
52
+
53
+ const auth0Domain = `docupace-${env}-${site}.us.auth0.com`
54
+ const auth0ClientId = siteCommonSecrets.AUTH0_CLIENT_ID;
55
+ const auth0ClientSecret = siteCommonSecrets.AUTH0_CLIENT_SECRET;
56
+ const auth0Token = await getAuth0AuthToken(auth0Domain, auth0ClientId, auth0ClientSecret);
57
+
58
+ await cloneEnvRepository(env);
59
+
60
+ const { deployConfig: deployGraphQLServerConfig} = await readDeployConfig('graphql-server', env, site, 'values');
61
+ const coreUrl = deployGraphQLServerConfig.graphqlServer.coreUrl;
62
+
63
+ const clientCredentialsAlias = await getCCAlias({
64
+ application: 'docupace-graphql-client-credentials',
65
+ auth0Domain: auth0Domain,
66
+ auth0AuthToken: auth0Token
67
+ });
68
+
69
+ await createAlias(
70
+ coreUrl,
71
+ username,
72
+ password,
73
+ realm,
74
+ clientCredentialsAlias);
75
+ }
package/src/auth0/cli.js CHANGED
@@ -9,16 +9,19 @@ import {
9
9
  } from './vault.js'
10
10
 
11
11
  import dotenv from 'dotenv';
12
+ import {
13
+ configureAlias
14
+ } from "./alias.js";
12
15
 
13
16
  dotenv.config({ path: ['.env.pipeline.local', 'config/.env.pipeline.local'] });
14
17
 
15
18
  const program = new Command();
16
19
 
17
20
  program
18
- .command('configureFromSite <fromSite> <toSite> <fromEnv> <toEnv> <deployUI> <deployGraphQLServer> <useNewDomain>')
21
+ .command('configureFromSite <fromSite> <toSite> <fromEnv> <toEnv> <deployUI> <deployGraphQLServer> <useNewDomain> <configureMFA>')
19
22
  .description('Configure the Auth0 tenants in env for the given site')
20
- .action(async (fromSite, toSite, fromEnv,toEnv, deployUI, deployGraphQLServer, useNewDomain) => {
21
- await configureFromSite(fromSite, toSite, fromEnv, toEnv, deployUI, deployGraphQLServer, useNewDomain);
23
+ .action(async (fromSite, toSite, fromEnv,toEnv, deployUI, deployGraphQLServer, useNewDomain, configureMFA) => {
24
+ await configureFromSite(fromSite, toSite, fromEnv, toEnv, deployUI, deployGraphQLServer, useNewDomain, configureMFA);
22
25
  });
23
26
 
24
27
  program
@@ -28,4 +31,11 @@ program
28
31
  await getVaultSecrets(vaultPath);
29
32
  });
30
33
 
34
+ program
35
+ .command('configureAlias <site> <env> <username> <password> <realm>')
36
+ .description('Configure Core Alias for the given site')
37
+ .action(async (site, env, username, password, realm) => {
38
+ await configureAlias(site, env, username, password, realm);
39
+ });
40
+
31
41
  program.parse(process.argv);
@@ -1,10 +1,9 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import yaml from 'js-yaml';
4
- import { $ } from 'zx';
5
3
  import axios from 'axios';
6
4
  import crypto from 'crypto';
7
5
  import { deploy } from 'auth0-deploy-cli';
6
+ import fl from 'fs/promises';
8
7
 
9
8
  import {
10
9
  cloneEnvRepository,
@@ -22,6 +21,8 @@ import {
22
21
  getVaultSecretsConfigs,
23
22
  environmentConfig
24
23
  } from '../next/config.js';
24
+ import { connect } from 'http2';
25
+ import { promise } from 'zod';
25
26
 
26
27
  async function ensureDirectoryExists(dirPath) {
27
28
  try {
@@ -32,6 +33,27 @@ async function ensureDirectoryExists(dirPath) {
32
33
  }
33
34
  }
34
35
 
36
+ async function copyDirectory(source, destination) {
37
+ try {
38
+ await fl.mkdir(destination, { recursive: true });
39
+ const items = await fl.readdir(source, { withFileTypes: true });
40
+
41
+ for (const item of items) {
42
+ const sourcePath = path.join(source, item.name);
43
+ const destinationPath = path.join(destination, item.name);
44
+
45
+ if (item.isDirectory()) {
46
+ await copyDirectory(sourcePath, destinationPath);
47
+ } else {
48
+ await fl.copyFile(sourcePath, destinationPath);
49
+ }
50
+ }
51
+ } catch (err) {
52
+ console.error(`Error copying directory: ${err.message}`);
53
+ throw err;
54
+ }
55
+ }
56
+
35
57
  async function addApplicationToApi ({application, auth0Domain, auth0AuthToken, coreApiIdentifier}){
36
58
  console.log("Adding application to API authorized applications...");
37
59
 
@@ -155,13 +177,18 @@ async function replaceInFile(filePath, replacements) {
155
177
  await fs.promises.writeFile(filePath, content, 'utf8');
156
178
  }
157
179
 
158
- async function templateAuth0(siteUrl, coreApiContext, env, filePaths, deployUI, deployGraphQLServer, commonSecrets) {
180
+ async function templateAuth0(siteUrl, coreApiContext, env, filePaths, deployUI, deployGraphQLServer, commonSecrets, configureMFA) {
159
181
  try {
160
182
  let uiAllowedCallbacksUrls,
161
183
  uiAllowedLogoutUrls;
162
184
  let graphqlAllowedCallbacksUrls,
163
185
  graphqlAllowedLogoutUrls;
186
+ let connectAllowedCallbacksUrls,
187
+ connectlAllowedLogoutUrls;
164
188
 
189
+ let connectClientMetadata,
190
+ connectCallbacks,
191
+ connectAddons;
165
192
  // Configure URLs based on environment
166
193
  if (env === 'prd') {
167
194
  uiAllowedCallbacksUrls = [`${siteUrl}/api/auth/callback`];
@@ -172,8 +199,6 @@ async function templateAuth0(siteUrl, coreApiContext, env, filePaths, deployUI,
172
199
 
173
200
  connectAllowedCallbacksUrls = [`${siteUrl}/connect/samlCallback?client_name=auth0`];
174
201
  connectlAllowedLogoutUrls = [ `${siteUrl}/connect`];
175
-
176
-
177
202
  } else {
178
203
  uiAllowedCallbacksUrls = [
179
204
  `${siteUrl}/api/auth/callback`,
@@ -183,7 +208,6 @@ async function templateAuth0(siteUrl, coreApiContext, env, filePaths, deployUI,
183
208
  `${siteUrl}`,
184
209
  `http://localhost:3000`,
185
210
  ];
186
-
187
211
  graphqlAllowedCallbacksUrls = [
188
212
  `${siteUrl}/api/graphql/callback`,
189
213
  `http://localhost:4000/api/graphql/callback`,
@@ -192,7 +216,6 @@ async function templateAuth0(siteUrl, coreApiContext, env, filePaths, deployUI,
192
216
  `http://localhost:4000/api/graphql/`,
193
217
  `${siteUrl}/api/graphql/`,
194
218
  ];
195
-
196
219
  connectAllowedCallbacksUrls = [
197
220
  `${siteUrl}/connect/samlCallback?client_name=auth0`,
198
221
  `http://localhost:9000/connect/samlCallback?client_name=auth0`,
@@ -200,10 +223,38 @@ async function templateAuth0(siteUrl, coreApiContext, env, filePaths, deployUI,
200
223
  connectlAllowedLogoutUrls = [
201
224
  `${siteUrl}/connect`
202
225
  ];
203
-
204
-
226
+
227
+ const siteUrlNoPrefix=siteUrl.replace(/^https?:\/\//, '');
228
+ connectClientMetadata ={
229
+ "docupaceContext" : "core",
230
+ "docupaceHost" : `${siteUrlNoPrefix}`,
231
+ "docupace_context" : "core",
232
+ "docupace_host" : `${siteUrlNoPrefix} `
233
+ };
234
+
235
+ connectCallbacks = [
236
+ `${siteUrl}/connect/samlCallback?client_name=auth0`
237
+ ];
238
+
239
+ connectAddons = {
240
+ "samlp": {
241
+ "audience": `${siteUrl}/connect`,
242
+ "recipient": `${siteUrl}/connect/samlCallback?client_name=auth0`,
243
+ "destination": `${siteUrl}/connect/samlCallback?client_name=auth0`,
244
+ "nameIdentifierFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
245
+ "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
246
+ "nameIdentifierProbes": [
247
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/docupace-username"
248
+ ],
249
+ "mappings": {
250
+ "proposalHandle": "ProposalHandle"
251
+ }
252
+ }
253
+ };
254
+
205
255
  }
206
256
 
257
+
207
258
  const configureUI = deployUI === 'true';
208
259
  if (configureUI) {
209
260
  console.log('ui_allowed_callbacks_urls ->', uiAllowedCallbacksUrls);
@@ -214,15 +265,21 @@ async function templateAuth0(siteUrl, coreApiContext, env, filePaths, deployUI,
214
265
  allowed_logout_urls: uiAllowedLogoutUrls,
215
266
  });
216
267
 
268
+
217
269
  //TODO: move to separate function for connect
218
270
  console.log('connect_allowed_callbacks_urls ->', connectAllowedCallbacksUrls);
219
- console.log('connect_allowed_logout_urls ->', connectAllowedLogoutUrls);
271
+ console.log('connect_allowed_logout_urls ->', connectlAllowedLogoutUrls);
220
272
 
273
+ // update allowed callback url
221
274
  await updateJsonFile(filePaths.connectJson, {
222
275
  callbacks: connectAllowedCallbacksUrls,
223
- allowed_logout_urls: connectAllowedLogoutUrls,
276
+ allowed_logout_urls: connectlAllowedLogoutUrls,
277
+ client_metadata: connectClientMetadata,
278
+ addons: connectAddons
224
279
  });
225
280
 
281
+
282
+
226
283
  console.log('Updated URLs for main UI...');
227
284
  } else {
228
285
  await fs.promises.unlink(filePaths.uiJson);
@@ -259,28 +316,36 @@ async function templateAuth0(siteUrl, coreApiContext, env, filePaths, deployUI,
259
316
 
260
317
  console.log('TWILIO configuration updated...');
261
318
 
319
+ const tmpSiteUrl = siteUrl.replace(/^https?:\/\//, '');
262
320
  // Database configuration
263
321
  await replaceInFile(filePaths.databaseLoginJs, [
264
- ['${docupaceHost}', siteUrl],
322
+ ['${docupaceHost}', tmpSiteUrl],
265
323
  ['${docupaceContext}', coreApiContext],
266
324
  ]);
267
325
 
268
- // MFA configuration
269
- // if (process.env.AUTH0_MFA === 'ENABLE') {
270
- // console.log('AUTH0 MFA is enabled');
271
- // await execAsync('rsync -av ./auth0template/templateMFA/ ./auth0template/template/');
272
- // } else if (process.env.AUTH0_MFA === 'DISABLE') {
273
- // console.log('AUTH0 MFA is disabled');
274
- // await execAsync('rsync -av ./auth0template/templateNoMFA/ ./auth0template/template/');
275
- // }
326
+ console.log('MFA Template configuration started...');
327
+
328
+ try {
329
+ const sourceDir = configureMFA === 'DISABLED' ? 'auth0-site-setup/templateNoMFA/' : 'auth0-site-setup/templateMFA/';
330
+ const destinationDir = 'auth0-site-setup/template/';
331
+
332
+ console.log(`AUTH0 MFA is ${configureMFA === 'DISABLED' ? 'disabled' : 'enabled'}`);
333
+ await copyDirectory(sourceDir, destinationDir);
334
+
335
+ console.log('MFA configuration completed.');
336
+ } catch (err) {
337
+ console.error('Error configuring MFA:', err);
338
+ throw err;
339
+ }
276
340
 
277
341
  console.log('Template configuration completed.');
278
342
  } catch (err) {
279
- console.error('Error configuring Auth0 templates:', err);
343
+ // console.error('Error configuring Auth0 templates:', err);
344
+ throw err;
280
345
  }
281
346
  }
282
347
 
283
- async function getAuth0AuthToken(auth0Domain, clientId, clientSecret) {
348
+ export async function getAuth0AuthToken(auth0Domain, clientId, clientSecret) {
284
349
  try {
285
350
  const response = await axios.post(`https://${auth0Domain}/oauth/token`, {
286
351
  client_id: clientId,
@@ -487,6 +552,7 @@ graphqlServer:
487
552
  env:
488
553
  AUTH0_CLIENT_SECRET: vault:secret/data/${site}/graphql-server/config#AUTH0_CLIENT_SECRET
489
554
  STANDARD_CONFIG_REMOTE_PATH: vault:secret/data/common/config#STANDARD_CONFIG_REMOTE_PATH
555
+ SITE_CONFIG_REMOTE_PATH: vault:secret/data/${site}/common/config#SITE_CONFIG_REMOTE_PATH
490
556
  AUTH0_CC_CLIENT_ID: vault:secret/data/${site}/graphql-server/config#AUTH0_CC_CLIENT_ID
491
557
  AUTH0_CC_CLIENT_SECRET: vault:secret/data/${site}/graphql-server/config#AUTH0_CC_CLIENT_SECRET
492
558
  image:
@@ -539,7 +605,7 @@ ingress:
539
605
  }
540
606
 
541
607
 
542
- export async function configureFromSite(fromSite, toSite, fromEnv,toEnv, deployUI, deployGraphQLServer, useNewDomain) {
608
+ export async function configureFromSite(fromSite, toSite, fromEnv,toEnv, deployUI, deployGraphQLServer, useNewDomain, configureMFA) {
543
609
  console.log(`Configuring Auth0 tenants and ArgoCD apps for site: ${toSite} in env: ${toEnv} from site: ${fromSite}`);
544
610
  // Common Secrets
545
611
  const commonSecretsPath = getVaultSecretsConfigs(toSite).commonSecretsPath;
@@ -575,7 +641,6 @@ export async function configureFromSite(fromSite, toSite, fromEnv,toEnv, deployU
575
641
  repoPathToEnv = await cloneEnvRepository(toEnv);
576
642
  }
577
643
 
578
-
579
644
  //TODO: clone fromEnv and toEnv. replace above with this
580
645
 
581
646
  const auth0RepoPath = await cloneRepository('auth0-site-setup');
@@ -584,13 +649,12 @@ export async function configureFromSite(fromSite, toSite, fromEnv,toEnv, deployU
584
649
  const { deployConfig: deployUIConfig } = await readDeployConfig('ui', fromEnv, fromSite, 'values');
585
650
  const uiImageTag = deployUIConfig.image.tag;
586
651
 
587
- const { deployConfig: deployGraphQLServerConfig} = await readDeployConfig('graphql-server', fromEnv, fromSite, 'values');
652
+ const { deployConfig: deployGraphQLServerConfig } = await readDeployConfig('graphql-server', fromEnv, fromSite, 'values');
588
653
  const graphqlImageTag = deployGraphQLServerConfig.image.tag;
589
654
  const graphqlStandardConfigRemoteBranch = deployGraphQLServerConfig.graphqlServer.standardConfigRemoteBranch;
590
655
 
591
656
  // File paths
592
657
  const filePaths = {
593
- clientJson: './auth0-site-setup/template/clients/docupace-connect.json',
594
658
  databaseLoginJs: './auth0-site-setup/template/database-connections/docupace/login.js',
595
659
  loginHtml: './auth0-site-setup/template/pages/login.html',
596
660
  graphqlJson: './auth0-site-setup/template/clients/docupace-graphql.json',
@@ -625,7 +689,7 @@ export async function configureFromSite(fromSite, toSite, fromEnv,toEnv, deployU
625
689
  CONNECT_URL = `${oldUrl}_ui`;
626
690
  }
627
691
 
628
- await templateAuth0(SITE_HOST, CORE_API_CONTEXT, toEnv, filePaths, deployUI, deployGraphQLServer, commonSecrets);
692
+ await templateAuth0(SITE_HOST, CORE_API_CONTEXT, toEnv, filePaths, deployUI, deployGraphQLServer, commonSecrets, configureMFA);
629
693
  await importAuth0Templates('./auth0-site-setup/template', auth0Domain, auth0ClientId, auth0ClientSecret);
630
694
 
631
695
  if (deployUI === 'true') {
@@ -648,4 +712,4 @@ export async function configureFromSite(fromSite, toSite, fromEnv,toEnv, deployU
648
712
  auth0AuthToken: auth0Token,
649
713
  coreApiIdentifier: commonSecrets.CORE_API_IDENTIFIER
650
714
  })
651
- }
715
+ }
@@ -0,0 +1,53 @@
1
+ import { BasicAuth, DomainApi } from '@docupace/core-client';
2
+
3
+ const userFilter = (userId) => {
4
+ return {
5
+ orSections: [
6
+ {
7
+ andSections: [
8
+ {
9
+ attrId: 9501,
10
+ '@type': 'string',
11
+ not: false,
12
+ orSections: [
13
+ { searchType: 'EXACT_MATCH', matchToValues: [userId] },
14
+ ],
15
+ },
16
+ ],
17
+ },
18
+ ],
19
+ };
20
+ };
21
+
22
+ /*
23
+ Example:
24
+ await createAlias(
25
+ 'https://www.dev.docupaceinc.com/financialdev',
26
+ 'docupace',
27
+ 'pw',
28
+ 'Connect',
29
+ 'qhnospjRjwUAeKFDhucHEabPsfihrGQQ@clients',
30
+ );
31
+ */
32
+ export async function createAlias(coreUrl, username, password, realm, alias) {
33
+ const coreInfo = {
34
+ url: coreUrl,
35
+ };
36
+
37
+ let auth = new BasicAuth(username, password);
38
+
39
+ const domainApi = new DomainApi(coreInfo, auth);
40
+
41
+ const userResults = await domainApi.listRecords(50, {
42
+ filter: JSON.stringify(userFilter(username)),
43
+ });
44
+
45
+ const record = {
46
+ domainId: 302,
47
+ '5001': userResults.records[0].id,
48
+ '9102': realm,
49
+ '9504': alias,
50
+ };
51
+
52
+ await domainApi.create(record);
53
+ }
package/src/next/cli.js CHANGED
@@ -9,7 +9,7 @@ import { deployTemplate } from './deploy.js';
9
9
  import { copy } from './copy.js';
10
10
  import { vaultAddSiteData } from './vault.js';
11
11
  import { addApacheSite } from './apache.js';
12
- import { haproxySync } from './haproxy.js';
12
+ import { haproxySync } from './haproxy.js';
13
13
  import { connectClone } from './connect.js';
14
14
  import dotenv from 'dotenv';
15
15
 
@@ -17,9 +17,8 @@ dotenv.config({ path: ['.env.pipeline.local', 'config/.env.pipeline.local'] });
17
17
 
18
18
  const program = new Command();
19
19
 
20
- // GIT SHA computation
21
20
  import { $ } from 'zx';
22
- import {deployConnect, deployCore} from './jenkins.js';
21
+ import { deployConnect, deployCore } from './jenkins.js';
23
22
  import { runPipeline } from './pipline.js';
24
23
 
25
24
  const GIT_SHA = (await $`git log --pretty=format:'%h' -n 1`).stdout.trim();
@@ -39,36 +38,37 @@ program
39
38
  });
40
39
 
41
40
  program
42
- .command('addApacheSite')
43
- .description('Add site to apache')
44
- .action(async () => {
45
- await addApacheSite();
46
- });
41
+ .command('addApacheSite')
42
+ .description('Add site to apache')
43
+ .action(async () => {
44
+ await addApacheSite();
45
+ });
47
46
 
48
47
  program
49
- .command('connectClone')
50
- .description('Clone connect site')
51
- .action(async () => {
52
- await connectClone();
53
- });
54
-
48
+ .command('connectClone')
49
+ .description('Clone connect site')
50
+ .action(async () => {
51
+ await connectClone();
52
+ });
55
53
 
56
54
  program
57
- .command('haproxySync')
58
- .description('Sync haproxy config')
59
- .action(async () => {
60
- await haproxySync();
61
- });
62
-
63
-
55
+ .command('haproxySync')
56
+ .description('Sync haproxy config')
57
+ .action(async () => {
58
+ await haproxySync();
59
+ });
64
60
 
65
61
  program
66
62
  .command('vaultAddSiteData')
67
63
  .description('Add m2m auth0 data to vault')
68
64
  .requiredOption('-s, --site-name <siteName>', 'Site name')
65
+ .requiredOption(
66
+ '-p, --site-config-remote-path <siteConfigRemotePath>',
67
+ 'Site Config Remote Path',
68
+ )
69
69
  .action(async (options) => {
70
- const { siteName, } = options;
71
- await vaultAddSiteData(siteName);
70
+ const { siteName, siteConfigRemotePath } = options;
71
+ await vaultAddSiteData(siteName, siteConfigRemotePath);
72
72
  });
73
73
 
74
74
  program
@@ -130,8 +130,7 @@ program
130
130
  });
131
131
  });
132
132
 
133
-
134
- program
133
+ program
135
134
  .command('copy')
136
135
  .description('Copy a Docker image between registries')
137
136
  .requiredOption('-a, --application <application>', 'Application name')
@@ -6,7 +6,6 @@ import lodash from 'lodash';
6
6
  import { appInfo, environmentConfig, getRepUrl } from './config.js';
7
7
  import { copy } from './copy.js';
8
8
  import axios from 'axios';
9
- import { runPipeline } from './pipline.js';
10
9
  import { deployCore } from './jenkins.js';
11
10
 
12
11
  /**
@@ -34,7 +33,7 @@ function cleanUpRepoPath(repoPath) {
34
33
  console.log(`${repoPath} directory exists. Removing it...`);
35
34
  fs.rmSync(repoPath, {
36
35
  recursive: true,
37
- force: true
36
+ force: true,
38
37
  });
39
38
  }
40
39
  }
@@ -43,6 +42,7 @@ export async function cloneEnvRepository(env) {
43
42
  const { repoPath, repoName } = getRepoLocalPath(env);
44
43
  const repoUrl = getRepUrl(repoName);
45
44
  console.log(`Cloning repository: ${repoName}`);
45
+ await cleanUpRepoPath(repoPath);
46
46
  await $`git clone --depth 1 ${repoUrl}`;
47
47
  console.log(`Repository cloned to: ${repoPath}`);
48
48
  return repoPath;
@@ -52,7 +52,7 @@ export async function cloneRepository(repoSlug) {
52
52
  const { repoPath, repoName } = getRepoLocalPathByRepoSlug(repoSlug);
53
53
  const repoUrl = getRepUrl(repoName);
54
54
 
55
- await cleanUpRepoPath(repoPath)
55
+ await cleanUpRepoPath(repoPath);
56
56
 
57
57
  console.log(`Cloning repository: ${repoName}`);
58
58
  await $`git clone --depth 1 ${repoUrl}`;
@@ -70,6 +70,24 @@ function getConfigPath(application, env, site, name) {
70
70
  return { repoPath, deployConfigFilePath };
71
71
  }
72
72
 
73
+ function getAppTypesFromRepo(env, site) {
74
+ const { repoPath } = getRepoLocalPath(env);
75
+ const deployConfigFilePath = path.join(repoPath, `dp/${site}`);
76
+
77
+ const applications = [];
78
+ if (fs.existsSync(deployConfigFilePath)) {
79
+ const files = fs.readdirSync(deployConfigFilePath);
80
+ files.forEach((file) => {
81
+ if (file.includes('.values.yaml')) {
82
+ const appName = file.split('.')[0];
83
+ applications.push(appName);
84
+ }
85
+ });
86
+ }
87
+
88
+ return { applications };
89
+ }
90
+
73
91
  export async function readDeployConfig(application, env, site, name) {
74
92
  const { deployConfigFilePath } = getConfigPath(application, env, site, name);
75
93
 
@@ -265,6 +283,60 @@ async function getCoreBranchName(fromEnv, fromSite) {
265
283
  return branchName;
266
284
  }
267
285
 
286
+ export async function deployApp(
287
+ application,
288
+ appDetails,
289
+ fromEnv,
290
+ fromSite,
291
+ toEnv,
292
+ toSite,
293
+ ) {
294
+ let changesMade = false;
295
+ console.log(`Processing application: ${application}`);
296
+
297
+ // Read the deployment configuration for the source environment and site
298
+ const { deployConfig: fromDeployConfig } = await readDeployConfig(
299
+ application,
300
+ fromEnv,
301
+ fromSite,
302
+ 'values',
303
+ );
304
+
305
+ if (fromEnv !== toEnv) {
306
+ await copy(application, fromEnv, toEnv, fromDeployConfig.image.tag);
307
+ }
308
+
309
+ // Read the deployment configuration for the target environment and site
310
+ const {
311
+ deployConfig: toDeployConfig,
312
+ deployConfigFilePath: toDeployConfigFilePath,
313
+ } = await readDeployConfig(application, toEnv, toSite, 'values');
314
+
315
+ // Update target configuration using attributes specified in appInfo
316
+ for (const attribute of appDetails.deployAttributes) {
317
+ const sourceValue = lodash.get(fromDeployConfig, attribute);
318
+
319
+ if (sourceValue !== undefined) {
320
+ // Update the target configuration with the source value
321
+ lodash.set(toDeployConfig, attribute, sourceValue);
322
+ changesMade = true;
323
+ }
324
+ }
325
+
326
+ const {
327
+ deployConfig: toDeployAppConfig,
328
+ deployConfigFilePath: toDeployAppConfigFilePath,
329
+ } = await readDeployConfig(application, toEnv, toSite, 'app');
330
+
331
+ toDeployAppConfig.revision = fromDeployConfig.image.tag;
332
+
333
+ // Write updated configuration to the target YAML file
334
+ writeDeployConfig(toDeployConfigFilePath, toDeployConfig);
335
+
336
+ writeDeployConfig(toDeployAppConfigFilePath, toDeployAppConfig);
337
+ return changesMade;
338
+ }
339
+
268
340
  export async function deployFromSite(
269
341
  fromEnv,
270
342
  fromSite,
@@ -294,52 +366,47 @@ export async function deployFromSite(
294
366
 
295
367
  // Initialize a flag to track changes
296
368
  let changesMade = false;
297
-
369
+ const applications = await getAppTypesFromRepo(fromEnv, fromSite);
298
370
  // Iterate over applications in appInfo
299
- for (const [application, appDetails] of Object.entries(appInfo)) {
300
- console.log(`Processing application: ${application}`);
371
+ let appInfoLocal = {};
372
+ // let appInfoLocal = Object.fromEntries(
373
+ // applications
374
+ // .filter((application) => appInfo[application])
375
+ // .map((application) => [application, appInfo[application]]),
376
+ // );
377
+
378
+ for (const application of applications) {
379
+ if (Object.prototype.hasOwnProperty.call(appInfo, application)) {
380
+ appInfoLocal[application] = appInfo[application];
381
+ }
382
+ }
301
383
 
302
- // Read the deployment configuration for the source environment and site
303
- const { deployConfig: fromDeployConfig } = await readDeployConfig(
304
- application,
305
- fromEnv,
384
+ if (Object.keys(appInfoLocal).length === 0) {
385
+ const { deployConfig: toDeployAppConfig } = await readDeployConfig(
306
386
  fromSite,
307
- 'values',
387
+ toEnv,
388
+ toSite,
389
+ 'app',
308
390
  );
309
391
 
310
- if (fromEnv !== toEnv) {
311
- await copy(application, fromEnv, toEnv, fromDeployConfig.image.tag);
312
- }
313
-
314
- // Read the deployment configuration for the target environment and site
315
- const {
316
- deployConfig: toDeployConfig,
317
- deployConfigFilePath: toDeployConfigFilePath,
318
- } = await readDeployConfig(application, toEnv, toSite, 'values');
319
-
320
- // Update target configuration using attributes specified in appInfo
321
- for (const attribute of appDetails.deployAttributes) {
322
- const sourceValue = lodash.get(fromDeployConfig, attribute);
392
+ appInfoLocal[fromSite] = {
393
+ repositoryName: toDeployAppConfig.repo,
394
+ deployAttributes: ['image.tag'],
395
+ };
396
+ }
323
397
 
324
- if (sourceValue !== undefined) {
325
- // Update the target configuration with the source value
326
- lodash.set(toDeployConfig, attribute, sourceValue);
327
- changesMade = true;
328
- }
398
+ for (const [application, appDetails] of Object.entries(appInfo)) {
399
+ let cm = await deployApp(
400
+ application,
401
+ appDetails,
402
+ fromEnv,
403
+ fromSite,
404
+ toEnv,
405
+ toSite,
406
+ );
407
+ if (cm) {
408
+ changesMade = true;
329
409
  }
330
-
331
- const {
332
- deployConfig: toDeployAppConfig,
333
- deployConfigFilePath: toDeployAppConfigFilePath,
334
- } = await readDeployConfig(application, toEnv, toSite, 'app');
335
-
336
- toDeployAppConfig.revision = fromDeployConfig.image.tag;
337
-
338
- // Write updated configuration to the target YAML file
339
- writeDeployConfig(toDeployConfigFilePath, toDeployConfig);
340
-
341
- writeDeployConfig(toDeployAppConfigFilePath, toDeployAppConfig);
342
-
343
410
  }
344
411
 
345
412
  // Push all changes if any updates were made
package/src/next/vault.js CHANGED
@@ -1,39 +1,43 @@
1
1
  import axios from 'axios';
2
2
 
3
- export async function vaultAddSiteData(SITE) {
4
- const AUTH0_CLIENT_ID = process.env.AUTH0_CLIENT_ID;
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
3
+ export async function vaultAddSiteData(SITE, SITE_CONFIG_REMOTE_PATH) {
4
+ const AUTH0_CLIENT_ID = process.env.AUTH0_CLIENT_ID;
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
8
8
 
9
- if (!VAULT_ADDR || !VAULT_TOKEN) {
10
- throw new Error('Missing VAULT_ADDR or VAULT_TOKEN environment variable.');
11
- }
9
+ if (!VAULT_ADDR || !VAULT_TOKEN) {
10
+ throw new Error('Missing VAULT_ADDR or VAULT_TOKEN environment variable.');
11
+ }
12
12
 
13
- const vaultApiUrl = `${VAULT_ADDR}/v1/secret/data/${SITE}/common/config`;
13
+ const vaultApiUrl = `${VAULT_ADDR}/v1/secret/data/${SITE}/common/config`;
14
14
 
15
- try {
16
- const response = await axios.post(
17
- vaultApiUrl,
18
- {
19
- data: {
20
- AUTH0_CLIENT_ID: AUTH0_CLIENT_ID,
21
- AUTH0_CLIENT_SECRET: AUTH0_CLIENT_SECRET,
22
- },
23
- },
24
- {
25
- headers: {
26
- 'X-Vault-Token': VAULT_TOKEN,
27
- 'Content-Type': 'application/json',
28
- },
29
- }
30
- );
15
+ try {
31
16
 
32
- console.log('Data added to Vault successfully:', response.data);
33
- } catch (error) {
34
- console.error('Error adding data to Vault:', error.response?.data || error.message);
35
- throw error;
17
+ if (process.env.VAULT_SKIP_VERIFY === 'true') {
18
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
36
19
  }
37
- }
38
20
 
21
+ const response = await axios.post(
22
+ vaultApiUrl,
23
+ {
24
+ data: {
25
+ AUTH0_CLIENT_ID: AUTH0_CLIENT_ID,
26
+ AUTH0_CLIENT_SECRET: AUTH0_CLIENT_SECRET,
27
+ SITE_CONFIG_REMOTE_PATH: SITE_CONFIG_REMOTE_PATH,
28
+ },
29
+ },
30
+ {
31
+ headers: {
32
+ 'X-Vault-Token': VAULT_TOKEN,
33
+ 'Content-Type': 'application/json',
34
+ },
35
+ }
36
+ );
39
37
 
38
+ console.log('Data added to Vault successfully:', response.data);
39
+ } catch (error) {
40
+ console.error('Error adding data to Vault:', error.response?.data || error.message);
41
+ throw error;
42
+ }
43
+ }
package/terraform/init.sh CHANGED
@@ -33,4 +33,16 @@ echo "$atlassian_workspace_runner_ssh_key" | base64 -d > ~/.ssh/id_ed25519
33
33
  chmod 600 ~/.ssh/id_ed25519
34
34
  ssh-keyscan bitbucket.org > ~/.ssh/known_hosts
35
35
 
36
- terraform init -backend-config=./env/${CURRENT_ENVIRONMENT}/us-west-2/backend.tfvars --reconfigure
36
+
37
+
38
+ if [[ "$PROJECT" == "s3" ]]; then
39
+ terraform init \
40
+ -input=false \
41
+ -reconfigure \
42
+ -backend=true \
43
+ -backend-config=./env/${CURRENT_ENVIRONMENT}/us-west-2/backend.tfvars \
44
+ -backend-config="key=us-west-2/${PROJECT}/${SITE_NAME}/${CURRENT_ENVIRONMENT}/terraform.tfstate"
45
+
46
+ else
47
+ terraform init -backend-config=./env/${CURRENT_ENVIRONMENT}/us-west-2/backend.tfvars --reconfigure
48
+ fi
package/terraform/plan.sh CHANGED
@@ -39,6 +39,16 @@ if [[ "$PROJECT" == "bb-build-agent-shell" ]]; then
39
39
  terraform plan -var-file="./env/${CURRENT_ENVIRONMENT}/us-west-2/terraform.tfvars" \
40
40
  -var-file="./env/${CURRENT_ENVIRONMENT}/us-west-2/build_agent_configuration.tfvars.json" \
41
41
  -out .tfplan
42
+ elif [[ "$PROJECT" == "s3" ]];then
43
+ terraform plan -var-file="./env/${CURRENT_ENVIRONMENT}/us-west-2/terraform.tfvars" \
44
+ -var="site=${SITE_NAME}" \
45
+ -var="env=${CURRENT_ENVIRONMENT}" \
46
+ -out .tfplan
42
47
  else
43
48
  terraform plan -var-file="./env/${CURRENT_ENVIRONMENT}/us-west-2/terraform.tfvars" -out .tfplan
44
49
  fi
50
+
51
+
52
+
53
+
54
+
@@ -14,4 +14,4 @@ cd "$BITBUCKET_CLONE_DIR/${PROJECT}"
14
14
  terraform version
15
15
  terraform init -backend=false
16
16
  terraform validate
17
- terraform fmt -check -recursive --diff
17
+ terraform fmt -check -recursive --diff || exit 0