@docupace/pipeline 1.0.77 → 1.0.79
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/.prettierrc.cjs +12 -12
- package/README.md +135 -135
- package/bin/azuread_update_callbacks_for_app.sh +58 -58
- package/bin/next-changeset-validate.sh +8 -8
- package/bitbucket-pipelines.yml +59 -59
- package/eslint.config.js +49 -49
- package/jest.config.js +15 -15
- package/next/changeset.sh +75 -75
- package/next/copy.sh +34 -34
- package/next/deploy.sh +40 -40
- package/next/execute.sh +123 -123
- package/next/sonar.sh +23 -23
- package/package.json +1 -1
- package/src/auth0/alias.js +79 -79
- package/src/auth0/alias.test.js +172 -172
- package/src/auth0/cli.js +82 -82
- package/src/auth0/configure.js +902 -902
- package/src/auth0/configure.test.js +167 -167
- package/src/auth0/export.js +48 -48
- package/src/auth0/export.test.js +103 -103
- package/src/auth0/metadata.js +141 -141
- package/src/auth0/metadata.test.js +186 -186
- package/src/auth0/vault.js +60 -60
- package/src/auth0/vault.test.js +134 -134
- package/src/changeset/changelog-wiki.js +328 -328
- package/src/changeset/changeset-config.js +34 -34
- package/src/changeset/cli.js +237 -237
- package/src/changeset/create.js +215 -215
- package/src/changeset/package-util.js +87 -87
- package/src/changeset/util.js +43 -43
- package/src/changeset/validate.js +91 -91
- package/src/changeset/version.js +102 -102
- package/src/jenkins/setParams.groovy +58 -58
- package/src/lib/merge-driver.js +204 -204
- package/src/merge/cli-merge-all.js +507 -507
- package/src/merge/cli-merge.js +492 -492
- package/src/merge/cli-resolve.js +399 -399
- package/src/merge/cli.js +38 -38
- package/src/merge/merge-changelog.js +87 -87
- package/src/merge/merge-package.js +106 -106
- package/src/merge/merge-types.js +82 -82
- package/src/merge/pr.js +231 -231
- package/src/micro/deploy-microservice.js +153 -0
- package/src/micro/{ms-publish.js → publish-ms.js} +8 -6
- package/src/next/alias.js +53 -53
- package/src/next/apache.js +81 -81
- package/src/next/cli.js +10 -1
- package/src/next/config.js +137 -137
- package/src/next/connect.js +226 -226
- package/src/next/copy.js +61 -61
- package/src/next/deploy.js +666 -633
- package/src/next/git-to-semver.js +79 -79
- package/src/next/haproxy.js +76 -76
- package/src/next/jenkins.js +123 -123
- package/src/next/jira.js +84 -84
- package/src/next/logger.js +17 -17
- package/src/next/pipline.js +114 -114
- package/src/next/publish.js +71 -71
- package/src/next/pull.js +7 -7
- package/src/next/sonar.js +23 -23
- package/src/next/test.js +5 -5
- package/src/next/util.js +95 -93
- package/src/next/vault.js +45 -45
- package/terraform/apply.sh +37 -37
- package/terraform/init.sh +72 -72
- package/terraform/plan.sh +76 -76
- package/terraform/validate.sh +17 -17
- package/src/micro/cli.js +0 -71
- package/src/micro/ms-deploy.js +0 -271
package/src/merge/pr.js
CHANGED
|
@@ -1,231 +1,231 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Create a Bitbucket pull request
|
|
3
|
-
* @param {string} sourceBranch - Source branch name
|
|
4
|
-
* @param {string} targetBranch - Target branch name
|
|
5
|
-
* @param {string} title - PR title
|
|
6
|
-
* @param {string} description - PR description
|
|
7
|
-
* @returns {Promise<Object>} - PR creation result
|
|
8
|
-
*/
|
|
9
|
-
import { execSync } from 'child_process';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Check for existing pull requests with specific description pattern
|
|
13
|
-
* @param {string} descriptionPattern - Pattern to match in PR descriptions
|
|
14
|
-
* @returns {Promise<Object[]>} - Array of matching PRs
|
|
15
|
-
*/
|
|
16
|
-
export async function getExistingPRsWithDescription(
|
|
17
|
-
descriptionPattern,
|
|
18
|
-
repositories,
|
|
19
|
-
) {
|
|
20
|
-
// If no repositories provided, fall back to current repo behavior for backward compatibility
|
|
21
|
-
if (!repositories || !Array.isArray(repositories)) {
|
|
22
|
-
return getExistingPRsFromCurrentRepo(descriptionPattern);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
// Check for Bitbucket credentials
|
|
27
|
-
const username = process.env.BITBUCKET_USERNAME;
|
|
28
|
-
const password = process.env.BITBUCKET_APP_PASSWORD;
|
|
29
|
-
|
|
30
|
-
if (!username || !password) {
|
|
31
|
-
console.log(
|
|
32
|
-
`\n⚠️ Bitbucket credentials not found. Cannot check existing PRs.`,
|
|
33
|
-
);
|
|
34
|
-
return [];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const auth = Buffer.from(`${username}:${password}`).toString('base64');
|
|
38
|
-
const allMatchingPRs = [];
|
|
39
|
-
|
|
40
|
-
// Check each repository for matching PRs
|
|
41
|
-
for (const repo of repositories) {
|
|
42
|
-
try {
|
|
43
|
-
const match = repo.url.match(/bitbucket\.org[\/:]([^\/]+)\/([^\/\.]+)/);
|
|
44
|
-
|
|
45
|
-
if (!match) {
|
|
46
|
-
console.warn(`Could not parse repository URL: ${repo.url}`);
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const [, workspace, repoSlug] = match;
|
|
51
|
-
|
|
52
|
-
const response = await fetch(
|
|
53
|
-
`https://api.bitbucket.org/2.0/repositories/${workspace}/${repoSlug}/pullrequests?state=OPEN`,
|
|
54
|
-
{
|
|
55
|
-
method: 'GET',
|
|
56
|
-
headers: {
|
|
57
|
-
Authorization: `Basic ${auth}`,
|
|
58
|
-
'Content-Type': 'application/json',
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
if (!response.ok) {
|
|
64
|
-
const error = await response.text();
|
|
65
|
-
console.warn(
|
|
66
|
-
`Bitbucket API error for ${repo.name}: ${response.status} - ${error}`,
|
|
67
|
-
);
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const data = await response.json();
|
|
72
|
-
const matchingPRs = data.values.filter(
|
|
73
|
-
(pr) =>
|
|
74
|
-
pr.description && pr.description.startsWith(descriptionPattern),
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
// Add repository info to each PR for context
|
|
78
|
-
matchingPRs.forEach((pr) => {
|
|
79
|
-
pr.repositoryName = repo.name;
|
|
80
|
-
pr.repositoryUrl = repo.url;
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
allMatchingPRs.push(...matchingPRs);
|
|
84
|
-
} catch (error) {
|
|
85
|
-
console.warn(
|
|
86
|
-
`Failed to check PRs for repository ${repo.name}: ${error.message}`,
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return allMatchingPRs;
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.error(`Failed to get existing PRs: ${error.message}`);
|
|
94
|
-
return [];
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Legacy function for backward compatibility - checks PRs in current repo only
|
|
100
|
-
*/
|
|
101
|
-
export async function getExistingPRsFromCurrentRepo(descriptionPattern) {
|
|
102
|
-
try {
|
|
103
|
-
// Get Bitbucket workspace and repo from git remote
|
|
104
|
-
const remoteUrl = execSync('git config --get remote.origin.url', {
|
|
105
|
-
encoding: 'utf-8',
|
|
106
|
-
}).trim();
|
|
107
|
-
const match = remoteUrl.match(/bitbucket\.org[\/:]([^\/]+)\/([^\/\.]+)/);
|
|
108
|
-
|
|
109
|
-
if (!match) {
|
|
110
|
-
throw new Error(
|
|
111
|
-
'Could not parse Bitbucket workspace and repository from remote URL',
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const [, workspace, repoSlug] = match;
|
|
116
|
-
|
|
117
|
-
// Check for Bitbucket credentials
|
|
118
|
-
const username = process.env.BITBUCKET_USERNAME;
|
|
119
|
-
const password = process.env.BITBUCKET_APP_PASSWORD;
|
|
120
|
-
|
|
121
|
-
if (!username || !password) {
|
|
122
|
-
console.log(
|
|
123
|
-
`\n⚠️ Bitbucket credentials not found. Cannot check existing PRs.`,
|
|
124
|
-
);
|
|
125
|
-
return [];
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const auth = Buffer.from(`${username}:${password}`).toString('base64');
|
|
129
|
-
const response = await fetch(
|
|
130
|
-
`https://api.bitbucket.org/2.0/repositories/${workspace}/${repoSlug}/pullrequests?state=OPEN`,
|
|
131
|
-
{
|
|
132
|
-
method: 'GET',
|
|
133
|
-
headers: {
|
|
134
|
-
Authorization: `Basic ${auth}`,
|
|
135
|
-
'Content-Type': 'application/json',
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
if (!response.ok) {
|
|
141
|
-
const error = await response.text();
|
|
142
|
-
throw new Error(`Bitbucket API error: ${response.status} - ${error}`);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const data = await response.json();
|
|
146
|
-
const matchingPRs = data.values.filter(
|
|
147
|
-
(pr) => pr.description && pr.description.startsWith(descriptionPattern),
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
return matchingPRs;
|
|
151
|
-
} catch (error) {
|
|
152
|
-
console.error(`Failed to get existing PRs: ${error.message}`);
|
|
153
|
-
return [];
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export async function createBitbucketPR(
|
|
158
|
-
sourceBranch,
|
|
159
|
-
targetBranch,
|
|
160
|
-
title,
|
|
161
|
-
description,
|
|
162
|
-
) {
|
|
163
|
-
try {
|
|
164
|
-
// Get Bitbucket workspace and repo from git remote
|
|
165
|
-
const remoteUrl = execSync('git config --get remote.origin.url', {
|
|
166
|
-
encoding: 'utf-8',
|
|
167
|
-
}).trim();
|
|
168
|
-
const match = remoteUrl.match(/bitbucket\.org[\/:]([^\/]+)\/([^\/\.]+)/);
|
|
169
|
-
|
|
170
|
-
if (!match) {
|
|
171
|
-
throw new Error(
|
|
172
|
-
'Could not parse Bitbucket workspace and repository from remote URL',
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const [, workspace, repoSlug] = match;
|
|
177
|
-
|
|
178
|
-
// Check for Bitbucket credentials
|
|
179
|
-
const username = process.env.BITBUCKET_USERNAME;
|
|
180
|
-
const password = process.env.BITBUCKET_APP_PASSWORD;
|
|
181
|
-
|
|
182
|
-
if (!username || !password) {
|
|
183
|
-
console.log(
|
|
184
|
-
`\n⚠️ Bitbucket credentials not found in environment variables.`,
|
|
185
|
-
);
|
|
186
|
-
console.log(
|
|
187
|
-
'Please set BITBUCKET_USERNAME and BITBUCKET_APP_PASSWORD to auto-create PR.',
|
|
188
|
-
);
|
|
189
|
-
console.log(
|
|
190
|
-
`Manual PR creation URL: https://bitbucket.org/${workspace}/${repoSlug}/pull-requests/new?source=${sourceBranch}&dest=${targetBranch}`,
|
|
191
|
-
);
|
|
192
|
-
return {
|
|
193
|
-
success: false,
|
|
194
|
-
manual: true,
|
|
195
|
-
url: `https://bitbucket.org/${workspace}/${repoSlug}/pull-requests/new?source=${sourceBranch}&dest=${targetBranch}`,
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Create PR via Bitbucket API
|
|
200
|
-
const prData = {
|
|
201
|
-
title,
|
|
202
|
-
description,
|
|
203
|
-
source: { branch: { name: sourceBranch } },
|
|
204
|
-
destination: { branch: { name: targetBranch } },
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
const auth = Buffer.from(`${username}:${password}`).toString('base64');
|
|
208
|
-
const response = await fetch(
|
|
209
|
-
`https://api.bitbucket.org/2.0/repositories/${workspace}/${repoSlug}/pullrequests`,
|
|
210
|
-
{
|
|
211
|
-
method: 'POST',
|
|
212
|
-
headers: {
|
|
213
|
-
Authorization: `Basic ${auth}`,
|
|
214
|
-
'Content-Type': 'application/json',
|
|
215
|
-
},
|
|
216
|
-
body: JSON.stringify(prData),
|
|
217
|
-
},
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
if (!response.ok) {
|
|
221
|
-
const error = await response.text();
|
|
222
|
-
throw new Error(`Bitbucket API error: ${response.status} - ${error}`);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const pr = await response.json();
|
|
226
|
-
return { success: true, pr, url: pr.links.html.href };
|
|
227
|
-
} catch (error) {
|
|
228
|
-
console.error(`Failed to create Bitbucket PR: ${error.message}`);
|
|
229
|
-
return { success: false, error: error.message };
|
|
230
|
-
}
|
|
231
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Create a Bitbucket pull request
|
|
3
|
+
* @param {string} sourceBranch - Source branch name
|
|
4
|
+
* @param {string} targetBranch - Target branch name
|
|
5
|
+
* @param {string} title - PR title
|
|
6
|
+
* @param {string} description - PR description
|
|
7
|
+
* @returns {Promise<Object>} - PR creation result
|
|
8
|
+
*/
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Check for existing pull requests with specific description pattern
|
|
13
|
+
* @param {string} descriptionPattern - Pattern to match in PR descriptions
|
|
14
|
+
* @returns {Promise<Object[]>} - Array of matching PRs
|
|
15
|
+
*/
|
|
16
|
+
export async function getExistingPRsWithDescription(
|
|
17
|
+
descriptionPattern,
|
|
18
|
+
repositories,
|
|
19
|
+
) {
|
|
20
|
+
// If no repositories provided, fall back to current repo behavior for backward compatibility
|
|
21
|
+
if (!repositories || !Array.isArray(repositories)) {
|
|
22
|
+
return getExistingPRsFromCurrentRepo(descriptionPattern);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
// Check for Bitbucket credentials
|
|
27
|
+
const username = process.env.BITBUCKET_USERNAME;
|
|
28
|
+
const password = process.env.BITBUCKET_APP_PASSWORD;
|
|
29
|
+
|
|
30
|
+
if (!username || !password) {
|
|
31
|
+
console.log(
|
|
32
|
+
`\n⚠️ Bitbucket credentials not found. Cannot check existing PRs.`,
|
|
33
|
+
);
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const auth = Buffer.from(`${username}:${password}`).toString('base64');
|
|
38
|
+
const allMatchingPRs = [];
|
|
39
|
+
|
|
40
|
+
// Check each repository for matching PRs
|
|
41
|
+
for (const repo of repositories) {
|
|
42
|
+
try {
|
|
43
|
+
const match = repo.url.match(/bitbucket\.org[\/:]([^\/]+)\/([^\/\.]+)/);
|
|
44
|
+
|
|
45
|
+
if (!match) {
|
|
46
|
+
console.warn(`Could not parse repository URL: ${repo.url}`);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const [, workspace, repoSlug] = match;
|
|
51
|
+
|
|
52
|
+
const response = await fetch(
|
|
53
|
+
`https://api.bitbucket.org/2.0/repositories/${workspace}/${repoSlug}/pullrequests?state=OPEN`,
|
|
54
|
+
{
|
|
55
|
+
method: 'GET',
|
|
56
|
+
headers: {
|
|
57
|
+
Authorization: `Basic ${auth}`,
|
|
58
|
+
'Content-Type': 'application/json',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
const error = await response.text();
|
|
65
|
+
console.warn(
|
|
66
|
+
`Bitbucket API error for ${repo.name}: ${response.status} - ${error}`,
|
|
67
|
+
);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const data = await response.json();
|
|
72
|
+
const matchingPRs = data.values.filter(
|
|
73
|
+
(pr) =>
|
|
74
|
+
pr.description && pr.description.startsWith(descriptionPattern),
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Add repository info to each PR for context
|
|
78
|
+
matchingPRs.forEach((pr) => {
|
|
79
|
+
pr.repositoryName = repo.name;
|
|
80
|
+
pr.repositoryUrl = repo.url;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
allMatchingPRs.push(...matchingPRs);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.warn(
|
|
86
|
+
`Failed to check PRs for repository ${repo.name}: ${error.message}`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return allMatchingPRs;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error(`Failed to get existing PRs: ${error.message}`);
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Legacy function for backward compatibility - checks PRs in current repo only
|
|
100
|
+
*/
|
|
101
|
+
export async function getExistingPRsFromCurrentRepo(descriptionPattern) {
|
|
102
|
+
try {
|
|
103
|
+
// Get Bitbucket workspace and repo from git remote
|
|
104
|
+
const remoteUrl = execSync('git config --get remote.origin.url', {
|
|
105
|
+
encoding: 'utf-8',
|
|
106
|
+
}).trim();
|
|
107
|
+
const match = remoteUrl.match(/bitbucket\.org[\/:]([^\/]+)\/([^\/\.]+)/);
|
|
108
|
+
|
|
109
|
+
if (!match) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
'Could not parse Bitbucket workspace and repository from remote URL',
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const [, workspace, repoSlug] = match;
|
|
116
|
+
|
|
117
|
+
// Check for Bitbucket credentials
|
|
118
|
+
const username = process.env.BITBUCKET_USERNAME;
|
|
119
|
+
const password = process.env.BITBUCKET_APP_PASSWORD;
|
|
120
|
+
|
|
121
|
+
if (!username || !password) {
|
|
122
|
+
console.log(
|
|
123
|
+
`\n⚠️ Bitbucket credentials not found. Cannot check existing PRs.`,
|
|
124
|
+
);
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const auth = Buffer.from(`${username}:${password}`).toString('base64');
|
|
129
|
+
const response = await fetch(
|
|
130
|
+
`https://api.bitbucket.org/2.0/repositories/${workspace}/${repoSlug}/pullrequests?state=OPEN`,
|
|
131
|
+
{
|
|
132
|
+
method: 'GET',
|
|
133
|
+
headers: {
|
|
134
|
+
Authorization: `Basic ${auth}`,
|
|
135
|
+
'Content-Type': 'application/json',
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
if (!response.ok) {
|
|
141
|
+
const error = await response.text();
|
|
142
|
+
throw new Error(`Bitbucket API error: ${response.status} - ${error}`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const data = await response.json();
|
|
146
|
+
const matchingPRs = data.values.filter(
|
|
147
|
+
(pr) => pr.description && pr.description.startsWith(descriptionPattern),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
return matchingPRs;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
console.error(`Failed to get existing PRs: ${error.message}`);
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export async function createBitbucketPR(
|
|
158
|
+
sourceBranch,
|
|
159
|
+
targetBranch,
|
|
160
|
+
title,
|
|
161
|
+
description,
|
|
162
|
+
) {
|
|
163
|
+
try {
|
|
164
|
+
// Get Bitbucket workspace and repo from git remote
|
|
165
|
+
const remoteUrl = execSync('git config --get remote.origin.url', {
|
|
166
|
+
encoding: 'utf-8',
|
|
167
|
+
}).trim();
|
|
168
|
+
const match = remoteUrl.match(/bitbucket\.org[\/:]([^\/]+)\/([^\/\.]+)/);
|
|
169
|
+
|
|
170
|
+
if (!match) {
|
|
171
|
+
throw new Error(
|
|
172
|
+
'Could not parse Bitbucket workspace and repository from remote URL',
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const [, workspace, repoSlug] = match;
|
|
177
|
+
|
|
178
|
+
// Check for Bitbucket credentials
|
|
179
|
+
const username = process.env.BITBUCKET_USERNAME;
|
|
180
|
+
const password = process.env.BITBUCKET_APP_PASSWORD;
|
|
181
|
+
|
|
182
|
+
if (!username || !password) {
|
|
183
|
+
console.log(
|
|
184
|
+
`\n⚠️ Bitbucket credentials not found in environment variables.`,
|
|
185
|
+
);
|
|
186
|
+
console.log(
|
|
187
|
+
'Please set BITBUCKET_USERNAME and BITBUCKET_APP_PASSWORD to auto-create PR.',
|
|
188
|
+
);
|
|
189
|
+
console.log(
|
|
190
|
+
`Manual PR creation URL: https://bitbucket.org/${workspace}/${repoSlug}/pull-requests/new?source=${sourceBranch}&dest=${targetBranch}`,
|
|
191
|
+
);
|
|
192
|
+
return {
|
|
193
|
+
success: false,
|
|
194
|
+
manual: true,
|
|
195
|
+
url: `https://bitbucket.org/${workspace}/${repoSlug}/pull-requests/new?source=${sourceBranch}&dest=${targetBranch}`,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Create PR via Bitbucket API
|
|
200
|
+
const prData = {
|
|
201
|
+
title,
|
|
202
|
+
description,
|
|
203
|
+
source: { branch: { name: sourceBranch } },
|
|
204
|
+
destination: { branch: { name: targetBranch } },
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const auth = Buffer.from(`${username}:${password}`).toString('base64');
|
|
208
|
+
const response = await fetch(
|
|
209
|
+
`https://api.bitbucket.org/2.0/repositories/${workspace}/${repoSlug}/pullrequests`,
|
|
210
|
+
{
|
|
211
|
+
method: 'POST',
|
|
212
|
+
headers: {
|
|
213
|
+
Authorization: `Basic ${auth}`,
|
|
214
|
+
'Content-Type': 'application/json',
|
|
215
|
+
},
|
|
216
|
+
body: JSON.stringify(prData),
|
|
217
|
+
},
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
if (!response.ok) {
|
|
221
|
+
const error = await response.text();
|
|
222
|
+
throw new Error(`Bitbucket API error: ${response.status} - ${error}`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const pr = await response.json();
|
|
226
|
+
return { success: true, pr, url: pr.links.html.href };
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.error(`Failed to create Bitbucket PR: ${error.message}`);
|
|
229
|
+
return { success: false, error: error.message };
|
|
230
|
+
}
|
|
231
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { $ } from '../next/logger.js';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import axios from 'axios';
|
|
5
|
+
|
|
6
|
+
export async function deployMicroservice(
|
|
7
|
+
appName,
|
|
8
|
+
helmPath,
|
|
9
|
+
environment = 'dev',
|
|
10
|
+
tag = null,
|
|
11
|
+
) {
|
|
12
|
+
if (!appName || !helmPath) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
'Missing required parameters. Usage: deployMicroservice(appName, helmPath, [environment], [tag])',
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let deployTag = tag;
|
|
19
|
+
if (!deployTag) {
|
|
20
|
+
deployTag =
|
|
21
|
+
process.env.VERSION_TAG ||
|
|
22
|
+
process.env.BITBUCKET_TAG ||
|
|
23
|
+
(process.env.BITBUCKET_BUILD_NUMBER
|
|
24
|
+
? `build-${process.env.BITBUCKET_BUILD_NUMBER}`
|
|
25
|
+
: null);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!deployTag) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
'No tag specified and no default tag available from environment variables',
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const repoName = `gitops-${environment}`;
|
|
35
|
+
const filePath = `dp/${helmPath}/${appName}.values.yaml`;
|
|
36
|
+
|
|
37
|
+
const gitopsBranch =
|
|
38
|
+
environment === 'dev' || environment === 'uat'
|
|
39
|
+
? process.env.GITOPS_BRANCH || 'master'
|
|
40
|
+
: process.env.GITOPS_BRANCH || 'main';
|
|
41
|
+
|
|
42
|
+
let repoUrl;
|
|
43
|
+
if (environment === 'dev' && process.env.GITOPS_REP_TOKEN) {
|
|
44
|
+
repoUrl = `https://x-token-auth:${process.env.GITOPS_REP_TOKEN}@bitbucket.org/dp-cloud/${repoName}.git`;
|
|
45
|
+
} else if (
|
|
46
|
+
process.env.BITBUCKET_USERNAME &&
|
|
47
|
+
process.env.BITBUCKET_APP_PASSWORD
|
|
48
|
+
) {
|
|
49
|
+
repoUrl = `https://${process.env.BITBUCKET_USERNAME}:${process.env.BITBUCKET_APP_PASSWORD}@bitbucket.org/dp-cloud/${repoName}.git`;
|
|
50
|
+
} else {
|
|
51
|
+
throw new Error(
|
|
52
|
+
'No authentication credentials found for GitOps repository',
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
console.log('=========================================');
|
|
57
|
+
console.log('Microservice Deployment Configuration');
|
|
58
|
+
console.log('=========================================');
|
|
59
|
+
console.log(`Application: ${appName}`);
|
|
60
|
+
console.log(`Environment: ${environment}`);
|
|
61
|
+
console.log(`Tag: ${deployTag}`);
|
|
62
|
+
console.log(`GitOps Repo: ${repoName}`);
|
|
63
|
+
console.log(`Values File: ${filePath}`);
|
|
64
|
+
console.log(`Branch: ${gitopsBranch}`);
|
|
65
|
+
console.log('=========================================');
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
console.log('Cloning GitOps repository...');
|
|
69
|
+
await $`git clone --depth 1 ${repoUrl} ${repoName}`;
|
|
70
|
+
|
|
71
|
+
console.log('Checking if directory exists...');
|
|
72
|
+
await $`ls -la ${repoName}`;
|
|
73
|
+
|
|
74
|
+
console.log(`Changing to directory: ${repoName}`);
|
|
75
|
+
const originalDir = process.cwd();
|
|
76
|
+
process.chdir(repoName);
|
|
77
|
+
|
|
78
|
+
console.log('Verifying directory change...');
|
|
79
|
+
const newDir = process.cwd();
|
|
80
|
+
console.log(`Original: ${originalDir}`);
|
|
81
|
+
console.log(`New: ${newDir}`);
|
|
82
|
+
|
|
83
|
+
await $`cd ${repoName} && git config user.email "pipeline@bitbucket.org"`;
|
|
84
|
+
|
|
85
|
+
if (process.env.BITBUCKET_STEP_TRIGGERER_UUID) {
|
|
86
|
+
try {
|
|
87
|
+
const response = await axios.get(
|
|
88
|
+
`https://api.bitbucket.org/2.0/users/${process.env.BITBUCKET_STEP_TRIGGERER_UUID}`,
|
|
89
|
+
);
|
|
90
|
+
const triggererUsername = response.data.display_name;
|
|
91
|
+
console.log(`📌 Run triggered by: ${triggererUsername}`);
|
|
92
|
+
await $`cd ${repoName} && git config user.name ${triggererUsername}`;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.warn('Failed to fetch Bitbucket user info:', error.message);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
console.log(`Attempting to checkout branch: ${gitopsBranch}`);
|
|
99
|
+
await $`cd ${repoName} && git checkout ${gitopsBranch}`;
|
|
100
|
+
|
|
101
|
+
const fullFilePath = path.resolve(filePath);
|
|
102
|
+
console.log(`Looking for file at: ${fullFilePath}`);
|
|
103
|
+
if (!fs.existsSync(fullFilePath)) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
`Values file ${filePath} does not exist in ${repoName} on branch ${gitopsBranch}`,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
console.log(`Updating image tag to ${deployTag}...`);
|
|
110
|
+
|
|
111
|
+
let fileContent = fs.readFileSync(fullFilePath, 'utf8');
|
|
112
|
+
|
|
113
|
+
const tagRegex = /^ {2}tag: .*/gm;
|
|
114
|
+
const newContent = fileContent.replace(tagRegex, ` tag: ${deployTag}`);
|
|
115
|
+
|
|
116
|
+
if (fileContent === newContent) {
|
|
117
|
+
console.log(`No changes detected - tag is already ${deployTag}`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
fs.writeFileSync(fullFilePath, newContent, 'utf8');
|
|
122
|
+
|
|
123
|
+
console.log('Changes to be committed:');
|
|
124
|
+
await $`cd ${repoName} && git diff ${filePath}`;
|
|
125
|
+
|
|
126
|
+
await $`cd ${repoName} && git add ${filePath}`;
|
|
127
|
+
await $`cd ${repoName} && git commit -m "Update ${appName} image tag to ${deployTag} in ${environment} environment"`;
|
|
128
|
+
|
|
129
|
+
console.log('Pushing changes to GitOps repository...');
|
|
130
|
+
await $`cd ${repoName} && git push origin ${gitopsBranch}`;
|
|
131
|
+
|
|
132
|
+
console.log('=========================================');
|
|
133
|
+
console.log(
|
|
134
|
+
`✅ Successfully deployed ${appName}:${deployTag} to ${environment}`,
|
|
135
|
+
);
|
|
136
|
+
console.log('=========================================');
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error('Error during microservice deployment:', error.message);
|
|
139
|
+
throw error;
|
|
140
|
+
} finally {
|
|
141
|
+
try {
|
|
142
|
+
process.chdir('..');
|
|
143
|
+
await $`rm -rf ${repoName}`;
|
|
144
|
+
} catch (cleanupError) {
|
|
145
|
+
console.warn(
|
|
146
|
+
'Warning: Failed to clean up temporary directory:',
|
|
147
|
+
cleanupError.message,
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export default deployMicroservice;
|
|
@@ -11,19 +11,21 @@ import { $ } from '../next/logger.js';
|
|
|
11
11
|
* @param {string} options.password - JFrog password
|
|
12
12
|
* @param {string} options.buildNumber - Build number
|
|
13
13
|
*/
|
|
14
|
-
export async function publishMicroservice(
|
|
14
|
+
export async function publishMicroservice(gitSha, options = {}) {
|
|
15
15
|
// Use environment variables as defaults, but allow overrides
|
|
16
|
-
|
|
17
|
-
const gitSha = (await $`git log --pretty=format:'%h' -n 1 `).stdout.trim();
|
|
18
|
-
|
|
19
16
|
const config = {
|
|
20
|
-
imageName:
|
|
17
|
+
imageName:
|
|
18
|
+
options.imageName || process.env.IMAGE_NAME || process.env.APP_NAME,
|
|
21
19
|
registryUrl: options.registryUrl || process.env.JF_REGISTRY_URL,
|
|
22
20
|
repoName: options.repoName || process.env.JF_REGISTRY_REPO_NAME,
|
|
23
21
|
username: options.username || process.env.JF_REGISTRY_USER_DEV,
|
|
24
22
|
password: options.password || process.env.JF_REGISTRY_PASSWORD_DEV,
|
|
25
23
|
buildNumber: options.buildNumber || process.env.BITBUCKET_BUILD_NUMBER,
|
|
26
|
-
tag:
|
|
24
|
+
tag:
|
|
25
|
+
options.tag ||
|
|
26
|
+
process.env.TAG ||
|
|
27
|
+
process.env.BITBUCKET_TAG ||
|
|
28
|
+
process.env.VERSION_TAG,
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
// Validate required fields
|