Skip to content

Commit 4ad3f7c

Browse files
authored
Merge branch 'main' into aeisenberg/truncated-log-msg
2 parents 55b65e3 + 0f1f00d commit 4ad3f7c

11 files changed

Lines changed: 201 additions & 32 deletions

File tree

extensions/ql-vscode/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Add settings `codeQL.variantAnalysis.defaultResultsFilter` and `codeQL.variantAnalysis.defaultResultsSort` for configuring how variant analysis results are filtered and sorted in the results view. The default is to show all repositories, and to sort by the number of results. [#2392](https://github.com/github/vscode-codeql/pull/2392)
66
- Fix bug to ensure error messages have complete stack trace in message logs. [#2425](https://github.com/github/vscode-codeql/pull/2425)
7+
- Fix bug where the `CodeQL: Compare Query` command did not work for comparing quick-eval queries. [#2422](https://github.com/github/vscode-codeql/pull/2422)
78

89
## 1.8.4 - 3 May 2023
910

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ export type VariantAnalysisCommands = {
251251
"codeQL.monitorRehydratedVariantAnalysis": (
252252
variantAnalysis: VariantAnalysis,
253253
) => Promise<void>;
254+
"codeQL.monitorReauthenticatedVariantAnalysis": (
255+
variantAnalysis: VariantAnalysis,
256+
) => Promise<void>;
254257
"codeQL.openVariantAnalysisLogs": (
255258
variantAnalysisId: number,
256259
) => Promise<void>;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as Octokit from "@octokit/rest";
33
import { retry } from "@octokit/plugin-retry";
44
import { Credentials } from "../authentication";
55

6-
const GITHUB_AUTH_PROVIDER_ID = "github";
6+
export const GITHUB_AUTH_PROVIDER_ID = "github";
77

88
// We need 'repo' scope for triggering workflows, 'gist' scope for exporting results to Gist,
99
// and 'read:packages' for reading private CodeQL packages.

extensions/ql-vscode/src/compare/compare-view.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,21 +175,40 @@ export class CompareView extends AbstractWebview<
175175
const commonResultSetNames = fromSchemaNames.filter((name) =>
176176
toSchemaNames.includes(name),
177177
);
178+
179+
// Fall back on the default result set names if there are no common ones.
180+
const defaultFromResultSetName = fromSchemaNames.find((name) =>
181+
name.startsWith("#"),
182+
);
183+
const defaultToResultSetName = toSchemaNames.find((name) =>
184+
name.startsWith("#"),
185+
);
186+
187+
if (
188+
commonResultSetNames.length === 0 &&
189+
!(defaultFromResultSetName || defaultToResultSetName)
190+
) {
191+
throw new Error(
192+
"No common result sets found between the two queries. Please check that the queries are compatible.",
193+
);
194+
}
195+
178196
const currentResultSetName =
179197
selectedResultSetName || commonResultSetNames[0];
180198
const fromResultSet = await this.getResultSet(
181199
fromSchemas,
182-
currentResultSetName,
200+
currentResultSetName || defaultFromResultSetName!,
183201
from.completedQuery.query.resultsPaths.resultsPath,
184202
);
185203
const toResultSet = await this.getResultSet(
186204
toSchemas,
187-
currentResultSetName,
205+
currentResultSetName || defaultToResultSetName!,
188206
to.completedQuery.query.resultsPaths.resultsPath,
189207
);
190208
return [
191209
commonResultSetNames,
192-
currentResultSetName,
210+
currentResultSetName ||
211+
`${defaultFromResultSetName} <-> ${defaultToResultSetName}`,
193212
fromResultSet,
194213
toResultSet,
195214
];

extensions/ql-vscode/src/queries-panel/query-tree-data-provider.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,20 @@ export class QueryTreeDataProvider
1717
private createTree(): QueryTreeViewItem[] {
1818
// Temporary mock data, just to populate the tree view.
1919
return [
20-
{
21-
label: "name1",
22-
tooltip: "path1",
23-
children: [],
24-
},
20+
new QueryTreeViewItem("custom-pack", [
21+
new QueryTreeViewItem("custom-pack/example.ql", []),
22+
]),
23+
new QueryTreeViewItem("ql", [
24+
new QueryTreeViewItem("ql/javascript", [
25+
new QueryTreeViewItem("ql/javascript/example.ql", []),
26+
]),
27+
new QueryTreeViewItem("ql/go", [
28+
new QueryTreeViewItem("ql/go/security", [
29+
new QueryTreeViewItem("ql/go/security/query1.ql", []),
30+
new QueryTreeViewItem("ql/go/security/query2.ql", []),
31+
]),
32+
]),
33+
]),
2534
];
2635
}
2736

@@ -30,9 +39,7 @@ export class QueryTreeDataProvider
3039
* @param item The item to represent.
3140
* @returns The UI presentation of the item.
3241
*/
33-
public getTreeItem(
34-
item: QueryTreeViewItem,
35-
): vscode.TreeItem | Thenable<vscode.TreeItem> {
42+
public getTreeItem(item: QueryTreeViewItem): vscode.TreeItem {
3643
return item;
3744
}
3845

@@ -41,14 +48,12 @@ export class QueryTreeDataProvider
4148
* @param item The item to expand.
4249
* @returns The children of the item.
4350
*/
44-
public getChildren(
45-
item?: QueryTreeViewItem,
46-
): vscode.ProviderResult<QueryTreeViewItem[]> {
51+
public getChildren(item?: QueryTreeViewItem): QueryTreeViewItem[] {
4752
if (!item) {
4853
// We're at the root.
49-
return Promise.resolve(this.queryTreeItems);
54+
return this.queryTreeItems;
5055
} else {
51-
return Promise.resolve(item.children);
56+
return item.children;
5257
}
5358
}
5459
}
Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import * as vscode from "vscode";
2+
import { basename } from "path";
23

34
export class QueryTreeViewItem extends vscode.TreeItem {
4-
constructor(
5-
public readonly label: string,
6-
public readonly tooltip: string | undefined,
7-
public readonly children: QueryTreeViewItem[],
8-
) {
9-
super(label);
5+
constructor(path: string, public readonly children: QueryTreeViewItem[]) {
6+
super(basename(path));
7+
this.tooltip = path;
8+
this.collapsibleState = this.children.length
9+
? vscode.TreeItemCollapsibleState.Collapsed
10+
: vscode.TreeItemCollapsibleState.None;
11+
if (this.children.length === 0) {
12+
this.command = {
13+
title: "Open",
14+
command: "vscode.open",
15+
arguments: [vscode.Uri.file(path)],
16+
};
17+
}
1018
}
1119
}

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {
55
getVariantAnalysisRepo,
66
} from "./gh-api/gh-api-client";
77
import {
8+
authentication,
9+
AuthenticationSessionsChangeEvent,
810
CancellationToken,
911
env,
1012
EventEmitter,
@@ -72,6 +74,7 @@ import {
7274
REPO_STATES_FILENAME,
7375
writeRepoStates,
7476
} from "./repo-states-store";
77+
import { GITHUB_AUTH_PROVIDER_ID } from "../common/vscode/authentication";
7578

7679
export class VariantAnalysisManager
7780
extends DisposableObject
@@ -131,6 +134,10 @@ export class VariantAnalysisManager
131134
this.variantAnalysisResultsManager.onResultLoaded(
132135
this.onRepoResultLoaded.bind(this),
133136
);
137+
138+
this.push(
139+
authentication.onDidChangeSessions(this.onDidChangeSessions.bind(this)),
140+
);
134141
}
135142

136143
getCommands(): VariantAnalysisCommands {
@@ -144,6 +151,8 @@ export class VariantAnalysisManager
144151
this.monitorVariantAnalysis.bind(this),
145152
"codeQL.monitorRehydratedVariantAnalysis":
146153
this.monitorVariantAnalysis.bind(this),
154+
"codeQL.monitorReauthenticatedVariantAnalysis":
155+
this.monitorVariantAnalysis.bind(this),
147156
"codeQL.openVariantAnalysisLogs": this.openVariantAnalysisLogs.bind(this),
148157
"codeQL.openVariantAnalysisView": this.showView.bind(this),
149158
"codeQL.runVariantAnalysis":
@@ -504,6 +513,38 @@ export class VariantAnalysisManager
504513
repoStates[repoState.repositoryId] = repoState;
505514
}
506515

516+
private async onDidChangeSessions(
517+
event: AuthenticationSessionsChangeEvent,
518+
): Promise<void> {
519+
if (event.provider.id !== GITHUB_AUTH_PROVIDER_ID) {
520+
return;
521+
}
522+
523+
for (const variantAnalysis of this.variantAnalyses.values()) {
524+
if (
525+
this.variantAnalysisMonitor.isMonitoringVariantAnalysis(
526+
variantAnalysis.id,
527+
)
528+
) {
529+
continue;
530+
}
531+
532+
if (
533+
await isVariantAnalysisComplete(
534+
variantAnalysis,
535+
this.makeResultDownloadChecker(variantAnalysis),
536+
)
537+
) {
538+
continue;
539+
}
540+
541+
void this.app.commands.execute(
542+
"codeQL.monitorReauthenticatedVariantAnalysis",
543+
variantAnalysis,
544+
);
545+
}
546+
}
547+
507548
public async monitorVariantAnalysis(
508549
variantAnalysis: VariantAnalysis,
509550
): Promise<void> {

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

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { env, EventEmitter } from "vscode";
22
import { getVariantAnalysis } from "./gh-api/gh-api-client";
3+
import { RequestError } from "@octokit/request-error";
34

45
import {
56
isFinalVariantAnalysisStatus,
@@ -27,6 +28,8 @@ export class VariantAnalysisMonitor extends DisposableObject {
2728
);
2829
readonly onVariantAnalysisChange = this._onVariantAnalysisChange.event;
2930

31+
private readonly monitoringVariantAnalyses = new Set<number>();
32+
3033
constructor(
3134
private readonly app: App,
3235
private readonly shouldCancelMonitor: (
@@ -36,9 +39,37 @@ export class VariantAnalysisMonitor extends DisposableObject {
3639
super();
3740
}
3841

42+
public isMonitoringVariantAnalysis(variantAnalysisId: number): boolean {
43+
return this.monitoringVariantAnalyses.has(variantAnalysisId);
44+
}
45+
3946
public async monitorVariantAnalysis(
4047
variantAnalysis: VariantAnalysis,
4148
): Promise<void> {
49+
if (this.monitoringVariantAnalyses.has(variantAnalysis.id)) {
50+
void extLogger.log(
51+
`Already monitoring variant analysis ${variantAnalysis.id}`,
52+
);
53+
return;
54+
}
55+
56+
this.monitoringVariantAnalyses.add(variantAnalysis.id);
57+
try {
58+
await this._monitorVariantAnalysis(variantAnalysis);
59+
} finally {
60+
this.monitoringVariantAnalyses.delete(variantAnalysis.id);
61+
}
62+
}
63+
64+
private async _monitorVariantAnalysis(
65+
variantAnalysis: VariantAnalysis,
66+
): Promise<void> {
67+
const variantAnalysisLabel = `${variantAnalysis.query.name} (${
68+
variantAnalysis.query.language
69+
}) [${new Date(variantAnalysis.executionStartTime).toLocaleString(
70+
env.language,
71+
)}]`;
72+
4273
let attemptCount = 0;
4374
const scannedReposDownloaded: number[] = [];
4475

@@ -61,11 +92,7 @@ export class VariantAnalysisMonitor extends DisposableObject {
6192
} catch (e) {
6293
const errorMessage = getErrorMessage(e);
6394

64-
const message = `Error while monitoring variant analysis ${
65-
variantAnalysis.query.name
66-
} (${variantAnalysis.query.language}) [${new Date(
67-
variantAnalysis.executionStartTime,
68-
).toLocaleString(env.language)}]: ${errorMessage}`;
95+
const message = `Error while monitoring variant analysis ${variantAnalysisLabel}: ${errorMessage}`;
6996

7097
// If we have already shown this error to the user, don't show it again.
7198
if (lastErrorShown === errorMessage) {
@@ -75,6 +102,19 @@ export class VariantAnalysisMonitor extends DisposableObject {
75102
lastErrorShown = errorMessage;
76103
}
77104

105+
if (e instanceof RequestError && e.status === 404) {
106+
// We want to show the error message to the user, but we don't want to
107+
// keep polling for the variant analysis if it no longer exists.
108+
// Therefore, this block is down here rather than at the top of the
109+
// catch block.
110+
void extLogger.log(
111+
`Variant analysis ${variantAnalysisLabel} no longer exists or is no longer accessible, stopping monitoring.`,
112+
);
113+
// Cancel monitoring on 404, as this probably means the user does not have access to it anymore
114+
// e.g. lost access to repo, or repo was deleted
115+
return;
116+
}
117+
78118
continue;
79119
}
80120

extensions/ql-vscode/src/view/compare/Compare.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,7 @@ export function Compare(_: Record<string, never>): JSX.Element {
5959
return (
6060
<>
6161
<div className="vscode-codeql__compare-header">
62-
<div className="vscode-codeql__compare-header-item">
63-
Table to compare:
64-
</div>
62+
<div className="vscode-codeql__compare-header-item">Comparing:</div>
6563
<CompareSelector
6664
availableResultSets={comparison.commonResultSetNames}
6765
currentResultSetName={comparison.currentResultSetName}

extensions/ql-vscode/src/view/compare/CompareSelector.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ interface Props {
77
}
88

99
export default function CompareSelector(props: Props) {
10-
return (
10+
return props.availableResultSets.length ? (
11+
// Handle case where there are shared result sets
1112
<select
1213
value={props.currentResultSetName}
1314
onChange={(e) => props.updateResultSet(e.target.value)}
@@ -18,5 +19,8 @@ export default function CompareSelector(props: Props) {
1819
</option>
1920
))}
2021
</select>
22+
) : (
23+
// Handle case where there are no shared result sets
24+
<div>{props.currentResultSetName}</div>
2125
);
2226
}

0 commit comments

Comments
 (0)