Skip to content

Commit b84587c

Browse files
authored
[rush] Fix an issue where properties can be dropped from common-versions.json. (#5407)
* Clean up the add and remove actions. * fixup! Clean up the add and remove actions. * fixup! Clean up the add and remove actions. * Fix an issue where properties can be dropped from common-versions.json.
1 parent 3a5cc0e commit b84587c

10 files changed

Lines changed: 139 additions & 111 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@microsoft/rush",
5+
"comment": "Fix an issue where `rush add --make-consistent ...` may drop the `implicitlyPreferredVersions` and `ensureConsistentVersions` properties from `common/config/rush/common-versions.json`.",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@microsoft/rush"
10+
}

common/config/rush/version-policies.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
"policyName": "rush",
104104
"definitionName": "lockStepVersion",
105105
"version": "5.160.1",
106-
"nextBump": "patch",
106+
"nextBump": "minor",
107107
"mainProject": "@microsoft/rush"
108108
}
109109
]

libraries/rush-lib/src/api/CommonVersionsConfiguration.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
Sort
1414
} from '@rushstack/node-core-library';
1515

16+
import type { OptionalToUndefined } from '../utilities/Utilities';
1617
import { PackageNameParsers } from './PackageNameParsers';
1718
import { JsonSchemaUrls } from '../logic/JsonSchemaUrls';
1819
import type { RushConfiguration } from './RushConfiguration';
@@ -67,6 +68,7 @@ export class CommonVersionsConfiguration {
6768
private _preferredVersions: ProtectableMap<string, string>;
6869
private _allowedAlternativeVersions: ProtectableMap<string, string[]>;
6970
private _modified: boolean = false;
71+
private _commonVersionsJsonHasEnsureConsistentVersionsProperty: boolean;
7072

7173
/**
7274
* Get the absolute file path of the common-versions.json file.
@@ -163,6 +165,8 @@ export class CommonVersionsConfiguration {
163165

164166
this.ensureConsistentVersions =
165167
commonVersionsEnsureConsistentVersions ?? rushJsonEnsureConsistentVersions ?? false;
168+
this._commonVersionsJsonHasEnsureConsistentVersionsProperty =
169+
commonVersionsEnsureConsistentVersions !== undefined;
166170

167171
if (commonVersionsJson) {
168172
try {
@@ -242,7 +246,10 @@ export class CommonVersionsConfiguration {
242246
*/
243247
public save(): boolean {
244248
if (this._modified) {
245-
JsonFile.save(this._serialize(), this.filePath, { updateExistingFile: true });
249+
JsonFile.save(this._serialize(), this.filePath, {
250+
updateExistingFile: true,
251+
ignoreUndefinedValues: true
252+
});
246253
this._modified = false;
247254
return true;
248255
}
@@ -284,20 +291,27 @@ export class CommonVersionsConfiguration {
284291
}
285292

286293
private _serialize(): ICommonVersionsJson {
287-
const result: ICommonVersionsJson = {
288-
$schema: JsonSchemaUrls.commonVersions
289-
};
290-
294+
let preferredVersions: ICommonVersionsJsonVersionMap | undefined;
291295
if (this._preferredVersions.size) {
292-
result.preferredVersions = CommonVersionsConfiguration._serializeTable(this.preferredVersions);
296+
preferredVersions = CommonVersionsConfiguration._serializeTable(this.preferredVersions);
293297
}
294298

299+
let allowedAlternativeVersions: ICommonVersionsJsonVersionsMap | undefined;
295300
if (this._allowedAlternativeVersions.size) {
296-
result.allowedAlternativeVersions = CommonVersionsConfiguration._serializeTable(
301+
allowedAlternativeVersions = CommonVersionsConfiguration._serializeTable(
297302
this.allowedAlternativeVersions
298303
) as ICommonVersionsJsonVersionsMap;
299304
}
300305

306+
const result: OptionalToUndefined<ICommonVersionsJson> = {
307+
$schema: JsonSchemaUrls.commonVersions,
308+
preferredVersions,
309+
implicitlyPreferredVersions: this.implicitlyPreferredVersions,
310+
allowedAlternativeVersions,
311+
ensureConsistentVersions: this._commonVersionsJsonHasEnsureConsistentVersionsProperty
312+
? this.ensureConsistentVersions
313+
: undefined
314+
};
301315
return result;
302316
}
303317
}

libraries/rush-lib/src/api/test/__snapshots__/RushCommandLine.test.ts.snap

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@ Object {
2222
"required": true,
2323
"shortName": "-p",
2424
},
25+
Object {
26+
"description": "If specified, the dependency will be added to all projects.",
27+
"environmentVariable": undefined,
28+
"kind": "Flag",
29+
"longName": "--all",
30+
"required": false,
31+
"shortName": undefined,
32+
},
33+
Object {
34+
"description": "Run command using a variant installation configuration",
35+
"environmentVariable": "RUSH_VARIANT",
36+
"kind": "String",
37+
"longName": "--variant",
38+
"required": false,
39+
"shortName": undefined,
40+
},
2541
Object {
2642
"description": "If specified, the SemVer specifier added to the package.json will be an exact version (e.g. without tilde or caret).",
2743
"environmentVariable": undefined,
@@ -62,22 +78,6 @@ Object {
6278
"required": false,
6379
"shortName": "-m",
6480
},
65-
Object {
66-
"description": "If specified, the dependency will be added to all projects.",
67-
"environmentVariable": undefined,
68-
"kind": "Flag",
69-
"longName": "--all",
70-
"required": false,
71-
"shortName": undefined,
72-
},
73-
Object {
74-
"description": "Run command using a variant installation configuration",
75-
"environmentVariable": "RUSH_VARIANT",
76-
"kind": "String",
77-
"longName": "--variant",
78-
"required": false,
79-
"shortName": undefined,
80-
},
8181
],
8282
},
8383
Object {

libraries/rush-lib/src/cli/actions/AddAction.ts

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,9 @@
33

44
import * as semver from 'semver';
55

6-
import type {
7-
CommandLineFlagParameter,
8-
CommandLineStringListParameter,
9-
CommandLineStringParameter
10-
} from '@rushstack/ts-command-line';
6+
import type { CommandLineFlagParameter } from '@rushstack/ts-command-line';
117

12-
import { BaseAddAndRemoveAction } from './BaseAddAndRemoveAction';
8+
import { BaseAddAndRemoveAction, PACKAGE_PARAMETER_NAME } from './BaseAddAndRemoveAction';
139
import type { RushCommandLineParser } from '../RushCommandLineParser';
1410
import { DependencySpecifier } from '../../logic/DependencySpecifier';
1511
import type { RushConfigurationProject } from '../../api/RushConfigurationProject';
@@ -18,55 +14,52 @@ import {
1814
type IPackageJsonUpdaterRushAddOptions,
1915
SemVerStyle
2016
} from '../../logic/PackageJsonUpdaterTypes';
21-
import { getVariantAsync, VARIANT_PARAMETER } from '../../api/Variants';
17+
import { getVariantAsync } from '../../api/Variants';
18+
19+
const ADD_ACTION_NAME: 'add' = 'add';
20+
export const MAKE_CONSISTENT_FLAG_NAME: '--make-consistent' = '--make-consistent';
21+
const EXACT_FLAG_NAME: '--exact' = '--exact';
22+
const CARET_FLAG_NAME: '--caret' = '--caret';
2223

2324
export class AddAction extends BaseAddAndRemoveAction {
24-
protected readonly _allFlag: CommandLineFlagParameter;
25-
protected readonly _packageNameList: CommandLineStringListParameter;
2625
private readonly _exactFlag: CommandLineFlagParameter;
2726
private readonly _caretFlag: CommandLineFlagParameter;
2827
private readonly _devDependencyFlag: CommandLineFlagParameter;
2928
private readonly _peerDependencyFlag: CommandLineFlagParameter;
3029
private readonly _makeConsistentFlag: CommandLineFlagParameter;
31-
private readonly _variantParameter: CommandLineStringParameter;
3230

3331
public constructor(parser: RushCommandLineParser) {
3432
const documentation: string = [
3533
'Adds specified package(s) to the dependencies of the current project (as determined by the current working directory)' +
3634
' and then runs "rush update". If no version is specified, a version will be automatically detected (typically' +
3735
' either the latest version or a version that won\'t break the "ensureConsistentVersions" policy). If a version' +
3836
' range (or a workspace range) is specified, the latest version in the range will be used. The version will be' +
39-
' automatically prepended with a tilde, unless the "--exact" or "--caret" flags are used. The "--make-consistent"' +
40-
' flag can be used to update all packages with the dependency.'
37+
` automatically prepended with a tilde, unless the "${EXACT_FLAG_NAME}" or "${CARET_FLAG_NAME}" flags are used.` +
38+
` The "${MAKE_CONSISTENT_FLAG_NAME}" flag can be used to update all packages with the dependency.`
4139
].join('\n');
4240
super({
43-
actionName: 'add',
41+
actionName: ADD_ACTION_NAME,
4442
summary: 'Adds one or more dependencies to the package.json and runs rush update.',
4543
documentation,
4644
safeForSimultaneousRushProcesses: false,
47-
parser
48-
});
49-
50-
this._packageNameList = this.defineStringListParameter({
51-
parameterLongName: '--package',
52-
parameterShortName: '-p',
53-
required: true,
54-
argumentName: 'PACKAGE',
55-
description:
45+
parser,
46+
allFlagDescription: 'If specified, the dependency will be added to all projects.',
47+
packageNameListParameterDescription:
5648
'The name of the package which should be added as a dependency.' +
5749
' A SemVer version specifier can be appended after an "@" sign. WARNING: Symbol characters' +
5850
" are usually interpreted by your shell, so it's recommended to use quotes." +
59-
' For example, write "rush add --package "example@^1.2.3"" instead of "rush add --package example@^1.2.3".' +
60-
' To add multiple packages, write "rush add --package foo --package bar".'
51+
` For example, write "rush add ${PACKAGE_PARAMETER_NAME} "example@^1.2.3"" instead of "rush add ${PACKAGE_PARAMETER_NAME} example@^1.2.3".` +
52+
` To add multiple packages, write "rush add ${PACKAGE_PARAMETER_NAME} foo ${PACKAGE_PARAMETER_NAME} bar".`
6153
});
54+
6255
this._exactFlag = this.defineFlagParameter({
63-
parameterLongName: '--exact',
56+
parameterLongName: EXACT_FLAG_NAME,
6457
description:
6558
'If specified, the SemVer specifier added to the' +
6659
' package.json will be an exact version (e.g. without tilde or caret).'
6760
});
6861
this._caretFlag = this.defineFlagParameter({
69-
parameterLongName: '--caret',
62+
parameterLongName: CARET_FLAG_NAME,
7063
description:
7164
'If specified, the SemVer specifier added to the' +
7265
' package.json will be a prepended with a "caret" specifier ("^").'
@@ -82,17 +75,12 @@ export class AddAction extends BaseAddAndRemoveAction {
8275
'If specified, the package will be added to the "peerDependencies" section of the package.json'
8376
});
8477
this._makeConsistentFlag = this.defineFlagParameter({
85-
parameterLongName: '--make-consistent',
78+
parameterLongName: MAKE_CONSISTENT_FLAG_NAME,
8679
parameterShortName: '-m',
8780
description:
8881
'If specified, other packages with this dependency will have their package.json' +
8982
' files updated to use the same version of the dependency.'
9083
});
91-
this._allFlag = this.defineFlagParameter({
92-
parameterLongName: '--all',
93-
description: 'If specified, the dependency will be added to all projects.'
94-
});
95-
this._variantParameter = this.defineStringParameter(VARIANT_PARAMETER);
9684
}
9785

9886
public async getUpdateOptionsAsync(): Promise<IPackageJsonUpdaterRushAddOptions> {
@@ -142,7 +130,7 @@ export class AddAction extends BaseAddAndRemoveAction {
142130
if (this._exactFlag.value || this._caretFlag.value) {
143131
throw new Error(
144132
`The "${this._caretFlag.longName}" and "${this._exactFlag.longName}" flags may not be specified if a ` +
145-
`version is provided in the ${this._packageNameList.longName} specifier. In this case "${version}" was provided.`
133+
`version is provided in the ${this._packageNameListParameter.longName} specifier. In this case "${version}" was provided.`
146134
);
147135
}
148136

@@ -165,7 +153,7 @@ export class AddAction extends BaseAddAndRemoveAction {
165153
);
166154

167155
return {
168-
projects: projects,
156+
projects,
169157
packagesToUpdate: packagesToAdd,
170158
devDependency: this._devDependencyFlag.value,
171159
peerDependency: this._peerDependencyFlag.value,

libraries/rush-lib/src/cli/actions/BaseAddAndRemoveAction.ts

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
22
// See LICENSE in the project root for license information.
33

4-
import type { CommandLineFlagParameter, CommandLineStringListParameter } from '@rushstack/ts-command-line';
4+
import type {
5+
CommandLineFlagParameter,
6+
CommandLineStringListParameter,
7+
CommandLineStringParameter
8+
} from '@rushstack/ts-command-line';
59

610
import { BaseRushAction, type IBaseRushActionOptions } from './BaseRushAction';
711
import type { RushConfigurationProject } from '../../api/RushConfigurationProject';
@@ -11,6 +15,9 @@ import type {
1115
IPackageJsonUpdaterRushBaseUpdateOptions
1216
} from '../../logic/PackageJsonUpdaterTypes';
1317
import { RushConstants } from '../../logic/RushConstants';
18+
import { VARIANT_PARAMETER } from '../../api/Variants';
19+
20+
export const PACKAGE_PARAMETER_NAME: '--package' = '--package';
1421

1522
export interface IBasePackageJsonUpdaterRushOptions {
1623
/**
@@ -31,27 +38,50 @@ export interface IBasePackageJsonUpdaterRushOptions {
3138
debugInstall: boolean;
3239
}
3340

41+
export interface IBaseAddAndRemoveActionOptions extends IBaseRushActionOptions {
42+
allFlagDescription: string;
43+
packageNameListParameterDescription: string;
44+
}
45+
3446
/**
3547
* This is the common base class for AddAction and RemoveAction.
3648
*/
3749
export abstract class BaseAddAndRemoveAction extends BaseRushAction {
38-
protected abstract readonly _allFlag: CommandLineFlagParameter;
39-
protected readonly _skipUpdateFlag!: CommandLineFlagParameter;
40-
protected abstract readonly _packageNameList: CommandLineStringListParameter;
50+
protected readonly _skipUpdateFlag: CommandLineFlagParameter;
51+
protected readonly _packageNameListParameter: CommandLineStringListParameter;
52+
protected readonly _allFlag: CommandLineFlagParameter;
53+
protected readonly _variantParameter: CommandLineStringParameter;
4154

4255
protected get specifiedPackageNameList(): readonly string[] {
43-
return this._packageNameList.values!;
56+
return this._packageNameListParameter.values;
4457
}
4558

46-
public constructor(options: IBaseRushActionOptions) {
59+
public constructor(options: IBaseAddAndRemoveActionOptions) {
4760
super(options);
4861

62+
const { packageNameListParameterDescription, allFlagDescription } = options;
63+
4964
this._skipUpdateFlag = this.defineFlagParameter({
5065
parameterLongName: '--skip-update',
5166
parameterShortName: '-s',
5267
description:
5368
'If specified, the "rush update" command will not be run after updating the package.json files.'
5469
});
70+
71+
this._packageNameListParameter = this.defineStringListParameter({
72+
parameterLongName: PACKAGE_PARAMETER_NAME,
73+
parameterShortName: '-p',
74+
required: true,
75+
argumentName: 'PACKAGE',
76+
description: packageNameListParameterDescription
77+
});
78+
79+
this._allFlag = this.defineFlagParameter({
80+
parameterLongName: '--all',
81+
description: allFlagDescription
82+
});
83+
84+
this._variantParameter = this.defineStringParameter(VARIANT_PARAMETER);
5585
}
5686

5787
protected abstract getUpdateOptionsAsync(): Promise<IPackageJsonUpdaterRushBaseUpdateOptions>;

0 commit comments

Comments
 (0)