@docupace/pipeline 1.0.8-6.xray → 1.0.8
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/eslint.config.js +2 -25
- package/next/execute.sh +2 -8
- package/package.json +8 -24
- package/src/changeset/cli.js +195 -151
- package/src/changeset/validate.js +1 -45
- package/src/jenkins/setParams.groovy +2 -1
- package/src/next/cli.js +15 -111
- package/src/next/config.js +7 -72
- package/src/next/copy.js +1 -32
- package/src/next/deploy.js +69 -520
- package/src/next/jenkins.js +2 -3
- package/src/next/pipline.js +1 -0
- package/src/next/publish.js +30 -53
- package/README.md +0 -136
- package/bin/azuread_update_callbacks_for_app.sh +0 -58
- package/bin/xray.sh +0 -273
- package/bitbucket-pipelines.yml +0 -142
- package/jest.config.js +0 -15
- package/src/auth0/alias.js +0 -79
- package/src/auth0/alias.test.js +0 -172
- package/src/auth0/cli.js +0 -82
- package/src/auth0/configure.js +0 -902
- package/src/auth0/configure.test.js +0 -167
- package/src/auth0/export.js +0 -48
- package/src/auth0/export.test.js +0 -103
- package/src/auth0/metadata.js +0 -141
- package/src/auth0/metadata.test.js +0 -186
- package/src/auth0/vault.js +0 -60
- package/src/auth0/vault.test.js +0 -134
- package/src/changeset/changelog-wiki.js +0 -328
- package/src/changeset/changeset-config.js +0 -34
- package/src/changeset/create.js +0 -215
- package/src/changeset/package-util.js +0 -87
- package/src/changeset/util.js +0 -43
- package/src/changeset/version.js +0 -102
- package/src/jfrog/xray-scan.yaml +0 -29
- package/src/lib/merge-driver.js +0 -204
- package/src/merge/cli-merge-all.js +0 -521
- package/src/merge/cli-merge.js +0 -572
- package/src/merge/cli-resolve.js +0 -399
- package/src/merge/cli.js +0 -38
- package/src/merge/common.js +0 -7
- package/src/merge/merge-changelog.js +0 -87
- package/src/merge/merge-package.js +0 -106
- package/src/merge/merge-types.js +0 -82
- package/src/merge/pr.js +0 -231
- package/src/micro/cli.js +0 -51
- package/src/micro/ms-deploy.js +0 -451
- package/src/micro/ms-publish.js +0 -186
- package/src/next/alias.js +0 -53
- package/src/next/apache.js +0 -81
- package/src/next/connect.js +0 -226
- package/src/next/git-to-semver.js +0 -79
- package/src/next/haproxy.js +0 -76
- package/src/next/jira.js +0 -84
- package/src/next/logger.js +0 -17
- package/src/next/test.js +0 -5
- package/src/next/util.js +0 -95
- package/src/next/vault.js +0 -45
- package/terraform/apply.sh +0 -41
- package/terraform/import.sh +0 -111
- package/terraform/init.sh +0 -78
- package/terraform/plan.sh +0 -95
- package/terraform/validate.sh +0 -17
package/eslint.config.js
CHANGED
|
@@ -2,48 +2,25 @@ import globals from 'globals';
|
|
|
2
2
|
import pluginJs from '@eslint/js';
|
|
3
3
|
import prettierConfig from 'eslint-config-prettier';
|
|
4
4
|
import prettierPlugin from 'eslint-plugin-prettier';
|
|
5
|
-
import importPlugin from 'eslint-plugin-import';
|
|
6
5
|
|
|
6
|
+
/** @type {import('eslint').Linter.Config[]} */
|
|
7
7
|
export default [
|
|
8
8
|
{
|
|
9
9
|
languageOptions: {
|
|
10
10
|
globals: {
|
|
11
11
|
...globals.browser,
|
|
12
|
-
...globals.node,
|
|
12
|
+
...globals.node, // Add Node.js globals
|
|
13
13
|
},
|
|
14
14
|
},
|
|
15
15
|
},
|
|
16
|
-
|
|
17
|
-
// Core JS rules
|
|
18
16
|
pluginJs.configs.recommended,
|
|
19
|
-
|
|
20
|
-
// Jest globals for test files only
|
|
21
|
-
{
|
|
22
|
-
files: ['**/*.test.js', '**/__tests__/**/*.js'],
|
|
23
|
-
languageOptions: {
|
|
24
|
-
globals: {
|
|
25
|
-
...globals.jest,
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
|
|
30
17
|
{
|
|
31
18
|
plugins: {
|
|
32
19
|
prettier: prettierPlugin,
|
|
33
|
-
import: importPlugin,
|
|
34
|
-
},
|
|
35
|
-
settings: {
|
|
36
|
-
'import/resolver': {
|
|
37
|
-
node: { extensions: ['.js', '.mjs', '.cjs'] },
|
|
38
|
-
typescript: {},
|
|
39
|
-
},
|
|
40
20
|
},
|
|
41
21
|
rules: {
|
|
42
22
|
...prettierConfig.rules,
|
|
43
23
|
'prettier/prettier': 'error',
|
|
44
|
-
'import/no-unresolved': 'error',
|
|
45
|
-
'import/named': 'error',
|
|
46
|
-
'import/no-extraneous-dependencies': 'error',
|
|
47
24
|
},
|
|
48
25
|
},
|
|
49
26
|
];
|
package/next/execute.sh
CHANGED
|
@@ -53,14 +53,8 @@ copy() {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
publish() {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
SLUG_SUFFIX="-${APP_NAME}"
|
|
59
|
-
fi
|
|
60
|
-
|
|
61
|
-
BUILD_IMAGE_NAME="${BITBUCKET_REPO_SLUG}${SLUG_SUFFIX}:build-${BITBUCKET_BUILD_NUMBER}"
|
|
62
|
-
IMAGE_NAME="${BITBUCKET_REPO_SLUG}${SLUG_SUFFIX}:sha-${GIT_SHA}"
|
|
63
|
-
|
|
56
|
+
BUILD_IMAGE_NAME="${BITBUCKET_REPO_SLUG}:build-${BITBUCKET_BUILD_NUMBER}"
|
|
57
|
+
IMAGE_NAME="${BITBUCKET_REPO_SLUG}:sha-${GIT_SHA}"
|
|
64
58
|
export DOCKER_HOST=""
|
|
65
59
|
|
|
66
60
|
echo "Publishing Docker image ${IMAGE_NAME}..."
|
package/package.json
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docupace/pipeline",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
|
+
"description": "",
|
|
4
5
|
"main": "index.js",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"bin": {
|
|
7
8
|
"dp-changeset-cli": "src/changeset/cli.js",
|
|
8
|
-
"dp-next-cli": "src/next/cli.js"
|
|
9
|
-
"dp-auth0-cli": "src/auth0/cli.js",
|
|
10
|
-
"dp-merge-cli": "src/merge/cli.js",
|
|
11
|
-
"dp-micro-cli": "src/micro/cli.js"
|
|
9
|
+
"dp-next-cli": "src/next/cli.js"
|
|
12
10
|
},
|
|
13
11
|
"keywords": [
|
|
14
12
|
"bash"
|
|
@@ -17,41 +15,27 @@
|
|
|
17
15
|
"license": "ISC",
|
|
18
16
|
"dependencies": {
|
|
19
17
|
"@changesets/cli": "^2.27.10",
|
|
20
|
-
"@docupace/core-client": "^1.0.1",
|
|
21
|
-
"@docupace/pipeline": "^1.0.12",
|
|
22
|
-
"@jest/globals": "^30.1.2",
|
|
23
|
-
"auth0-deploy-cli": "^8.8.0",
|
|
24
18
|
"axios": "^1.7.9",
|
|
25
19
|
"commander": "^12.1.0",
|
|
26
20
|
"dotenv": "^16.4.7",
|
|
27
|
-
"eslint-plugin-import": "^2.32.0",
|
|
28
|
-
"fs-extra": "^11.3.0",
|
|
29
|
-
"inquirer": "^12.6.1",
|
|
30
21
|
"js-yaml": "^4.1.0",
|
|
31
22
|
"lodash": "^4.17.21",
|
|
32
23
|
"openai": "^4.76.3",
|
|
33
|
-
"semver": "^7.7.2",
|
|
34
24
|
"zod": "^3.24.1",
|
|
35
|
-
"zx": "^8.
|
|
25
|
+
"zx": "^8.2.4"
|
|
36
26
|
},
|
|
37
27
|
"devDependencies": {
|
|
38
28
|
"@eslint/js": "^9.17.0",
|
|
39
|
-
"esbuild": "^0.
|
|
40
|
-
"eslint": "^9.
|
|
29
|
+
"esbuild": "^0.24.0",
|
|
30
|
+
"eslint": "^9.17.0",
|
|
41
31
|
"eslint-config-prettier": "^9.1.0",
|
|
42
|
-
"eslint-import-resolver-node": "^0.3.9",
|
|
43
|
-
"eslint-import-resolver-typescript": "^4.4.4",
|
|
44
32
|
"eslint-plugin-prettier": "^5.2.1",
|
|
45
33
|
"globals": "^15.14.0",
|
|
46
|
-
"jest": "^30.1.3",
|
|
47
34
|
"prettier": "^3.4.2"
|
|
48
35
|
},
|
|
49
36
|
"scripts": {
|
|
50
|
-
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage --testPathIgnorePatterns='src/next/test\\.js'",
|
|
51
37
|
"test-deploy-core": "dp-next-cli deploy-core-pipeline dev template",
|
|
52
|
-
"test-deploy-from-site": "dp-next-cli deploy-from-site --from-env
|
|
53
|
-
"test-run-pipline": "dp-next-cli run-pipeline -r docupace-next-e2e -b master -p run-tests-qa"
|
|
54
|
-
"test-validate": "dp-changset-cli validate",
|
|
55
|
-
"test-create": "dp-changset-cli create-changeset"
|
|
38
|
+
"test-deploy-from-site": "dp-next-cli deploy-from-site --from-env qa --to-env qa --from-site rockefeller --to-site rockefeller --deploy-core true",
|
|
39
|
+
"test-run-pipline": "dp-next-cli run-pipeline -r docupace-next-e2e -b master -p run-tests-qa"
|
|
56
40
|
}
|
|
57
41
|
}
|
package/src/changeset/cli.js
CHANGED
|
@@ -1,111 +1,123 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { $ } from 'zx';
|
|
4
|
+
import path from 'path';
|
|
4
5
|
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';
|
|
5
10
|
import dotenv from 'dotenv';
|
|
6
|
-
import { isMonoRepo, setGitInfo } from '../next/util.js';
|
|
7
|
-
import {
|
|
8
|
-
toShortVersion,
|
|
9
|
-
updateJiraWithVersion,
|
|
10
|
-
versionCommand,
|
|
11
|
-
} from './version.js';
|
|
12
|
-
import { createChangeset } from './create.js';
|
|
13
|
-
import {
|
|
14
|
-
updateWikiWithVersion,
|
|
15
|
-
upsertReleaseNotesFromFile,
|
|
16
|
-
} from './changelog-wiki.js';
|
|
17
|
-
|
|
18
11
|
dotenv.config({ path: ['.env.pipeline.local', 'config/.env.pipeline.local'] });
|
|
12
|
+
import { exec } from 'child_process';
|
|
19
13
|
|
|
20
14
|
const program = new Command();
|
|
21
15
|
|
|
22
16
|
const args = process.argv;
|
|
23
17
|
|
|
24
|
-
async function
|
|
25
|
-
|
|
18
|
+
async function createChangesetDirectory() {
|
|
19
|
+
try {
|
|
20
|
+
// Use path.join to build a safe path to `.changeset`
|
|
21
|
+
const targetDir = path.join(process.cwd(), '.changeset');
|
|
26
22
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
console.
|
|
31
|
-
return;
|
|
23
|
+
// Create the directory recursively if it doesn't exist
|
|
24
|
+
await fs.promises.mkdir(targetDir, { recursive: true });
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error('Error creating .changeset directory:', error);
|
|
32
27
|
}
|
|
28
|
+
}
|
|
33
29
|
|
|
34
|
-
console.log('📌 Committing and tagging the new version...');
|
|
35
|
-
await setGitInfo();
|
|
36
|
-
await $`git add .`;
|
|
37
30
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
+
});
|
|
43
41
|
}
|
|
44
42
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
async function fileExists(filePath) {
|
|
44
|
+
try {
|
|
45
|
+
await fs.promises.access(filePath);
|
|
46
|
+
return true;
|
|
47
|
+
} catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
function
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
async function getMainPackage() {
|
|
53
|
+
const mainModulePath = process.cwd();
|
|
54
|
+
if (mainModulePath) {
|
|
55
|
+
const packageJsonPath = path.join(mainModulePath, 'package.json');
|
|
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
|
+
}
|
|
61
|
+
}
|
|
62
|
+
throw new Error('Main package.json not found');
|
|
63
|
+
}
|
|
57
64
|
|
|
58
|
-
|
|
65
|
+
// Helper function to set Git info
|
|
66
|
+
async function setGitInfo() {
|
|
67
|
+
await $`git config --global user.email "gitops@docupace.com"`;
|
|
68
|
+
await $`git config --global user.name "Gitops"`;
|
|
69
|
+
await $`git remote set-url origin https://${process.env.THIS_REP_TOKEN}@bitbucket.org/${process.env.BITBUCKET_REPO_FULL_NAME}.git`;
|
|
59
70
|
}
|
|
60
71
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
const changeSetPackage = `{
|
|
73
|
+
"name": "changeset-package",
|
|
74
|
+
"version": "1.0.0",
|
|
75
|
+
"description": "",
|
|
76
|
+
"scripts": {
|
|
77
|
+
},
|
|
78
|
+
"type": "module",
|
|
79
|
+
"keywords": [],
|
|
80
|
+
"author": "",
|
|
81
|
+
"license": "ISC",
|
|
82
|
+
"dependencies": {},
|
|
83
|
+
"devDependencies": {
|
|
84
|
+
"@changesets/cli": "^2.27.10"
|
|
67
85
|
}
|
|
86
|
+
}
|
|
87
|
+
`;
|
|
68
88
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
89
|
+
async function versionCommand() {
|
|
90
|
+
console.log('📦 Running Changeset versioning...');
|
|
91
|
+
await setGitInfo();
|
|
92
|
+
await $`mv package.json package.json.bak`;
|
|
93
|
+
await $`mv pnpm-lock.yaml pnpm-lock.yaml.bak`;
|
|
94
|
+
await fs.promises.writeFile('package.json', changeSetPackage);
|
|
95
|
+
await $`pnpm install`;
|
|
96
|
+
await $`rm package.json pnpm-lock.yaml`;
|
|
97
|
+
await $`mv package.json.bak package.json`;
|
|
98
|
+
await $`mv pnpm-lock.yaml.bak pnpm-lock.yaml`;
|
|
99
|
+
await $`pnpm changeset version`;
|
|
100
|
+
console.log('✅ Changeset versioning complete.');
|
|
101
|
+
}
|
|
77
102
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
await $`git tag ${newVersion}`;
|
|
81
|
-
console.log(`✅ Version ${newVersion} tagged.`);
|
|
82
|
-
} else {
|
|
83
|
-
console.log(`✅ Simulate Version ${newVersion} tagged.`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
103
|
+
async function commitTagCommand() {
|
|
104
|
+
console.log('📌 Checking for updates to commit...');
|
|
86
105
|
|
|
87
|
-
if
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
106
|
+
// Check if there are changes to commit
|
|
107
|
+
const status = (await $`git status --porcelain`).stdout.trim();
|
|
108
|
+
if (!status) {
|
|
109
|
+
console.log('✅ No changes to commit. Exiting.');
|
|
110
|
+
return;
|
|
92
111
|
}
|
|
93
|
-
}
|
|
94
112
|
|
|
95
|
-
|
|
113
|
+
console.log('📌 Committing and tagging the new version...');
|
|
114
|
+
await setGitInfo();
|
|
115
|
+
await $`git add .`;
|
|
96
116
|
const newVersion = (
|
|
97
117
|
await $`node -p "require('./package.json').version"`
|
|
98
118
|
).stdout.trim();
|
|
99
|
-
|
|
100
|
-
if (process.env.IS_DEV) {
|
|
101
|
-
console.log(`Simulate commit of version ${newVersion}`);
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const defaultBranch = process.env.BITBUCKET_BRANCH;
|
|
106
|
-
|
|
107
119
|
await $`git commit -m "Version bump to ${newVersion} and changelog"`;
|
|
108
|
-
await $`git push origin
|
|
120
|
+
await $`git push origin`;
|
|
109
121
|
await $`git tag v${newVersion}`;
|
|
110
122
|
await $`git push origin --tags`;
|
|
111
123
|
console.log(`✅ Version ${newVersion} tagged and pushed.`);
|
|
@@ -113,13 +125,22 @@ async function commitTag() {
|
|
|
113
125
|
|
|
114
126
|
// Command: validate
|
|
115
127
|
program
|
|
116
|
-
.command('validate')
|
|
128
|
+
.command('validate <path>')
|
|
117
129
|
.description('Validate changesets for the provided PR')
|
|
118
|
-
.action(async () => {
|
|
130
|
+
.action(async (path) => {
|
|
119
131
|
if (!process.env.BITBUCKET_PR_ID) {
|
|
120
132
|
return;
|
|
121
133
|
}
|
|
122
|
-
|
|
134
|
+
console.log('🔍 Validating changesets...');
|
|
135
|
+
try {
|
|
136
|
+
await validateChangesets(path);
|
|
137
|
+
console.log('✅ Changeset validation passed.');
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error(
|
|
140
|
+
'❌ 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',
|
|
141
|
+
);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
123
144
|
});
|
|
124
145
|
// Command: version
|
|
125
146
|
program
|
|
@@ -143,49 +164,8 @@ program
|
|
|
143
164
|
.description('Run versioning and commit-and-tag in sequence')
|
|
144
165
|
.action(async () => {
|
|
145
166
|
console.log('📦 Running all steps...');
|
|
146
|
-
|
|
147
|
-
await
|
|
148
|
-
await updateWikiWithVersion(releases);
|
|
149
|
-
await commitTagCommand(releases);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
program
|
|
153
|
-
.command('close-version')
|
|
154
|
-
.description('Closes a version')
|
|
155
|
-
.action(async () => {
|
|
156
|
-
console.log('📦 Running all steps...');
|
|
157
|
-
const releases = await versionCommand(true);
|
|
158
|
-
await commitTagCommand(releases);
|
|
159
|
-
|
|
160
|
-
const { stdout: currentBranch } = await $`git rev-parse --abbrev-ref HEAD`;
|
|
161
|
-
|
|
162
|
-
if (isMonoRepo()) {
|
|
163
|
-
for (const release of getAppReleases(releases)) {
|
|
164
|
-
const appName = getAppNameFromPackageName(release.name);
|
|
165
|
-
const newVersion = toShortVersion(release.newVersion);
|
|
166
|
-
if (!newVersion) {
|
|
167
|
-
throw new Error('Error calculating branch name');
|
|
168
|
-
}
|
|
169
|
-
await $`git checkout -b release/${appName}/${newVersion}`;
|
|
170
|
-
await $`git push origin release/${appName}/${newVersion}`;
|
|
171
|
-
}
|
|
172
|
-
} else {
|
|
173
|
-
const newVersion = toShortVersion(releases[0].newVersion);
|
|
174
|
-
if (!newVersion) {
|
|
175
|
-
throw new Error('Error calculating branch name');
|
|
176
|
-
}
|
|
177
|
-
await $`git checkout -b release/${newVersion}`;
|
|
178
|
-
await $`git push origin release/${newVersion}`;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Return to original branch
|
|
182
|
-
await $`git checkout ${currentBranch.trim()}`;
|
|
183
|
-
|
|
184
|
-
// Open next alpha version
|
|
185
|
-
await $`pnpm changeset pre enter alpha`;
|
|
186
|
-
await $`git add .`;
|
|
187
|
-
await $`git commit -m "Open next alpha version"`;
|
|
188
|
-
await $`git push origin`;
|
|
167
|
+
await versionCommand();
|
|
168
|
+
await commitTagCommand();
|
|
189
169
|
});
|
|
190
170
|
|
|
191
171
|
program
|
|
@@ -194,41 +174,105 @@ program
|
|
|
194
174
|
'Creates a changeset based on the current branch and Jira ticket information',
|
|
195
175
|
)
|
|
196
176
|
.action(async () => {
|
|
197
|
-
await
|
|
198
|
-
|
|
177
|
+
const mainPackage = await getMainPackage();
|
|
178
|
+
const componentName = mainPackage.name;
|
|
199
179
|
|
|
200
|
-
program
|
|
201
|
-
.command('upload-wiki')
|
|
202
|
-
.description('Upload release notes from markdown file to Confluence')
|
|
203
|
-
.requiredOption(
|
|
204
|
-
'-v, --version <version>',
|
|
205
|
-
'Version title (e.g., "Version 1.0")',
|
|
206
|
-
)
|
|
207
|
-
.requiredOption(
|
|
208
|
-
'-c, --component <component>',
|
|
209
|
-
'Component title (e.g., "Component A")',
|
|
210
|
-
)
|
|
211
|
-
.requiredOption('-f, --file <file>', 'Path to markdown file')
|
|
212
|
-
.requiredOption('-g, --group <group>', 'Group of release notes')
|
|
213
|
-
|
|
214
|
-
.action(async (options) => {
|
|
215
180
|
try {
|
|
216
|
-
|
|
217
|
-
const {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
181
|
+
// Step 1: Get the current branch name
|
|
182
|
+
const { stdout: branchStdout } = await run(`git branch --show-current`);
|
|
183
|
+
const branchName = branchStdout.trim();
|
|
184
|
+
console.log(`Current branch: ${branchName}`);
|
|
185
|
+
|
|
186
|
+
// Step 2: Extract Jira ticket number (e.g., matching JIRA-1234 pattern)
|
|
187
|
+
const jiraTicketMatch = branchName.match(/([A-Z]+-\d+)/);
|
|
188
|
+
if (!jiraTicketMatch) {
|
|
189
|
+
throw new Error('No Jira ticket found in the branch name.');
|
|
190
|
+
}
|
|
191
|
+
const jiraTicketId = jiraTicketMatch[0];
|
|
192
|
+
|
|
193
|
+
// Step 3: Fetch Jira ticket information
|
|
194
|
+
const jiraBaseUrl = 'https://docupacellc.atlassian.net';
|
|
195
|
+
const jiraEmail = process.env.JIRA_API_EMAIL;
|
|
196
|
+
const jiraApiKey = process.env.JIRA_API_KEY;
|
|
197
|
+
const jiraFullApiKey = `${jiraEmail}:${jiraApiKey}`;
|
|
198
|
+
const jiraUrl = `${jiraBaseUrl}/rest/api/2/issue/${jiraTicketId}`;
|
|
199
|
+
const jiraResponse = await fetch(jiraUrl, {
|
|
200
|
+
headers: {
|
|
201
|
+
Authorization: `Basic ${Buffer.from(jiraFullApiKey).toString('base64')}`,
|
|
202
|
+
'Content-Type': 'application/json',
|
|
203
|
+
},
|
|
222
204
|
});
|
|
223
205
|
|
|
224
|
-
|
|
225
|
-
|
|
206
|
+
if (!jiraResponse.ok) {
|
|
207
|
+
throw new Error(
|
|
208
|
+
`Failed to fetch Jira ticket. Status: ${jiraResponse.status}`,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
const jiraTicketData = await jiraResponse.json();
|
|
212
|
+
|
|
213
|
+
if (jiraTicketData.fields.customfield_10107?.value !== 'Product') {
|
|
214
|
+
throw new Error('Issue Type of Work must be Product');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const jiraSummary = jiraTicketData.fields.summary;
|
|
218
|
+
|
|
226
219
|
console.log(
|
|
227
|
-
|
|
228
|
-
componentPage._links?.webui || componentPage.id,
|
|
220
|
+
`Generating release notes for ${jiraTicketId} - ${jiraSummary}`,
|
|
229
221
|
);
|
|
230
|
-
|
|
231
|
-
|
|
222
|
+
|
|
223
|
+
// Step 4: Use OpenAI to generate release notes
|
|
224
|
+
const openaiClient = new OpenAI({
|
|
225
|
+
apiKey: process.env['OPENAI_API_KEY'],
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const ChangeRequestSchema = z.object({
|
|
229
|
+
change_type: z.enum(['patch', 'minor']),
|
|
230
|
+
summary: z.string(),
|
|
231
|
+
jira_ticket_id: z.string(),
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
const openAiResponse = await openaiClient.chat.completions.create({
|
|
235
|
+
model: 'gpt-4o-mini',
|
|
236
|
+
messages: [
|
|
237
|
+
{
|
|
238
|
+
role: 'system',
|
|
239
|
+
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`,
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
role: 'user',
|
|
243
|
+
content: JSON.stringify(jiraTicketData),
|
|
244
|
+
},
|
|
245
|
+
],
|
|
246
|
+
response_format: zodResponseFormat(
|
|
247
|
+
ChangeRequestSchema,
|
|
248
|
+
'changeset_schema',
|
|
249
|
+
),
|
|
250
|
+
temperature: 0,
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
const assistantResponse = openAiResponse.choices[0].message.content;
|
|
254
|
+
const parsedResponse = JSON.parse(assistantResponse);
|
|
255
|
+
|
|
256
|
+
const { change_type, summary } = parsedResponse;
|
|
257
|
+
console.log(`Change type: ${change_type}`);
|
|
258
|
+
console.log(`Release note: ${summary}`);
|
|
259
|
+
|
|
260
|
+
// Step 5: Create a changeset .md file
|
|
261
|
+
const changesetContent = `---
|
|
262
|
+
"${componentName}": ${change_type}
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
${summary} [${jiraTicketId}]
|
|
266
|
+
`;
|
|
267
|
+
const changesetFile = `./.changeset/${jiraTicketId}.md`;
|
|
268
|
+
|
|
269
|
+
await createChangesetDirectory();
|
|
270
|
+
await fs.promises.writeFile(changesetFile, changesetContent);
|
|
271
|
+
console.log(`Created changeset file at ${changesetFile}`);
|
|
272
|
+
|
|
273
|
+
console.log('Done!');
|
|
274
|
+
} catch (err) {
|
|
275
|
+
console.error(`Error: ${err.message}`);
|
|
232
276
|
process.exit(1);
|
|
233
277
|
}
|
|
234
278
|
});
|
|
@@ -1,51 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { $ } from 'zx';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
import { versionStatus } from './version.js';
|
|
7
|
-
|
|
8
|
-
const CHANGESET_DIR = '.changeset';
|
|
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
|
-
|
|
19
|
-
export async function validateChangesets() {
|
|
20
|
-
await setGitInfo();
|
|
21
|
-
const destBranch = process.env.BITBUCKET_PR_DESTINATION_BRANCH;
|
|
22
|
-
await $`git fetch origin ${destBranch}:${destBranch}`;
|
|
23
|
-
let releases;
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
console.log('🔍 Validating changesets...');
|
|
27
|
-
releases = await versionStatus(destBranch);
|
|
28
|
-
} catch (e) {
|
|
29
|
-
console.error(
|
|
30
|
-
'❌ No changeset found. Please add a changeset to this PR. Please see more information at https://docupacellc.atlassian.net/wiki/spaces/PM/pages/1350893571/Creating+changesets+for+Docupace+Next',
|
|
31
|
-
e,
|
|
32
|
-
);
|
|
33
|
-
process.exit(-1);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (!['master', 'main'].includes(destBranch)) {
|
|
37
|
-
if (releases.some((item) => item.type !== 'patch')) {
|
|
38
|
-
console.error(
|
|
39
|
-
'❌ A changeset must be a patch for change to a release branch',
|
|
40
|
-
);
|
|
41
|
-
process.exit(-1);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
console.log('✅ Changeset validation passed.');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function validateChangesetPath(directoryPath) {
|
|
4
|
+
export async function validateChangesets(directoryPath) {
|
|
49
5
|
try {
|
|
50
6
|
// Step 1: Read the directory for md files excluding README.md
|
|
51
7
|
const allFiles = fs.readdirSync(directoryPath);
|