Skip to content

Commit fc01bfc

Browse files
Merge branch 'main' into a61-main-run-concurrency
2 parents 89d173a + 7cc64e6 commit fc01bfc

4 files changed

Lines changed: 109 additions & 7 deletions

File tree

‎tools/build.sh‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,12 @@ if [[ $GITHUB_REF =~ $TAG_TEST ]]; then
99
NPM_TAG=next
1010
fi;
1111
else
12-
FULL_VERSION=$(node -e "console.log(require('./package.json').version)")
13-
# Name the canary after the release itself, never after a prerelease of it. A canary built on
14-
# `21.0.0-rc.1` sorts above it, so the caret range `ng add` writes into a user's package.json
15-
# resolves to the canary rather than to the release candidate they asked for.
16-
BASE_VERSION=${FULL_VERSION%%-*}
17-
if [[ $BASE_VERSION != "$FULL_VERSION" ]]; then
18-
echo "package.json version is $FULL_VERSION. Naming this canary after $BASE_VERSION instead, so it does not outrank $FULL_VERSION on npm. Prereleases are published from their own git tag, so this field is meant to hold a plain release number." >&2
12+
PACKAGE_VERSION=$(node -e "console.log(require('./package.json').version)")
13+
if ! PUBLISHED_VERSIONS=$(npm view @angular/fire versions --json); then
14+
echo "Could not read the published @angular/fire versions from npm, so the canary has no version to build on." >&2
15+
exit 1
1916
fi
17+
BASE_VERSION=$(node ./tools/canary-version.js "$PACKAGE_VERSION" "$PUBLISHED_VERSIONS") || exit 1
2018
# `sha-` stops npm dropping an all-digit sha's leading zero.
2119
CANARY_ID=$(TZ=UTC git show -s --date=format-local:%Y%m%d%H%M%S --format=%cd.sha-%h $GITHUB_SHA)
2220
OVERRIDE_VERSION=$BASE_VERSION-canary.$CANARY_ID

‎tools/canary-version.jasmine.ts‎

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { maxSatisfying as semverMaxSatisfying } from 'semver';
2+
import { canaryBaseVersion } from './canary-version.js';
3+
import 'jasmine';
4+
5+
/* What's on npm today: a placeholder, v20 releases, rc.1, canaries named after the rc series
6+
* (deprecated), and canaries named after 21.0.0. */
7+
const publishedToday = [
8+
'0.0.0',
9+
'20.0.0',
10+
'20.1.0',
11+
'21.0.0-rc.0',
12+
'21.0.0-rc.0-canary.fb6796b',
13+
'21.0.0-rc.1',
14+
'21.0.0-rc.1-canary.95b3de1',
15+
'21.0.0-canary.a2662fe',
16+
'21.0.0-canary.20260930011755.sha-59d44e7',
17+
];
18+
19+
const canaryNamedAfter = (base: string) => `${base}-canary.20261001000000.sha-abcdef0`;
20+
21+
describe('canaryBaseVersion', () => {
22+
23+
it('names the canary one patch above the release candidate', () => {
24+
expect(canaryBaseVersion('21.0.0', publishedToday)).toBe('21.0.1');
25+
});
26+
27+
it('names the canary one patch above the release once it ships', () => {
28+
expect(canaryBaseVersion('21.0.0', [...publishedToday, '21.0.0'])).toBe('21.0.1');
29+
expect(canaryBaseVersion('21.0.0', [...publishedToday, '21.0.0', '21.0.1'])).toBe('21.0.2');
30+
});
31+
32+
it('names the canary above a minor or patch release candidate', () => {
33+
expect(canaryBaseVersion('21.0.0', [...publishedToday, '21.0.0', '21.1.0-rc.0'])).toBe('21.1.1');
34+
expect(canaryBaseVersion('21.0.0', [...publishedToday, '21.0.0', '21.0.1-rc.0'])).toBe('21.0.2');
35+
});
36+
37+
it('does not count earlier canaries', () => {
38+
const published = [...publishedToday, canaryNamedAfter('21.0.1'), canaryNamedAfter('21.0.1')];
39+
expect(canaryBaseVersion('21.0.0', published)).toBe('21.0.1');
40+
});
41+
42+
it('ignores releases from other majors', () => {
43+
expect(canaryBaseVersion('21.0.0', [...publishedToday, '21.0.0', '20.0.4'])).toBe('21.0.1');
44+
expect(canaryBaseVersion('21.0.0', [...publishedToday, '21.0.0', '22.0.0-rc.0'])).toBe('21.0.1');
45+
});
46+
47+
it('uses the package.json version when nothing in its major is published yet', () => {
48+
expect(canaryBaseVersion('22.0.0-rc.0', publishedToday)).toBe('22.0.0');
49+
expect(canaryBaseVersion('22.0.0-rc.0', [...publishedToday, '22.0.0-rc.0'])).toBe('22.0.1');
50+
});
51+
52+
it('throws when the package.json version has no version number in it', () => {
53+
expect(() => canaryBaseVersion('abc', publishedToday)).toThrowError(TypeError);
54+
});
55+
56+
it('gives a canary that its own caret range selects, and that release ranges never select', () => {
57+
const states = [
58+
publishedToday,
59+
[...publishedToday, '21.0.0'],
60+
[...publishedToday, '21.0.0', '21.0.1'],
61+
[...publishedToday, '21.0.0', '21.1.0-rc.0'],
62+
[...publishedToday, '21.0.0', '21.0.1-rc.0'],
63+
];
64+
for (const published of states) {
65+
const canary = canaryNamedAfter(canaryBaseVersion('21.0.0', published));
66+
const versions = [...published, canary];
67+
expect(semverMaxSatisfying(versions, `^${canary}`)).toBe(canary);
68+
for (const range of ['^21.0.0', '~21.0.0', '^21.0.0-rc.1', '^20.0.0']) {
69+
expect(semverMaxSatisfying(versions, range)).not.toBe(canary);
70+
}
71+
}
72+
});
73+
74+
});

‎tools/canary-version.js‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const semver = require('semver');
2+
3+
/**
4+
* Picks the version a canary build is named after, as in `<base>-canary.<time>.sha-<sha>`.
5+
*
6+
* `ng add @angular/fire@canary` saves `^<canary>`, and npm installs the highest version in that
7+
* range, so the canary must rank above every release and release candidate already published
8+
* in its major.
9+
*
10+
* @param {string} packageVersion The `version` field of the repository's package.json.
11+
* @param {string[]} publishedVersions Every @angular/fire version on npm.
12+
* @returns {string} One patch above the highest published version of the same major, or the
13+
* package.json version without its prerelease part if that is higher.
14+
*/
15+
function canaryBaseVersion(packageVersion, publishedVersions) {
16+
const packageBase = semver.coerce(packageVersion);
17+
// Published canaries don't count, or every canary would be named one patch above the one before it.
18+
const releases = publishedVersions.filter(
19+
version => !version.includes('canary') && semver.major(version) === packageBase.major,
20+
);
21+
const nextPatch = releases.length ? semver.coerce(semver.rsort(releases)[0]).inc('patch') : packageBase;
22+
return semver.gt(packageBase, nextPatch) ? packageBase.version : nextPatch.version;
23+
}
24+
25+
module.exports = { canaryBaseVersion };
26+
27+
if (require.main === module) {
28+
console.log(canaryBaseVersion(process.argv[2], JSON.parse(process.argv[3])));
29+
}

‎tsconfig.jasmine.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
},
1515
"include": [
1616
"tools/jasmine.ts",
17+
"tools/**/*.jasmine.ts",
1718
"src/**/*.jasmine.ts",
1819
// Not sure what is wrong here, but since upgrading karma it's fallen apart
1920
// "src/**/*.spec.ts",

0 commit comments

Comments
 (0)