Merge pull request #3127 from github/robertbrignull/nightly-codeql
Provide option to point ReleasesApiConsumer at nightly builds repo
This commit is contained in:
Коммит
f5dbcc8cc1
|
@ -51,6 +51,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.
|
||||
*
|
||||
|
@ -453,9 +463,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.
|
||||
|
@ -485,19 +504,40 @@ 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 get 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 get 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 get usingNightlyReleases(): boolean {
|
||||
return (
|
||||
this.distributionOwnerName === NIGHTLY_DISTRIBUTION_OWNER_NAME &&
|
||||
this.distributionRepositoryName === NIGHTLY_DISTRIBUTION_REPOSITORY_NAME
|
||||
);
|
||||
}
|
||||
|
||||
private async bumpDistributionFolderIndex(): Promise<void> {
|
||||
const index = this.extensionContext.globalState.get(
|
||||
ExtensionSpecificDistributionManager._currentDistributionFolderIndexStateKey,
|
||||
|
@ -570,7 +610,8 @@ export class ReleasesApiConsumer {
|
|||
}
|
||||
|
||||
public async getLatestRelease(
|
||||
versionRange: semver.Range,
|
||||
versionRange: semver.Range | undefined,
|
||||
orderBySemver = true,
|
||||
includePrerelease = false,
|
||||
additionalCompatibilityCheck?: (release: GithubRelease) => boolean,
|
||||
): Promise<Release> {
|
||||
|
@ -583,12 +624,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 (
|
||||
|
@ -597,10 +640,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;
|
||||
}
|
||||
|
|
|
@ -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 = "stable" | "nightly";
|
||||
|
||||
export interface DistributionConfig {
|
||||
readonly customCodeQlPath?: string;
|
||||
updateCustomCodeQlPath: (newPath: string | undefined) => Promise<void>;
|
||||
|
@ -118,6 +121,7 @@ export interface DistributionConfig {
|
|||
personalAccessToken?: string;
|
||||
ownerName?: string;
|
||||
repositoryName?: string;
|
||||
channel: CLIChannel;
|
||||
onDidChangeConfiguration?: Event<void>;
|
||||
}
|
||||
|
||||
|
@ -278,6 +282,10 @@ export class DistributionConfigListener
|
|||
);
|
||||
}
|
||||
|
||||
public get channel(): CLIChannel {
|
||||
return CLI_CHANNEL_SETTING.getValue() === "nightly" ? "nightly" : "stable";
|
||||
}
|
||||
|
||||
protected handleDidChangeConfiguration(e: ConfigurationChangeEvent): void {
|
||||
this.handleDidChangeConfigurationForRelevantSettings(
|
||||
DISTRIBUTION_CHANGE_SETTINGS,
|
||||
|
|
|
@ -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 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);
|
||||
|
||||
|
@ -128,6 +148,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 +159,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,9 +173,21 @@ describe("Releases API consumer", () => {
|
|||
const latestRelease = await consumer.getLatestRelease(
|
||||
unconstrainedVersionRange,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
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 () => {
|
||||
|
|
Загрузка…
Ссылка в новой задаче