From 66c0714606b92c625f35ef7b60450a13e661c611 Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 11 Dec 2023 17:26:55 +0000 Subject: [PATCH 1/8] Point ReleasesApiConsumer at nightly repo if config value is set --- .../ql-vscode/src/codeql-cli/distribution.ts | 40 +++++++++++++++---- extensions/ql-vscode/src/config.ts | 10 +++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/extensions/ql-vscode/src/codeql-cli/distribution.ts b/extensions/ql-vscode/src/codeql-cli/distribution.ts index 37548e918..7307d1a24 100644 --- a/extensions/ql-vscode/src/codeql-cli/distribution.ts +++ b/extensions/ql-vscode/src/codeql-cli/distribution.ts @@ -50,6 +50,16 @@ const DEFAULT_DISTRIBUTION_OWNER_NAME = "github"; */ const DEFAULT_DISTRIBUTION_REPOSITORY_NAME = "codeql-cli-binaries"; +/** + * Owner name of the nightly version of the extension-managed distribution on GitHub. + */ +const NIGHTLY_DISTRIBUTION_OWNER_NAME = "dsp-testing"; + +/** + * Repository name of the nightly version of the extension-managed distribution on GitHub. + */ +const NIGHTLY_DISTRIBUTION_REPOSITORY_NAME = "codeql-cli-nightlies"; + /** * Range of versions of the CLI that are compatible with the extension. * @@ -476,19 +486,33 @@ class ExtensionSpecificDistributionManager { } private createReleasesApiConsumer(): ReleasesApiConsumer { - const ownerName = this.config.ownerName - ? this.config.ownerName - : DEFAULT_DISTRIBUTION_OWNER_NAME; - const repositoryName = this.config.repositoryName - ? this.config.repositoryName - : DEFAULT_DISTRIBUTION_REPOSITORY_NAME; return new ReleasesApiConsumer( - ownerName, - repositoryName, + this.distributionOwnerName(), + this.distributionRepositoryName(), this.config.personalAccessToken, ); } + private distributionOwnerName(): string { + if (this.config.ownerName) { + return this.config.ownerName; + } else if (this.config.channel === "nightly") { + return NIGHTLY_DISTRIBUTION_OWNER_NAME; + } else { + return DEFAULT_DISTRIBUTION_OWNER_NAME; + } + } + + private distributionRepositoryName(): string { + if (this.config.repositoryName) { + return this.config.repositoryName; + } else if (this.config.channel === "nightly") { + return NIGHTLY_DISTRIBUTION_REPOSITORY_NAME; + } else { + return DEFAULT_DISTRIBUTION_REPOSITORY_NAME; + } + } + private async bumpDistributionFolderIndex(): Promise { const index = this.extensionContext.globalState.get( ExtensionSpecificDistributionManager._currentDistributionFolderIndexStateKey, diff --git a/extensions/ql-vscode/src/config.ts b/extensions/ql-vscode/src/config.ts index 4f89e2917..0b43ab52b 100644 --- a/extensions/ql-vscode/src/config.ts +++ b/extensions/ql-vscode/src/config.ts @@ -95,6 +95,7 @@ const PERSONAL_ACCESS_TOKEN_SETTING = new Setting( "personalAccessToken", DISTRIBUTION_SETTING, ); +const CLI_CHANNEL_SETTING = new Setting("channel", DISTRIBUTION_SETTING); // Query History configuration const QUERY_HISTORY_SETTING = new Setting("queryHistory", ROOT_SETTING); @@ -111,6 +112,8 @@ const DISTRIBUTION_CHANGE_SETTINGS = [ PERSONAL_ACCESS_TOKEN_SETTING, ]; +export type CLIChannel = "released" | "nightly"; + export interface DistributionConfig { readonly customCodeQlPath?: string; updateCustomCodeQlPath: (newPath: string | undefined) => Promise; @@ -118,6 +121,7 @@ export interface DistributionConfig { personalAccessToken?: string; ownerName?: string; repositoryName?: string; + channel: CLIChannel; onDidChangeConfiguration?: Event; /** @@ -283,6 +287,12 @@ export class DistributionConfigListener ); } + public get channel(): CLIChannel { + return CLI_CHANNEL_SETTING.getValue() === "nightly" + ? "nightly" + : "released"; + } + public forceUpdateConfiguration() { this._onDidChangeConfiguration.fire(undefined); } From 69dea08c47b0af7f773d1486d0ff4d10e05c3001 Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 19 Dec 2023 17:53:50 +0000 Subject: [PATCH 2/8] Don't check semver for nightly releases --- .../ql-vscode/src/codeql-cli/distribution.ts | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/extensions/ql-vscode/src/codeql-cli/distribution.ts b/extensions/ql-vscode/src/codeql-cli/distribution.ts index 4ae19e0e8..51e145ed5 100644 --- a/extensions/ql-vscode/src/codeql-cli/distribution.ts +++ b/extensions/ql-vscode/src/codeql-cli/distribution.ts @@ -453,9 +453,18 @@ class ExtensionSpecificDistributionManager { void extLogger.log( `Searching for latest release including ${requiredAssetName}.`, ); + + const versionRange = this.usingNightlyReleases() + ? undefined + : this.versionRange; + const orderBySemver = !this.usingNightlyReleases(); + const includePrerelease = + this.usingNightlyReleases() || this.config.includePrerelease; + return this.createReleasesApiConsumer().getLatestRelease( - this.versionRange, - this.config.includePrerelease, + versionRange, + orderBySemver, + includePrerelease, (release) => { // v2.12.3 was released with a bug that causes the extension to fail // so we force the extension to ignore it. @@ -512,6 +521,14 @@ class ExtensionSpecificDistributionManager { } } + private usingNightlyReleases(): boolean { + return ( + !this.config.ownerName && + !this.config.repositoryName && + this.config.channel === "nightly" + ); + } + private async bumpDistributionFolderIndex(): Promise { const index = this.extensionContext.globalState.get( ExtensionSpecificDistributionManager._currentDistributionFolderIndexStateKey, @@ -584,7 +601,8 @@ export class ReleasesApiConsumer { } public async getLatestRelease( - versionRange: semver.Range, + versionRange: semver.Range | undefined, + orderBySemver = true, includePrerelease = false, additionalCompatibilityCheck?: (release: GithubRelease) => boolean, ): Promise { @@ -597,12 +615,14 @@ export class ReleasesApiConsumer { return false; } - const version = semver.parse(release.tag_name); - if ( - version === null || - !semver.satisfies(version, versionRange, { includePrerelease }) - ) { - return false; + if (versionRange !== undefined) { + const version = semver.parse(release.tag_name); + if ( + version === null || + !semver.satisfies(version, versionRange, { includePrerelease }) + ) { + return false; + } } return ( @@ -611,10 +631,9 @@ export class ReleasesApiConsumer { }); // Tag names must all be parsable to semvers due to the previous filtering step. const latestRelease = compatibleReleases.sort((a, b) => { - const versionComparison = semver.compare( - semver.parse(b.tag_name)!, - semver.parse(a.tag_name)!, - ); + const versionComparison = orderBySemver + ? semver.compare(semver.parse(b.tag_name)!, semver.parse(a.tag_name)!) + : b.id - a.id; if (versionComparison !== 0) { return versionComparison; } From ba2f44b8ae0dd2cceb779b62599ebc000c8d4bd7 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 20 Dec 2023 11:37:11 +0000 Subject: [PATCH 3/8] Change to using getter for no-args methods --- .../ql-vscode/src/codeql-cli/distribution.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/ql-vscode/src/codeql-cli/distribution.ts b/extensions/ql-vscode/src/codeql-cli/distribution.ts index 51e145ed5..b8a4086a2 100644 --- a/extensions/ql-vscode/src/codeql-cli/distribution.ts +++ b/extensions/ql-vscode/src/codeql-cli/distribution.ts @@ -454,12 +454,12 @@ class ExtensionSpecificDistributionManager { `Searching for latest release including ${requiredAssetName}.`, ); - const versionRange = this.usingNightlyReleases() + const versionRange = this.usingNightlyReleases ? undefined : this.versionRange; - const orderBySemver = !this.usingNightlyReleases(); + const orderBySemver = !this.usingNightlyReleases; const includePrerelease = - this.usingNightlyReleases() || this.config.includePrerelease; + this.usingNightlyReleases || this.config.includePrerelease; return this.createReleasesApiConsumer().getLatestRelease( versionRange, @@ -495,13 +495,13 @@ class ExtensionSpecificDistributionManager { private createReleasesApiConsumer(): ReleasesApiConsumer { return new ReleasesApiConsumer( - this.distributionOwnerName(), - this.distributionRepositoryName(), + this.distributionOwnerName, + this.distributionRepositoryName, this.config.personalAccessToken, ); } - private distributionOwnerName(): string { + private get distributionOwnerName(): string { if (this.config.ownerName) { return this.config.ownerName; } else if (this.config.channel === "nightly") { @@ -511,7 +511,7 @@ class ExtensionSpecificDistributionManager { } } - private distributionRepositoryName(): string { + private get distributionRepositoryName(): string { if (this.config.repositoryName) { return this.config.repositoryName; } else if (this.config.channel === "nightly") { @@ -521,7 +521,7 @@ class ExtensionSpecificDistributionManager { } } - private usingNightlyReleases(): boolean { + private get usingNightlyReleases(): boolean { return ( !this.config.ownerName && !this.config.repositoryName && From c7e2d69daa5589c711550aad6da6cdef23fa51d7 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 20 Dec 2023 11:38:58 +0000 Subject: [PATCH 4/8] Define nightly by whether the value matches the default --- extensions/ql-vscode/src/codeql-cli/distribution.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/extensions/ql-vscode/src/codeql-cli/distribution.ts b/extensions/ql-vscode/src/codeql-cli/distribution.ts index b8a4086a2..0345c4e27 100644 --- a/extensions/ql-vscode/src/codeql-cli/distribution.ts +++ b/extensions/ql-vscode/src/codeql-cli/distribution.ts @@ -523,9 +523,8 @@ class ExtensionSpecificDistributionManager { private get usingNightlyReleases(): boolean { return ( - !this.config.ownerName && - !this.config.repositoryName && - this.config.channel === "nightly" + this.distributionOwnerName === NIGHTLY_DISTRIBUTION_OWNER_NAME && + this.distributionRepositoryName === NIGHTLY_DISTRIBUTION_REPOSITORY_NAME ); } From 4140303b5cb66943782745e18c7589a3c174678a Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 20 Dec 2023 11:41:33 +0000 Subject: [PATCH 5/8] Fix arguemnts to calls to getLatestRelease --- .../vscode-tests/no-workspace/codeql-cli/distribution.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts index 6c577aec9..4861413ff 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts @@ -128,6 +128,7 @@ describe("Releases API consumer", () => { const latestRelease = await consumer.getLatestRelease( new Range("2.*.*"), true, + true, (release) => release.assets.some((asset) => asset.name === "exampleAsset.txt"), ); @@ -138,7 +139,7 @@ describe("Releases API consumer", () => { const consumer = new MockReleasesApiConsumer(owner, repo); await expect( - consumer.getLatestRelease(new Range("2.*.*"), true, (release) => + consumer.getLatestRelease(new Range("2.*.*"), true, true, (release) => release.assets.some( (asset) => asset.name === "otherExampleAsset.txt", ), @@ -152,6 +153,7 @@ describe("Releases API consumer", () => { const latestRelease = await consumer.getLatestRelease( unconstrainedVersionRange, true, + true, ); expect(latestRelease.id).toBe(5); }); From 37b2e422cdbfc17d285d2b08c36150127394445f Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 20 Dec 2023 11:43:49 +0000 Subject: [PATCH 6/8] Use stable instead of released --- extensions/ql-vscode/src/config.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/extensions/ql-vscode/src/config.ts b/extensions/ql-vscode/src/config.ts index fd4bb09b3..cf018a186 100644 --- a/extensions/ql-vscode/src/config.ts +++ b/extensions/ql-vscode/src/config.ts @@ -112,7 +112,7 @@ const DISTRIBUTION_CHANGE_SETTINGS = [ PERSONAL_ACCESS_TOKEN_SETTING, ]; -export type CLIChannel = "released" | "nightly"; +export type CLIChannel = "stable" | "nightly"; export interface DistributionConfig { readonly customCodeQlPath?: string; @@ -283,9 +283,7 @@ export class DistributionConfigListener } public get channel(): CLIChannel { - return CLI_CHANNEL_SETTING.getValue() === "nightly" - ? "nightly" - : "released"; + return CLI_CHANNEL_SETTING.getValue() === "nightly" ? "nightly" : "stable"; } protected handleDidChangeConfiguration(e: ConfigurationChangeEvent): void { From e56503249d32a703c419591c2ffffa8aa4b10fa4 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 20 Dec 2023 16:19:45 +0000 Subject: [PATCH 7/8] Add tests that cover the new semver options --- .../codeql-cli/distribution.test.ts | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts index 4861413ff..40a8d507a 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts @@ -85,6 +85,15 @@ describe("Releases API consumer", () => { prerelease: true, tag_name: "v3.1.2-pre-2.0", }, + // Has a tag_name that is not valid semver + { + assets: [], + created_at: "2019-08-010T00:00:00Z", + id: 6, + name: "", + prerelease: true, + tag_name: "codeql-bundle-20231220", + }, ]; class MockReleasesApiConsumer extends ReleasesApiConsumer { @@ -98,15 +107,26 @@ describe("Releases API consumer", () => { } } - it("picked release has version with the highest precedence", async () => { + it("picked release is non-prerelease with with the highest semver", async () => { const consumer = new MockReleasesApiConsumer(owner, repo); const latestRelease = await consumer.getLatestRelease( unconstrainedVersionRange, + true, ); expect(latestRelease.id).toBe(2); }); + it("picked release is non-prerelease with highest id", async () => { + const consumer = new MockReleasesApiConsumer(owner, repo); + + const latestRelease = await consumer.getLatestRelease( + unconstrainedVersionRange, + false, + ); + expect(latestRelease.id).toBe(3); + }); + it("version of picked release is within the version range", async () => { const consumer = new MockReleasesApiConsumer(owner, repo); @@ -157,6 +177,17 @@ describe("Releases API consumer", () => { ); expect(latestRelease.id).toBe(5); }); + + it("ignores invalid semver and picks (pre-)release with highest id", async () => { + const consumer = new MockReleasesApiConsumer(owner, repo); + + const latestRelease = await consumer.getLatestRelease( + undefined, + false, + true, + ); + expect(latestRelease.id).toBe(6); + }); }); it("gets correct assets for a release", async () => { From c423505c04ff473b66961bc87525451119b02caa Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 2 Jan 2024 12:05:43 +0000 Subject: [PATCH 8/8] Update extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts Co-authored-by: Koen Vlaswinkel --- .../vscode-tests/no-workspace/codeql-cli/distribution.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts index 40a8d507a..e6ddd8aec 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/codeql-cli/distribution.test.ts @@ -107,7 +107,7 @@ describe("Releases API consumer", () => { } } - it("picked release is non-prerelease with with the highest semver", async () => { + it("picked release is non-prerelease with the highest semver", async () => { const consumer = new MockReleasesApiConsumer(owner, repo); const latestRelease = await consumer.getLatestRelease(