Introduce release compatibility check before selecting the most recent

This commit is contained in:
Henry Mercer 2020-06-01 20:13:33 +01:00
Родитель 71d4038744
Коммит 8208940532
2 изменённых файлов: 47 добавлений и 13 удалений

Просмотреть файл

@ -322,16 +322,22 @@ class ExtensionSpecificDistributionManager {
}
private async getLatestRelease(): Promise<Release> {
const release = await this.createReleasesApiConsumer().getLatestRelease(this._versionRange, this._config.includePrerelease);
// FIXME: Look for platform-specific codeql distribution if available
release.assets = release.assets.filter(asset => asset.name === 'codeql.zip');
if (release.assets.length === 0) {
throw new Error("Release had no asset named codeql.zip");
}
else if (release.assets.length > 1) {
throw new Error("Release had more than one asset named codeql.zip");
}
return release;
return await this.createReleasesApiConsumer().getLatestRelease(
this._versionRange,
this._config.includePrerelease,
release => {
// FIXME: Look for platform-specific codeql distribution if available
// https://github.com/github/vscode-codeql/issues/417
const matchingAssets = release.assets.filter(asset => asset.name === 'codeql.zip');
if (matchingAssets.length !== 1) {
if (matchingAssets.length > 1) {
logger.log("WARNING: Ignoring a release with more than one asset named codeql.zip");
}
return false;
}
return true;
}
);
}
private createReleasesApiConsumer(): ReleasesApiConsumer {
@ -391,7 +397,7 @@ export class ReleasesApiConsumer {
this._repoName = repoName;
}
public async getLatestRelease(versionRange: semver.Range, includePrerelease = false): Promise<Release> {
public async getLatestRelease(versionRange: semver.Range, includePrerelease = false, additionalCompatibilityCheck?: (release: GithubRelease) => boolean): Promise<Release> {
const apiPath = `/repos/${this._ownerName}/${this._repoName}/releases`;
const allReleases: GithubRelease[] = await (await this.makeApiCall(apiPath)).json();
const compatibleReleases = allReleases.filter(release => {
@ -400,7 +406,11 @@ export class ReleasesApiConsumer {
}
const version = semver.parse(release.tag_name);
return version !== null && semver.satisfies(version, versionRange);
if (version === null || !semver.satisfies(version, versionRange)) {
return false;
}
return !additionalCompatibilityCheck || additionalCompatibilityCheck(release);
});
// Tag names must all be parsable to semvers due to the previous filtering step.
const latestRelease = compatibleReleases.sort((a, b) => {

Просмотреть файл

@ -35,7 +35,11 @@ describe("Releases API consumer", () => {
"tag_name": "v3.1.1"
},
{
"assets": [],
"assets": [{
id: 1,
name: "exampleAsset.txt",
size: 1
}],
"created_at": "2019-09-05T00:00:00Z",
"id": 3,
"name": "",
@ -85,6 +89,26 @@ describe("Releases API consumer", () => {
expect(latestRelease.id).to.equal(1);
});
it("picking latest release: release passes additional compatibility test if additional compatibility test specified", async () => {
class MockReleasesApiConsumer extends ReleasesApiConsumer {
protected async makeApiCall(apiPath: string): Promise<fetch.Response> {
if (apiPath === `/repos/${owner}/${repo}/releases`) {
return Promise.resolve(new fetch.Response(JSON.stringify(sampleReleaseResponse)));
}
return Promise.reject(new Error(`Unknown API path: ${apiPath}`));
}
}
const consumer = new MockReleasesApiConsumer(owner, repo);
const latestRelease = await consumer.getLatestRelease(
new semver.Range("2.*.*"),
true,
release => release.assets.some(asset => asset.name === "exampleAsset.txt")
);
expect(latestRelease.id).to.equal(3);
});
it("picking latest release: includes prereleases when option set", async () => {
class MockReleasesApiConsumer extends ReleasesApiConsumer {
protected async makeApiCall(apiPath: string): Promise<fetch.Response> {