@docupace/pipeline 1.0.39-matttest.23 → 1.0.39-matttest.25
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 +4 -2
- package/src/auth0/configure.js +4 -4
- package/src/auth0/metadata.js +1 -2
- package/src/changeset/cli.js +59 -220
- package/src/changeset/create.js +182 -0
- package/src/changeset/util.js +27 -0
- package/src/changeset/validate.js +25 -24
- package/src/changeset/version.js +89 -0
- package/src/jenkins/setParams.groovy +1 -2
- package/src/next/apache.js +38 -35
- package/src/next/cli.js +4 -6
- package/src/next/deploy.js +1 -1
- package/src/next/haproxy.js +25 -26
- package/src/next/jira.js +1 -6
- package/src/next/publish.js +4 -3
- package/src/next/util.js +34 -26
- package/src/next/vault.js +7 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docupace/pipeline",
|
|
3
|
-
"version": "1.0.39-matttest.
|
|
3
|
+
"version": "1.0.39-matttest.25",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"commander": "^12.1.0",
|
|
24
24
|
"dotenv": "^16.4.7",
|
|
25
25
|
"fs-extra": "^11.3.0",
|
|
26
|
+
"inquirer": "^12.6.1",
|
|
26
27
|
"js-yaml": "^4.1.0",
|
|
27
28
|
"lodash": "^4.17.21",
|
|
28
29
|
"openai": "^4.76.3",
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
"test-deploy-core": "dp-next-cli deploy-core-pipeline dev template",
|
|
43
44
|
"test-deploy-from-site": "dp-next-cli deploy-from-site --from-env dev --to-env dev --from-site financialdev --to-site template --deploy-core true",
|
|
44
45
|
"test-run-pipline": "dp-next-cli run-pipeline -r docupace-next-e2e -b master -p run-tests-qa",
|
|
45
|
-
"test-validate": "dp-changset-cli validate"
|
|
46
|
+
"test-validate": "dp-changset-cli validate",
|
|
47
|
+
"test-create": "dp-changset-cli create-changeset"
|
|
46
48
|
}
|
|
47
49
|
}
|
package/src/auth0/configure.js
CHANGED
|
@@ -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) {
|
package/src/auth0/metadata.js
CHANGED
|
@@ -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 {
|
package/src/changeset/cli.js
CHANGED
|
@@ -1,146 +1,71 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { $ } from 'zx';
|
|
4
|
-
import path from 'path';
|
|
5
4
|
import { validateChangesets } from './validate.js';
|
|
6
|
-
import fs from 'fs';
|
|
7
|
-
import OpenAI from 'openai';
|
|
8
|
-
import { zodResponseFormat } from 'openai/helpers/zod';
|
|
9
|
-
import z from 'zod';
|
|
10
5
|
import dotenv from 'dotenv';
|
|
11
|
-
import {
|
|
6
|
+
import { isMonoRepo, setGitInfo } from '../next/util.js';
|
|
7
|
+
import { updateJiraWithVersion, versionCommand } from './version.js';
|
|
8
|
+
import { createChangeset } from './create.js';
|
|
9
|
+
|
|
12
10
|
dotenv.config({ path: ['.env.pipeline.local', 'config/.env.pipeline.local'] });
|
|
13
|
-
import { setGitInfo } from '../next/util.js';
|
|
14
11
|
|
|
15
12
|
const program = new Command();
|
|
16
13
|
|
|
17
14
|
const args = process.argv;
|
|
18
15
|
|
|
19
|
-
async function
|
|
20
|
-
|
|
21
|
-
// Use path.join to build a safe path to `.changeset`
|
|
22
|
-
const targetDir = path.join(process.cwd(), '.changeset');
|
|
16
|
+
async function commitTagCommand(releases) {
|
|
17
|
+
console.log('📌 Checking for updates to commit...');
|
|
23
18
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
console.
|
|
19
|
+
// Check if there are changes to commit
|
|
20
|
+
const status = (await $`git status --porcelain`).stdout.trim();
|
|
21
|
+
if (!status) {
|
|
22
|
+
console.log('✅ No changes to commit. Exiting.');
|
|
23
|
+
return;
|
|
28
24
|
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function run(command) {
|
|
32
|
-
return new Promise((resolve, reject) => {
|
|
33
|
-
exec(command, { shell: true }, (error, stdout, stderr) => {
|
|
34
|
-
if (error) {
|
|
35
|
-
reject(error);
|
|
36
|
-
} else {
|
|
37
|
-
resolve({ stdout, stderr });
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
25
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return true;
|
|
47
|
-
} catch {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
26
|
+
console.log('📌 Committing and tagging the new version...');
|
|
27
|
+
await setGitInfo();
|
|
28
|
+
await $`git add .`;
|
|
51
29
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (await fileExists(packageJsonPath)) {
|
|
57
|
-
const fileContent = await fs.promises.readFile(packageJsonPath, 'utf-8');
|
|
58
|
-
const packageJson = JSON.parse(fileContent);
|
|
59
|
-
return packageJson;
|
|
60
|
-
}
|
|
30
|
+
if (isMonoRepo()) {
|
|
31
|
+
await commitTagMono(releases);
|
|
32
|
+
} else {
|
|
33
|
+
await commitTag();
|
|
61
34
|
}
|
|
62
|
-
throw new Error('Main package.json not found');
|
|
63
35
|
}
|
|
64
36
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
},
|
|
71
|
-
"type": "module",
|
|
72
|
-
"keywords": [],
|
|
73
|
-
"author": "",
|
|
74
|
-
"license": "ISC",
|
|
75
|
-
"dependencies": {},
|
|
76
|
-
"devDependencies": {
|
|
77
|
-
"@changesets/cli": "^2.27.10"
|
|
78
|
-
}
|
|
37
|
+
export function getAppReleases(releases) {
|
|
38
|
+
const appReleases = releases.filter((release) =>
|
|
39
|
+
release.name.endsWith('-app'),
|
|
40
|
+
);
|
|
41
|
+
return appReleases;
|
|
79
42
|
}
|
|
80
|
-
`;
|
|
81
|
-
|
|
82
|
-
async function versionCommand(closeVersion = false) {
|
|
83
|
-
console.log('📦 Running Changeset versioning...');
|
|
84
|
-
await setGitInfo();
|
|
85
|
-
await $`mv package.json package.json.bak`;
|
|
86
|
-
await $`mv pnpm-lock.yaml pnpm-lock.yaml.bak`;
|
|
87
|
-
await fs.promises.writeFile('package.json', changeSetPackage);
|
|
88
|
-
await $`pnpm install`;
|
|
89
|
-
await $`rm package.json pnpm-lock.yaml`;
|
|
90
|
-
await $`mv package.json.bak package.json`;
|
|
91
|
-
await $`mv pnpm-lock.yaml.bak pnpm-lock.yaml`;
|
|
92
|
-
if (closeVersion) {
|
|
93
|
-
await $`pnpm changeset pre exit`;
|
|
94
|
-
}
|
|
95
43
|
|
|
96
|
-
|
|
44
|
+
function getAppNameFromPackageName(packageName) {
|
|
45
|
+
const appName = packageName.includes('/')
|
|
46
|
+
? packageName.split('/')[1]
|
|
47
|
+
: packageName;
|
|
97
48
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
await fs.promises.readFile('package.json', 'utf-8'),
|
|
101
|
-
);
|
|
102
|
-
const version = packageJson.version;
|
|
103
|
-
const packageName = packageJson.name;
|
|
49
|
+
return appName;
|
|
50
|
+
}
|
|
104
51
|
|
|
105
|
-
|
|
106
|
-
|
|
52
|
+
async function commitTagMono(releases) {
|
|
53
|
+
let versions = [];
|
|
54
|
+
for (const release of getAppReleases(releases)) {
|
|
55
|
+
const newVersion = release.newVersion;
|
|
56
|
+
const appName = getAppNameFromPackageName(release.name);
|
|
57
|
+
versions.push(`${appName}@${newVersion}`);
|
|
107
58
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const jiraTicketMatch = lastCommit.match(/([A-Z]+-\d+)/);
|
|
114
|
-
const jiraTicketId = jiraTicketMatch ? jiraTicketMatch[0] : null;
|
|
115
|
-
|
|
116
|
-
// If we have all the necessary data, update the component version in Jira
|
|
117
|
-
if (jiraTicketId && version && packageName) {
|
|
118
|
-
try {
|
|
119
|
-
await updateComponentVersion(jiraTicketId, packageName, version);
|
|
120
|
-
} catch (error) {
|
|
121
|
-
console.error(
|
|
122
|
-
`Failed to update Jira component version: ${error.message}`,
|
|
123
|
-
);
|
|
124
|
-
}
|
|
59
|
+
await $`git commit -m "Version bump to ${versions.join(',')} and changelog"`;
|
|
60
|
+
for (const newVersion of versions) {
|
|
61
|
+
await $`git tag v${newVersion}`;
|
|
62
|
+
console.log(`✅ Version ${newVersion} tagged.`);
|
|
125
63
|
}
|
|
126
|
-
|
|
127
|
-
console.log(
|
|
128
|
-
return { version, packageName };
|
|
64
|
+
await $`git push origin --tags`;
|
|
65
|
+
console.log(`✅ Version pushed.`);
|
|
129
66
|
}
|
|
130
67
|
|
|
131
|
-
async function
|
|
132
|
-
console.log('📌 Checking for updates to commit...');
|
|
133
|
-
|
|
134
|
-
// Check if there are changes to commit
|
|
135
|
-
const status = (await $`git status --porcelain`).stdout.trim();
|
|
136
|
-
if (!status) {
|
|
137
|
-
console.log('✅ No changes to commit. Exiting.');
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
console.log('📌 Committing and tagging the new version...');
|
|
142
|
-
await setGitInfo();
|
|
143
|
-
await $`git add .`;
|
|
68
|
+
async function commitTag() {
|
|
144
69
|
const newVersion = (
|
|
145
70
|
await $`node -p "require('./package.json').version"`
|
|
146
71
|
).stdout.trim();
|
|
@@ -163,7 +88,7 @@ program
|
|
|
163
88
|
try {
|
|
164
89
|
await validateChangesets();
|
|
165
90
|
console.log('✅ Changeset validation passed.');
|
|
166
|
-
} catch
|
|
91
|
+
} catch {
|
|
167
92
|
console.error(
|
|
168
93
|
'❌ 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',
|
|
169
94
|
);
|
|
@@ -192,8 +117,9 @@ program
|
|
|
192
117
|
.description('Run versioning and commit-and-tag in sequence')
|
|
193
118
|
.action(async () => {
|
|
194
119
|
console.log('📦 Running all steps...');
|
|
195
|
-
await versionCommand();
|
|
196
|
-
await
|
|
120
|
+
const releases = await versionCommand();
|
|
121
|
+
await updateJiraWithVersion(releases);
|
|
122
|
+
await commitTagCommand(releases);
|
|
197
123
|
});
|
|
198
124
|
|
|
199
125
|
program
|
|
@@ -201,15 +127,21 @@ program
|
|
|
201
127
|
.description('Closes a version')
|
|
202
128
|
.action(async () => {
|
|
203
129
|
console.log('📦 Running all steps...');
|
|
204
|
-
const
|
|
205
|
-
await commitTagCommand();
|
|
130
|
+
const releases = await versionCommand(true);
|
|
131
|
+
await commitTagCommand(releases);
|
|
206
132
|
|
|
207
|
-
// Get current branch
|
|
208
133
|
const { stdout: currentBranch } = await $`git rev-parse --abbrev-ref HEAD`;
|
|
209
134
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
135
|
+
if (isMonoRepo()) {
|
|
136
|
+
for (const release of getAppReleases(releases)) {
|
|
137
|
+
const appName = getAppNameFromPackageName(release.name);
|
|
138
|
+
await $`git checkout -b release/${appName}/${release.newVersion}`;
|
|
139
|
+
await $`git push origin release/${appName}/${release.newVersion}`;
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
await $`git checkout -b release/${releases[0].newVersion}`;
|
|
143
|
+
await $`git push origin release/${releases[0].newVersion}`;
|
|
144
|
+
}
|
|
213
145
|
|
|
214
146
|
// Return to original branch
|
|
215
147
|
await $`git checkout ${currentBranch.trim()}`;
|
|
@@ -227,100 +159,7 @@ program
|
|
|
227
159
|
'Creates a changeset based on the current branch and Jira ticket information',
|
|
228
160
|
)
|
|
229
161
|
.action(async () => {
|
|
230
|
-
|
|
231
|
-
const componentName = mainPackage.name;
|
|
232
|
-
|
|
233
|
-
try {
|
|
234
|
-
// Step 1: Get the current branch name
|
|
235
|
-
const branchName = (await $`git branch --show-current`).stdout.trim();
|
|
236
|
-
console.log(`Current branch: ${branchName}`);
|
|
237
|
-
|
|
238
|
-
// Step 2: Extract Jira ticket number (e.g., matching JIRA-1234 pattern)
|
|
239
|
-
const jiraTicketMatch = branchName.match(/([A-Z]+-\d+)/);
|
|
240
|
-
if (!jiraTicketMatch) {
|
|
241
|
-
throw new Error('No Jira ticket found in the branch name.');
|
|
242
|
-
}
|
|
243
|
-
const jiraTicketId = jiraTicketMatch[0];
|
|
244
|
-
|
|
245
|
-
const jiraBaseUrl = 'https://docupacellc.atlassian.net';
|
|
246
|
-
const jiraEmail = process.env.JIRA_API_EMAIL;
|
|
247
|
-
const jiraApiKey = process.env.JIRA_API_KEY;
|
|
248
|
-
const jiraFullApiKey = `${jiraEmail}:${jiraApiKey}`;
|
|
249
|
-
const jiraUrl = `${jiraBaseUrl}/rest/api/2/issue/${jiraTicketId}`;
|
|
250
|
-
const jiraResponse = await fetch(jiraUrl, {
|
|
251
|
-
headers: {
|
|
252
|
-
Authorization: `Basic ${Buffer.from(jiraFullApiKey).toString('base64')}`,
|
|
253
|
-
'Content-Type': 'application/json',
|
|
254
|
-
},
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
if (!jiraResponse.ok) {
|
|
258
|
-
throw new Error(
|
|
259
|
-
`Failed to fetch Jira ticket. Status: ${jiraResponse.status}`,
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
const jiraTicketData = await jiraResponse.json();
|
|
263
|
-
|
|
264
|
-
const jiraSummary = jiraTicketData.fields.summary;
|
|
265
|
-
|
|
266
|
-
console.log(
|
|
267
|
-
`Generating release notes for ${jiraTicketId} - ${jiraSummary}`,
|
|
268
|
-
);
|
|
269
|
-
|
|
270
|
-
const openaiClient = new OpenAI({
|
|
271
|
-
apiKey: process.env['OPENAI_API_KEY'],
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
const ChangeRequestSchema = z.object({
|
|
275
|
-
change_type: z.enum(['patch', 'minor']),
|
|
276
|
-
summary: z.string(),
|
|
277
|
-
jira_ticket_id: z.string(),
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
const openAiResponse = await openaiClient.chat.completions.create({
|
|
281
|
-
model: 'gpt-4o-mini',
|
|
282
|
-
messages: [
|
|
283
|
-
{
|
|
284
|
-
role: 'system',
|
|
285
|
-
content: `Process JSON from a Jira ticket to generate simple maximum 2 sentence release note for the ticket and determine the change type for bug it should be a patch for new feature it should be a minor change`,
|
|
286
|
-
},
|
|
287
|
-
{
|
|
288
|
-
role: 'user',
|
|
289
|
-
content: JSON.stringify(jiraTicketData),
|
|
290
|
-
},
|
|
291
|
-
],
|
|
292
|
-
response_format: zodResponseFormat(
|
|
293
|
-
ChangeRequestSchema,
|
|
294
|
-
'changeset_schema',
|
|
295
|
-
),
|
|
296
|
-
temperature: 0,
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
const assistantResponse = openAiResponse.choices[0].message.content;
|
|
300
|
-
const parsedResponse = JSON.parse(assistantResponse);
|
|
301
|
-
|
|
302
|
-
const { change_type, summary } = parsedResponse;
|
|
303
|
-
console.log(`Change type: ${change_type}`);
|
|
304
|
-
console.log(`Release note: ${summary}`);
|
|
305
|
-
|
|
306
|
-
// Step 5: Create a changeset .md file
|
|
307
|
-
const changesetContent = `---
|
|
308
|
-
"${componentName}": ${change_type}
|
|
309
|
-
---
|
|
310
|
-
|
|
311
|
-
${summary} [${jiraTicketId}]
|
|
312
|
-
`;
|
|
313
|
-
const changesetFile = `./.changeset/${jiraTicketId}.md`;
|
|
314
|
-
|
|
315
|
-
await createChangesetDirectory();
|
|
316
|
-
await fs.promises.writeFile(changesetFile, changesetContent);
|
|
317
|
-
console.log(`Created changeset file at ${changesetFile}`);
|
|
318
|
-
|
|
319
|
-
console.log('Done!');
|
|
320
|
-
} catch (err) {
|
|
321
|
-
console.error(`Error: ${err.message}`);
|
|
322
|
-
process.exit(1);
|
|
323
|
-
}
|
|
162
|
+
await createChangeset();
|
|
324
163
|
});
|
|
325
164
|
|
|
326
165
|
// Parse arguments
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { $ } from 'zx';
|
|
2
|
+
import OpenAI from 'openai';
|
|
3
|
+
import z from 'zod';
|
|
4
|
+
import { zodResponseFormat } from 'openai/helpers/zod';
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { getAllAppPackages, isMonoRepo } from '../next/util.js';
|
|
8
|
+
import inquirer from 'inquirer';
|
|
9
|
+
import { getMainPackage, getPackage } from './util.js';
|
|
10
|
+
|
|
11
|
+
async function createChangesetDirectory() {
|
|
12
|
+
try {
|
|
13
|
+
// Use path.join to build a safe path to `.changeset`
|
|
14
|
+
const targetDir = path.join(process.cwd(), '.changeset');
|
|
15
|
+
|
|
16
|
+
// Create the directory recursively if it doesn't exist
|
|
17
|
+
await fs.promises.mkdir(targetDir, { recursive: true });
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.error('Error creating .changeset directory:', error);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Gets the current git branch name
|
|
25
|
+
*/
|
|
26
|
+
async function getCurrentBranch() {
|
|
27
|
+
const branchName = (await $`git branch --show-current`).stdout.trim();
|
|
28
|
+
console.log(`Current branch: ${branchName}`);
|
|
29
|
+
return branchName;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Extracts a Jira ticket ID from a branch name
|
|
34
|
+
*/
|
|
35
|
+
function extractJiraTicketId(branchName) {
|
|
36
|
+
const jiraTicketMatch = branchName.match(/([A-Z]+-\d+)/);
|
|
37
|
+
if (!jiraTicketMatch) {
|
|
38
|
+
throw new Error('No Jira ticket found in the branch name.');
|
|
39
|
+
}
|
|
40
|
+
return jiraTicketMatch[0];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Fetches Jira ticket data from Jira API
|
|
45
|
+
*/
|
|
46
|
+
async function fetchJiraTicketData(jiraTicketId) {
|
|
47
|
+
const jiraBaseUrl = 'https://docupacellc.atlassian.net';
|
|
48
|
+
const jiraEmail = process.env.JIRA_API_EMAIL;
|
|
49
|
+
const jiraApiKey = process.env.JIRA_API_KEY;
|
|
50
|
+
const jiraFullApiKey = `${jiraEmail}:${jiraApiKey}`;
|
|
51
|
+
const jiraUrl = `${jiraBaseUrl}/rest/api/2/issue/${jiraTicketId}`;
|
|
52
|
+
|
|
53
|
+
const jiraResponse = await fetch(jiraUrl, {
|
|
54
|
+
headers: {
|
|
55
|
+
Authorization: `Basic ${Buffer.from(jiraFullApiKey).toString('base64')}`,
|
|
56
|
+
'Content-Type': 'application/json',
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (!jiraResponse.ok) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
`Failed to fetch Jira ticket. Status: ${jiraResponse.status}`,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return await jiraResponse.json();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Generates release notes using OpenAI
|
|
71
|
+
*/
|
|
72
|
+
async function generateReleaseNotes(jiraTicketData) {
|
|
73
|
+
const openaiClient = new OpenAI({
|
|
74
|
+
apiKey: process.env['OPENAI_API_KEY'],
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const ChangeRequestSchema = z.object({
|
|
78
|
+
change_type: z.enum(['patch', 'minor']),
|
|
79
|
+
summary: z.string(),
|
|
80
|
+
jira_ticket_id: z.string(),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const openAiResponse = await openaiClient.chat.completions.create({
|
|
84
|
+
model: 'gpt-4o-mini',
|
|
85
|
+
messages: [
|
|
86
|
+
{
|
|
87
|
+
role: 'system',
|
|
88
|
+
content: `Process JSON from a Jira ticket to generate simple maximum 2 sentence release note for the ticket and determine the change type for bug it should be a patch for new feature it should be a minor change`,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
role: 'user',
|
|
92
|
+
content: JSON.stringify(jiraTicketData),
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
response_format: zodResponseFormat(ChangeRequestSchema, 'changeset_schema'),
|
|
96
|
+
temperature: 0,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const assistantResponse = openAiResponse.choices[0].message.content;
|
|
100
|
+
return JSON.parse(assistantResponse);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Writes the changeset file
|
|
105
|
+
*/
|
|
106
|
+
async function writeChangesetFile(
|
|
107
|
+
componentName,
|
|
108
|
+
jiraTicketId,
|
|
109
|
+
changeType,
|
|
110
|
+
summary,
|
|
111
|
+
) {
|
|
112
|
+
const changesetContent = `---
|
|
113
|
+
"${componentName}": ${changeType}
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
${summary} [${jiraTicketId}]
|
|
117
|
+
`;
|
|
118
|
+
const changesetFile = `./.changeset/${jiraTicketId}.md`;
|
|
119
|
+
|
|
120
|
+
await createChangesetDirectory();
|
|
121
|
+
await fs.promises.writeFile(changesetFile, changesetContent);
|
|
122
|
+
console.log(`Created changeset file at ${changesetFile}`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Main function to create a changeset
|
|
127
|
+
*/
|
|
128
|
+
|
|
129
|
+
export async function createChangeset() {
|
|
130
|
+
if (isMonoRepo()) {
|
|
131
|
+
const appPackages = await getAllAppPackages();
|
|
132
|
+
const response = await inquirer.prompt([
|
|
133
|
+
{
|
|
134
|
+
type: 'list',
|
|
135
|
+
name: 'package',
|
|
136
|
+
message: 'Which package do you want to generate changesetfor?',
|
|
137
|
+
choices: appPackages.map((appPackage) => appPackage.name),
|
|
138
|
+
},
|
|
139
|
+
]);
|
|
140
|
+
|
|
141
|
+
const selectedPackage = appPackages.find(
|
|
142
|
+
(appPackage) => appPackage.name == response.package,
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
const selectedPackageContent = await getPackage(selectedPackage.path);
|
|
146
|
+
await createChangesetForPackage(selectedPackageContent);
|
|
147
|
+
} else {
|
|
148
|
+
const mainPackage = await getMainPackage();
|
|
149
|
+
await createChangesetForPackage(mainPackage);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export async function createChangesetForPackage(mainPackage) {
|
|
154
|
+
const componentName = mainPackage.name;
|
|
155
|
+
try {
|
|
156
|
+
// Step 1: Get the current branch name
|
|
157
|
+
const branchName = await getCurrentBranch();
|
|
158
|
+
|
|
159
|
+
// Step 2: Extract Jira ticket number
|
|
160
|
+
const jiraTicketId = extractJiraTicketId(branchName);
|
|
161
|
+
|
|
162
|
+
// Step 3: Fetch Jira ticket data
|
|
163
|
+
const jiraTicketData = await fetchJiraTicketData(jiraTicketId);
|
|
164
|
+
const jiraSummary = jiraTicketData.fields.summary;
|
|
165
|
+
console.log(
|
|
166
|
+
`Generating release notes for ${jiraTicketId} - ${jiraSummary}`,
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// Step 4: Generate release notes using OpenAI
|
|
170
|
+
const { change_type, summary } = await generateReleaseNotes(jiraTicketData);
|
|
171
|
+
console.log(`Change type: ${change_type}`);
|
|
172
|
+
console.log(`Release note: ${summary}`);
|
|
173
|
+
|
|
174
|
+
// Step 5: Create a changeset .md file
|
|
175
|
+
await writeChangesetFile(componentName, jiraTicketId, change_type, summary);
|
|
176
|
+
|
|
177
|
+
console.log('Done!');
|
|
178
|
+
} catch (err) {
|
|
179
|
+
console.error(`Error: ${err.message}`);
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
|
|
4
|
+
async function fileExists(filePath) {
|
|
5
|
+
try {
|
|
6
|
+
await fs.promises.access(filePath);
|
|
7
|
+
return true;
|
|
8
|
+
} catch {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export async function getMainPackage() {
|
|
13
|
+
const mainModulePath = process.cwd();
|
|
14
|
+
return getPackage(mainModulePath);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function getPackage(mainModulePath) {
|
|
18
|
+
if (mainModulePath) {
|
|
19
|
+
const packageJsonPath = path.join(mainModulePath, 'package.json');
|
|
20
|
+
if (await fileExists(packageJsonPath)) {
|
|
21
|
+
const fileContent = await fs.promises.readFile(packageJsonPath, 'utf-8');
|
|
22
|
+
const packageJson = JSON.parse(fileContent);
|
|
23
|
+
return packageJson;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
throw new Error('Main package.json not found');
|
|
27
|
+
}
|
|
@@ -2,39 +2,40 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { $ } from 'zx';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { isMonoRepo, setGitInfo } from '../next/util.js';
|
|
6
|
+
import { versionStatus } from './version.js';
|
|
6
7
|
|
|
7
8
|
const CHANGESET_DIR = '.changeset';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const branch = process.env.BITBUCKET_BRANCH;
|
|
12
|
-
const destBranch = process.env.BITBUCKET_PR_DESTINATION_BRANCH;
|
|
10
|
+
function areArraysEqualIgnoringOrder(arr1, arr2) {
|
|
11
|
+
if (arr1.length !== arr2.length) return false;
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
const sortedA = [...arr1].sort();
|
|
14
|
+
const sortedB = [...arr2].sort();
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
return sortedA.every((element, index) => element === sortedB[index]);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function validateChangesets() {
|
|
20
|
+
if (isMonoRepo()) {
|
|
21
|
+
await setGitInfo();
|
|
22
|
+
const destBranch = process.env.BITBUCKET_PR_DESTINATION_BRANCH;
|
|
23
|
+
await $`git fetch origin ${destBranch}:${destBranch}`;
|
|
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,
|
|
18
29
|
);
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
await validateChangesetPath(changesetPath);
|
|
26
|
-
}
|
|
27
|
-
} else {
|
|
28
|
-
throw new Error('No changeset for at least one app');
|
|
29
|
-
}
|
|
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
|
+
}*/
|
|
30
36
|
} else {
|
|
31
37
|
await validateChangesetPath(path.resolve(process.cwd(), CHANGESET_DIR));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
await setGitInfo();
|
|
35
|
-
const destBranch = process.env.BITBUCKET_PR_DESTINATION_BRANCH;
|
|
36
|
-
await $`git fetch origin ${destBranch}:${destBranch}`;
|
|
37
|
-
await $`changeset status --since=${destBranch}`;
|
|
38
|
+
}
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
export async function validateChangesetPath(directoryPath) {
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { setGitInfo } from '../next/util.js';
|
|
2
|
+
import { $ } from 'zx';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { updateComponentVersion } from '../next/jira.js';
|
|
5
|
+
|
|
6
|
+
const changeSetPackage = `{
|
|
7
|
+
"name": "changeset-package",
|
|
8
|
+
"version": "1.0.0",
|
|
9
|
+
"description": "",
|
|
10
|
+
"scripts": {
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"keywords": [],
|
|
14
|
+
"author": "",
|
|
15
|
+
"license": "ISC",
|
|
16
|
+
"dependencies": {},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@changesets/cli": "^2.27.10"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
export async function versionStatus(sinceBranch) {
|
|
24
|
+
const outputPath = './changeset-output.json';
|
|
25
|
+
|
|
26
|
+
if (sinceBranch) {
|
|
27
|
+
await $`pnpm changeset status --output=${outputPath} --since=${sinceBranch}`;
|
|
28
|
+
} else {
|
|
29
|
+
await $`pnpm changeset status --output=${outputPath}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Read the file and parse JSON
|
|
33
|
+
const jsonOutput = JSON.parse(await fs.promises.readFile(outputPath, 'utf8'));
|
|
34
|
+
|
|
35
|
+
await fs.promises.rm(outputPath);
|
|
36
|
+
return jsonOutput.releases;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function versionCommand(closeVersion = false) {
|
|
40
|
+
console.log('📦 Running Changeset versioning...');
|
|
41
|
+
await setGitInfo();
|
|
42
|
+
await $`mv package.json package.json.bak`;
|
|
43
|
+
await $`mv pnpm-lock.yaml pnpm-lock.yaml.bak`;
|
|
44
|
+
await fs.promises.writeFile('package.json', changeSetPackage);
|
|
45
|
+
await $`pnpm install`;
|
|
46
|
+
await $`rm package.json pnpm-lock.yaml`;
|
|
47
|
+
await $`mv package.json.bak package.json`;
|
|
48
|
+
await $`mv pnpm-lock.yaml.bak pnpm-lock.yaml`;
|
|
49
|
+
if (closeVersion) {
|
|
50
|
+
await $`pnpm changeset pre exit`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const releases = await versionStatus();
|
|
55
|
+
|
|
56
|
+
await $`pnpm changeset version`;
|
|
57
|
+
|
|
58
|
+
return releases;
|
|
59
|
+
} catch {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function updateJiraWithVersion(releases) {
|
|
65
|
+
const lastCommit = (await $`git log -1 --pretty=%B`).stdout.trim();
|
|
66
|
+
console.log(`Last commit '${lastCommit}' being processed to get Jira ticket`);
|
|
67
|
+
|
|
68
|
+
const jiraTicketMatch = lastCommit.match(/([A-Z]+-\d+)/);
|
|
69
|
+
const jiraTicketId = jiraTicketMatch ? jiraTicketMatch[0] : null;
|
|
70
|
+
|
|
71
|
+
// If we have all the necessary data, update the component version in Jira
|
|
72
|
+
if (jiraTicketId) {
|
|
73
|
+
for (const release of releases) {
|
|
74
|
+
try {
|
|
75
|
+
await updateComponentVersion(
|
|
76
|
+
jiraTicketId,
|
|
77
|
+
release.name,
|
|
78
|
+
release.newVersion,
|
|
79
|
+
);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error(
|
|
82
|
+
`Failed to update Jira component version: ${error.message}`,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log('✅ Changeset versioning complete.');
|
|
89
|
+
}
|
package/src/next/apache.js
CHANGED
|
@@ -1,40 +1,43 @@
|
|
|
1
1
|
import { $ } from 'zx';
|
|
2
2
|
|
|
3
3
|
export async function addApacheSite() {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
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
|
package/src/next/deploy.js
CHANGED
|
@@ -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 {
|
|
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.
|
package/src/next/haproxy.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { $ } from 'zx';
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
export async function haproxySync() {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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/jira.js
CHANGED
|
@@ -12,11 +12,6 @@ const jiraClient = axios.create({
|
|
|
12
12
|
},
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
-
const packageComponents = {
|
|
16
|
-
'docupace-ui': 'next-ui',
|
|
17
|
-
'docupace-graphql-server': 'graphql-server',
|
|
18
|
-
'@docupace/template': 'template',
|
|
19
|
-
};
|
|
20
15
|
/**
|
|
21
16
|
* Updates the component version custom field in Jira
|
|
22
17
|
* @param {string} issueKey - The Jira issue key
|
|
@@ -24,7 +19,7 @@ const packageComponents = {
|
|
|
24
19
|
* @param {string} version - The version to set
|
|
25
20
|
*/
|
|
26
21
|
export async function updateComponentVersion(issueKey, packageName, version) {
|
|
27
|
-
const component =
|
|
22
|
+
const component = packageName;
|
|
28
23
|
console.log(
|
|
29
24
|
`Updating ${issueKey} for package ${packageName} translated to component ${component} with version ${version}`,
|
|
30
25
|
);
|
package/src/next/publish.js
CHANGED
|
@@ -56,12 +56,13 @@ export async function publish(gitSha) {
|
|
|
56
56
|
await $`docker tag ${IMAGE_NAME} ${JF_REGISTRY_FULL_URL}/${BUILD_IMAGE_NAME}`;
|
|
57
57
|
await $`docker push ${JF_REGISTRY_FULL_URL}/${BUILD_IMAGE_NAME}`;
|
|
58
58
|
|
|
59
|
-
const
|
|
59
|
+
const gitTags = (await $`git tag --points-at HEAD`).stdout
|
|
60
60
|
.trim()
|
|
61
61
|
.split('\n')
|
|
62
62
|
.filter(Boolean);
|
|
63
|
-
for (const
|
|
64
|
-
const
|
|
63
|
+
for (const gitTag of gitTags) {
|
|
64
|
+
const version = gitTag.includes('@') ? 'v' + gitTag.split('@')[1] : gitTag;
|
|
65
|
+
const tagName = `${IMAGE_PREFIX}:${version}`;
|
|
65
66
|
await $`docker tag ${IMAGE_NAME} ${JF_REGISTRY_FULL_URL}/${tagName}`;
|
|
66
67
|
await $`docker push ${JF_REGISTRY_FULL_URL}/${tagName}`;
|
|
67
68
|
}
|
package/src/next/util.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { existsSync } from 'fs';
|
|
2
|
-
import { join } from 'path';
|
|
3
|
-
import {
|
|
4
|
-
import path from 'path';
|
|
5
|
-
|
|
6
|
-
const GIT_SHA = (await $`git log --pretty=format:'%h' -n 1`).stdout.trim();
|
|
2
|
+
import path, { join } from 'path';
|
|
3
|
+
import { $ } from 'zx';
|
|
7
4
|
|
|
8
5
|
export function isMonoRepo() {
|
|
9
6
|
// Check for the presence of turbo.json which indicates a Turborepo monorepo
|
|
@@ -41,6 +38,33 @@ export async function getChangedPackagesInternal(fromRef, toRef) {
|
|
|
41
38
|
}
|
|
42
39
|
}
|
|
43
40
|
|
|
41
|
+
export async function getAllPackages() {
|
|
42
|
+
try {
|
|
43
|
+
const turboDryOutput = await $`turbo run build --dry=json`;
|
|
44
|
+
const dryRunJson = turboDryOutput.stdout.trim();
|
|
45
|
+
const dryRun = JSON.parse(dryRunJson);
|
|
46
|
+
|
|
47
|
+
const packages = dryRun.tasks.map((task) => ({
|
|
48
|
+
name: task.package,
|
|
49
|
+
directory: task.directory,
|
|
50
|
+
path: path.resolve(process.cwd(), task.directory),
|
|
51
|
+
}));
|
|
52
|
+
|
|
53
|
+
return packages;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error('Error getting changed packages:', error);
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function getAllAppPackages() {
|
|
61
|
+
const changedPackages = await getAllPackages();
|
|
62
|
+
const appPackages = changedPackages.filter((appPackage) =>
|
|
63
|
+
appPackage.directory.startsWith('apps'),
|
|
64
|
+
);
|
|
65
|
+
return appPackages;
|
|
66
|
+
}
|
|
67
|
+
|
|
44
68
|
export async function getChangedPackages() {
|
|
45
69
|
const branch = process.env.BITBUCKET_BRANCH;
|
|
46
70
|
const destBranch = process.env.BITBUCKET_PR_DESTINATION_BRANCH;
|
|
@@ -60,26 +84,10 @@ export async function getChangedAppPackages() {
|
|
|
60
84
|
return appPackages;
|
|
61
85
|
}
|
|
62
86
|
|
|
63
|
-
export async function buildChangePackages() {
|
|
64
|
-
const appPackages = await getChangedAppPackages();
|
|
65
|
-
if (appPackages.length == 0) {
|
|
66
|
-
throw new Error('Nothing to build');
|
|
67
|
-
}
|
|
68
|
-
for (const appPackage of appPackages) {
|
|
69
|
-
await dockerBuild(appPackage);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export async function dockerBuild(appPackage) {
|
|
74
|
-
process.env.DOCKER_HOST = '';
|
|
75
|
-
const shortName = appPackage.name.replace('@docupace/', '');
|
|
76
|
-
const imageName = `${process.env.BITBUCKET_REPO_SLUG}-${shortName}:sha-${GIT_SHA}-withMaps`;
|
|
77
|
-
console.log(`Building Docker image ${imageName}...`);
|
|
78
|
-
await $`docker build --secret id=npm_token,env=DOCUPACE_NPM_TOKEN . --file ${path.resolve(appPackage.path, 'Dockerfile')} --target builder --tag ${imageName}`;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
87
|
export async function setGitInfo() {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
+
}
|
|
85
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;
|
|
7
|
-
const VAULT_TOKEN = process.env.VAULT_TOKEN;
|
|
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(
|
|
39
|
+
console.error(
|
|
40
|
+
'Error adding data to Vault:',
|
|
41
|
+
error.response?.data || error.message,
|
|
42
|
+
);
|
|
41
43
|
throw error;
|
|
42
44
|
}
|
|
43
45
|
}
|