Skip to content

Commit bfa88fd

Browse files
devversionandrewseguin
authored andcommitted
fix(ng-update): migrations not running for release candidate versions (#17704)
* fix(ng-update): migrations not running for release candidate versions 7a433f6 set up the migrations for v9, but we actually forgot that we want to run migrations in the next and RC versions too. * build: add validation check for migration collection
1 parent 5715a9c commit bfa88fd

File tree

9 files changed

+122
-29
lines changed

9 files changed

+122
-29
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
"@types/node": "^12.11.1",
9494
"@types/parse5": "^5.0.0",
9595
"@types/run-sequence": "^0.0.29",
96+
"@types/semver": "^6.2.0",
9697
"@types/send": "^0.14.5",
9798
"autoprefixer": "^6.7.6",
9899
"axe-webdriverjs": "^1.1.1",
@@ -147,6 +148,7 @@
147148
"run-sequence": "^1.2.2",
148149
"scss-bundle": "^2.5.1",
149150
"selenium-webdriver": "^3.6.0",
151+
"semver": "^6.3.0",
150152
"send": "^0.17.1",
151153
"shelljs": "^0.8.3",
152154
"sorcery": "^0.10.0",

src/cdk/schematics/migration.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
"$schema": "./node_modules/@angular-devkit/schematics/collection-schema.json",
33
"schematics": {
44
"migration-v6": {
5-
"version": "6",
5+
"version": "6.0.0",
66
"description": "Updates the Angular CDK to v6",
77
"factory": "./ng-update/index#updateToV6"
88
},
99
"migration-v7": {
10-
"version": "7",
10+
"version": "7.0.0",
1111
"description": "Updates the Angular CDK to v7",
1212
"factory": "./ng-update/index#updateToV7"
1313
},
1414
"migration-v8": {
15-
"version": "8-beta",
15+
"version": "8.0.0",
1616
"description": "Updates the Angular CDK to v8",
1717
"factory": "./ng-update/index#updateToV8"
1818
},
1919
"migration-v9": {
20-
"version": "9",
20+
"version": "9.0.0-0",
2121
"description": "Updates the Angular CDK to v9",
2222
"factory": "./ng-update/index#updateToV9"
2323
},

src/material/schematics/migration.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
"$schema": "./node_modules/@angular-devkit/schematics/collection-schema.json",
33
"schematics": {
44
"migration-v6": {
5-
"version": "6",
5+
"version": "6.0.0",
66
"description": "Updates Angular Material to v6",
77
"factory": "./ng-update/index#updateToV6"
88
},
99
"migration-v7": {
10-
"version": "7",
10+
"version": "7.0.0",
1111
"description": "Updates Angular Material to v7",
1212
"factory": "./ng-update/index#updateToV7"
1313
},
1414
"migration-v8": {
15-
"version": "8-beta",
15+
"version": "8.0.0",
1616
"description": "Updates Angular Material to v8",
1717
"factory": "./ng-update/index#updateToV8"
1818
},
1919
"migration-v9": {
20-
"version": "9",
20+
"version": "9.0.0-0",
2121
"description": "Updates Angular Material to v9",
2222
"factory": "./ng-update/index#updateToV9"
2323
},

tools/release/check-release-output.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@ import chalk from 'chalk';
22
import {join} from 'path';
33
import {checkReleasePackage} from './release-output/check-package';
44
import {releasePackages} from './release-output/release-packages';
5+
import {parseVersionName, Version} from './version-name/parse-version';
56

67
/**
78
* Checks the release output by running the release-output validations for each
89
* release package.
910
*/
10-
export function checkReleaseOutput(releaseOutputDir: string) {
11+
export function checkReleaseOutput(releaseOutputDir: string, currentVersion: Version) {
1112
let hasFailed = false;
1213

1314
releasePackages.forEach(packageName => {
14-
if (!checkReleasePackage(releaseOutputDir, packageName)) {
15+
if (!checkReleasePackage(releaseOutputDir, packageName, currentVersion)) {
1516
hasFailed = true;
1617
}
1718
});
@@ -29,5 +30,9 @@ export function checkReleaseOutput(releaseOutputDir: string) {
2930

3031

3132
if (require.main === module) {
32-
checkReleaseOutput(join(__dirname, '../../dist/releases'));
33+
const currentVersion = parseVersionName(require('../../package.json').version);
34+
if (currentVersion === null) {
35+
throw Error('Version in project "package.json" is invalid.');
36+
}
37+
checkReleaseOutput(join(__dirname, '../../dist/releases'), currentVersion);
3338
}

tools/release/publish-release.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class PublishReleaseTask extends BaseReleaseTask {
9191
console.info(chalk.green(` ✓ Built the release output.`));
9292

9393
// Checks all release packages against release output validations before releasing.
94-
checkReleaseOutput(this.releaseOutputPath);
94+
checkReleaseOutput(this.releaseOutputPath, this.currentVersion);
9595

9696
// Extract the release notes for the new version from the changelog file.
9797
const extractedReleaseNotes = extractReleaseNotes(

tools/release/release-output/check-package.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import chalk from 'chalk';
22
import {existsSync} from 'fs';
33
import {sync as glob} from 'glob';
44
import {join} from 'path';
5+
import {Version} from '../version-name/parse-version';
56

67
import {
78
checkCdkPackage,
89
checkMaterialPackage,
910
checkPackageJsonFile,
11+
checkPackageJsonMigrations,
1012
checkReleaseBundle,
1113
checkTypeDefinitionFile
1214
} from './output-validations';
@@ -32,7 +34,8 @@ type PackageFailures = Map<string, string[]>;
3234
* unexpected release output (e.g. the theming bundle is no longer generated)
3335
* @returns Whether the package passed all checks or not.
3436
*/
35-
export function checkReleasePackage(releasesPath: string, packageName: string): boolean {
37+
export function checkReleasePackage(
38+
releasesPath: string, packageName: string, currentVersion: Version): boolean {
3639
const packagePath = join(releasesPath, packageName);
3740
const failures = new Map() as PackageFailures;
3841
const addFailure = (message, filePath?) => {
@@ -79,6 +82,9 @@ export function checkReleasePackage(releasesPath: string, packageName: string):
7982
addFailure('No "README.md" file found in package output.');
8083
}
8184

85+
checkPackageJsonMigrations(join(packagePath, 'package.json'), currentVersion)
86+
.forEach(f => addFailure(f));
87+
8288
// In case there are failures for this package, we want to print those
8389
// and return a value that implies that there were failures.
8490
if (failures.size) {

tools/release/release-output/output-validations.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import {existsSync, readFileSync} from 'fs';
22
import {sync as glob} from 'glob';
33
import {basename, dirname, isAbsolute, join} from 'path';
4+
import * as semver from 'semver';
45
import * as ts from 'typescript';
6+
import {Version} from '../version-name/parse-version';
57

68
/** RegExp that matches Angular component inline styles that contain a sourcemap reference. */
79
const inlineStylesSourcemapRegex = /styles: ?\[["'].*sourceMappingURL=.*["']/;
@@ -101,6 +103,21 @@ export function checkTypeDefinitionFile(filePath: string): string[] {
101103
return failures;
102104
}
103105

106+
/**
107+
* Checks the ng-update migration setup for the specified "package.json"
108+
* file if present.
109+
*/
110+
export function checkPackageJsonMigrations(
111+
packageJsonPath: string, currentVersion: Version): string[] {
112+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
113+
114+
if (packageJson['ng-update'] && packageJson['ng-update'].migrations) {
115+
return checkMigrationCollection(
116+
packageJson['ng-update'].migrations, dirname(packageJsonPath), currentVersion);
117+
}
118+
return [];
119+
}
120+
104121
/**
105122
* Checks the Angular Material release package and ensures that prebuilt themes
106123
* and the theming bundle are built properly.
@@ -126,8 +143,39 @@ export function checkMaterialPackage(packagePath: string): string[] {
126143
*/
127144
export function checkCdkPackage(packagePath: string): string[] {
128145
const prebuiltFiles = glob('*-prebuilt.css', {cwd: packagePath}).map(path => basename(path));
129-
130146
return ['overlay', 'a11y', 'text-field']
131147
.filter(name => !prebuiltFiles.includes(`${name}-prebuilt.css`))
132148
.map(name => `Could not find the prebuilt ${name} styles.`);
133149
}
150+
151+
/**
152+
* Checks if the migration collected referenced in the specified "package.json"
153+
* has a migration set up for the given target version.
154+
*/
155+
function checkMigrationCollection(
156+
collectionPath: string, packagePath: string, targetVersion: Version): string[] {
157+
const collection = JSON.parse(readFileSync(join(packagePath, collectionPath), 'utf8'));
158+
if (!collection.schematics) {
159+
return ['No schematics found in migration collection.'];
160+
}
161+
162+
const failures: string[] = [];
163+
const lowerBoundaryVersion = `${targetVersion.major}.0.0-0`;
164+
const schematics = collection.schematics;
165+
const targetSchematics = Object.keys(schematics).filter(name => {
166+
const schematicVersion = schematics[name].version;
167+
try {
168+
return schematicVersion && semver.gte(schematicVersion, lowerBoundaryVersion) &&
169+
semver.lte(schematicVersion, targetVersion.format());
170+
} catch {
171+
failures.push(`Could not parse version for migration: ${name}`);
172+
}
173+
});
174+
175+
if (targetSchematics.length === 0) {
176+
failures.push(`No migration configured that handles versions: ^${lowerBoundaryVersion}`);
177+
} else if (targetSchematics.length > 1) {
178+
failures.push(`Multiple migrations targeting the same major version: ${targetVersion.major}`);
179+
}
180+
return failures;
181+
}

tools/release/stage-release.ts

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {promptAndGenerateChangelog} from './changelog';
77
import {GitClient} from './git/git-client';
88
import {getGithubBranchCommitsUrl} from './git/github-urls';
99
import {promptForNewVersion} from './prompt/new-version-prompt';
10+
import {checkPackageJsonMigrations} from './release-output/output-validations';
11+
import {releasePackages} from './release-output/release-packages';
1012
import {parseVersionName, Version} from './version-name/parse-version';
1113

1214
/** Default filename for the changelog. */
@@ -51,7 +53,8 @@ class StageReleaseTask extends BaseReleaseTask {
5153
githubApi: OctokitApi;
5254

5355
constructor(
54-
public projectDir: string, public repositoryOwner: string, public repositoryName: string) {
56+
public projectDir: string, public packagesDir: string, public repositoryOwner: string,
57+
public repositoryName: string) {
5558
super(new GitClient(projectDir, `https://github.com/${repositoryOwner}/${repositoryName}.git`));
5659

5760
this.packageJsonPath = join(projectDir, 'package.json');
@@ -93,6 +96,7 @@ class StageReleaseTask extends BaseReleaseTask {
9396

9497
this.verifyLocalCommitsMatchUpstream(publishBranch);
9598
this._verifyAngularPeerDependencyVersion(newVersion);
99+
this._checkUpdateMigrationCollection(newVersion);
96100
await this._verifyPassingGithubStatus(publishBranch);
97101

98102
if (!this.git.checkoutNewBranch(stagingBranch)) {
@@ -159,17 +163,19 @@ class StageReleaseTask extends BaseReleaseTask {
159163
*/
160164
private _verifyAngularPeerDependencyVersion(newVersion: Version) {
161165
const currentVersionRange = this._getAngularVersionPlaceholderOrExit();
162-
const isMajorWithPrerelease = newVersion.minor === 0 && newVersion.patch === 0 &&
163-
newVersion.prereleaseLabel !== null;
166+
const isMajorWithPrerelease =
167+
newVersion.minor === 0 && newVersion.patch === 0 && newVersion.prereleaseLabel !== null;
164168
const requiredRange = isMajorWithPrerelease ?
165-
`^${newVersion.major}.0.0-0 || ^${newVersion.major + 1}.0.0-0` :
166-
`^${newVersion.major}.0.0 || ^${newVersion.major + 1}.0.0-0`;
169+
`^${newVersion.major}.0.0-0 || ^${newVersion.major + 1}.0.0-0` :
170+
`^${newVersion.major}.0.0 || ^${newVersion.major + 1}.0.0-0`;
167171

168172
if (requiredRange !== currentVersionRange) {
169-
console.error(chalk.red(` ✘ Cannot stage release. The required Angular version range ` +
170-
`is invalid. The version range should be: ${requiredRange}`));
171-
console.error(chalk.red(` Please manually update the version range ` +
172-
`in: ${BAZEL_RELEASE_CONFIG_PATH}`));
173+
console.error(chalk.red(
174+
` ✘ Cannot stage release. The required Angular version range ` +
175+
`is invalid. The version range should be: ${requiredRange}`));
176+
console.error(chalk.red(
177+
` Please manually update the version range ` +
178+
`in: ${BAZEL_RELEASE_CONFIG_PATH}`));
173179
return process.exit(1);
174180
}
175181
}
@@ -181,17 +187,19 @@ class StageReleaseTask extends BaseReleaseTask {
181187
private _getAngularVersionPlaceholderOrExit(): string {
182188
const bzlConfigPath = join(this.projectDir, BAZEL_RELEASE_CONFIG_PATH);
183189
if (!existsSync(bzlConfigPath)) {
184-
console.error(chalk.red(` ✘ Cannot stage release. Could not find the file which sets ` +
185-
`the Angular peerDependency placeholder value. Looked for: ${bzlConfigPath}`));
190+
console.error(chalk.red(
191+
` ✘ Cannot stage release. Could not find the file which sets ` +
192+
`the Angular peerDependency placeholder value. Looked for: ${bzlConfigPath}`));
186193
return process.exit(1);
187194
}
188195

189196
const configFileContent = readFileSync(bzlConfigPath, 'utf8');
190197
const matches = configFileContent.match(/ANGULAR_PACKAGE_VERSION = ["']([^"']+)/);
191198
if (!matches || !matches[1]) {
192-
console.error(chalk.red(` ✘ Cannot stage release. Could not find the ` +
193-
`"ANGULAR_PACKAGE_VERSION" variable. Please ensure this variable exists. ` +
194-
`Looked in: ${bzlConfigPath}`));
199+
console.error(chalk.red(
200+
` ✘ Cannot stage release. Could not find the ` +
201+
`"ANGULAR_PACKAGE_VERSION" variable. Please ensure this variable exists. ` +
202+
`Looked in: ${bzlConfigPath}`));
195203
return process.exit(1);
196204
}
197205
return matches[1];
@@ -236,9 +244,28 @@ class StageReleaseTask extends BaseReleaseTask {
236244

237245
console.info(chalk.green(` ✓ Upstream commit is passing all github status checks.`));
238246
}
247+
248+
/**
249+
* Checks if the update migration collections are set up to properly
250+
* handle the given new version.
251+
*/
252+
private _checkUpdateMigrationCollection(newVersion: Version) {
253+
const failures: string[] = [];
254+
releasePackages.forEach(packageName => {
255+
failures.push(...checkPackageJsonMigrations(
256+
join(this.packagesDir, packageName, 'package.json'), newVersion)
257+
.map(f => chalk.yellow(` ⮑ ${chalk.bold(packageName)}: ${f}`)));
258+
});
259+
if (failures.length) {
260+
console.error(chalk.red(` ✘ Failures in ng-update migration collection detected:`));
261+
failures.forEach(f => console.error(f));
262+
process.exit(1);
263+
}
264+
}
239265
}
240266

241267
/** Entry-point for the release staging script. */
242268
if (require.main === module) {
243-
new StageReleaseTask(join(__dirname, '../../'), 'angular', 'components').run();
269+
const projectDir = join(__dirname, '../../');
270+
new StageReleaseTask(projectDir, join(projectDir, 'src/'), 'angular', 'components').run();
244271
}

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,6 +1405,11 @@
14051405
resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.13.tgz#deb799c641773c5e367abafc92d1e733d62cddd7"
14061406
integrity sha512-rI0LGoMiZGUM+tjDakQpwZOvcmQoubiJ7hxqrYU12VRxBuGGvOThxrBOU/QmJKlKg1WG6FMzuvcEyLffvVSsmw==
14071407

1408+
"@types/semver@^6.2.0":
1409+
version "6.2.0"
1410+
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.0.tgz#d688d574400d96c5b0114968705366f431831e1a"
1411+
integrity sha512-1OzrNb4RuAzIT7wHSsgZRlMBlNsJl+do6UblR7JMW4oB7bbR+uBEYtUh7gEc/jM84GGilh68lSOokyM/zNUlBA==
1412+
14081413
"@types/send@^0.14.5":
14091414
version "0.14.5"
14101415
resolved "https://registry.yarnpkg.com/@types/send/-/send-0.14.5.tgz#653f7d25b93c3f7f51a8994addaf8a229de022a7"

0 commit comments

Comments
 (0)