Skip to content

Commit 6ec1005

Browse files
authored
fix: API compatibility check fails in CI pipeline (#19069)
This is a re-roll of #19070, fixing a bug introduced in that one. In the master build, we do a version bump which turns `1.146.0` into `1.146.0-rc.0`, which makes the API compatibility checker try to install packages with those versions. Because none of those packages exist, the list of packages ends up empty, which turns our `npm install $PACKAGES` command into `npm install`, which subsequently complains that there's no `package.json`. In order to make this work properly, we need to query the ACTUAL released version numbers on GitHub so we can properly find the version to diff against. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent a87dee7 commit 6ec1005

File tree

3 files changed

+62
-20
lines changed

3 files changed

+62
-20
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"jsii-pacmak": "^1.54.0",
2626
"jsii-reflect": "^1.54.0",
2727
"jsii-rosetta": "^1.54.0",
28+
"semver": "^6.3.0",
2829
"lerna": "^4.0.0",
2930
"patch-package": "^6.4.7",
3031
"standard-version": "^9.3.2",

scripts/check-api-compatibility.sh

+27-20
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ package_name() {
1414
# Doesn't use 'npm view' as that is slow. Direct curl'ing npmjs is better
1515
package_exists_on_npm() {
1616
pkg=$1
17-
ver=$2 # optional
17+
ver=${2:-} # optional
1818
curl -I 2>/dev/null https://registry.npmjs.org/$pkg/$ver | head -n 1 | grep 200 >/dev/null
1919
}
2020

@@ -32,10 +32,13 @@ jsii_package_dirs=$(list_jsii_packages)
3232

3333
#----------------------------------------------------------------------
3434

35-
# Input a directory, output the directory IF it exists on NPM
35+
# dirs_for_existing_pkgs DIRECTORY VERSION
36+
#
37+
# Input a directory and a version, output the directory IF it exists on NPM at that version
3638
dirs_for_existing_pkgs() {
3739
local dir="$1"
38-
if package_exists_on_npm $(package_name $dir); then
40+
local ver="$2"
41+
if package_exists_on_npm $(package_name $dir) $ver; then
3942
echo "$dir"
4043
echo -n "." >&2
4144
else
@@ -49,30 +52,34 @@ export -f dirs_for_existing_pkgs
4952

5053
if ! ${SKIP_DOWNLOAD:-false}; then
5154
echo "Filtering on existing packages on NPM..." >&2
52-
# In parallel
53-
existing_pkg_dirs=$(echo "$jsii_package_dirs" | xargs -n1 -P4 -I {} bash -c 'dirs_for_existing_pkgs "$@"' _ {})
54-
existing_names=$(echo "$existing_pkg_dirs" | xargs -n1 -P4 -I {} bash -c 'package_name "$@"' _ {})
55-
echo " Done." >&2
5655

57-
echo "Determining baseline version..." >&2
58-
version=$(node -p 'require("./scripts/resolve-version.js").version')
59-
echo " Current version is $version." >&2
56+
echo "Determining baseline version... " >&2
57+
build_version=$(node -p 'require("./scripts/resolve-version.js").version')
58+
echo "Build version: ${build_version}." >&2
6059

61-
if ! package_exists_on_npm aws-cdk $version; then
62-
major_version=$(echo "$version" | sed -e 's/\..*//g')
63-
echo " Version $version does not exist in npm. Falling back to package major version ${major_version}" >&2
64-
existing_names=$(echo "$existing_names" | sed -e "s/$/@$major_version/")
65-
else
66-
echo "Using version '$version' as the baseline..."
67-
existing_names=$(echo "$existing_names" | sed -e "s/$/@$version/")
68-
fi
60+
# Either called as:
61+
# - find-latest-release "<=2.14.0" (PR build); or
62+
# - find-latest-release "<=2.15.0-rc.0" (CI build); or
63+
# - find-latest-release "<=2.15.0" (release build)
64+
# all of which will find 2.14.0 as the version to compare against.
65+
version=$(node ./scripts/find-latest-release.js "<=${build_version}")
66+
echo "Released version: $version." >&2
67+
68+
echo "Using version '$version' as the baseline..." >&2
69+
70+
# Filter packages by existing at the target version
71+
existing_pkg_dirs=$(echo "$jsii_package_dirs" | xargs -n1 -P4 -I {} bash -c 'dirs_for_existing_pkgs "$@" "'$version'"' _ {})
72+
existing_names=$(echo "$existing_pkg_dirs" | xargs -n1 -P4 -I {} bash -c 'package_name "$@"' _ {})
73+
install_versions=$(for name in $existing_names; do echo "${name}@${version}"; done)
74+
echo " Done." >&2
6975

7076
rm -rf $tmpdir
7177
mkdir -p $tmpdir
7278

7379
echo "Installing from NPM..." >&2
74-
# use npm7 to automatically install peer dependencies
75-
(cd $tmpdir && npx npm@^7.0.0 install --prefix $tmpdir $existing_names)
80+
# Use npm7 instead of whatever the current NPM version is to make sure we
81+
# automatically install peer dependencies
82+
(cd $tmpdir && npx npm@^7.0.0 install --prefix $tmpdir $install_versions)
7683
fi
7784

7885
#----------------------------------------------------------------------

scripts/find-latest-release.js

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Find the latest CDK release on GitHub matching a particular semver range
2+
//
3+
// The range can be something like '<1.2.3' to find the latest release before a given version,
4+
// or '2' to find the latest v2 release.
5+
//
6+
// Only searches the most recent 100 GitHub releases, so only use this to query fairly recent versions.
7+
const cp = require('child_process');
8+
const semver = require('semver');
9+
10+
async function main(matchRange) {
11+
if (matchRange === undefined) {
12+
throw new Error('Usage: find-latest-release.js RANGE');
13+
}
14+
const range = semver.validRange(matchRange);
15+
if (!range) {
16+
throw new Error(`Not a valid range: ${matchRange}`);
17+
}
18+
19+
const { stdout, error } = cp.spawnSync('curl', ['https://api.github.com/repos/aws/aws-cdk/releases?per_page=100'], { maxBuffer: 10_000_000 });
20+
if (error) { throw error; }
21+
const releases = JSON.parse(stdout);
22+
const versions = releases.map(r => r.name.replace(/^v/, '')); // v1.2.3 -> 1.2.3
23+
24+
const sat = semver.maxSatisfying(versions, range);
25+
if (!sat) {
26+
throw new Error(`No range satisfied ${range} (on the first page of GitHub releases)`);
27+
}
28+
console.log(sat);
29+
}
30+
31+
main(process.argv[2]).catch(e => {
32+
console.error(e);
33+
process.exitCode = 1;
34+
});

0 commit comments

Comments
 (0)