@aidc-toolkit/dev 0.9.16-beta → 0.9.18-beta
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/config/publish.json +60 -0
- package/dev.iml +9 -0
- package/dist/eslint-config-template.d.ts.map +1 -1
- package/dist/eslint-config-template.js +9 -2
- package/dist/eslint-config-template.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/{command-util.d.ts → utility.d.ts} +6 -1
- package/dist/utility.d.ts.map +1 -0
- package/dist/utility.js +58 -0
- package/dist/utility.js.map +1 -0
- package/eslint.config.ts +1 -1
- package/package.json +15 -17
- package/src/eslint-config-template.ts +10 -2
- package/src/index.ts +1 -1
- package/src/publish-external.ts +362 -0
- package/src/publish-internal.ts +174 -0
- package/src/publish.ts +287 -0
- package/src/{command-util.ts → utility.ts} +25 -1
- package/tsconfig-build-dev-local.json +1 -0
- package/tsconfig-build-dev.json +1 -0
- package/tsconfig.json +7 -0
- package/bin/publish-dev +0 -8
- package/bin/publish-dev-local +0 -8
- package/config/release.json +0 -30
- package/dist/command-util.d.ts.map +0 -1
- package/dist/command-util.js +0 -32
- package/dist/command-util.js.map +0 -1
- package/dist/publish-dev.d.ts +0 -5
- package/dist/publish-dev.d.ts.map +0 -1
- package/dist/publish-dev.js +0 -72
- package/dist/publish-dev.js.map +0 -1
- package/src/publish-dev.ts +0 -110
- package/src/release.ts +0 -428
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { setTimeout } from "node:timers/promises";
|
|
4
|
+
import { Octokit } from "octokit";
|
|
5
|
+
import { parse as yamlParse } from "yaml";
|
|
6
|
+
import {
|
|
7
|
+
anyChanges,
|
|
8
|
+
commitConfiguration,
|
|
9
|
+
configuration,
|
|
10
|
+
organizationRepository,
|
|
11
|
+
type PackageConfiguration,
|
|
12
|
+
publishRepositories,
|
|
13
|
+
type Repository,
|
|
14
|
+
saveConfiguration,
|
|
15
|
+
secureConfiguration
|
|
16
|
+
} from "./publish";
|
|
17
|
+
import { logger, run } from "./utility.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Configuration layout of release.yml workflow (relevant attributes only).
|
|
21
|
+
*/
|
|
22
|
+
interface WorkflowConfiguration {
|
|
23
|
+
/**
|
|
24
|
+
* Workflow name.
|
|
25
|
+
*/
|
|
26
|
+
name: string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Workflow trigger.
|
|
30
|
+
*/
|
|
31
|
+
on: {
|
|
32
|
+
/**
|
|
33
|
+
* Push trigger.
|
|
34
|
+
*/
|
|
35
|
+
push?: {
|
|
36
|
+
/**
|
|
37
|
+
* Push branches.
|
|
38
|
+
*/
|
|
39
|
+
branches?: string[];
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Release trigger.
|
|
44
|
+
*/
|
|
45
|
+
release?: {
|
|
46
|
+
/**
|
|
47
|
+
* Release types.
|
|
48
|
+
*/
|
|
49
|
+
types?: string[];
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Supported steps.
|
|
56
|
+
*/
|
|
57
|
+
type Step = "skipped" | "install" | "build" | "commit" | "tag" | "push" | "workflow (push)" | "release" | "workflow (release)" | "restore alpha" | "complete";
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Execute a step.
|
|
61
|
+
*
|
|
62
|
+
* @param repository
|
|
63
|
+
* Repository.
|
|
64
|
+
*
|
|
65
|
+
* @param step
|
|
66
|
+
* State at which step takes place.
|
|
67
|
+
*
|
|
68
|
+
* @param callback
|
|
69
|
+
* Callback to execute step.
|
|
70
|
+
*
|
|
71
|
+
* @returns
|
|
72
|
+
* Promise.
|
|
73
|
+
*/
|
|
74
|
+
async function runStep(repository: Repository, step: Step, callback: () => (void | Promise<void>)): Promise<void> {
|
|
75
|
+
if (repository.publishExternalStep === undefined || repository.publishExternalStep === step) {
|
|
76
|
+
logger.debug(`Running step ${step}`);
|
|
77
|
+
|
|
78
|
+
repository.publishExternalStep = step;
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
const result = callback();
|
|
82
|
+
|
|
83
|
+
if (result instanceof Promise) {
|
|
84
|
+
await result;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
repository.publishExternalStep = undefined;
|
|
88
|
+
} finally {
|
|
89
|
+
saveConfiguration();
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
logger.debug(`Skipping step ${step}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Update dependencies from the organization.
|
|
98
|
+
*
|
|
99
|
+
* @param restoreAlpha
|
|
100
|
+
* If true, restore "alpha" as the version for development.
|
|
101
|
+
*
|
|
102
|
+
* @param development
|
|
103
|
+
* True if updating development dependencies.
|
|
104
|
+
*
|
|
105
|
+
* @param internal
|
|
106
|
+
* True if the package is for internal use only and its version should not be used in dependencies.
|
|
107
|
+
*
|
|
108
|
+
* @param dependencies
|
|
109
|
+
* Dependencies.
|
|
110
|
+
*
|
|
111
|
+
* @returns
|
|
112
|
+
* True if any dependencies were updated.
|
|
113
|
+
*/
|
|
114
|
+
function updateDependencies(restoreAlpha: boolean, development: boolean, internal: boolean | undefined, dependencies: Record<string, string> | undefined): boolean {
|
|
115
|
+
let anyUpdated = false;
|
|
116
|
+
|
|
117
|
+
if (dependencies !== undefined) {
|
|
118
|
+
// eslint-disable-next-line guard-for-in -- Dependency record type is shallow.
|
|
119
|
+
for (const dependency in dependencies) {
|
|
120
|
+
const dependencyRepositoryName = organizationRepository(dependency);
|
|
121
|
+
|
|
122
|
+
if (dependencyRepositoryName !== null) {
|
|
123
|
+
const dependencyRepository = configuration.repositories[dependencyRepositoryName];
|
|
124
|
+
|
|
125
|
+
// Set to explicit version for external dependency.
|
|
126
|
+
if (dependencyRepository.dependencyType === "external") {
|
|
127
|
+
dependencies[dependency] = !restoreAlpha ? `^${dependencyRepository.lastExternalVersion}` : "alpha";
|
|
128
|
+
anyUpdated = true;
|
|
129
|
+
} else if (!restoreAlpha && !development && internal !== true) {
|
|
130
|
+
throw new Error("Internal dependency specified for external package");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return anyUpdated;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const octokit = new Octokit({
|
|
140
|
+
auth: secureConfiguration.token,
|
|
141
|
+
userAgent: `${configuration.organization} release`
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
await publishRepositories(async (name, repository) => {
|
|
145
|
+
const packageConfigurationPath = "package.json";
|
|
146
|
+
|
|
147
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Package configuration format is known.
|
|
148
|
+
const packageConfiguration = JSON.parse(fs.readFileSync(packageConfigurationPath).toString()) as PackageConfiguration;
|
|
149
|
+
|
|
150
|
+
let packageVersion = packageConfiguration.version;
|
|
151
|
+
|
|
152
|
+
const packageVersionSplits = packageVersion.split("-");
|
|
153
|
+
|
|
154
|
+
// Extract semantic version and pre-release identifier.
|
|
155
|
+
const semanticVersion = packageVersionSplits[0];
|
|
156
|
+
const preReleaseIdentifier = packageVersionSplits.length !== 1 ? `-${packageVersionSplits[1]}` : "";
|
|
157
|
+
|
|
158
|
+
// Parse semantic version into its components.
|
|
159
|
+
const [majorVersion, minorVersion, patchVersion] = semanticVersion.split(".").map(versionString => Number(versionString));
|
|
160
|
+
|
|
161
|
+
// Local code must be on branch matching version.
|
|
162
|
+
const branch = run(true, "git", "branch", "--show-current")[0];
|
|
163
|
+
if (branch !== `v${majorVersion}.${minorVersion}`) {
|
|
164
|
+
throw new Error(`Repository must be on version branch ${branch}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
let publish: boolean;
|
|
168
|
+
|
|
169
|
+
switch (repository.publishExternalStep) {
|
|
170
|
+
case undefined:
|
|
171
|
+
// Check for publish external always is done afterward so that check for uncommitted files can be done.
|
|
172
|
+
publish = anyChanges(repository, true) || repository.publishExternalAlways === true;
|
|
173
|
+
|
|
174
|
+
if (publish && anyChanges(repository, false)) {
|
|
175
|
+
throw new Error("Repository has internal changes that have not been published");
|
|
176
|
+
}
|
|
177
|
+
break;
|
|
178
|
+
|
|
179
|
+
case "complete":
|
|
180
|
+
// Previous publication succeeded but subsequent repository failed; skip this repository.
|
|
181
|
+
publish = false;
|
|
182
|
+
break;
|
|
183
|
+
|
|
184
|
+
default:
|
|
185
|
+
// Previous publication failed.
|
|
186
|
+
publish = true;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (packageVersion !== repository.lastExternalVersion) {
|
|
191
|
+
// Package version has already been updated, either manually or by previous failed run.
|
|
192
|
+
publish = true;
|
|
193
|
+
} else if (publish) {
|
|
194
|
+
// Increment patch version number.
|
|
195
|
+
packageVersion = `${majorVersion}.${minorVersion}.${patchVersion + 1}${preReleaseIdentifier}`;
|
|
196
|
+
packageConfiguration.version = packageVersion;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const tag = `v${packageVersion}`;
|
|
200
|
+
|
|
201
|
+
const octokitParameterBase = {
|
|
202
|
+
owner: configuration.organization,
|
|
203
|
+
repo: name
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const internal = repository.dependencyType === "internal";
|
|
207
|
+
|
|
208
|
+
if (publish) {
|
|
209
|
+
if (repository.publishExternalStep === undefined) {
|
|
210
|
+
updateDependencies(false, true, internal, packageConfiguration.devDependencies);
|
|
211
|
+
updateDependencies(false, false, internal, packageConfiguration.dependencies);
|
|
212
|
+
|
|
213
|
+
fs.writeFileSync(packageConfigurationPath, `${JSON.stringify(packageConfiguration, null, 2)}\n`);
|
|
214
|
+
} else {
|
|
215
|
+
logger.debug(`Repository failed at step ${repository.publishExternalStep} on prior run`);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const workflowsPath = ".github/workflows/";
|
|
219
|
+
|
|
220
|
+
let hasPushWorkflow = false;
|
|
221
|
+
let hasReleaseWorkflow = false;
|
|
222
|
+
|
|
223
|
+
if (fs.existsSync(workflowsPath)) {
|
|
224
|
+
logger.debug("Checking workflows");
|
|
225
|
+
|
|
226
|
+
for (const workflowFile of fs.readdirSync(workflowsPath).filter(workflowFile => workflowFile.endsWith(".yml"))) {
|
|
227
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Workflow configuration format is known.
|
|
228
|
+
const workflowOn = (yamlParse(fs.readFileSync(path.resolve(workflowsPath, workflowFile)).toString()) as WorkflowConfiguration).on;
|
|
229
|
+
|
|
230
|
+
if (workflowOn.push !== undefined && (workflowOn.push.branches === undefined || workflowOn.push.branches.includes("v*"))) {
|
|
231
|
+
logger.debug("Repository has push workflow");
|
|
232
|
+
|
|
233
|
+
hasPushWorkflow = true;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (workflowOn.release !== undefined && (workflowOn.release.types === undefined || workflowOn.release.types.includes("published"))) {
|
|
237
|
+
logger.debug("Repository has release workflow");
|
|
238
|
+
|
|
239
|
+
hasReleaseWorkflow = true;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Validate the workflow by waiting for it to complete.
|
|
246
|
+
*/
|
|
247
|
+
async function validateWorkflow(): Promise<void> {
|
|
248
|
+
const commitSHA = run(true, "git", "rev-parse", "HEAD")[0];
|
|
249
|
+
|
|
250
|
+
let completed = false;
|
|
251
|
+
let queryCount = 0;
|
|
252
|
+
let workflowRunID = -1;
|
|
253
|
+
|
|
254
|
+
do {
|
|
255
|
+
await setTimeout(2000);
|
|
256
|
+
|
|
257
|
+
const response = await octokit.rest.actions.listWorkflowRunsForRepo({
|
|
258
|
+
...octokitParameterBase,
|
|
259
|
+
head_sha: commitSHA
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
for (const workflowRun of response.data.workflow_runs) {
|
|
263
|
+
if (workflowRun.status !== "completed") {
|
|
264
|
+
if (workflowRun.id === workflowRunID) {
|
|
265
|
+
process.stdout.write(".");
|
|
266
|
+
} else if (workflowRunID === -1) {
|
|
267
|
+
workflowRunID = workflowRun.id;
|
|
268
|
+
|
|
269
|
+
logger.info(`Workflow run ID ${workflowRunID}`);
|
|
270
|
+
} else {
|
|
271
|
+
throw new Error(`Parallel workflow runs for SHA ${commitSHA}`);
|
|
272
|
+
}
|
|
273
|
+
} else if (workflowRun.id === workflowRunID) {
|
|
274
|
+
process.stdout.write("\n");
|
|
275
|
+
|
|
276
|
+
if (workflowRun.conclusion !== "success") {
|
|
277
|
+
throw new Error(`Workflow ${workflowRun.conclusion}`);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
completed = true;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Abort if workflow run not started after 10 queries.
|
|
285
|
+
if (++queryCount === 10 && workflowRunID === -1) {
|
|
286
|
+
throw new Error(`Workflow run not started for SHA ${commitSHA}`);
|
|
287
|
+
}
|
|
288
|
+
} while (!completed);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
await runStep(repository, "install", () => {
|
|
292
|
+
run(false, "npm", "install");
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
await runStep(repository, "build", () => {
|
|
296
|
+
run(false, "npm", "run", "build:release", "--if-present");
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
await runStep(repository, "commit", () => {
|
|
300
|
+
run(false, "git", "commit", "--all", "--message", `Updated to version ${packageVersion}.`);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
await runStep(repository, "tag", () => {
|
|
304
|
+
run(false, "git", "tag", tag);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
await runStep(repository, "push", () => {
|
|
308
|
+
run(false, "git", "push", "--atomic", "origin", branch, tag);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
if (hasPushWorkflow) {
|
|
312
|
+
await runStep(repository, "workflow (push)", async () => {
|
|
313
|
+
await validateWorkflow();
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
await runStep(repository, "release", async () => {
|
|
318
|
+
const versionSplit = packageVersion.split("-");
|
|
319
|
+
const prerelease = versionSplit.length !== 1;
|
|
320
|
+
|
|
321
|
+
await octokit.rest.repos.createRelease({
|
|
322
|
+
...octokitParameterBase,
|
|
323
|
+
tag_name: tag,
|
|
324
|
+
name: `${prerelease ? `${versionSplit[1].substring(0, 1).toUpperCase()}${versionSplit[1].substring(1)}` : "Production"} release ${versionSplit[0]}`,
|
|
325
|
+
prerelease
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
if (hasReleaseWorkflow) {
|
|
330
|
+
await runStep(repository, "workflow (release)", async () => {
|
|
331
|
+
await validateWorkflow();
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
await runStep(repository, "restore alpha", () => {
|
|
336
|
+
// Restore dependencies to "alpha" version for development.
|
|
337
|
+
const devDependenciesUpdated = updateDependencies(true, true, internal, packageConfiguration.devDependencies);
|
|
338
|
+
const dependenciesUpdated = updateDependencies(true, false, internal, packageConfiguration.dependencies);
|
|
339
|
+
|
|
340
|
+
if (devDependenciesUpdated || dependenciesUpdated) {
|
|
341
|
+
fs.writeFileSync(packageConfigurationPath, `${JSON.stringify(packageConfiguration, null, 2)}\n`);
|
|
342
|
+
|
|
343
|
+
run(false, "git", "commit", packageConfigurationPath, "--message", "Restored alpha versions to organization dependencies.");
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
repository.lastExternalPublished = new Date().toISOString();
|
|
348
|
+
repository.lastExternalVersion = packageVersion;
|
|
349
|
+
repository.publishExternalStep = "complete";
|
|
350
|
+
}
|
|
351
|
+
}).then(() => {
|
|
352
|
+
// Publication complete; reset steps to undefined for next run.
|
|
353
|
+
for (const repository of Object.values(configuration.repositories)) {
|
|
354
|
+
repository.publishExternalStep = undefined;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
saveConfiguration();
|
|
358
|
+
|
|
359
|
+
commitConfiguration(true);
|
|
360
|
+
}).catch((e: unknown) => {
|
|
361
|
+
logger.error(e);
|
|
362
|
+
});
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import {
|
|
3
|
+
anyChanges,
|
|
4
|
+
commitConfiguration,
|
|
5
|
+
organizationRepository,
|
|
6
|
+
type PackageConfiguration,
|
|
7
|
+
publishRepositories
|
|
8
|
+
} from "./publish";
|
|
9
|
+
import { logger, run } from "./utility.js";
|
|
10
|
+
|
|
11
|
+
// Detailed syntax checking not required as this is an internal tool.
|
|
12
|
+
const updateAll = process.argv[2] === "--update-all";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Check dependencies for belonging to the organization; if not, check for updates and log a message, and optionally
|
|
16
|
+
* update, if an update is available.
|
|
17
|
+
*
|
|
18
|
+
* @param dependencies
|
|
19
|
+
* Dependencies.
|
|
20
|
+
*
|
|
21
|
+
* @returns
|
|
22
|
+
* Dependencies belonging to the organization if not updating all, or external dependencies pending update if updating
|
|
23
|
+
* all.
|
|
24
|
+
*/
|
|
25
|
+
function checkDependencyUpdates(dependencies?: Record<string, string>): string[] {
|
|
26
|
+
const dependencyUpdates = [];
|
|
27
|
+
|
|
28
|
+
if (dependencies !== undefined) {
|
|
29
|
+
for (const [dependency, version] of Object.entries(dependencies)) {
|
|
30
|
+
if (organizationRepository(dependency) !== null) {
|
|
31
|
+
if (!updateAll) {
|
|
32
|
+
dependencyUpdates.push(dependency);
|
|
33
|
+
}
|
|
34
|
+
} else if (version.startsWith("^")) {
|
|
35
|
+
const [latestVersion] = run(true, "npm", "view", dependency, "version");
|
|
36
|
+
|
|
37
|
+
if (latestVersion !== version.substring(1)) {
|
|
38
|
+
logger.info(`Dependency ${dependency}@${version} ${!updateAll ? "pending update" : "updating"} to version ${latestVersion}.`);
|
|
39
|
+
|
|
40
|
+
if (updateAll) {
|
|
41
|
+
dependencies[dependency] = `^${latestVersion}`;
|
|
42
|
+
|
|
43
|
+
dependencyUpdates.push(dependency);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return dependencyUpdates;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Convert a number to a zero-padded string.
|
|
55
|
+
*
|
|
56
|
+
* @param n
|
|
57
|
+
* Number.
|
|
58
|
+
*
|
|
59
|
+
* @param length
|
|
60
|
+
* Length of required string.
|
|
61
|
+
*
|
|
62
|
+
* @returns
|
|
63
|
+
* Zero-padded string.
|
|
64
|
+
*/
|
|
65
|
+
function zeroPadded(n: number, length: number): string {
|
|
66
|
+
return `${"0".repeat(length - 1)}${n}`.slice(-length);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const dependencyDependenciesMap = new Map<string, string[]>();
|
|
70
|
+
|
|
71
|
+
await publishRepositories((name, repository) => {
|
|
72
|
+
const packageConfigurationPath = "package.json";
|
|
73
|
+
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Package configuration format is known.
|
|
75
|
+
const packageConfiguration = JSON.parse(fs.readFileSync(packageConfigurationPath).toString()) as PackageConfiguration;
|
|
76
|
+
|
|
77
|
+
// Check dependency updates, even if there are no changes.
|
|
78
|
+
const dependencyUpdates = [...checkDependencyUpdates(packageConfiguration.devDependencies), ...checkDependencyUpdates(packageConfiguration.dependencies)];
|
|
79
|
+
|
|
80
|
+
if (!updateAll) {
|
|
81
|
+
if (dependencyUpdates.length !== 0) {
|
|
82
|
+
dependencyDependenciesMap.set(name, dependencyUpdates);
|
|
83
|
+
|
|
84
|
+
const allDependencyUpdates = new Array<string>();
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Add all dependency updates and those of their dependencies.
|
|
88
|
+
*
|
|
89
|
+
* @param dependencies
|
|
90
|
+
* Dependencies.
|
|
91
|
+
*/
|
|
92
|
+
function addAllDependencyUpdates(dependencies: string[]): void {
|
|
93
|
+
for (const dependency of dependencies) {
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Dependency is an organization repository.
|
|
95
|
+
const dependencyDependencies = dependencyDependenciesMap.get(organizationRepository(dependency)!);
|
|
96
|
+
|
|
97
|
+
if (dependencyDependencies !== undefined) {
|
|
98
|
+
addAllDependencyUpdates(dependencyDependencies);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!allDependencyUpdates.includes(dependency)) {
|
|
102
|
+
allDependencyUpdates.push(dependency);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
addAllDependencyUpdates(dependencyUpdates);
|
|
108
|
+
|
|
109
|
+
logger.debug(`Updating organization dependencies ${JSON.stringify(allDependencyUpdates)}`);
|
|
110
|
+
|
|
111
|
+
run(false, "npm", "update", ...allDependencyUpdates);
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
if (dependencyUpdates.length !== 0) {
|
|
115
|
+
// Update the package configuration for the update.
|
|
116
|
+
fs.writeFileSync(packageConfigurationPath, `${JSON.stringify(packageConfiguration, null, 2)}\n`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
logger.debug("Updating all dependencies");
|
|
120
|
+
|
|
121
|
+
run(false, "npm", "update");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Run lint if present.
|
|
125
|
+
run(false, "npm", "run", "lint", "--if-present");
|
|
126
|
+
|
|
127
|
+
// Run development build if present.
|
|
128
|
+
run(false, "npm", "run", "build:dev", "--if-present");
|
|
129
|
+
|
|
130
|
+
// Nothing further required if this repository is not a dependency.
|
|
131
|
+
if (repository.dependencyType !== "none" && anyChanges(repository, false)) {
|
|
132
|
+
const backupPackageConfigurationPath = ".package.json";
|
|
133
|
+
|
|
134
|
+
// Backup the package configuration file.
|
|
135
|
+
fs.renameSync(packageConfigurationPath, backupPackageConfigurationPath);
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
const now = new Date();
|
|
139
|
+
|
|
140
|
+
// Strip pre-release identifier if any.
|
|
141
|
+
const [semanticVersion] = packageConfiguration.version.split("-");
|
|
142
|
+
|
|
143
|
+
// Parse semantic version into its components.
|
|
144
|
+
const [majorVersion, minorVersion, patchVersion] = semanticVersion.split(".").map(versionString => Number(versionString));
|
|
145
|
+
|
|
146
|
+
// Set version to alpha version with incremental patch version number.
|
|
147
|
+
packageConfiguration.version = `${majorVersion}.${minorVersion}.${patchVersion + 1}-alpha.${now.getFullYear()}${zeroPadded(now.getMonth() + 1, 2)}${zeroPadded(now.getDate(), 2)}${zeroPadded(now.getHours(), 2)}${zeroPadded(now.getMinutes(), 2)}`;
|
|
148
|
+
|
|
149
|
+
// Update the package configuration for the build.
|
|
150
|
+
fs.writeFileSync(packageConfigurationPath, `${JSON.stringify(packageConfiguration, null, 2)}\n`);
|
|
151
|
+
|
|
152
|
+
// Publish to development npm registry.
|
|
153
|
+
run(false, "npm", "publish", "--tag", "alpha");
|
|
154
|
+
|
|
155
|
+
// Unpublish all prior alpha versions.
|
|
156
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Output is a JSON array.
|
|
157
|
+
for (const version of JSON.parse(run(true, "npm", "view", packageConfiguration.name, "versions", "--json").join("\n")) as string[]) {
|
|
158
|
+
if (/^[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+$/.test(version) && version !== packageConfiguration.version) {
|
|
159
|
+
run(false, "npm", "unpublish", `${packageConfiguration.name}@${version}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
repository.lastInternalPublished = now.toISOString();
|
|
164
|
+
} finally {
|
|
165
|
+
// Restore the package configuration file.
|
|
166
|
+
fs.rmSync(packageConfigurationPath);
|
|
167
|
+
fs.renameSync(backupPackageConfigurationPath, packageConfigurationPath);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}).then(() => {
|
|
171
|
+
commitConfiguration(false);
|
|
172
|
+
}).catch((e: unknown) => {
|
|
173
|
+
logger.error(e);
|
|
174
|
+
});
|