Skip to content

Commit 7ea7d6c

Browse files
author
Dave Bartolomeo
committed
Merge remote-tracking branch 'origin/main' into dbartol/new-test-ui
2 parents 4804220 + eabcd00 commit 7ea7d6c

13 files changed

Lines changed: 1059 additions & 146 deletions

File tree

extensions/ql-vscode/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
## [UNRELEASED]
44

5+
## 1.8.2 - 12 April 2023
6+
7+
- Fix bug where users could end up with the managed CodeQL CLI getting uninstalled during upgrades and not reinstalled. [#2294](https://github.com/github/vscode-codeql/pull/2294)
58
- Fix bug that was causing code flows to not get updated when switching between results. [#2288](https://github.com/github/vscode-codeql/pull/2288)
69
- Restart the CodeQL language server whenever the _CodeQL: Restart Query Server_ command is invoked. This avoids bugs where the CLI version changes to support new language features, but the language server is not updated. [#2238](https://github.com/github/vscode-codeql/pull/2238)
10+
- Avoid requiring a manual restart of the query server when the [external CLI config file](https://docs.github.com/en/code-security/codeql-cli/using-the-codeql-cli/specifying-command-options-in-a-codeql-configuration-file#using-a-codeql-configuration-file) changes. [#2289](https://github.com/github/vscode-codeql/pull/2289)
711

812
## 1.8.1 - 23 March 2023
913

extensions/ql-vscode/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/ql-vscode/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "CodeQL for Visual Studio Code",
55
"author": "GitHub",
66
"private": true,
7-
"version": "1.8.2",
7+
"version": "1.8.3",
88
"publisher": "GitHub",
99
"license": "MIT",
1010
"icon": "media/VS-marketplace-CodeQL-icon.png",
@@ -361,6 +361,10 @@
361361
"command": "codeQL.quickQuery",
362362
"title": "CodeQL: Quick Query"
363363
},
364+
{
365+
"command": "codeQL.createSkeletonQuery",
366+
"title": "CodeQL: Create Query"
367+
},
364368
{
365369
"command": "codeQL.openDocumentation",
366370
"title": "CodeQL: Open Documentation"

extensions/ql-vscode/src/common/commands.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export type BaseCommands = {
7171
"codeQL.restartQueryServer": () => Promise<void>;
7272
"codeQL.restartQueryServerOnConfigChange": () => Promise<void>;
7373
"codeQL.restartLegacyQueryServerOnConfigChange": () => Promise<void>;
74+
"codeQL.restartQueryServerOnExternalConfigChange": () => Promise<void>;
7475
};
7576

7677
// Commands used when working with queries in the editor
@@ -98,6 +99,7 @@ export type LocalQueryCommands = {
9899
"codeQL.quickEvalContextEditor": (uri: Uri) => Promise<void>;
99100
"codeQL.codeLensQuickEval": (uri: Uri, range: Range) => Promise<void>;
100101
"codeQL.quickQuery": () => Promise<void>;
102+
"codeQL.createSkeletonQuery": () => Promise<void>;
101103
};
102104

103105
export type ResultsViewCommands = {

extensions/ql-vscode/src/databaseFetcher.ts

Lines changed: 81 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import fetch, { Response } from "node-fetch";
22
import { zip } from "zip-a-folder";
33
import { Open } from "unzipper";
4-
import { Uri, CancellationToken, window } from "vscode";
4+
import { Uri, CancellationToken, window, InputBoxOptions } from "vscode";
55
import { CodeQLCliServer } from "./cli";
66
import {
77
ensureDir,
@@ -78,6 +78,10 @@ export async function promptImportInternetDatabase(
7878
*
7979
* @param databaseManager the DatabaseManager
8080
* @param storagePath where to store the unzipped database.
81+
* @param credentials the credentials to use to authenticate with GitHub
82+
* @param progress the progress callback
83+
* @param token the cancellation token
84+
* @param cli the CodeQL CLI server
8185
*/
8286
export async function promptImportGithubDatabase(
8387
commandManager: AppCommandManager,
@@ -88,21 +92,78 @@ export async function promptImportGithubDatabase(
8892
token: CancellationToken,
8993
cli?: CodeQLCliServer,
9094
): Promise<DatabaseItem | undefined> {
91-
progress({
95+
const githubRepo = await askForGitHubRepo(progress);
96+
if (!githubRepo) {
97+
return;
98+
}
99+
100+
const databaseItem = await downloadGitHubDatabase(
101+
githubRepo,
102+
databaseManager,
103+
storagePath,
104+
credentials,
105+
progress,
106+
token,
107+
cli,
108+
);
109+
110+
if (databaseItem) {
111+
await commandManager.execute("codeQLDatabases.focus");
112+
void showAndLogInformationMessage(
113+
"Database downloaded and imported successfully.",
114+
);
115+
return databaseItem;
116+
}
117+
118+
return;
119+
}
120+
121+
export async function askForGitHubRepo(
122+
progress?: ProgressCallback,
123+
suggestedValue?: string,
124+
): Promise<string | undefined> {
125+
progress?.({
92126
message: "Choose repository",
93127
step: 1,
94128
maxStep: 2,
95129
});
96-
const githubRepo = await window.showInputBox({
130+
131+
const options: InputBoxOptions = {
97132
title:
98133
'Enter a GitHub repository URL or "name with owner" (e.g. https://github.com/github/codeql or github/codeql)',
99134
placeHolder: "https://github.com/<owner>/<repo> or <owner>/<repo>",
100135
ignoreFocusOut: true,
101-
});
102-
if (!githubRepo) {
103-
return;
136+
};
137+
138+
if (suggestedValue) {
139+
options.value = suggestedValue;
104140
}
105141

142+
return await window.showInputBox(options);
143+
}
144+
145+
/**
146+
* Downloads a database from GitHub
147+
*
148+
* @param githubRepo the GitHub repository to download the database from
149+
* @param databaseManager the DatabaseManager
150+
* @param storagePath where to store the unzipped database.
151+
* @param credentials the credentials to use to authenticate with GitHub
152+
* @param progress the progress callback
153+
* @param token the cancellation token
154+
* @param cli the CodeQL CLI server
155+
* @param language the language to download. If undefined, the user will be prompted to choose a language.
156+
**/
157+
export async function downloadGitHubDatabase(
158+
githubRepo: string,
159+
databaseManager: DatabaseManager,
160+
storagePath: string,
161+
credentials: Credentials | undefined,
162+
progress: ProgressCallback,
163+
token: CancellationToken,
164+
cli?: CodeQLCliServer,
165+
language?: string,
166+
): Promise<DatabaseItem | undefined> {
106167
const nwo = getNwoFromGitHubUrl(githubRepo) || githubRepo;
107168
if (!isValidGitHubNwo(nwo)) {
108169
throw new Error(`Invalid GitHub repository: ${githubRepo}`);
@@ -112,7 +173,12 @@ export async function promptImportGithubDatabase(
112173
? await credentials.getOctokit()
113174
: new Octokit.Octokit({ retry });
114175

115-
const result = await convertGithubNwoToDatabaseUrl(nwo, octokit, progress);
176+
const result = await convertGithubNwoToDatabaseUrl(
177+
nwo,
178+
octokit,
179+
progress,
180+
language,
181+
);
116182
if (!result) {
117183
return;
118184
}
@@ -130,7 +196,7 @@ export async function promptImportGithubDatabase(
130196
* We only need the actual token string.
131197
*/
132198
const octokitToken = ((await octokit.auth()) as { token: string })?.token;
133-
const item = await databaseArchiveFetcher(
199+
return await databaseArchiveFetcher(
134200
databaseUrl,
135201
{
136202
Accept: "application/zip",
@@ -143,14 +209,6 @@ export async function promptImportGithubDatabase(
143209
token,
144210
cli,
145211
);
146-
if (item) {
147-
await commandManager.execute("codeQLDatabases.focus");
148-
void showAndLogInformationMessage(
149-
"Database downloaded and imported successfully.",
150-
);
151-
return item;
152-
}
153-
return;
154212
}
155213

156214
/**
@@ -450,6 +508,7 @@ export async function convertGithubNwoToDatabaseUrl(
450508
nwo: string,
451509
octokit: Octokit.Octokit,
452510
progress: ProgressCallback,
511+
language?: string,
453512
): Promise<
454513
| {
455514
databaseUrl: string;
@@ -468,9 +527,11 @@ export async function convertGithubNwoToDatabaseUrl(
468527

469528
const languages = response.data.map((db: any) => db.language);
470529

471-
const language = await promptForLanguage(languages, progress);
472-
if (!language) {
473-
return;
530+
if (!language || !languages.includes(language)) {
531+
language = await promptForLanguage(languages, progress);
532+
if (!language) {
533+
return;
534+
}
474535
}
475536

476537
return {
@@ -484,7 +545,7 @@ export async function convertGithubNwoToDatabaseUrl(
484545
}
485546
}
486547

487-
async function promptForLanguage(
548+
export async function promptForLanguage(
488549
languages: string[],
489550
progress: ProgressCallback,
490551
): Promise<string | undefined> {

extensions/ql-vscode/src/extension.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ import {
1313
workspace,
1414
} from "vscode";
1515
import { LanguageClient } from "vscode-languageclient/node";
16-
import { arch, platform } from "os";
16+
import { arch, platform, homedir } from "os";
1717
import { ensureDir } from "fs-extra";
1818
import { join } from "path";
1919
import { dirSync } from "tmp-promise";
2020
import { testExplorerExtensionId, TestHub } from "vscode-test-adapter-api";
2121
import { lt, parse } from "semver";
22+
import { watch } from "chokidar";
2223

2324
import { AstViewer } from "./astViewer";
2425
import {
@@ -197,6 +198,7 @@ function getCommands(
197198
"codeQL.restartQueryServer": restartQueryServer,
198199
"codeQL.restartQueryServerOnConfigChange": restartQueryServer,
199200
"codeQL.restartLegacyQueryServerOnConfigChange": restartQueryServer,
201+
"codeQL.restartQueryServerOnExternalConfigChange": restartQueryServer,
200202
"codeQL.copyVersion": async () => {
201203
const text = `CodeQL extension version: ${
202204
extension?.packageJSON.version
@@ -675,6 +677,7 @@ async function activateWithInstalledDistribution(
675677
extLogger,
676678
);
677679
ctx.subscriptions.push(cliServer);
680+
watchExternalConfigFile(app, ctx);
678681

679682
const statusBar = new CodeQlStatusBarHandler(
680683
cliServer,
@@ -1023,6 +1026,34 @@ async function activateWithInstalledDistribution(
10231026
};
10241027
}
10251028

1029+
/**
1030+
* Handle changes to the external config file. This is used to restart the query server
1031+
* when the user changes options.
1032+
* See https://docs.github.com/en/code-security/codeql-cli/using-the-codeql-cli/specifying-command-options-in-a-codeql-configuration-file#using-a-codeql-configuration-file
1033+
*/
1034+
function watchExternalConfigFile(app: ExtensionApp, ctx: ExtensionContext) {
1035+
const home = homedir();
1036+
if (home) {
1037+
const configPath = join(home, ".config", "codeql", "config");
1038+
const configWatcher = watch(configPath, {
1039+
// These options avoid firing the event twice.
1040+
persistent: true,
1041+
ignoreInitial: true,
1042+
awaitWriteFinish: true,
1043+
});
1044+
configWatcher.on("all", async () => {
1045+
await app.commands.execute(
1046+
"codeQL.restartQueryServerOnExternalConfigChange",
1047+
);
1048+
});
1049+
ctx.subscriptions.push({
1050+
dispose: () => {
1051+
void configWatcher.close();
1052+
},
1053+
});
1054+
}
1055+
}
1056+
10261057
async function showResultsForComparison(
10271058
compareView: CompareView,
10281059
from: CompletedLocalQueryInfo,

extensions/ql-vscode/src/local-queries.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
window,
99
} from "vscode";
1010
import { BaseLogger, extLogger, Logger, TeeLogger } from "./common";
11-
import { MAX_QUERIES } from "./config";
11+
import { isCanary, MAX_QUERIES } from "./config";
1212
import { gatherQlFiles } from "./pure/files";
1313
import { basename } from "path";
1414
import {
@@ -51,6 +51,7 @@ import { App } from "./common/app";
5151
import { DisposableObject } from "./pure/disposable-object";
5252
import { QueryResultType } from "./pure/new-messages";
5353
import { redactableError } from "./pure/errors";
54+
import { SkeletonQueryWizard } from "./skeleton-query-wizard";
5455

5556
interface DatabaseQuickPickItem extends QuickPickItem {
5657
databaseItem: DatabaseItem;
@@ -237,6 +238,7 @@ export class LocalQueries extends DisposableObject {
237238
"codeQL.quickEvalContextEditor": this.quickEval.bind(this),
238239
"codeQL.codeLensQuickEval": this.codeLensQuickEval.bind(this),
239240
"codeQL.quickQuery": this.quickQuery.bind(this),
241+
"codeQL.createSkeletonQuery": this.createSkeletonQuery.bind(this),
240242
};
241243
}
242244

@@ -375,6 +377,26 @@ export class LocalQueries extends DisposableObject {
375377
);
376378
}
377379

380+
private async createSkeletonQuery(): Promise<void> {
381+
await withProgress(
382+
async (progress: ProgressCallback, token: CancellationToken) => {
383+
const credentials = isCanary() ? this.app.credentials : undefined;
384+
const skeletonQueryWizard = new SkeletonQueryWizard(
385+
this.cliServer,
386+
progress,
387+
credentials,
388+
extLogger,
389+
this.databaseManager,
390+
token,
391+
);
392+
await skeletonQueryWizard.execute();
393+
},
394+
{
395+
title: "Create Query",
396+
},
397+
);
398+
}
399+
378400
/**
379401
* Creates a new `LocalQueryRun` object to track a query evaluation. This creates a timestamp
380402
* file in the query's output directory, creates a `LocalQueryInfo` object, and registers that

extensions/ql-vscode/src/qlpack-generator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ export class QlPackGenerator {
6666
await writeFile(qlPackFilePath, this.header + dump(qlPackYml), "utf8");
6767
}
6868

69-
private async createExampleQlFile() {
70-
const exampleQlFilePath = join(this.folderUri.fsPath, "example.ql");
69+
public async createExampleQlFile(fileName = "example.ql") {
70+
const exampleQlFilePath = join(this.folderUri.fsPath, fileName);
7171

7272
const exampleQl = `
7373
/**

0 commit comments

Comments
 (0)