@elliemae/ds-monorepo-devops 3.51.0-next.10 → 3.51.0-next.12
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.
|
@@ -75,6 +75,25 @@ export async function promptForCommandOptions() {
|
|
|
75
75
|
...answers,
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
|
+
/*
|
|
79
|
+
* given a file name, gitRemote and gitBranch and a command, return the command to execute the command on each file with xargs
|
|
80
|
+
* @param options
|
|
81
|
+
* @param {string} [options.gitRemote] - the remote to take the file from
|
|
82
|
+
* @param {string} [options.gitBranch] - the branch to take the file from
|
|
83
|
+
* @param {string} [options.fileName] - the file to restore
|
|
84
|
+
* @param {boolean} [options.wantSubfolder] - whether to restore the file in all subfolders or current folder only
|
|
85
|
+
* @param {string} [options.cmd] - the command to execute on each file
|
|
86
|
+
*
|
|
87
|
+
* @returns {string} - the command to execute the command on each file with xargs
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* // => git ls-files origin/develop '** /CHANGELOG.md' | xargs git restore --source=origin/develop'
|
|
91
|
+
* executeCmdOnEachFileWithXargs({gitRemote: 'origin', gitBranch: 'develop', fileName: 'CHANGELOG.md', cmd: 'git restore --source=origin/develop' })
|
|
92
|
+
*/
|
|
93
|
+
const executeCmdOnEachFileWithXargs = ({ gitRemote, gitBranch, fileName, wantSubfolder = true, cmd }) =>
|
|
94
|
+
wantSubfolder
|
|
95
|
+
? `git ls-files ${gitRemote}/${gitBranch} '**/${fileName}' | xargs ${cmd}`
|
|
96
|
+
: `git ls-files ${gitRemote}/${gitBranch} '${fileName}' | xargs ${cmd}`;
|
|
78
97
|
|
|
79
98
|
/*
|
|
80
99
|
* given a file name, gitRemote and gitBranch, return the command to restore the file in all subfolders, taking the file from the remote branch
|
|
@@ -90,9 +109,35 @@ export async function promptForCommandOptions() {
|
|
|
90
109
|
* getRestoreFileFromBranchUnixCmd({gitRemote: 'origin', gitBranch: 'develop', fileName: 'CHANGELOG.md'})
|
|
91
110
|
*/
|
|
92
111
|
const getRestoreFileFromBranchUnixCmd = ({ gitRemote, gitBranch, fileName, wantSubfolder = true }) =>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
112
|
+
executeCmdOnEachFileWithXargs({
|
|
113
|
+
gitRemote,
|
|
114
|
+
gitBranch,
|
|
115
|
+
fileName,
|
|
116
|
+
wantSubfolder,
|
|
117
|
+
cmd: `git restore --source=${gitRemote}/${gitBranch} `,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
/*
|
|
121
|
+
* given a file name, gitRemote and gitBranch, return the command to add the files in all subfolders to the commit
|
|
122
|
+
* @param options
|
|
123
|
+
* @param {string} [options.gitRemote] - the remote to take the file from
|
|
124
|
+
* @param {string} [options.gitBranch] - the branch to take the file from
|
|
125
|
+
* @param {string} [options.fileName] - the file to restore
|
|
126
|
+
* @param {boolean} [options.wantSubfolder] - whether to restore the file in all subfolders or current folder only
|
|
127
|
+
* @returns {string} - the command to add the files in all subfolders to the commit
|
|
128
|
+
* @example
|
|
129
|
+
*
|
|
130
|
+
* // => git ls-files origin/develop '** /CHANGELOG.md' | xargs git add '
|
|
131
|
+
* getAddChangedFilesToCommitCmd({gitRemote: 'origin', gitBranch: 'develop', fileName: 'CHANGELOG.md'})
|
|
132
|
+
*/
|
|
133
|
+
const getAddChangedFilesToCommitCmd = ({ gitRemote, gitBranch, fileName, wantSubfolder = true }) =>
|
|
134
|
+
executeCmdOnEachFileWithXargs({
|
|
135
|
+
gitRemote,
|
|
136
|
+
gitBranch,
|
|
137
|
+
fileName,
|
|
138
|
+
wantSubfolder,
|
|
139
|
+
cmd: `git add `,
|
|
140
|
+
});
|
|
96
141
|
|
|
97
142
|
// 0 nothing to do, 1 can't auto-solve, -1 can auto-solve
|
|
98
143
|
const canAutosolvePackageJsonConflict = async (packageJsonFilePath) => {
|
|
@@ -138,6 +183,8 @@ const gitReverseMerge = async (options) => {
|
|
|
138
183
|
.replace(/\//g, '');
|
|
139
184
|
const newBranchName = `${gitBranch}-${gitCurrent}-${todayMMDDYYYY}`;
|
|
140
185
|
|
|
186
|
+
// pull latest version of current branch
|
|
187
|
+
await execSyntaxSugar({ command: `git pull` });
|
|
141
188
|
// create a new branch
|
|
142
189
|
await execSyntaxSugar({ command: `git checkout -b ${newBranchName}` });
|
|
143
190
|
// run the git merge command
|
|
@@ -156,19 +203,33 @@ const gitReverseMerge = async (options) => {
|
|
|
156
203
|
// 3 - keep any branch CHANGELOG.md (they will be auto-generated anyway)
|
|
157
204
|
const restoreChangelogCmd = getRestoreFileFromBranchUnixCmd({
|
|
158
205
|
gitRemote,
|
|
159
|
-
gitCurrent,
|
|
206
|
+
gitBranch: gitCurrent,
|
|
160
207
|
fileName: 'CHANGELOG.md',
|
|
161
208
|
wantSubfolder: false,
|
|
162
209
|
});
|
|
163
210
|
await execSyntaxSugar({ command: restoreChangelogCmd });
|
|
211
|
+
const addChangelogCmd = getAddChangedFilesToCommitCmd({
|
|
212
|
+
gitRemote,
|
|
213
|
+
gitBranch: gitCurrent,
|
|
214
|
+
fileName: 'CHANGELOG.md',
|
|
215
|
+
wantSubfolder: false,
|
|
216
|
+
});
|
|
217
|
+
await execSyntaxSugar({ command: addChangelogCmd });
|
|
164
218
|
// 4 - keep any branch ** /CHANGELOG.md (they will be auto-generated anyway)
|
|
165
219
|
const restoreChangelogsCmd = getRestoreFileFromBranchUnixCmd({
|
|
166
220
|
gitRemote,
|
|
167
|
-
gitCurrent,
|
|
221
|
+
gitBranch: gitCurrent,
|
|
168
222
|
fileName: 'CHANGELOG.md',
|
|
169
223
|
wantSubfolder: true,
|
|
170
224
|
});
|
|
171
225
|
await execSyntaxSugar({ command: restoreChangelogsCmd });
|
|
226
|
+
const addChangelogsCmd = getAddChangedFilesToCommitCmd({
|
|
227
|
+
gitRemote,
|
|
228
|
+
gitBranch: gitCurrent,
|
|
229
|
+
fileName: 'CHANGELOG.md',
|
|
230
|
+
wantSubfolder: true,
|
|
231
|
+
});
|
|
232
|
+
await execSyntaxSugar({ command: addChangelogsCmd });
|
|
172
233
|
|
|
173
234
|
// we check all package.json files for conflicts and resolve those that can be auto-resolved, listin the ones that can't
|
|
174
235
|
const cantAutoSolve = [];
|
|
@@ -192,15 +253,29 @@ const gitReverseMerge = async (options) => {
|
|
|
192
253
|
wantSubfolder: false,
|
|
193
254
|
});
|
|
194
255
|
await execSyntaxSugar({ command: restorePackageJsonCmd });
|
|
256
|
+
const addPackageJsonCmd = getAddChangedFilesToCommitCmd({
|
|
257
|
+
gitRemote,
|
|
258
|
+
gitBranch,
|
|
259
|
+
fileName: packageJsonFilePath,
|
|
260
|
+
wantSubfolder: false,
|
|
261
|
+
});
|
|
262
|
+
await execSyntaxSugar({ command: addPackageJsonCmd });
|
|
195
263
|
}
|
|
196
264
|
|
|
197
|
-
// 6 - run 'pnpm run use-registry-version && pnpm run use-workspace-version' to update the package.json files with the correct version
|
|
198
|
-
await execSyntaxSugar({ command: 'pnpm run use-registry-version && pnpm run use-workspace-version' });
|
|
199
|
-
|
|
200
265
|
// if there are conflicts that can't be auto-solved, list them
|
|
266
|
+
// and because we can't resolve them, we can't continue with the automatic process
|
|
201
267
|
if (cantAutoSolve.length > 0) {
|
|
202
268
|
console.log("The following package.json files have conflicts that can't be auto-solved:");
|
|
203
269
|
console.log(cantAutoSolve.join('\n'));
|
|
270
|
+
console.log('Please resolve these conflicts manually and finish the merge manually too');
|
|
271
|
+
console.log(
|
|
272
|
+
'you probably will need to run \n\t`pnpm run use-registry-version && pnpm run use-workspace-version`\nafter you resolve the package.json conflicts',
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// 6 - run 'pnpm run use-registry-version && pnpm run use-workspace-version' to update the package.json files with the correct version
|
|
277
|
+
if (cantAutoSolve.length === 0) {
|
|
278
|
+
await execSyntaxSugar({ command: 'pnpm run use-registry-version && pnpm run use-workspace-version' });
|
|
204
279
|
}
|
|
205
280
|
};
|
|
206
281
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import inquirer from 'inquirer';
|
|
2
2
|
import { execSyncNxTags } from './execSyncNxTags/index.mjs';
|
|
3
|
-
import {execGitReverseMerge} from './execGitReverseMerge/index.mjs';
|
|
3
|
+
import { execGitReverseMerge } from './execGitReverseMerge/index.mjs';
|
|
4
|
+
import { execForcePnpmCatalogVersions } from './forcePnpmCatalogVersions/index.mjs';
|
|
4
5
|
|
|
5
6
|
const COMMANDS = {
|
|
6
7
|
SYNC_NX_TAGS: 'sync-nx-tags',
|
|
7
8
|
REVERSE_MERGE_BRANCH: 'reverse-merge-branch',
|
|
9
|
+
FORCE_PNPM_CATALOG_VERSIONS: 'force-pnpm-catalog-versions',
|
|
8
10
|
EXIT: 'exit',
|
|
9
11
|
};
|
|
10
12
|
export const checkCommandOrInquire = async (options) => {
|
|
@@ -32,6 +34,9 @@ export async function executeCommandsMap(args, options) {
|
|
|
32
34
|
case COMMANDS.REVERSE_MERGE_BRANCH:
|
|
33
35
|
execGitReverseMerge(options);
|
|
34
36
|
break;
|
|
37
|
+
case COMMANDS.FORCE_PNPM_CATALOG_VERSIONS:
|
|
38
|
+
execForcePnpmCatalogVersions(options);
|
|
39
|
+
break;
|
|
35
40
|
default:
|
|
36
41
|
break;
|
|
37
42
|
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/* eslint-disable complexity, no-console, max-statements */
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import defGlob from 'glob';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
const { glob } = defGlob;
|
|
7
|
+
|
|
8
|
+
export async function promptForCommandOptions(options) {
|
|
9
|
+
const questions = [];
|
|
10
|
+
if (!options.dryRun) {
|
|
11
|
+
questions.push({
|
|
12
|
+
type: 'list',
|
|
13
|
+
name: 'dryRun',
|
|
14
|
+
message: 'dry-run?',
|
|
15
|
+
default: 'n',
|
|
16
|
+
choices: ['y', 'n'],
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
const answers = await inquirer.prompt(questions);
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
...answers,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* read the file cwd + pnpm-workspace.yaml and based on the "catalog:" field,
|
|
27
|
+
*
|
|
28
|
+
* check all subfolders under cwd + packages/ for a package.json file
|
|
29
|
+
* any dependency/devDependency/peerDependency that matches something that is in the catalog: field
|
|
30
|
+
* will be pointed to the catalog version via the "catalog:" value
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
*
|
|
34
|
+
* `pnpm-workspace.yaml`
|
|
35
|
+
* ```yaml
|
|
36
|
+
* catalog:
|
|
37
|
+
* react: 18.2.0
|
|
38
|
+
* ```
|
|
39
|
+
* `packages/my-package/package.json`
|
|
40
|
+
* ```json
|
|
41
|
+
* {
|
|
42
|
+
* "dependencies": {
|
|
43
|
+
* "react": "no-matter-what",
|
|
44
|
+
* "some-other-dep": "^1.0.0",
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
* expected result:
|
|
49
|
+
* `packages/my-package/package.json`
|
|
50
|
+
* ```json
|
|
51
|
+
* {
|
|
52
|
+
* "dependencies": {
|
|
53
|
+
* "react": "catalog:",
|
|
54
|
+
* "some-other-dep": "^1.0.0",
|
|
55
|
+
* }
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @param options
|
|
60
|
+
* @param {string} [options.dryRun='n'] - Indicates whether to perform a dry run ('y' or 'n').
|
|
61
|
+
* @returns {Promise<void>}
|
|
62
|
+
*/
|
|
63
|
+
const convertDepsToCatalogIfExisting = async (options) => {
|
|
64
|
+
const { dryRun } = options;
|
|
65
|
+
const pnpmWorspaceFilePath = path.resolve(process.cwd(), 'pnpm-workspace.yaml');
|
|
66
|
+
const pnpmWorkspaceAsString = fs.existsSync(pnpmWorspaceFilePath)
|
|
67
|
+
? fs.readFileSync(pnpmWorspaceFilePath, 'utf8')
|
|
68
|
+
: -1;
|
|
69
|
+
if (pnpmWorkspaceAsString === -1) {
|
|
70
|
+
console.log('No pnpm-workspace.yaml found');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const catalogStrings = [...pnpmWorkspaceAsString.matchAll(/catalog:\n((?:\s{2}.*\n?)*)/gm)]?.[0]?.[1] ?? '';
|
|
74
|
+
const catalogPackagesKeys = [...catalogStrings.matchAll(/(?:[\ ]{2}["']?)([\s\S]*?)(?:["']?:)/gm)].map((m) => m?.[1]);
|
|
75
|
+
if (!catalogPackagesKeys.length === 0) {
|
|
76
|
+
console.log('No catalog packages found');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const globPatternPackage = 'packages/**/*/package.json';
|
|
80
|
+
const packageJsonFilesPaths = glob(globPatternPackage, { sync: true, ignore: ['**/node_modules/**', '**/dist/**'] });
|
|
81
|
+
for (let i = 0; i < packageJsonFilesPaths.length; i += 1) {
|
|
82
|
+
const packageJsonFilePath = packageJsonFilesPaths[i];
|
|
83
|
+
const finalPath = path.resolve(process.cwd(), packageJsonFilePath);
|
|
84
|
+
const packageJson = JSON.parse(fs.readFileSync(finalPath, 'utf8'));
|
|
85
|
+
|
|
86
|
+
const { dependencies = {}, devDependencies = {}, peerDependencies = {} } = packageJson;
|
|
87
|
+
|
|
88
|
+
const log = {
|
|
89
|
+
changedDeps: [],
|
|
90
|
+
changedDevDeps: [],
|
|
91
|
+
changedPeerDeps: [],
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
Object.keys(dependencies).forEach((pkg) => {
|
|
95
|
+
const isInCatalog = catalogPackagesKeys.includes(pkg);
|
|
96
|
+
if (isInCatalog) {
|
|
97
|
+
packageJson.dependencies[pkg] = 'catalog:';
|
|
98
|
+
log.changedDeps.push(pkg);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
Object.keys(devDependencies).forEach((pkg) => {
|
|
102
|
+
const isInCatalog = catalogPackagesKeys.includes(pkg);
|
|
103
|
+
if (isInCatalog) {
|
|
104
|
+
packageJson.devDependencies[pkg] = 'catalog:';
|
|
105
|
+
log.changedDevDeps.push(pkg);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
Object.keys(peerDependencies).forEach((pkg) => {
|
|
109
|
+
const isInCatalog = catalogPackagesKeys.includes(pkg);
|
|
110
|
+
if (isInCatalog) {
|
|
111
|
+
packageJson.peerDependencies[pkg] = 'catalog:';
|
|
112
|
+
log.changedPeerDeps.push(pkg);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
if (dryRun === 'n') {
|
|
117
|
+
fs.writeFileSync(packageJsonFilePath, JSON.stringify(packageJson, null, 2));
|
|
118
|
+
if (log.changedDeps.length > 0)
|
|
119
|
+
console.log(`Updated ${packageJsonFilePath} dependencies: ${log.changedDeps.join(', ')}`);
|
|
120
|
+
if (log.changedDevDeps.length > 0)
|
|
121
|
+
console.log(`Updated ${packageJsonFilePath} devDependencies: ${log.changedDevDeps.join(', ')}`);
|
|
122
|
+
if (log.changedPeerDeps.length > 0)
|
|
123
|
+
console.log(`Updated ${packageJsonFilePath} peerDependencies: ${log.changedPeerDeps.join(', ')}`);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (dryRun === 'y') {
|
|
127
|
+
if (log.changedDeps.length > 0)
|
|
128
|
+
console.log(`Would update ${packageJsonFilePath} dependencies: ${log.changedDeps.join(', ')}`);
|
|
129
|
+
if (log.changedDevDeps.length > 0)
|
|
130
|
+
console.log(`Would update ${packageJsonFilePath} devDependencies: ${log.changedDevDeps.join(', ')}`);
|
|
131
|
+
if (log.changedPeerDeps.length > 0)
|
|
132
|
+
console.log(`Would update ${packageJsonFilePath} peerDependencies: ${log.changedPeerDeps.join(', ')}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export const execForcePnpmCatalogVersions = async (options) => {
|
|
138
|
+
const commandOptions = await promptForCommandOptions(options);
|
|
139
|
+
await convertDepsToCatalogIfExisting(commandOptions);
|
|
140
|
+
};
|