@aidc-toolkit/dev 0.9.20-beta → 0.9.21-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/README.md +1 -1
- package/config/publish.json +49 -22
- package/dev.iml +3 -1
- package/dist/eslint-config-template.d.ts.map +1 -1
- package/dist/eslint-config-template.js +1 -0
- package/dist/eslint-config-template.js.map +1 -1
- package/package.json +3 -3
- package/src/eslint-config-template.ts +1 -0
- package/src/publish/configuration.ts +318 -0
- package/src/publish/logger.ts +18 -7
- package/src/publish/publish-alpha.ts +52 -21
- package/src/publish/publish-beta.ts +85 -23
- package/src/publish/publish.ts +324 -402
- package/src/publish/type-helper.ts +23 -0
package/src/publish/publish.ts
CHANGED
|
@@ -1,156 +1,130 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
|
-
import * as path from "node:path";
|
|
4
3
|
import * as process from "node:process";
|
|
5
|
-
import
|
|
6
|
-
|
|
4
|
+
import {
|
|
5
|
+
type Configuration,
|
|
6
|
+
loadConfiguration,
|
|
7
|
+
type Phase,
|
|
8
|
+
type PhaseState,
|
|
9
|
+
type Repository,
|
|
10
|
+
saveConfiguration,
|
|
11
|
+
SHARED_CONFIGURATION_PATH
|
|
12
|
+
} from "./configuration.js";
|
|
7
13
|
import { logger, setLogLevel } from "./logger.js";
|
|
8
|
-
import {
|
|
14
|
+
import { pick } from "./type-helper.js";
|
|
9
15
|
|
|
10
|
-
const
|
|
11
|
-
const LOCAL_CONFIGURATION_PATH = "config/publish.local.json";
|
|
16
|
+
export const PACKAGE_CONFIGURATION_PATH = "package.json";
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
const SHARED_CONFIGURATION_FULL_PATH = path.resolve(SHARED_CONFIGURATION_PATH);
|
|
15
|
-
const LOCAL_CONFIGURATION_FULL_PATH = path.resolve(LOCAL_CONFIGURATION_PATH);
|
|
18
|
+
export const PACKAGE_LOCK_CONFIGURATION_PATH = "package-lock.json";
|
|
16
19
|
|
|
17
20
|
/**
|
|
18
|
-
*
|
|
21
|
+
* Configuration layout of package.json (relevant attributes only).
|
|
19
22
|
*/
|
|
20
|
-
export interface
|
|
21
|
-
/**
|
|
22
|
-
* Directory in which repository resides, if different from repository name.
|
|
23
|
-
*/
|
|
24
|
-
directory?: string;
|
|
25
|
-
|
|
23
|
+
export interface PackageConfiguration {
|
|
26
24
|
/**
|
|
27
|
-
*
|
|
25
|
+
* Name.
|
|
28
26
|
*/
|
|
29
|
-
|
|
27
|
+
readonly name: string;
|
|
30
28
|
|
|
31
29
|
/**
|
|
32
|
-
*
|
|
30
|
+
* Version.
|
|
33
31
|
*/
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* CPU architecture of native modules to install.
|
|
37
|
-
*/
|
|
38
|
-
cpu: string;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* OS of native modules to install.
|
|
42
|
-
*/
|
|
43
|
-
os: string;
|
|
44
|
-
};
|
|
32
|
+
version: string;
|
|
45
33
|
|
|
46
34
|
/**
|
|
47
|
-
*
|
|
35
|
+
* Development dependencies.
|
|
48
36
|
*/
|
|
49
|
-
|
|
37
|
+
readonly devDependencies?: Record<string, string>;
|
|
50
38
|
|
|
51
39
|
/**
|
|
52
|
-
*
|
|
40
|
+
* Dependencies.
|
|
53
41
|
*/
|
|
54
|
-
|
|
42
|
+
readonly dependencies?: Record<string, string>;
|
|
43
|
+
}
|
|
55
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Repository state, derived from package configuration and updated during publishing.
|
|
47
|
+
*/
|
|
48
|
+
interface RepositoryState {
|
|
56
49
|
/**
|
|
57
|
-
*
|
|
50
|
+
* Repository name from configuration.
|
|
58
51
|
*/
|
|
59
|
-
|
|
52
|
+
readonly repositoryName: string;
|
|
60
53
|
|
|
61
54
|
/**
|
|
62
|
-
*
|
|
55
|
+
* Repository from configuration.
|
|
63
56
|
*/
|
|
64
|
-
|
|
57
|
+
repository: Repository;
|
|
65
58
|
|
|
66
59
|
/**
|
|
67
|
-
*
|
|
60
|
+
* Phase state.
|
|
68
61
|
*/
|
|
69
|
-
|
|
62
|
+
phaseState: PhaseState;
|
|
70
63
|
|
|
71
64
|
/**
|
|
72
|
-
*
|
|
65
|
+
* Phase date/time or undefined if phase never before published.
|
|
73
66
|
*/
|
|
74
|
-
|
|
67
|
+
phaseDateTime: Date | undefined;
|
|
75
68
|
|
|
76
69
|
/**
|
|
77
|
-
*
|
|
70
|
+
* NPM platform arguments if any.
|
|
78
71
|
*/
|
|
79
|
-
|
|
72
|
+
readonly npmPlatformArgs: readonly string[];
|
|
80
73
|
|
|
81
74
|
/**
|
|
82
|
-
*
|
|
75
|
+
* Branch.
|
|
83
76
|
*/
|
|
84
|
-
|
|
85
|
-
}
|
|
77
|
+
readonly branch: string;
|
|
86
78
|
|
|
87
|
-
/**
|
|
88
|
-
* Configuration layout of merged publish.json and publish.local.json.
|
|
89
|
-
*/
|
|
90
|
-
export interface Configuration {
|
|
91
79
|
/**
|
|
92
|
-
*
|
|
80
|
+
* Package configuration.
|
|
93
81
|
*/
|
|
94
|
-
|
|
82
|
+
readonly packageConfiguration: PackageConfiguration;
|
|
95
83
|
|
|
96
84
|
/**
|
|
97
|
-
*
|
|
85
|
+
* Major version.
|
|
98
86
|
*/
|
|
99
|
-
|
|
87
|
+
majorVersion: number;
|
|
100
88
|
|
|
101
89
|
/**
|
|
102
|
-
*
|
|
90
|
+
* Minor version.
|
|
103
91
|
*/
|
|
104
|
-
|
|
92
|
+
minorVersion: number;
|
|
105
93
|
|
|
106
94
|
/**
|
|
107
|
-
*
|
|
95
|
+
* Patch version.
|
|
108
96
|
*/
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export const PACKAGE_CONFIGURATION_PATH = "package.json";
|
|
97
|
+
patchVersion: number;
|
|
113
98
|
|
|
114
|
-
export const PACKAGE_LOCK_CONFIGURATION_PATH = "package-lock.json";
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Configuration layout of package.json (relevant attributes only).
|
|
118
|
-
*/
|
|
119
|
-
export interface PackageConfiguration {
|
|
120
99
|
/**
|
|
121
|
-
*
|
|
100
|
+
* Pre-release identifier or null if none.
|
|
122
101
|
*/
|
|
123
|
-
|
|
102
|
+
preReleaseIdentifier: string | null;
|
|
124
103
|
|
|
125
104
|
/**
|
|
126
|
-
*
|
|
105
|
+
* Dependency package names extracted directly from package configuration.
|
|
127
106
|
*/
|
|
128
|
-
|
|
107
|
+
readonly dependencyPackageNames: readonly string[];
|
|
129
108
|
|
|
130
109
|
/**
|
|
131
|
-
*
|
|
110
|
+
* All dependency package names in publication order.
|
|
132
111
|
*/
|
|
133
|
-
|
|
112
|
+
readonly allDependencyPackageNames: readonly string[];
|
|
134
113
|
|
|
135
114
|
/**
|
|
136
|
-
*
|
|
115
|
+
* True if any dependencies have been updated.
|
|
137
116
|
*/
|
|
138
|
-
|
|
117
|
+
readonly anyDependenciesUpdated: boolean;
|
|
139
118
|
}
|
|
140
119
|
|
|
141
|
-
/**
|
|
142
|
-
* Release type.
|
|
143
|
-
*/
|
|
144
|
-
type ReleaseType = "alpha" | "beta" | "production";
|
|
145
|
-
|
|
146
120
|
/**
|
|
147
121
|
* Publish base class.
|
|
148
122
|
*/
|
|
149
123
|
export abstract class Publish {
|
|
150
124
|
/**
|
|
151
|
-
*
|
|
125
|
+
* Phase.
|
|
152
126
|
*/
|
|
153
|
-
private readonly
|
|
127
|
+
private readonly _phase: Phase;
|
|
154
128
|
|
|
155
129
|
/**
|
|
156
130
|
* If true, outputs what would be run rather than running it.
|
|
@@ -173,64 +147,14 @@ export abstract class Publish {
|
|
|
173
147
|
private readonly _atOrganizationRegistry: string;
|
|
174
148
|
|
|
175
149
|
/**
|
|
176
|
-
*
|
|
150
|
+
* Repository states, keyed on repository name.
|
|
177
151
|
*/
|
|
178
|
-
private readonly
|
|
152
|
+
private readonly _repositoryStates: Record<string, Readonly<RepositoryState>>;
|
|
179
153
|
|
|
180
154
|
/**
|
|
181
|
-
* Current repository
|
|
155
|
+
* Current repository state.
|
|
182
156
|
*/
|
|
183
|
-
private
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Current repository.
|
|
187
|
-
*/
|
|
188
|
-
private _repository!: Repository;
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* NPM platform arguments if any.
|
|
192
|
-
*/
|
|
193
|
-
private _npmPlatformArgs!: string[];
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Branch.
|
|
197
|
-
*/
|
|
198
|
-
private _branch!: string;
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Package configuration.
|
|
202
|
-
*/
|
|
203
|
-
private _packageConfiguration!: PackageConfiguration;
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Major version.
|
|
207
|
-
*/
|
|
208
|
-
private _majorVersion!: number;
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Minor version.
|
|
212
|
-
*/
|
|
213
|
-
private _minorVersion!: number;
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Patch version.
|
|
217
|
-
*/
|
|
218
|
-
private _patchVersion!: number;
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Pre-release identifier or null if none.
|
|
222
|
-
*/
|
|
223
|
-
private _preReleaseIdentifier!: string | null;
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Dependencies that belong to the organization, keyed on repository name.
|
|
227
|
-
*/
|
|
228
|
-
private _organizationDependencies!: Record<string, string>;
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* True if any organization dependency has been updated.
|
|
232
|
-
*/
|
|
233
|
-
private _organizationDependenciesUpdated!: boolean;
|
|
157
|
+
private _repositoryState: RepositoryState | undefined;
|
|
234
158
|
|
|
235
159
|
/**
|
|
236
160
|
* Constructor.
|
|
@@ -241,36 +165,29 @@ export abstract class Publish {
|
|
|
241
165
|
* @param dryRun
|
|
242
166
|
* If true, outputs what would be run rather than running it.
|
|
243
167
|
*/
|
|
244
|
-
protected constructor(releaseType:
|
|
245
|
-
this.
|
|
168
|
+
protected constructor(releaseType: Phase, dryRun: boolean) {
|
|
169
|
+
this._phase = releaseType;
|
|
246
170
|
this._dryRun = dryRun;
|
|
247
171
|
|
|
248
|
-
|
|
249
|
-
this._configuration = {
|
|
250
|
-
...omit(sharedConfigurationJSON, "repositories"),
|
|
251
|
-
...omit(localConfigurationJSON, "repositories"),
|
|
252
|
-
repositories: Object.fromEntries(Object.entries(sharedConfigurationJSON.repositories).map(([repositoryName, repository]) => [repositoryName, {
|
|
253
|
-
...repository,
|
|
254
|
-
...((localConfigurationJSON.repositories as Record<string, Partial<Repository> | undefined>)[repositoryName] ?? {})
|
|
255
|
-
}]))
|
|
256
|
-
};
|
|
172
|
+
this._configuration = loadConfiguration();
|
|
257
173
|
|
|
258
174
|
this._atOrganization = `@${this.configuration.organization}`;
|
|
259
175
|
|
|
260
176
|
this._atOrganizationRegistry = `${this.atOrganization}:registry${releaseType === "alpha" ? `=${this.configuration.alphaRegistry}` : ""}`;
|
|
261
177
|
|
|
262
|
-
this._allOrganizationDependencies = {};
|
|
263
|
-
|
|
264
178
|
if (this._configuration.logLevel !== undefined) {
|
|
265
179
|
setLogLevel(this._configuration.logLevel);
|
|
266
180
|
}
|
|
181
|
+
|
|
182
|
+
this._repositoryStates = {};
|
|
183
|
+
this._repositoryState = undefined;
|
|
267
184
|
}
|
|
268
185
|
|
|
269
186
|
/**
|
|
270
|
-
* Get the
|
|
187
|
+
* Get the phase.
|
|
271
188
|
*/
|
|
272
|
-
protected get
|
|
273
|
-
return this.
|
|
189
|
+
protected get phase(): Phase {
|
|
190
|
+
return this._phase;
|
|
274
191
|
}
|
|
275
192
|
|
|
276
193
|
/**
|
|
@@ -302,88 +219,83 @@ export abstract class Publish {
|
|
|
302
219
|
}
|
|
303
220
|
|
|
304
221
|
/**
|
|
305
|
-
* Get
|
|
306
|
-
*/
|
|
307
|
-
protected get allOrganizationDependencies(): Record<string, Record<string, string>> {
|
|
308
|
-
return this._allOrganizationDependencies;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Get the current repository name.
|
|
313
|
-
*/
|
|
314
|
-
protected get repositoryName(): string {
|
|
315
|
-
return this._repositoryName;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Get the current repository.
|
|
320
|
-
*/
|
|
321
|
-
protected get repository(): Repository {
|
|
322
|
-
return this._repository;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Get the NPM platform arguments if any.
|
|
222
|
+
* Get the repository states, keyed on repository name.
|
|
327
223
|
*/
|
|
328
|
-
get
|
|
329
|
-
return this.
|
|
224
|
+
protected get repositoryStates(): Record<string, Readonly<RepositoryState>> {
|
|
225
|
+
return this._repositoryStates;
|
|
330
226
|
}
|
|
331
227
|
|
|
332
228
|
/**
|
|
333
|
-
* Get the
|
|
229
|
+
* Get the current repository state.
|
|
334
230
|
*/
|
|
335
|
-
protected get
|
|
336
|
-
|
|
337
|
-
|
|
231
|
+
protected get repositoryState(): RepositoryState {
|
|
232
|
+
// Repository state should be accessed only during active publication.
|
|
233
|
+
if (this._repositoryState === undefined) {
|
|
234
|
+
throw new Error("Repository state not defined");
|
|
235
|
+
}
|
|
338
236
|
|
|
339
|
-
|
|
340
|
-
* Get the package configuration.
|
|
341
|
-
*/
|
|
342
|
-
protected get packageConfiguration(): PackageConfiguration {
|
|
343
|
-
return this._packageConfiguration;
|
|
237
|
+
return this._repositoryState;
|
|
344
238
|
}
|
|
345
239
|
|
|
346
240
|
/**
|
|
347
|
-
* Get the
|
|
241
|
+
* Get the dependency version for a dependency repository.
|
|
242
|
+
*
|
|
243
|
+
* @param dependencyRepositoryName
|
|
244
|
+
* Dependency repository name.
|
|
245
|
+
*
|
|
246
|
+
* @param dependencyRepository
|
|
247
|
+
* Dependency repository.
|
|
248
|
+
*
|
|
249
|
+
* @returns
|
|
250
|
+
* Dependency version.
|
|
348
251
|
*/
|
|
349
|
-
protected
|
|
350
|
-
return this._majorVersion;
|
|
351
|
-
}
|
|
252
|
+
protected abstract dependencyVersionFor(dependencyRepositoryName: string, dependencyRepository: Repository): string;
|
|
352
253
|
|
|
353
254
|
/**
|
|
354
|
-
*
|
|
255
|
+
* Determine the latest date/time or undefined if all undefined.
|
|
256
|
+
*
|
|
257
|
+
* @param initialDateTime
|
|
258
|
+
* Initial date/time.
|
|
259
|
+
*
|
|
260
|
+
* @param additionalDateTimes
|
|
261
|
+
* Additional date/times.
|
|
262
|
+
*
|
|
263
|
+
* @returns
|
|
264
|
+
* Latest date/time.
|
|
355
265
|
*/
|
|
356
|
-
protected
|
|
357
|
-
|
|
358
|
-
}
|
|
266
|
+
protected latestDateTime(initialDateTime: Date, ...additionalDateTimes: Array<Date | undefined>): Date {
|
|
267
|
+
let latestDateTime = initialDateTime;
|
|
359
268
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
}
|
|
269
|
+
for (const dateTime of additionalDateTimes) {
|
|
270
|
+
if (dateTime !== undefined && latestDateTime.getTime() < dateTime.getTime()) {
|
|
271
|
+
latestDateTime = dateTime;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
366
274
|
|
|
367
|
-
|
|
368
|
-
* Get the pre-release identifier.
|
|
369
|
-
*/
|
|
370
|
-
protected get preReleaseIdentifier(): string | null {
|
|
371
|
-
return this._preReleaseIdentifier;
|
|
275
|
+
return latestDateTime;
|
|
372
276
|
}
|
|
373
277
|
|
|
374
278
|
/**
|
|
375
|
-
* Get
|
|
279
|
+
* Get the phase date/time for a repository.
|
|
280
|
+
*
|
|
281
|
+
* @param repository
|
|
282
|
+
* Repository.
|
|
283
|
+
*
|
|
284
|
+
* @param phaseDateTime
|
|
285
|
+
* Initial phase date/time.
|
|
286
|
+
*
|
|
287
|
+
* @returns
|
|
288
|
+
* Phase date/time or undefined if phase never before published.
|
|
376
289
|
*/
|
|
377
|
-
protected
|
|
378
|
-
return this._organizationDependencies;
|
|
379
|
-
}
|
|
290
|
+
protected abstract getPhaseDateTime(repository: Repository, phaseDateTime: Date): Date;
|
|
380
291
|
|
|
381
292
|
/**
|
|
382
|
-
* Determine if
|
|
293
|
+
* Determine if branch is valid for the phase.
|
|
294
|
+
*
|
|
295
|
+
* @returns
|
|
296
|
+
* True if branch is valid for the phase.
|
|
383
297
|
*/
|
|
384
|
-
protected
|
|
385
|
-
return this._organizationDependenciesUpdated;
|
|
386
|
-
}
|
|
298
|
+
protected abstract isValidBranch(): boolean;
|
|
387
299
|
|
|
388
300
|
/**
|
|
389
301
|
* Run a command and optionally capture its output.
|
|
@@ -461,22 +373,61 @@ export abstract class Publish {
|
|
|
461
373
|
return parsedDependency.length === 2 && parsedDependency[0] === this.atOrganization ? parsedDependency[1] : null;
|
|
462
374
|
}
|
|
463
375
|
|
|
376
|
+
/**
|
|
377
|
+
* Determine if an organization dependency has been updated.
|
|
378
|
+
*
|
|
379
|
+
* @param phaseDateTime
|
|
380
|
+
* Phase date/time of the current repository.
|
|
381
|
+
*
|
|
382
|
+
* @param dependencyRepositoryName
|
|
383
|
+
* Dependency repository name.
|
|
384
|
+
*
|
|
385
|
+
* @param isAdditional
|
|
386
|
+
* True if this is an additional dependency.
|
|
387
|
+
*
|
|
388
|
+
* @returns
|
|
389
|
+
* True if organization dependency has been updated.
|
|
390
|
+
*/
|
|
391
|
+
private isOrganizationDependencyUpdated(phaseDateTime: Date, dependencyRepositoryName: string, isAdditional: boolean): boolean {
|
|
392
|
+
const dependencyString = !isAdditional ? "Dependency" : "Additional dependency";
|
|
393
|
+
|
|
394
|
+
// If dependency repository state exists, so does dependency repository.
|
|
395
|
+
if (!(dependencyRepositoryName in this.repositoryStates)) {
|
|
396
|
+
throw new Error(`${dependencyString} repository ${dependencyRepositoryName} not yet published`);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const dependencyRepository = this.configuration.repositories[dependencyRepositoryName];
|
|
400
|
+
const dependencyPhaseState = dependencyRepository.phaseStates[this.phase];
|
|
401
|
+
|
|
402
|
+
if (dependencyPhaseState === undefined) {
|
|
403
|
+
throw new Error(`*** Internal error *** ${dependencyString} ${dependencyRepositoryName} does not have state for ${this.phase} phase`);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const isUpdated = phaseDateTime.getTime() < this.getPhaseDateTime(dependencyRepository, dependencyPhaseState.dateTime).getTime();
|
|
407
|
+
|
|
408
|
+
if (isUpdated) {
|
|
409
|
+
logger.trace(`Dependency repository ${dependencyRepositoryName} updated`);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return isUpdated;
|
|
413
|
+
}
|
|
414
|
+
|
|
464
415
|
/**
|
|
465
416
|
* Determine if there have been any changes to the current repository.
|
|
466
417
|
*
|
|
467
|
-
* @param
|
|
468
|
-
*
|
|
418
|
+
* @param phaseDateTime
|
|
419
|
+
* Phase date/time to check against or undefined if phase never before published.
|
|
469
420
|
*
|
|
470
421
|
* @param ignoreGitHub
|
|
471
422
|
* If true, ignore .github directory.
|
|
472
423
|
*
|
|
473
424
|
* @returns
|
|
474
|
-
* True if there
|
|
425
|
+
* True if there have been any changes since the phase date/time.
|
|
475
426
|
*/
|
|
476
|
-
protected anyChanges(
|
|
427
|
+
protected anyChanges(phaseDateTime: Date | undefined, ignoreGitHub: boolean): boolean {
|
|
477
428
|
let anyChanges: boolean;
|
|
478
429
|
|
|
479
|
-
const excludePaths = this.repository.excludePaths ?? [];
|
|
430
|
+
const excludePaths = this.repositoryState.repository.excludePaths ?? [];
|
|
480
431
|
|
|
481
432
|
const changedFilesSet = new Set<string>();
|
|
482
433
|
|
|
@@ -515,13 +466,14 @@ export abstract class Publish {
|
|
|
515
466
|
}
|
|
516
467
|
}
|
|
517
468
|
|
|
518
|
-
if (this.
|
|
469
|
+
if (this.phase !== "alpha" && this.run(true, true, "git", "fetch", "--porcelain", "--dry-run").length !== 0) {
|
|
519
470
|
throw new Error("Remote repository has outstanding changes");
|
|
520
471
|
}
|
|
521
472
|
|
|
522
|
-
|
|
473
|
+
// Phase date/time is undefined if never before published.
|
|
474
|
+
if (phaseDateTime !== undefined) {
|
|
523
475
|
// Get all files committed since last published.
|
|
524
|
-
for (const line of this.run(true, true, "git", "log", "--since",
|
|
476
|
+
for (const line of this.run(true, true, "git", "log", "--since", phaseDateTime.toISOString(), "--name-status", "--pretty=oneline")) {
|
|
525
477
|
// Header starts with 40-character SHA.
|
|
526
478
|
if (/^[0-9a-f]{40} /.test(line)) {
|
|
527
479
|
logger.debug(`Commit SHA ${line.substring(0, 40)}`);
|
|
@@ -549,12 +501,12 @@ export abstract class Publish {
|
|
|
549
501
|
}
|
|
550
502
|
|
|
551
503
|
// Beta or production publication requires that repository be fully committed except for excluded paths.
|
|
552
|
-
if (this.
|
|
504
|
+
if (this.phase !== "alpha" && changedFilesSet.size !== committedCount) {
|
|
553
505
|
throw new Error("Repository has uncommitted changes");
|
|
554
506
|
}
|
|
555
507
|
}
|
|
556
508
|
|
|
557
|
-
const lastPublishedDateTime = new Date(
|
|
509
|
+
const lastPublishedDateTime = new Date(phaseDateTime);
|
|
558
510
|
|
|
559
511
|
anyChanges = false;
|
|
560
512
|
|
|
@@ -574,7 +526,7 @@ export abstract class Publish {
|
|
|
574
526
|
logger.info("No changes");
|
|
575
527
|
}
|
|
576
528
|
} else {
|
|
577
|
-
logger.info("
|
|
529
|
+
logger.info("Never published");
|
|
578
530
|
|
|
579
531
|
// No last published, so there must have been changes.
|
|
580
532
|
anyChanges = true;
|
|
@@ -620,10 +572,12 @@ export abstract class Publish {
|
|
|
620
572
|
* Save package configuration.
|
|
621
573
|
*/
|
|
622
574
|
protected savePackageConfiguration(): void {
|
|
575
|
+
const packageConfiguration = this.repositoryState.packageConfiguration;
|
|
576
|
+
|
|
623
577
|
if (this.dryRun) {
|
|
624
|
-
logger.info(`Dry run: Saving package configuration\n${JSON.stringify(pick(
|
|
578
|
+
logger.info(`Dry run: Saving package configuration\n${JSON.stringify(pick(packageConfiguration, "name", "version", "devDependencies", "dependencies"), null, 2)}\n`);
|
|
625
579
|
} else {
|
|
626
|
-
fs.writeFileSync(PACKAGE_CONFIGURATION_PATH, `${JSON.stringify(
|
|
580
|
+
fs.writeFileSync(PACKAGE_CONFIGURATION_PATH, `${JSON.stringify(packageConfiguration, null, 2)}\n`);
|
|
627
581
|
}
|
|
628
582
|
}
|
|
629
583
|
|
|
@@ -643,23 +597,25 @@ export abstract class Publish {
|
|
|
643
597
|
* Pre-release identifier or undefined if no change.
|
|
644
598
|
*/
|
|
645
599
|
protected updatePackageVersion(majorVersion: number | undefined, minorVersion: number | undefined, patchVersion: number | undefined, preReleaseIdentifier: string | null | undefined): void {
|
|
600
|
+
const repositoryState = this.repositoryState;
|
|
601
|
+
|
|
646
602
|
if (majorVersion !== undefined) {
|
|
647
|
-
|
|
603
|
+
repositoryState.majorVersion = majorVersion;
|
|
648
604
|
}
|
|
649
605
|
|
|
650
606
|
if (minorVersion !== undefined) {
|
|
651
|
-
|
|
607
|
+
repositoryState.minorVersion = minorVersion;
|
|
652
608
|
}
|
|
653
609
|
|
|
654
610
|
if (patchVersion !== undefined) {
|
|
655
|
-
|
|
611
|
+
repositoryState.patchVersion = patchVersion;
|
|
656
612
|
}
|
|
657
613
|
|
|
658
614
|
if (preReleaseIdentifier !== undefined) {
|
|
659
|
-
|
|
615
|
+
repositoryState.preReleaseIdentifier = preReleaseIdentifier;
|
|
660
616
|
}
|
|
661
617
|
|
|
662
|
-
|
|
618
|
+
repositoryState.packageConfiguration.version = `${repositoryState.majorVersion}.${repositoryState.minorVersion}.${repositoryState.patchVersion}${repositoryState.preReleaseIdentifier !== null ? `-${repositoryState.preReleaseIdentifier}` : ""}`;
|
|
663
619
|
|
|
664
620
|
this.savePackageConfiguration();
|
|
665
621
|
}
|
|
@@ -668,11 +624,11 @@ export abstract class Publish {
|
|
|
668
624
|
* Update organization dependencies.
|
|
669
625
|
*/
|
|
670
626
|
protected updateOrganizationDependencies(): void {
|
|
671
|
-
const
|
|
627
|
+
const repositoryState = this.repositoryState;
|
|
672
628
|
|
|
673
|
-
logger.debug(`Updating organization dependencies [${
|
|
629
|
+
logger.debug(`Updating organization dependencies [${repositoryState.allDependencyPackageNames.join(", ")}]`);
|
|
674
630
|
|
|
675
|
-
this.run(false, false, "npm", "update", ...
|
|
631
|
+
this.run(false, false, "npm", "update", ...repositoryState.allDependencyPackageNames, ...this.repositoryState.npmPlatformArgs);
|
|
676
632
|
}
|
|
677
633
|
|
|
678
634
|
/**
|
|
@@ -682,40 +638,40 @@ export abstract class Publish {
|
|
|
682
638
|
* Files to commit; if none, defaults to "--all".
|
|
683
639
|
*/
|
|
684
640
|
protected commitUpdatedPackageVersion(...files: string[]): void {
|
|
685
|
-
this.commitModified(`Updated to version ${this.packageConfiguration.version}.`, ...files);
|
|
641
|
+
this.commitModified(`Updated to version ${this.repositoryState.packageConfiguration.version}.`, ...files);
|
|
686
642
|
}
|
|
687
643
|
|
|
688
644
|
/**
|
|
689
|
-
*
|
|
645
|
+
* Update the phase state. This will replace the phase state object in the repository and repository state and may
|
|
646
|
+
* update the phase date/time in the repository state.
|
|
647
|
+
*
|
|
648
|
+
* @param phaseState
|
|
649
|
+
* Partial phases state. Only those properties provided will be updated.
|
|
690
650
|
*/
|
|
691
|
-
protected
|
|
692
|
-
const
|
|
693
|
-
const saveLocalRepositories: Record<string, Pick<Repository, "platform" | "lastAlphaPublished">> = {};
|
|
651
|
+
protected updatePhaseState(phaseState: Partial<PhaseState>): void {
|
|
652
|
+
const repositoryState = this.repositoryState;
|
|
694
653
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
const saveSharedConfigurationJSON = JSON.stringify({
|
|
701
|
-
...omit(this.configuration, "logLevel", "alphaRegistry", "repositories"),
|
|
702
|
-
repositories: saveSharedRepositories
|
|
703
|
-
}, null, 2);
|
|
654
|
+
const updatedPhaseState = {
|
|
655
|
+
...this.repositoryState.phaseState,
|
|
656
|
+
...phaseState
|
|
657
|
+
};
|
|
704
658
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
repositories: saveLocalRepositories
|
|
708
|
-
}, null, 2);
|
|
659
|
+
repositoryState.repository.phaseStates[this.phase] = updatedPhaseState;
|
|
660
|
+
repositoryState.phaseState = updatedPhaseState;
|
|
709
661
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
} else {
|
|
714
|
-
fs.writeFileSync(SHARED_CONFIGURATION_FULL_PATH, saveSharedConfigurationJSON);
|
|
715
|
-
fs.writeFileSync(LOCAL_CONFIGURATION_FULL_PATH, saveLocalConfigurationJSON);
|
|
662
|
+
// Setting the phase date/time overrides the logic of its initial determination.
|
|
663
|
+
if (phaseState.dateTime !== undefined) {
|
|
664
|
+
repositoryState.phaseDateTime = phaseState.dateTime;
|
|
716
665
|
}
|
|
717
666
|
}
|
|
718
667
|
|
|
668
|
+
/**
|
|
669
|
+
* Save the configuration.
|
|
670
|
+
*/
|
|
671
|
+
private saveConfiguration(): void {
|
|
672
|
+
saveConfiguration(this.configuration, this.dryRun);
|
|
673
|
+
}
|
|
674
|
+
|
|
719
675
|
/**
|
|
720
676
|
* Publish current repository.
|
|
721
677
|
*/
|
|
@@ -728,20 +684,6 @@ export abstract class Publish {
|
|
|
728
684
|
const startDirectory = process.cwd();
|
|
729
685
|
|
|
730
686
|
for (const [repositoryName, repository] of Object.entries(this.configuration.repositories)) {
|
|
731
|
-
this._repositoryName = repositoryName;
|
|
732
|
-
this._repository = repository;
|
|
733
|
-
|
|
734
|
-
this._npmPlatformArgs = repository.platform !== undefined ?
|
|
735
|
-
[
|
|
736
|
-
"--cpu",
|
|
737
|
-
repository.platform.cpu,
|
|
738
|
-
"--os",
|
|
739
|
-
repository.platform.os
|
|
740
|
-
] :
|
|
741
|
-
[];
|
|
742
|
-
|
|
743
|
-
this._branch = this.run(true, true, "git", "branch", "--show-current")[0];
|
|
744
|
-
|
|
745
687
|
// All repositories are expected to be children of the parent of this repository.
|
|
746
688
|
const directory = `../${repository.directory ?? repositoryName}`;
|
|
747
689
|
|
|
@@ -750,173 +692,156 @@ export abstract class Publish {
|
|
|
750
692
|
|
|
751
693
|
process.chdir(directory);
|
|
752
694
|
|
|
753
|
-
|
|
754
|
-
this._packageConfiguration = JSON.parse(fs.readFileSync(PACKAGE_CONFIGURATION_PATH).toString()) as PackageConfiguration;
|
|
695
|
+
let phaseState = repository.phaseStates[this.phase];
|
|
755
696
|
|
|
756
|
-
|
|
697
|
+
// Create phase state if necessary.
|
|
698
|
+
if (phaseState === undefined) {
|
|
699
|
+
phaseState = {
|
|
700
|
+
dateTime: new Date(0)
|
|
701
|
+
};
|
|
757
702
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
if (parsedVersion === null) {
|
|
761
|
-
throw new Error(`Invalid package version ${version}`);
|
|
703
|
+
repository.phaseStates[this.phase] = phaseState;
|
|
762
704
|
}
|
|
763
705
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
this._patchVersion = Number(parsedVersion[3]);
|
|
767
|
-
this._preReleaseIdentifier = parsedVersion.length === 6 ? parsedVersion[5] : null;
|
|
706
|
+
try {
|
|
707
|
+
const phaseDateTime = this.getPhaseDateTime(repository, phaseState.dateTime);
|
|
768
708
|
|
|
769
|
-
|
|
709
|
+
const npmPlatformArgs = repository.platform !== undefined ?
|
|
710
|
+
[
|
|
711
|
+
"--cpu",
|
|
712
|
+
repository.platform.cpu,
|
|
713
|
+
"--os",
|
|
714
|
+
repository.platform.os
|
|
715
|
+
] :
|
|
716
|
+
[];
|
|
770
717
|
|
|
771
|
-
|
|
772
|
-
throw new Error(`Beta release must be from version branch v${this.majorVersion}.${this.minorVersion}`);
|
|
773
|
-
}
|
|
718
|
+
const branch = this.run(true, true, "git", "branch", "--show-current")[0];
|
|
774
719
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
}
|
|
720
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Package configuration format is known.
|
|
721
|
+
const packageConfiguration = JSON.parse(fs.readFileSync(PACKAGE_CONFIGURATION_PATH).toString()) as PackageConfiguration;
|
|
778
722
|
|
|
779
|
-
|
|
723
|
+
const version = packageConfiguration.version;
|
|
780
724
|
|
|
781
|
-
|
|
782
|
-
if (currentDependencies !== undefined) {
|
|
783
|
-
for (const dependency of Object.keys(currentDependencies)) {
|
|
784
|
-
const dependencyRepositoryName = this.dependencyRepositoryName(dependency);
|
|
725
|
+
const parsedVersion = /^(\d+)\.(\d+)\.(\d+)(-(alpha|beta))?$/.exec(version);
|
|
785
726
|
|
|
786
|
-
|
|
787
|
-
|
|
727
|
+
if (parsedVersion === null) {
|
|
728
|
+
throw new Error(`Invalid package version ${version}`);
|
|
729
|
+
}
|
|
788
730
|
|
|
789
|
-
|
|
731
|
+
const majorVersion = Number(parsedVersion[1]);
|
|
732
|
+
const minorVersion = Number(parsedVersion[2]);
|
|
733
|
+
const patchVersion = Number(parsedVersion[3]);
|
|
734
|
+
const preReleaseIdentifier = parsedVersion.length === 6 ? parsedVersion[5] : null;
|
|
790
735
|
|
|
791
|
-
|
|
736
|
+
const dependencyPackageNames: string[] = [];
|
|
737
|
+
const allDependencyPackageNames: string[] = [];
|
|
792
738
|
|
|
793
|
-
|
|
794
|
-
switch (this.releaseType) {
|
|
795
|
-
case "alpha":
|
|
796
|
-
currentDependencies[dependency] = "alpha";
|
|
797
|
-
break;
|
|
739
|
+
let anyDependenciesUpdated = false;
|
|
798
740
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
currentDependencies[dependency] = "beta";
|
|
803
|
-
break;
|
|
741
|
+
for (const dependencies of [packageConfiguration.devDependencies ?? {}, packageConfiguration.dependencies ?? {}]) {
|
|
742
|
+
for (const dependencyPackageName of Object.keys(dependencies)) {
|
|
743
|
+
const dependencyRepositoryName = this.dependencyRepositoryName(dependencyPackageName);
|
|
804
744
|
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
745
|
+
// Dependency repository name is null if dependency is not within the organization.
|
|
746
|
+
if (dependencyRepositoryName !== null) {
|
|
747
|
+
logger.trace(`Organization dependency ${dependencyPackageName} from package configuration`);
|
|
808
748
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
749
|
+
// Check every dependency for logging purposes.
|
|
750
|
+
if (this.isOrganizationDependencyUpdated(phaseDateTime, dependencyRepositoryName, false)) {
|
|
751
|
+
anyDependenciesUpdated = true;
|
|
752
|
+
}
|
|
812
753
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
754
|
+
for (const dependencyDependencyPackageName of this.repositoryStates[dependencyRepositoryName].allDependencyPackageNames) {
|
|
755
|
+
if (!allDependencyPackageNames.includes(dependencyDependencyPackageName)) {
|
|
756
|
+
logger.trace(`Organization dependency ${dependencyDependencyPackageName} from dependencies`);
|
|
816
757
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
break;
|
|
758
|
+
allDependencyPackageNames.push(dependencyDependencyPackageName);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
821
761
|
|
|
822
|
-
|
|
823
|
-
{
|
|
824
|
-
const lastProductionVersion = dependencyRepository.lastProductionVersion;
|
|
762
|
+
dependencyPackageNames.push(dependencyPackageName);
|
|
825
763
|
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
}
|
|
764
|
+
// Current dependency package name goes in last to preserve hierarchy.
|
|
765
|
+
allDependencyPackageNames.push(dependencyPackageName);
|
|
829
766
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
break;
|
|
833
|
-
}
|
|
767
|
+
// Dependency changes will ultimately be discarded if there are no changes and no updates to repository states.
|
|
768
|
+
dependencies[dependencyPackageName] = this.dependencyVersionFor(dependencyRepositoryName, this.configuration.repositories[dependencyRepositoryName]);
|
|
834
769
|
}
|
|
835
770
|
}
|
|
836
771
|
}
|
|
837
|
-
}
|
|
838
772
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
if (additionalDependencyName in this.organizationDependencies) {
|
|
842
|
-
logger.warn(`Additional dependency ${additionalDependencyName} already exists`);
|
|
843
|
-
} else {
|
|
844
|
-
const dependency = `${this.atOrganization}/${additionalDependencyName}`;
|
|
773
|
+
if (repository.additionalDependencies !== undefined) {
|
|
774
|
+
const additionalRepositoryNames: string[] = [];
|
|
845
775
|
|
|
846
|
-
|
|
776
|
+
for (const additionalDependencyRepositoryName of repository.additionalDependencies) {
|
|
777
|
+
const additionalDependencyPackageName = `${this.atOrganization}/${additionalDependencyRepositoryName}`;
|
|
847
778
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
// Add dependency repositories of dependency repositories.
|
|
854
|
-
for (const dependencyRepositoryName of Object.keys(this.organizationDependencies)) {
|
|
855
|
-
const dependencyOrganizationDependencies = this.allOrganizationDependencies[dependencyRepositoryName];
|
|
779
|
+
if (allDependencyPackageNames.includes(additionalDependencyPackageName) || additionalRepositoryNames.includes(additionalDependencyRepositoryName)) {
|
|
780
|
+
logger.warn(`Additional dependency repository ${additionalDependencyRepositoryName} already a dependency`);
|
|
781
|
+
} else {
|
|
782
|
+
logger.trace(`Organization dependency ${additionalDependencyRepositoryName} from additional dependencies`);
|
|
856
783
|
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
784
|
+
// Check every dependency for logging purposes.
|
|
785
|
+
if (this.isOrganizationDependencyUpdated(phaseDateTime, additionalDependencyRepositoryName, true)) {
|
|
786
|
+
anyDependenciesUpdated = true;
|
|
787
|
+
}
|
|
860
788
|
|
|
861
|
-
|
|
789
|
+
additionalRepositoryNames.push(additionalDependencyRepositoryName);
|
|
790
|
+
}
|
|
862
791
|
}
|
|
863
792
|
}
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
// Save organization dependencies for future repositories.
|
|
867
|
-
this.allOrganizationDependencies[repositoryName] = this.organizationDependencies;
|
|
868
|
-
|
|
869
|
-
let getLastPublished: (repository: Repository) => string | undefined;
|
|
870
|
-
|
|
871
|
-
switch (this.releaseType) {
|
|
872
|
-
case "alpha":
|
|
873
|
-
getLastPublished = repository => repository.lastAlphaPublished;
|
|
874
|
-
break;
|
|
875
|
-
|
|
876
|
-
case "beta":
|
|
877
|
-
getLastPublished = repository => repository.lastBetaPublished;
|
|
878
|
-
break;
|
|
879
|
-
|
|
880
|
-
case "production":
|
|
881
|
-
getLastPublished = repository => repository.lastProductionPublished;
|
|
882
|
-
break;
|
|
883
|
-
}
|
|
884
793
|
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
794
|
+
this._repositoryState = {
|
|
795
|
+
repositoryName,
|
|
796
|
+
repository,
|
|
797
|
+
phaseState,
|
|
798
|
+
phaseDateTime,
|
|
799
|
+
npmPlatformArgs,
|
|
800
|
+
branch,
|
|
801
|
+
packageConfiguration,
|
|
802
|
+
majorVersion,
|
|
803
|
+
minorVersion,
|
|
804
|
+
patchVersion,
|
|
805
|
+
preReleaseIdentifier,
|
|
806
|
+
dependencyPackageNames,
|
|
807
|
+
allDependencyPackageNames,
|
|
808
|
+
anyDependenciesUpdated
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
// Save repository state for future repositories.
|
|
812
|
+
this.repositoryStates[repositoryName] = this._repositoryState;
|
|
813
|
+
|
|
814
|
+
if (!this.isValidBranch()) {
|
|
815
|
+
throw new Error(`Branch ${branch} is not valid for ${this.phase} phase`);
|
|
895
816
|
}
|
|
896
817
|
|
|
897
|
-
|
|
898
|
-
logger.info(`Dependency ${dependencyRepositoryName} recently published`);
|
|
818
|
+
const parsedBranch = /^v(\d+)\.(\d+)/.exec(branch);
|
|
899
819
|
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
820
|
+
// If this is a version branch, update the package version if required.
|
|
821
|
+
if (parsedBranch !== null) {
|
|
822
|
+
const branchMajorVersion = Number(parsedBranch[1]);
|
|
823
|
+
const branchMinorVersion = Number(parsedBranch[2]);
|
|
904
824
|
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
825
|
+
// If in a version branch and version doesn't match, update it.
|
|
826
|
+
if (majorVersion !== branchMajorVersion || minorVersion !== branchMinorVersion) {
|
|
827
|
+
if (majorVersion !== branchMajorVersion ? majorVersion !== branchMajorVersion - 1 : minorVersion !== branchMinorVersion - 1) {
|
|
828
|
+
throw new Error(`Invalid transition from ${majorVersion}.${minorVersion} to ${branchMajorVersion}.${branchMinorVersion}`);
|
|
829
|
+
}
|
|
908
830
|
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
this.commitUpdatedPackageVersion(PACKAGE_CONFIGURATION_PATH);
|
|
831
|
+
this.updatePackageVersion(branchMajorVersion, branchMinorVersion, 0, null);
|
|
832
|
+
this.commitUpdatedPackageVersion(PACKAGE_CONFIGURATION_PATH);
|
|
833
|
+
}
|
|
913
834
|
}
|
|
914
|
-
}
|
|
915
835
|
|
|
916
|
-
try {
|
|
917
836
|
// eslint-disable-next-line no-await-in-loop -- Next iteration requires previous to finish.
|
|
918
837
|
await this.publish();
|
|
919
838
|
} finally {
|
|
839
|
+
// Clear repository state to prevent accidental access.
|
|
840
|
+
this._repositoryState = undefined;
|
|
841
|
+
|
|
842
|
+
// Return to the start directory.
|
|
843
|
+
process.chdir(startDirectory);
|
|
844
|
+
|
|
920
845
|
this.saveConfiguration();
|
|
921
846
|
}
|
|
922
847
|
// Non-external repositories may be private and not accessible to all developers.
|
|
@@ -925,15 +850,12 @@ export abstract class Publish {
|
|
|
925
850
|
}
|
|
926
851
|
}
|
|
927
852
|
|
|
928
|
-
// Return to the start directory.
|
|
929
|
-
process.chdir(startDirectory);
|
|
930
|
-
|
|
931
853
|
this.finalizeAll();
|
|
932
854
|
|
|
933
855
|
this.saveConfiguration();
|
|
934
856
|
|
|
935
|
-
if (this.
|
|
936
|
-
this.commitModified(`Published ${this.
|
|
857
|
+
if (this.phase !== "alpha") {
|
|
858
|
+
this.commitModified(`Published ${this.phase} release.`, SHARED_CONFIGURATION_PATH);
|
|
937
859
|
}
|
|
938
860
|
}
|
|
939
861
|
|