-
-
Notifications
You must be signed in to change notification settings - Fork 84
Expand file tree
/
Copy pathprepare-current-release-plan.mjs
More file actions
129 lines (110 loc) · 3.78 KB
/
prepare-current-release-plan.mjs
File metadata and controls
129 lines (110 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import { listWorkspaces } from '../list-workspaces/list-workspaces.mjs';
import fs from 'node:fs/promises';
import path from 'node:path';
import { currentVersion } from './current-version.mjs';
import { canPublish } from './npm-can-publish.mjs';
import { whoami } from './npm-whoami.mjs';
export async function prepareCurrentReleasePlan() {
const iam = await whoami();
if (!iam) {
throw new Error('Could not determine current npm user');
}
const workspaces = await listWorkspaces();
// Things to release
const needsRelease = new Map();
// Things that should be released after this plan
const maybeNextPlan = new Map();
// Things not to release
const notReleasableNow = new Map();
WORKSPACES_LOOP:
for (const workspace of workspaces) {
if (workspace.private) {
continue;
}
for (const dependency of workspace.dependencies) {
if (needsRelease.has(dependency) || notReleasableNow.has(dependency)) {
notReleasableNow.set(workspace.name, workspace);
let changelog = (await fs.readFile(path.join(workspace.path, 'CHANGELOG.md'))).toString();
if (changelog.includes('Unreleased')) {
maybeNextPlan.set(workspace.name, workspace);
}
// Can not be released before all modified dependencies have been released.
continue WORKSPACES_LOOP;
}
}
let changelog = (await fs.readFile(path.join(workspace.path, 'CHANGELOG.md'))).toString();
if (changelog.includes('Unreleased')) {
let increment;
if (changelog.includes('Unreleased (patch)')) {
increment = 'patch';
} else if (changelog.includes('Unreleased (minor)')) {
increment = 'minor';
} else if (changelog.includes('Unreleased (major)')) {
increment = 'major';
} else {
// eslint-disable-next-line no-console
console.warn('Invalid CHANGELOG.md in', workspace.name);
notReleasableNow.set(workspace.name, workspace);
continue WORKSPACES_LOOP;
}
if (!(await canPublish(workspace.name, iam))) {
if (increment !== 'patch') {
// Patch releases that we can not publish are safe to skip.
// Only new features and breaking changes are important down stream.
notReleasableNow.set(workspace.name, workspace);
}
// eslint-disable-next-line no-console
console.warn('Current npm user does not have write access for', workspace.name);
continue WORKSPACES_LOOP;
}
workspace.increment = increment;
workspace.changelog = changelog;
needsRelease.set(workspace.name, workspace);
}
}
// Only do a single initial publish at a time
for (const [workspaceName, workspace] of needsRelease) {
const version = await currentVersion(workspace.path);
if (version === '0.0.0') {
const allWorkspaces = new Map(needsRelease);
allWorkspaces.delete(workspaceName);
needsRelease.clear();
needsRelease.set(workspaceName, workspace);
for (const [workspaceName, workspace] of allWorkspaces) {
maybeNextPlan.set(workspaceName, workspace);
notReleasableNow.set(workspaceName, workspace);
}
break;
}
}
if (needsRelease.size === 0) {
// eslint-disable-next-line no-console
console.log('Nothing to release');
process.exit(0);
}
if (maybeNextPlan.size) {
// eslint-disable-next-line no-console
console.log('Excluded:');
for (const workspace of maybeNextPlan.values()) {
// eslint-disable-next-line no-console
console.log(` - ${workspace.name}`);
}
// eslint-disable-next-line no-console
console.log(''); // empty line
}
if (needsRelease.size) {
// eslint-disable-next-line no-console
console.log('Release plan:');
for (const workspace of needsRelease.values()) {
// eslint-disable-next-line no-console
console.log(` - ${workspace.name} (${workspace.increment})`);
}
// eslint-disable-next-line no-console
console.log(''); // empty line
}
return {
needsRelease,
maybeNextPlan,
notReleasableNow,
};
}