@docupace/pipeline 1.0.72 → 1.0.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docupace/pipeline",
3
- "version": "1.0.72",
3
+ "version": "1.0.74",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,6 +2,7 @@ import { execSync } from 'child_process';
2
2
  import { readFileSync, existsSync, mkdirSync } from 'fs';
3
3
  import { join, dirname } from 'path';
4
4
  import { fileURLToPath } from 'url';
5
+ import { getExistingPRsWithDescription } from './pr.js';
5
6
 
6
7
  const __dirname = dirname(fileURLToPath(import.meta.url));
7
8
 
@@ -373,6 +374,28 @@ async function mergeAll(verbose = false) {
373
374
  // Read configuration
374
375
  const config = readMergeConfig(verbose);
375
376
 
377
+ // Check for existing PRs with "Automated merge with changeset" description
378
+ if (verbose) console.log('šŸ” Checking for existing automated merge PRs...');
379
+ const existingPRs = await getExistingPRsWithDescription(
380
+ 'Automated merge with changeset',
381
+ config.repositories,
382
+ );
383
+
384
+ if (existingPRs.length > 0) {
385
+ console.log(
386
+ `āŒ Found ${existingPRs.length} existing pull request(s) with "Automated merge with changeset" description. Exiting to prevent conflicts.`,
387
+ );
388
+ if (verbose) {
389
+ existingPRs.forEach((pr) => {
390
+ console.log(` - PR #${pr.id}: ${pr.title} in ${pr.repositoryName || 'unknown repo'} (${pr.links.html.href})`);
391
+ });
392
+ }
393
+ process.exit(1);
394
+ }
395
+
396
+ if (verbose)
397
+ console.log('āœ… No existing automated merge PRs found. Proceeding...');
398
+
376
399
  // Setup repos directory
377
400
  const reposDir = join(process.cwd(), 'repos');
378
401
  if (!existsSync(reposDir)) {
package/src/merge/pr.js CHANGED
@@ -8,6 +8,144 @@
8
8
  */
9
9
  import { execSync } from 'child_process';
10
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(descriptionPattern, repositories) {
17
+ // If no repositories provided, fall back to current repo behavior for backward compatibility
18
+ if (!repositories || !Array.isArray(repositories)) {
19
+ return getExistingPRsFromCurrentRepo(descriptionPattern);
20
+ }
21
+
22
+ try {
23
+ // Check for Bitbucket credentials
24
+ const username = process.env.BITBUCKET_USERNAME;
25
+ const password = process.env.BITBUCKET_APP_PASSWORD;
26
+
27
+ if (!username || !password) {
28
+ console.log(
29
+ `\nāš ļø Bitbucket credentials not found. Cannot check existing PRs.`,
30
+ );
31
+ return [];
32
+ }
33
+
34
+ const auth = Buffer.from(`${username}:${password}`).toString('base64');
35
+ const allMatchingPRs = [];
36
+
37
+ // Check each repository for matching PRs
38
+ for (const repo of repositories) {
39
+ try {
40
+ const match = repo.url.match(/bitbucket\.org[\/:]([^\/]+)\/([^\/\.]+)/);
41
+
42
+ if (!match) {
43
+ console.warn(`Could not parse repository URL: ${repo.url}`);
44
+ continue;
45
+ }
46
+
47
+ const [, workspace, repoSlug] = match;
48
+
49
+ const response = await fetch(
50
+ `https://api.bitbucket.org/2.0/repositories/${workspace}/${repoSlug}/pullrequests?state=OPEN`,
51
+ {
52
+ method: 'GET',
53
+ headers: {
54
+ Authorization: `Basic ${auth}`,
55
+ 'Content-Type': 'application/json',
56
+ },
57
+ },
58
+ );
59
+
60
+ if (!response.ok) {
61
+ const error = await response.text();
62
+ console.warn(`Bitbucket API error for ${repo.name}: ${response.status} - ${error}`);
63
+ continue;
64
+ }
65
+
66
+ const data = await response.json();
67
+ const matchingPRs = data.values.filter(pr =>
68
+ pr.description && pr.description.startsWith(descriptionPattern)
69
+ );
70
+
71
+ // Add repository info to each PR for context
72
+ matchingPRs.forEach(pr => {
73
+ pr.repositoryName = repo.name;
74
+ pr.repositoryUrl = repo.url;
75
+ });
76
+
77
+ allMatchingPRs.push(...matchingPRs);
78
+ } catch (error) {
79
+ console.warn(`Failed to check PRs for repository ${repo.name}: ${error.message}`);
80
+ }
81
+ }
82
+
83
+ return allMatchingPRs;
84
+ } catch (error) {
85
+ console.error(`Failed to get existing PRs: ${error.message}`);
86
+ return [];
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Legacy function for backward compatibility - checks PRs in current repo only
92
+ */
93
+ export async function getExistingPRsFromCurrentRepo(descriptionPattern) {
94
+ try {
95
+ // Get Bitbucket workspace and repo from git remote
96
+ const remoteUrl = execSync('git config --get remote.origin.url', {
97
+ encoding: 'utf-8',
98
+ }).trim();
99
+ const match = remoteUrl.match(/bitbucket\.org[\/:]([^\/]+)\/([^\/\.]+)/);
100
+
101
+ if (!match) {
102
+ throw new Error(
103
+ 'Could not parse Bitbucket workspace and repository from remote URL',
104
+ );
105
+ }
106
+
107
+ const [, workspace, repoSlug] = match;
108
+
109
+ // Check for Bitbucket credentials
110
+ const username = process.env.BITBUCKET_USERNAME;
111
+ const password = process.env.BITBUCKET_APP_PASSWORD;
112
+
113
+ if (!username || !password) {
114
+ console.log(
115
+ `\nāš ļø Bitbucket credentials not found. Cannot check existing PRs.`,
116
+ );
117
+ return [];
118
+ }
119
+
120
+ const auth = Buffer.from(`${username}:${password}`).toString('base64');
121
+ const response = await fetch(
122
+ `https://api.bitbucket.org/2.0/repositories/${workspace}/${repoSlug}/pullrequests?state=OPEN`,
123
+ {
124
+ method: 'GET',
125
+ headers: {
126
+ Authorization: `Basic ${auth}`,
127
+ 'Content-Type': 'application/json',
128
+ },
129
+ },
130
+ );
131
+
132
+ if (!response.ok) {
133
+ const error = await response.text();
134
+ throw new Error(`Bitbucket API error: ${response.status} - ${error}`);
135
+ }
136
+
137
+ const data = await response.json();
138
+ const matchingPRs = data.values.filter(pr =>
139
+ pr.description && pr.description.startsWith(descriptionPattern)
140
+ );
141
+
142
+ return matchingPRs;
143
+ } catch (error) {
144
+ console.error(`Failed to get existing PRs: ${error.message}`);
145
+ return [];
146
+ }
147
+ }
148
+
11
149
  export async function createBitbucketPR(
12
150
  sourceBranch,
13
151
  targetBranch,
@@ -20,13 +20,13 @@ export const environmentConfig = {
20
20
  uat: {
21
21
  newUrl: (site) => `https://${site}.uat.dpai.tech`,
22
22
  oldUrl: (site) => `https://uat.paperout.com/${site}`,
23
- docupaceHost: () => 'uat.paperout.com',
23
+ docupaceHost: () => 'www.uat.paperout.com',
24
24
  ccUrl: (site) => `https://${site}-cc.uat.dpai.tech`,
25
25
  },
26
26
  stage: {
27
27
  newUrl: (site) => `https://${site}.stage.dpai.tech`,
28
28
  oldUrl: (site) => `https://stage.paperout.com/${site}`,
29
- docupaceHost: () => 'stage.paperout.com',
29
+ docupaceHost: () => 'www.stage.paperout.com',
30
30
  ccUrl: (site) => `https://${site}-cc.stage.dpai.tech`,
31
31
  },
32
32
  prod: {