Skip to content

Commit 1c267e4

Browse files
Merge pull request #3569 from github/robertbrignull/ghec_dr_mode
Detect when the github-enterprise.uri setting is set
2 parents 27d6a74 + 2f67cce commit 1c267e4

File tree

6 files changed

+219
-4
lines changed

6 files changed

+219
-4
lines changed

extensions/ql-vscode/src/config.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type {
44
ConfigurationScope,
55
Event,
66
} from "vscode";
7-
import { ConfigurationTarget, EventEmitter, workspace } from "vscode";
7+
import { ConfigurationTarget, EventEmitter, workspace, Uri } from "vscode";
88
import type { DistributionManager } from "./codeql-cli/distribution";
99
import { extLogger } from "./common/logging/vscode";
1010
import { ONE_DAY_IN_MS } from "./common/time";
@@ -14,6 +14,7 @@ import {
1414
SortKey,
1515
} from "./variant-analysis/shared/variant-analysis-filter-sort";
1616
import { substituteConfigVariables } from "./common/config-template";
17+
import { getErrorMessage } from "./common/helpers-pure";
1718

1819
export const ALL_SETTINGS: Setting[] = [];
1920

@@ -69,6 +70,52 @@ export const VSCODE_SAVE_BEFORE_START_SETTING = new Setting(
6970
VSCODE_DEBUG_SETTING,
7071
);
7172

73+
const VSCODE_GITHUB_ENTERPRISE_SETTING = new Setting(
74+
"github-enterprise",
75+
undefined,
76+
);
77+
export const VSCODE_GITHUB_ENTERPRISE_URI_SETTING = new Setting(
78+
"uri",
79+
VSCODE_GITHUB_ENTERPRISE_SETTING,
80+
);
81+
82+
/**
83+
* Get the value of the `github-enterprise.uri` setting, parsed as a URI.
84+
* If the value is not set or cannot be parsed, return `undefined`.
85+
*/
86+
export function getEnterpriseUri(): Uri | undefined {
87+
const config = VSCODE_GITHUB_ENTERPRISE_URI_SETTING.getValue<string>();
88+
if (config) {
89+
try {
90+
let uri = Uri.parse(config, true);
91+
if (uri.scheme === "http") {
92+
uri = uri.with({ scheme: "https" });
93+
}
94+
return uri;
95+
} catch (e) {
96+
void extLogger.log(
97+
`Failed to parse the GitHub Enterprise URI: ${getErrorMessage(e)}`,
98+
);
99+
}
100+
}
101+
return undefined;
102+
}
103+
104+
/**
105+
* Is the GitHub Enterprise URI set?
106+
*/
107+
export function hasEnterpriseUri(): boolean {
108+
return getEnterpriseUri() !== undefined;
109+
}
110+
111+
/**
112+
* Is the GitHub Enterprise URI set to something that looks like GHEC-DR?
113+
*/
114+
export function hasGhecDrUri(): boolean {
115+
const uri = getEnterpriseUri();
116+
return uri !== undefined && uri.authority.toLowerCase().endsWith(".ghe.com");
117+
}
118+
72119
const ROOT_SETTING = new Setting("codeQL");
73120

74121
// Telemetry configuration
@@ -576,6 +623,11 @@ export function getVariantAnalysisDefaultResultsSort(): SortKey {
576623
*/
577624
const ACTION_BRANCH = new Setting("actionBranch", VARIANT_ANALYSIS_SETTING);
578625

626+
export const VARIANT_ANALYSIS_ENABLE_GHEC_DR = new Setting(
627+
"enableGhecDr",
628+
VARIANT_ANALYSIS_SETTING,
629+
);
630+
579631
export function getActionBranch(): string {
580632
return ACTION_BRANCH.getValue<string>() || "main";
581633
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {
2+
VARIANT_ANALYSIS_ENABLE_GHEC_DR,
3+
hasEnterpriseUri,
4+
hasGhecDrUri,
5+
} from "../config";
6+
7+
/**
8+
* Determines whether MRVA should be enabled or not for the current GitHub host.
9+
* This is based on the `github-enterprise.uri` setting.
10+
*/
11+
export function isVariantAnalysisEnabledForGitHubHost(): boolean {
12+
return (
13+
// MRVA is always enabled on github.com
14+
!hasEnterpriseUri() ||
15+
// MRVA can be enabled on GHEC-DR using a feature flag
16+
(hasGhecDrUri() && !!VARIANT_ANALYSIS_ENABLE_GHEC_DR.getValue<boolean>())
17+
);
18+
}

extensions/ql-vscode/src/variant-analysis/variant-analysis-manager.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
9797
import { findVariantAnalysisQlPackRoot } from "./ql";
9898
import { resolveCodeScanningQueryPack } from "./code-scanning-pack";
9999
import { isSarifResultsQueryKind } from "../common/query-metadata";
100+
import { isVariantAnalysisEnabledForGitHubHost } from "./ghec-dr";
101+
import { getEnterpriseUri } from "../config";
100102

101103
const maxRetryCount = 3;
102104

@@ -327,6 +329,12 @@ export class VariantAnalysisManager
327329
token: CancellationToken,
328330
openViewAfterSubmission = true,
329331
): Promise<number | undefined> {
332+
if (!isVariantAnalysisEnabledForGitHubHost()) {
333+
throw new Error(
334+
`Multi-repository variant analysis is not enabled for ${getEnterpriseUri()}`,
335+
);
336+
}
337+
330338
await saveBeforeStart();
331339

332340
progress({

extensions/ql-vscode/test/vscode-tests/cli-integration/variant-analysis/variant-analysis-manager.test.ts

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1-
import { CancellationTokenSource, commands, window, Uri } from "vscode";
1+
import {
2+
CancellationTokenSource,
3+
commands,
4+
window,
5+
Uri,
6+
ConfigurationTarget,
7+
} from "vscode";
28
import { extLogger } from "../../../../src/common/logging/vscode";
3-
import { setRemoteControllerRepo } from "../../../../src/config";
9+
import {
10+
VSCODE_GITHUB_ENTERPRISE_URI_SETTING,
11+
setRemoteControllerRepo,
12+
} from "../../../../src/config";
413
import * as ghApiClient from "../../../../src/variant-analysis/gh-api/gh-api-client";
514
import { isAbsolute, join } from "path";
615

@@ -99,6 +108,32 @@ describe("Variant Analysis Manager", () => {
99108
await setRemoteControllerRepo("github/vscode-codeql");
100109
});
101110

111+
it("fails if MRVA is not supported for this GHE URI", async () => {
112+
await VSCODE_GITHUB_ENTERPRISE_URI_SETTING.updateValue(
113+
"https://github.example.com",
114+
ConfigurationTarget.Global,
115+
);
116+
117+
const qlPackDetails: QlPackDetails = {
118+
queryFiles: [getFileOrDir("data-remote-qlpack/in-pack.ql")],
119+
qlPackRootPath: getFileOrDir("data-remote-qlpack"),
120+
qlPackFilePath: getFileOrDir("data-remote-qlpack/qlpack.yml"),
121+
language: QueryLanguage.Javascript,
122+
};
123+
124+
await expect(
125+
variantAnalysisManager.runVariantAnalysis(
126+
qlPackDetails,
127+
progress,
128+
cancellationTokenSource.token,
129+
),
130+
).rejects.toThrow(
131+
new Error(
132+
"Multi-repository variant analysis is not enabled for https://github.example.com/",
133+
),
134+
);
135+
});
136+
102137
it("should run a variant analysis that is part of a qlpack", async () => {
103138
const filePath = getFileOrDir("data-remote-qlpack/in-pack.ql");
104139
const qlPackRootPath = getFileOrDir("data-remote-qlpack");

extensions/ql-vscode/test/vscode-tests/minimal-workspace/config.test.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
import { workspace } from "vscode";
1+
import { ConfigurationTarget, workspace } from "vscode";
22

33
import type { ConfigListener } from "../../../src/config";
44
import {
55
CliConfigListener,
66
QueryHistoryConfigListener,
77
QueryServerConfigListener,
8+
VSCODE_GITHUB_ENTERPRISE_URI_SETTING,
9+
getEnterpriseUri,
10+
hasEnterpriseUri,
11+
hasGhecDrUri,
812
} from "../../../src/config";
913
import { vscodeGetConfigurationMock } from "../test-config";
1014

@@ -126,3 +130,49 @@ describe("config listeners", () => {
126130
return new Promise((resolve) => setTimeout(resolve, ms));
127131
}
128132
});
133+
134+
describe("enterprise URI", () => {
135+
it("detects no enterprise URI when config value is not set", async () => {
136+
expect(getEnterpriseUri()).toBeUndefined();
137+
expect(hasEnterpriseUri()).toBe(false);
138+
expect(hasGhecDrUri()).toBe(false);
139+
});
140+
141+
it("detects no enterprise URI when config value is set to an invalid value", async () => {
142+
await VSCODE_GITHUB_ENTERPRISE_URI_SETTING.updateValue(
143+
"invalid-uri",
144+
ConfigurationTarget.Global,
145+
);
146+
expect(getEnterpriseUri()).toBeUndefined();
147+
expect(hasEnterpriseUri()).toBe(false);
148+
expect(hasGhecDrUri()).toBe(false);
149+
});
150+
151+
it("detects an enterprise URI when config value is set to a GHES URI", async () => {
152+
await VSCODE_GITHUB_ENTERPRISE_URI_SETTING.updateValue(
153+
"https://github.example.com",
154+
ConfigurationTarget.Global,
155+
);
156+
expect(getEnterpriseUri()?.toString()).toBe("https://github.example.com/");
157+
expect(hasEnterpriseUri()).toBe(true);
158+
expect(hasGhecDrUri()).toBe(false);
159+
});
160+
161+
it("detects a GHEC-DR URI when config value is set to a GHEC-DR URI", async () => {
162+
await VSCODE_GITHUB_ENTERPRISE_URI_SETTING.updateValue(
163+
"https://example.ghe.com",
164+
ConfigurationTarget.Global,
165+
);
166+
expect(getEnterpriseUri()?.toString()).toBe("https://example.ghe.com/");
167+
expect(hasEnterpriseUri()).toBe(true);
168+
expect(hasGhecDrUri()).toBe(true);
169+
});
170+
171+
it("Upgrades HTTP URIs to HTTPS", async () => {
172+
await VSCODE_GITHUB_ENTERPRISE_URI_SETTING.updateValue(
173+
"http://example.ghe.com",
174+
ConfigurationTarget.Global,
175+
);
176+
expect(getEnterpriseUri()?.toString()).toBe("https://example.ghe.com/");
177+
});
178+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { ConfigurationTarget } from "vscode";
2+
import {
3+
VARIANT_ANALYSIS_ENABLE_GHEC_DR,
4+
VSCODE_GITHUB_ENTERPRISE_URI_SETTING,
5+
} from "../../../../src/config";
6+
import { isVariantAnalysisEnabledForGitHubHost } from "../../../../src/variant-analysis/ghec-dr";
7+
8+
describe("checkVariantAnalysisEnabled", () => {
9+
it("returns cleanly when no enterprise URI is set", async () => {
10+
expect(isVariantAnalysisEnabledForGitHubHost()).toBe(true);
11+
});
12+
13+
it("returns false when GHES enterprise URI is set and variant analysis feature flag is not set", async () => {
14+
await VSCODE_GITHUB_ENTERPRISE_URI_SETTING.updateValue(
15+
"https://github.example.com",
16+
ConfigurationTarget.Global,
17+
);
18+
expect(isVariantAnalysisEnabledForGitHubHost()).toBe(false);
19+
});
20+
21+
it("returns false when GHES enterprise URI is set and variant analysis feature flag is set", async () => {
22+
await VSCODE_GITHUB_ENTERPRISE_URI_SETTING.updateValue(
23+
"https://github.example.com",
24+
ConfigurationTarget.Global,
25+
);
26+
await VARIANT_ANALYSIS_ENABLE_GHEC_DR.updateValue(
27+
"true",
28+
ConfigurationTarget.Global,
29+
);
30+
expect(isVariantAnalysisEnabledForGitHubHost()).toBe(false);
31+
});
32+
33+
it("returns false when GHEC-DR URI is set and variant analysis feature flag is not set", async () => {
34+
await VSCODE_GITHUB_ENTERPRISE_URI_SETTING.updateValue(
35+
"https://example.ghe.com",
36+
ConfigurationTarget.Global,
37+
);
38+
expect(isVariantAnalysisEnabledForGitHubHost()).toBe(false);
39+
});
40+
41+
it("returns true when GHEC-DR URI is set and variant analysis feature flag is set", async () => {
42+
await VSCODE_GITHUB_ENTERPRISE_URI_SETTING.updateValue(
43+
"https://example.ghe.com",
44+
ConfigurationTarget.Global,
45+
);
46+
await VARIANT_ANALYSIS_ENABLE_GHEC_DR.updateValue(
47+
"true",
48+
ConfigurationTarget.Global,
49+
);
50+
expect(isVariantAnalysisEnabledForGitHubHost()).toBe(true);
51+
});
52+
});

0 commit comments

Comments
 (0)