Skip to content

Commit e14dae5

Browse files
committed
fix(@schematics/update): allow for rc/beta migrations
1 parent d499b1b commit e14dae5

File tree

4 files changed

+125
-4
lines changed

4 files changed

+125
-4
lines changed

packages/schematics/update/migrate/index.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { PostUpdateSchema } from './schema';
2020

2121
export default function(options: PostUpdateSchema): Rule {
2222
return (tree: Tree, context: SchematicContext) => {
23-
const schematicsToRun: string[] = [];
23+
const schematicsToRun: { name: string; version: string; }[] = [];
2424

2525
// Create the collection for the package.
2626
const collection = context.engine.createCollection(options.collection);
@@ -37,20 +37,27 @@ export default function(options: PostUpdateSchema): Rule {
3737
if (!version.match(/^\d{1,30}\.\d{1,30}\.\d{1,30}$/)) {
3838
version += '.0';
3939
}
40-
if (!version.match(/^\d{1,30}\.\d{1,30}\.\d{1,30}$/)) {
40+
if (!semver.valid(version)) {
4141
throw new SchematicsException(
4242
`Invalid migration version: ${JSON.stringify(description['version'])}`,
4343
);
4444
}
4545

4646
if (semver.gt(version, options.from) && semver.lte(version, options.to)) {
47-
schematicsToRun.push(name);
47+
schematicsToRun.push({ name, version });
4848
}
4949
}
5050
}
5151

52+
schematicsToRun.sort((a, b) => {
53+
const cmp = semver.compare(a.version, b.version);
54+
55+
// Revert to comparing the names of the collection if the versions are equal.
56+
return cmp == 0 ? a.name.localeCompare(b.name) : cmp;
57+
});
58+
5259
if (schematicsToRun.length > 0) {
53-
const rules = schematicsToRun.map(name => externalSchematic(options.collection, name, {}));
60+
const rules = schematicsToRun.map(x => externalSchematic(options.collection, x.name, {}));
5461

5562
return chain(rules)(tree, context);
5663
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import { virtualFs } from '@angular-devkit/core';
9+
import { HostTree, VirtualTree } from '@angular-devkit/schematics';
10+
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
11+
import { map } from 'rxjs/operators';
12+
13+
14+
describe('@schematics/update:migrate', () => {
15+
const schematicRunner = new SchematicTestRunner(
16+
'@schematics/update', __dirname + '/../collection.json',
17+
);
18+
let host: virtualFs.test.TestHost;
19+
let appTree: UnitTestTree = new UnitTestTree(new VirtualTree());
20+
21+
beforeEach(() => {
22+
host = new virtualFs.test.TestHost({});
23+
appTree = new UnitTestTree(new HostTree(host));
24+
});
25+
26+
it('sorts and understand RC', done => {
27+
// Since we cannot run tasks in unit tests, we need to validate that the default
28+
// update schematic updates the package.json appropriately, AND validate that the
29+
// migrate schematic actually do work appropriately, in a separate test.
30+
schematicRunner.runSchematicAsync('migrate', {
31+
package: 'test',
32+
collection: __dirname + '/test/migration.json',
33+
from: '1.0.0',
34+
to: '2.0.0',
35+
}, appTree).pipe(
36+
map(tree => {
37+
const resultJson = JSON.parse(tree.readContent('/migrations'));
38+
39+
expect(resultJson).toEqual([
40+
'migration-03', // "1.0.5"
41+
'migration-05', // "1.1.0-beta.0"
42+
'migration-04', // "1.1.0-beta.1"
43+
'migration-02', // "1.1.0"
44+
'migration-13', // "1.1.0"
45+
'migration-19', // "1.1"
46+
'migration-06', // "1.4.0"
47+
'migration-17', // "2.0.0-alpha"
48+
'migration-16', // "2.0.0-alpha.5"
49+
'migration-08', // "2.0.0-beta.0"
50+
'migration-07', // "2.0.0-rc.0"
51+
'migration-12', // "2.0.0-rc.4"
52+
'migration-14', // "2.0.0"
53+
'migration-20', // "2"
54+
]);
55+
}),
56+
).subscribe(undefined, done.fail, done);
57+
});
58+
});
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"schematics": {
3+
"migration-00": { "version": "0.1.0", "factory": "./t1", "description": "." },
4+
"migration-01": { "version": "1.0.0", "factory": "./t1", "description": "." },
5+
"migration-02": { "version": "1.1.0", "factory": "./t1", "description": "." },
6+
"migration-03": { "version": "1.0.5", "factory": "./t1", "description": "." },
7+
"migration-04": { "version": "1.1.0-beta.1", "factory": "./t1", "description": "." },
8+
"migration-05": { "version": "1.1.0-beta.0", "factory": "./t1", "description": "." },
9+
"migration-06": { "version": "1.4.0", "factory": "./t1", "description": "." },
10+
"migration-07": { "version": "2.0.0-rc.0", "factory": "./t1", "description": "." },
11+
"migration-08": { "version": "2.0.0-beta.0", "factory": "./t1", "description": "." },
12+
"migration-09": { "version": "4.0.0", "factory": "./t1", "description": "." },
13+
"migration-10": { "version": "0.1.0", "factory": "./t1", "description": "." },
14+
"migration-11": { "version": "2.1.0", "factory": "./t1", "description": "." },
15+
"migration-12": { "version": "2.0.0-rc.4", "factory": "./t1", "description": "." },
16+
"migration-13": { "version": "1.1.0", "factory": "./t1", "description": "." },
17+
"migration-14": { "version": "2.0.0", "factory": "./t1", "description": "." },
18+
"migration-15": { "version": "2.0.1", "factory": "./t1", "description": "." },
19+
"migration-16": { "version": "2.0.0-alpha.5", "factory": "./t1", "description": "." },
20+
"migration-17": { "version": "2.0.0-alpha", "factory": "./t1", "description": "." },
21+
"migration-18": { "version": "1", "factory": "./t1", "description": "." },
22+
"migration-19": { "version": "1.1", "factory": "./t1", "description": "." },
23+
"migration-20": { "version": "2", "factory": "./t1", "description": "." }
24+
}
25+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import { Rule, SchematicsException } from '@angular-devkit/schematics';
9+
10+
export default function(): Rule {
11+
return (tree, context) => {
12+
let content = tree.read('/migrations');
13+
14+
// Append the information to migration file. We then verify the order of execution.
15+
if (!content) {
16+
tree.create('/migrations', '[]');
17+
content = tree.read('/migrations');
18+
19+
if (!content) {
20+
throw new SchematicsException();
21+
}
22+
}
23+
24+
const json = JSON.parse(content.toString('utf-8'));
25+
json.push(context.schematic.description.name);
26+
27+
tree.overwrite('/migrations', JSON.stringify(json));
28+
29+
return tree;
30+
};
31+
}

0 commit comments

Comments
 (0)