Merge pull request #2071 from github/koesie10/remove-remote-queries-history-item

Remove remote queries history item
This commit is contained in:
Koen Vlaswinkel
2023-02-14 13:11:04 +01:00
committed by GitHub
24 changed files with 148 additions and 850 deletions

View File

@@ -652,7 +652,6 @@ async function activateWithInstalledDistribution(
void extLogger.log("Initializing query history.");
const qhm = new QueryHistoryManager(
app,
qs,
dbm,
localQueryResultsView,

View File

@@ -7,7 +7,6 @@ import {
getRawQueryName,
QueryHistoryInfo,
} from "./query-history-info";
import { RemoteQueryHistoryItem } from "../remote-queries/remote-query-history-item";
import { VariantAnalysisHistoryItem } from "./variant-analysis-history-item";
import { assertNever } from "../pure/helpers-pure";
import { pluralize } from "../pure/word";
@@ -34,9 +33,6 @@ export class HistoryItemLabelProvider {
case "local":
replacements = this.getLocalInterpolateReplacements(item);
break;
case "remote":
replacements = this.getRemoteInterpolateReplacements(item);
break;
case "variant-analysis":
replacements = this.getVariantAnalysisInterpolateReplacements(item);
break;
@@ -92,25 +88,6 @@ export class HistoryItemLabelProvider {
};
}
private getRemoteInterpolateReplacements(
item: RemoteQueryHistoryItem,
): InterpolateReplacements {
const resultCount = item.resultCount
? `(${pluralize(item.resultCount, "result", "results")})`
: "";
return {
t: new Date(item.remoteQuery.executionStartTime).toLocaleString(
env.language,
),
q: `${item.remoteQuery.queryName} (${item.remoteQuery.language})`,
d: buildRepoLabel(item),
r: resultCount,
s: humanizeQueryStatus(item.status),
f: basename(item.remoteQuery.queryFilePath),
"%": "%",
};
}
private getVariantAnalysisInterpolateReplacements(
item: VariantAnalysisHistoryItem,
): InterpolateReplacements {

View File

@@ -236,8 +236,6 @@ export class HistoryTreeDataProvider
switch (item.t) {
case "local":
return item.initialInfo.start.getTime();
case "remote":
return item.remoteQuery.executionStartTime;
case "variant-analysis":
return item.variantAnalysis.executionStartTime;
default:

View File

@@ -1,4 +1,3 @@
import { RemoteQueryHistoryItem } from "../remote-queries/remote-query-history-item";
import { VariantAnalysisHistoryItem } from "./variant-analysis-history-item";
import { LocalQueryInfo } from "../query-results";
import { assertNever } from "../pure/helpers-pure";
@@ -8,17 +7,12 @@ import {
getActionsWorkflowRunUrl as getVariantAnalysisActionsWorkflowRunUrl,
} from "../remote-queries/shared/variant-analysis";
export type QueryHistoryInfo =
| LocalQueryInfo
| RemoteQueryHistoryItem
| VariantAnalysisHistoryItem;
export type QueryHistoryInfo = LocalQueryInfo | VariantAnalysisHistoryItem;
export function getRawQueryName(item: QueryHistoryInfo): string {
switch (item.t) {
case "local":
return item.getQueryName();
case "remote":
return item.remoteQuery.queryName;
case "variant-analysis":
return item.variantAnalysis.query.name;
default:
@@ -37,8 +31,6 @@ export function getQueryId(item: QueryHistoryInfo): string {
switch (item.t) {
case "local":
return item.initialInfo.id;
case "remote":
return item.queryId;
case "variant-analysis":
return item.variantAnalysis.id.toString();
default:
@@ -50,8 +42,6 @@ export function getQueryText(item: QueryHistoryInfo): string {
switch (item.t) {
case "local":
return item.initialInfo.queryText;
case "remote":
return item.remoteQuery.queryText;
case "variant-analysis":
return item.variantAnalysis.query.text;
default:
@@ -59,47 +49,23 @@ export function getQueryText(item: QueryHistoryInfo): string {
}
}
export function buildRepoLabel(
item: RemoteQueryHistoryItem | VariantAnalysisHistoryItem,
): string {
if (item.t === "remote") {
// Return the number of repositories queried if available. Otherwise, use the controller repository name.
const repositoryCount = item.remoteQuery.repositoryCount;
export function buildRepoLabel(item: VariantAnalysisHistoryItem): string {
const totalScannedRepositoryCount =
item.variantAnalysis.scannedRepos?.length ?? 0;
const completedRepositoryCount =
item.variantAnalysis.scannedRepos?.filter((repo) =>
hasRepoScanCompleted(repo),
).length ?? 0;
if (repositoryCount) {
return pluralize(repositoryCount, "repository", "repositories");
}
return `${item.remoteQuery.controllerRepository.owner}/${item.remoteQuery.controllerRepository.name}`;
} else if (item.t === "variant-analysis") {
const totalScannedRepositoryCount =
item.variantAnalysis.scannedRepos?.length ?? 0;
const completedRepositoryCount =
item.variantAnalysis.scannedRepos?.filter((repo) =>
hasRepoScanCompleted(repo),
).length ?? 0;
return `${completedRepositoryCount}/${pluralize(
totalScannedRepositoryCount,
"repository",
"repositories",
)}`; // e.g. "2/3 repositories"
} else {
assertNever(item);
}
return `${completedRepositoryCount}/${pluralize(
totalScannedRepositoryCount,
"repository",
"repositories",
)}`; // e.g. "2/3 repositories"
}
export function getActionsWorkflowRunUrl(
item: RemoteQueryHistoryItem | VariantAnalysisHistoryItem,
item: VariantAnalysisHistoryItem,
): string {
if (item.t === "remote") {
const {
actionsWorkflowRunId: workflowRunId,
controllerRepository: { owner, name },
} = item.remoteQuery;
return `https://github.com/${owner}/${name}/actions/runs/${workflowRunId}`;
} else if (item.t === "variant-analysis") {
return getVariantAnalysisActionsWorkflowRunUrl(item.variantAnalysis);
} else {
assertNever(item);
}
return getVariantAnalysisActionsWorkflowRunUrl(item.variantAnalysis);
}

View File

@@ -53,8 +53,6 @@ import {
import { pathExists } from "fs-extra";
import { CliVersionConstraint } from "../cli";
import { HistoryItemLabelProvider } from "./history-item-label-provider";
import { cancelRemoteQuery } from "../remote-queries/gh-api/gh-actions-api-client";
import { RemoteQueryHistoryItem } from "../remote-queries/remote-query-history-item";
import { ResultsView } from "../interface";
import { WebviewReveal } from "../interface-utils";
import { EvalLogViewer } from "../eval-log-viewer";
@@ -65,7 +63,6 @@ import { QueryRunner } from "../queryRunner";
import { VariantAnalysisManager } from "../remote-queries/variant-analysis-manager";
import { VariantAnalysisHistoryItem } from "./variant-analysis-history-item";
import { getTotalResultCount } from "../remote-queries/shared/variant-analysis";
import { App } from "../common/app";
import { HistoryTreeDataProvider } from "./history-tree-data-provider";
import { redactableError } from "../pure/errors";
@@ -137,7 +134,6 @@ export class QueryHistoryManager extends DisposableObject {
readonly onDidCompleteQuery = this._onDidCompleteQuery.event;
constructor(
private readonly app: App,
private readonly qs: QueryRunner,
private readonly dbm: DatabaseManager,
private readonly localQueriesResultsView: ResultsView,
@@ -525,9 +521,6 @@ export class QueryHistoryManager extends DisposableObject {
case "local":
queryPath = finalSingleItem.initialInfo.queryPath;
break;
case "remote":
queryPath = finalSingleItem.remoteQuery.queryFilePath;
break;
default:
assertNever(finalSingleItem);
}
@@ -553,12 +546,6 @@ export class QueryHistoryManager extends DisposableObject {
return this.treeDataProvider.getCurrent();
}
getRemoteQueryById(queryId: string): RemoteQueryHistoryItem | undefined {
return this.treeDataProvider.allHistory.find(
(i) => i.t === "remote" && i.queryId === queryId,
) as RemoteQueryHistoryItem;
}
async removeDeletedQueries() {
await Promise.all(
this.treeDataProvider.allHistory.map(async (item) => {
@@ -595,8 +582,6 @@ export class QueryHistoryManager extends DisposableObject {
// We need to delete it from disk as well.
await item.completedQuery?.query.deleteQuery();
}
} else if (item.t === "remote") {
// Do nothing. TODO: Remove once remote queries are no longer supported.
} else if (item.t === "variant-analysis") {
await this.removeVariantAnalysis(item);
} else {
@@ -808,8 +793,6 @@ export class QueryHistoryManager extends DisposableObject {
if (queryHistoryItem.completedQuery) {
return queryHistoryItem.completedQuery.query.querySaveDir;
}
} else if (queryHistoryItem.t === "remote") {
return join(this.queryStorageDir, queryHistoryItem.queryId);
} else if (queryHistoryItem.t === "variant-analysis") {
return this.variantAnalysisManager.getVariantAnalysisStorageLocation(
queryHistoryItem.variantAnalysis.id,
@@ -840,12 +823,6 @@ export class QueryHistoryManager extends DisposableObject {
"timestamp",
);
}
} else if (finalSingleItem.t === "remote") {
externalFilePath = join(
this.queryStorageDir,
finalSingleItem.queryId,
"timestamp",
);
} else if (finalSingleItem.t === "variant-analysis") {
externalFilePath = join(
this.variantAnalysisManager.getVariantAnalysisStorageLocation(
@@ -1012,11 +989,6 @@ export class QueryHistoryManager extends DisposableObject {
if (item.status === QueryStatus.InProgress) {
if (item.t === "local") {
item.cancel();
} else if (item.t === "remote") {
void showAndLogInformationMessage(
"Cancelling variant analysis. This may take a while.",
);
await cancelRemoteQuery(this.app.credentials, item.remoteQuery);
} else if (item.t === "variant-analysis") {
await commands.executeCommand(
"codeQL.cancelVariantAnalysis",
@@ -1239,10 +1211,8 @@ export class QueryHistoryManager extends DisposableObject {
return;
}
// Remote queries and variant analysis only
if (finalSingleItem.t === "remote") {
// Do nothing. TODO: Remove this case once remote queries are removed.
} else if (finalSingleItem.t === "variant-analysis") {
// Variant analysis only
if (finalSingleItem.t === "variant-analysis") {
await commands.executeCommand(
"codeQL.exportVariantAnalysisResults",
finalSingleItem.variantAnalysis.id,
@@ -1475,8 +1445,6 @@ the file in the file explorer and dragging it into the workspace.`,
WebviewReveal.Forced,
false,
);
} else if (item.t === "remote") {
// Do nothing. TODO: Remove when remote queries is no longer supported.
} else if (item.t === "variant-analysis") {
await this.variantAnalysisManager.showView(item.variantAnalysis.id);
} else {

View File

@@ -10,7 +10,6 @@ import {
} from "./pure/helpers-pure";
import { CompletedQueryInfo, LocalQueryInfo } from "./query-results";
import { QueryHistoryInfo } from "./query-history/query-history-info";
import { QueryStatus } from "./query-status";
import { QueryEvaluationInfo } from "./run-queries-shared";
import { QueryResultType } from "./pure/legacy-messages";
import { redactableError } from "./pure/errors";
@@ -33,58 +32,57 @@ export async function deserializeQueryHistory(
}
const queries = obj.queries;
const parsedQueries = queries.map((q: QueryHistoryInfo) => {
// Need to explicitly set prototype since reading in from JSON will not
// do this automatically. Note that we can't call the constructor here since
// the constructor invokes extra logic that we don't want to do.
if (q.t === "local") {
Object.setPrototypeOf(q, LocalQueryInfo.prototype);
const parsedQueries = queries
// Remove remote queries, which are not supported anymore.
.filter((q: QueryHistoryInfo | { t: "remote" }) => q.t !== "remote")
.map((q: QueryHistoryInfo) => {
// Need to explicitly set prototype since reading in from JSON will not
// do this automatically. Note that we can't call the constructor here since
// the constructor invokes extra logic that we don't want to do.
if (q.t === "local") {
Object.setPrototypeOf(q, LocalQueryInfo.prototype);
// Date instances are serialized as strings. Need to
// convert them back to Date instances.
(q.initialInfo as any).start = new Date(q.initialInfo.start);
if (q.completedQuery) {
// Again, need to explicitly set prototypes.
Object.setPrototypeOf(q.completedQuery, CompletedQueryInfo.prototype);
Object.setPrototypeOf(
q.completedQuery.query,
QueryEvaluationInfo.prototype,
);
// deserialized queries do not need to be disposed
q.completedQuery.dispose = () => {
/**/
};
// Date instances are serialized as strings. Need to
// convert them back to Date instances.
(q.initialInfo as any).start = new Date(q.initialInfo.start);
if (q.completedQuery) {
// Again, need to explicitly set prototypes.
Object.setPrototypeOf(
q.completedQuery,
CompletedQueryInfo.prototype,
);
Object.setPrototypeOf(
q.completedQuery.query,
QueryEvaluationInfo.prototype,
);
// deserialized queries do not need to be disposed
q.completedQuery.dispose = () => {
/**/
};
// Previously, there was a typo in the completedQuery type. There was a field
// `sucessful` and it was renamed to `successful`. We need to handle this case.
if ("sucessful" in q.completedQuery) {
(q.completedQuery as any).successful = (
q.completedQuery as any
).sucessful;
delete (q.completedQuery as any).sucessful;
}
// Previously, there was a typo in the completedQuery type. There was a field
// `sucessful` and it was renamed to `successful`. We need to handle this case.
if ("sucessful" in q.completedQuery) {
(q.completedQuery as any).successful = (
q.completedQuery as any
).sucessful;
delete (q.completedQuery as any).sucessful;
}
if (!("successful" in q.completedQuery)) {
(q.completedQuery as any).successful =
q.completedQuery.result?.resultType === QueryResultType.SUCCESS;
if (!("successful" in q.completedQuery)) {
(q.completedQuery as any).successful =
q.completedQuery.result?.resultType === QueryResultType.SUCCESS;
}
}
}
} else if (q.t === "remote") {
// A bug was introduced that didn't set the completed flag in query history
// items. The following code makes sure that the flag is set in order to
// "patch" older query history items.
if (q.status === QueryStatus.Completed) {
q.completed = true;
}
}
return q;
});
return q;
});
// filter out queries that have been deleted on disk
// most likely another workspace has deleted them because the
// queries aged out.
return asyncFilter(parsedQueries, async (q) => {
if (q.t === "remote" || q.t === "variant-analysis") {
if (q.t === "variant-analysis") {
// the deserializer doesn't know where the remote queries are stored
// so we need to assume here that they exist. Later, we check to
// see if they exist on disk.

View File

@@ -47,9 +47,7 @@ export async function exportSelectedRemoteQueryResults(
);
}
if (queryHistoryItem.t === "remote") {
// Do nothing. TODO: Remove this branch once we stop supporting remote queries.
} else if (queryHistoryItem.t === "variant-analysis") {
if (queryHistoryItem.t === "variant-analysis") {
return commands.executeCommand(
"codeQL.exportVariantAnalysisResults",
queryHistoryItem.variantAnalysis.id,

View File

@@ -1,33 +1,6 @@
import { join } from "path";
import { pathExists, writeFile } from "fs-extra";
import { Credentials } from "../../common/authentication";
import { extLogger } from "../../common";
import { createDownloadPath, DownloadLink } from "../download-link";
import { RemoteQuery } from "../remote-query";
import { unzipFile } from "../../pure/zip";
import { VariantAnalysis } from "../shared/variant-analysis";
export async function cancelRemoteQuery(
credentials: Credentials,
remoteQuery: RemoteQuery,
): Promise<void> {
const octokit = await credentials.getOctokit();
const {
actionsWorkflowRunId,
controllerRepository: { owner, name },
} = remoteQuery;
const response = await octokit.request(
`POST /repos/${owner}/${name}/actions/runs/${actionsWorkflowRunId}/cancel`,
);
if (response.status >= 300) {
throw new Error(
`Error cancelling variant analysis: ${response.status} ${
response?.data?.message || ""
}`,
);
}
}
export async function cancelVariantAnalysis(
credentials: Credentials,
variantAnalysis: VariantAnalysis,
@@ -48,39 +21,3 @@ export async function cancelVariantAnalysis(
);
}
}
export async function downloadArtifactFromLink(
credentials: Credentials,
storagePath: string,
downloadLink: DownloadLink,
): Promise<string> {
const octokit = await credentials.getOctokit();
const extractedPath = createDownloadPath(storagePath, downloadLink);
// first check if we already have the artifact
if (!(await pathExists(extractedPath))) {
// Download the zipped artifact.
const response = await octokit.request(
`GET ${downloadLink.urlPath}/zip`,
{},
);
const zipFilePath = createDownloadPath(storagePath, downloadLink, "zip");
await unzipBuffer(response.data as ArrayBuffer, zipFilePath, extractedPath);
}
return join(extractedPath, downloadLink.innerFilePath || "");
}
async function unzipBuffer(
data: ArrayBuffer,
filePath: string,
destinationPath: string,
): Promise<void> {
void extLogger.log(`Saving file to ${filePath}`);
await writeFile(filePath, Buffer.from(data));
void extLogger.log(`Unzipping file to ${destinationPath}`);
await unzipFile(filePath, destinationPath);
}

View File

@@ -1,6 +1,5 @@
import { OctokitResponse } from "@octokit/types/dist-types";
import { Credentials } from "../../common/authentication";
import { RemoteQueriesSubmission } from "../shared/remote-queries";
import { VariantAnalysisSubmission } from "../shared/variant-analysis";
import {
VariantAnalysis,
@@ -8,10 +7,6 @@ import {
VariantAnalysisSubmissionRequest,
} from "./variant-analysis";
import { Repository } from "./repository";
import {
RemoteQueriesResponse,
RemoteQueriesSubmissionRequest,
} from "./remote-queries";
export async function submitVariantAnalysis(
credentials: Credentials,
@@ -116,40 +111,3 @@ export async function createGist(
}
return response.data.html_url;
}
export async function submitRemoteQueries(
credentials: Credentials,
submissionDetails: RemoteQueriesSubmission,
): Promise<RemoteQueriesResponse> {
const octokit = await credentials.getOctokit();
const {
ref,
language,
repositories,
repositoryLists,
repositoryOwners,
queryPack,
controllerRepoId,
} = submissionDetails;
const data: RemoteQueriesSubmissionRequest = {
ref,
language,
repositories,
repository_lists: repositoryLists,
repository_owners: repositoryOwners,
query_pack: queryPack,
};
const response: OctokitResponse<RemoteQueriesResponse> =
await octokit.request(
"POST /repositories/:controllerRepoId/code-scanning/codeql/queries",
{
controllerRepoId,
data,
},
);
return response.data;
}

View File

@@ -1,20 +0,0 @@
export interface RemoteQueriesSubmissionRequest {
ref: string;
language: string;
repositories?: string[];
repository_lists?: string[];
repository_owners?: string[];
query_pack: string;
}
export interface RemoteQueriesResponse {
workflow_run_id: number;
errors?: {
invalid_repositories?: string[];
repositories_without_database?: string[];
private_repositories?: string[];
cutoff_repositories?: string[];
cutoff_repositories_count?: number;
};
repositories_queried: string[];
}

View File

@@ -1,16 +0,0 @@
import { QueryStatus } from "../query-status";
import { RemoteQuery } from "./remote-query";
/**
* Information about a remote query.
*/
export interface RemoteQueryHistoryItem {
readonly t: "remote";
failureReason?: string;
resultCount?: number;
status: QueryStatus;
completed: boolean;
readonly queryId: string;
remoteQuery: RemoteQuery;
userSpecifiedLabel?: string;
}

View File

@@ -1,23 +0,0 @@
export interface RemoteQueryResultIndex {
artifactsUrlPath: string;
successes: RemoteQuerySuccessIndexItem[];
failures: RemoteQueryFailureIndexItem[];
}
export interface RemoteQuerySuccessIndexItem {
id: string;
artifactId: number;
nwo: string;
sha?: string;
resultCount: number;
bqrsFileSize: number;
sarifFileSize?: number;
sourceLocationPrefix: string;
}
export interface RemoteQueryFailureIndexItem {
id: string;
artifactId: number;
nwo: string;
error: string;
}

View File

@@ -1,20 +0,0 @@
import { DownloadLink } from "./download-link";
import { AnalysisFailure } from "./shared/analysis-failure";
export interface RemoteQueryResult {
executionEndTime: number; // Can't use a Date here since it needs to be serialized and desserialized.
analysisSummaries: AnalysisSummary[];
analysisFailures: AnalysisFailure[];
queryId: string;
}
export interface AnalysisSummary {
nwo: string;
databaseSha: string;
resultCount: number;
sourceLocationPrefix: string;
downloadLink: DownloadLink;
fileSizeInBytes: number;
starCount?: number;
lastUpdated?: number;
}

View File

@@ -1,8 +0,0 @@
import { RemoteQuery } from "./remote-query";
import { VariantAnalysis } from "./shared/variant-analysis";
export interface RemoteQuerySubmissionResult {
queryDirPath?: string;
query?: RemoteQuery;
variantAnalysis?: VariantAnalysis;
}

View File

@@ -1,10 +0,0 @@
export type RemoteQueryWorkflowStatus =
| "InProgress"
| "CompletedSuccessfully"
| "CompletedUnsuccessfully"
| "Cancelled";
export interface RemoteQueryWorkflowResult {
status: RemoteQueryWorkflowStatus;
error?: string;
}

View File

@@ -1,12 +0,0 @@
import { Repository as RemoteRepository } from "./repository";
export interface RemoteQuery {
queryName: string;
queryFilePath: string;
queryText: string;
language: string;
controllerRepository: RemoteRepository;
executionStartTime: number; // Use number here since it needs to be serialized and desserialized.
actionsWorkflowRunId: number;
repositoryCount: number;
}

View File

@@ -1,10 +0,0 @@
export interface RemoteQueriesSubmission {
ref: string;
language: string;
repositories?: string[];
repositoryLists?: string[];
repositoryOwners?: string[];
queryPack: string;
controllerRepoId: number;
}

View File

@@ -1,45 +0,0 @@
import { nanoid } from "nanoid";
import { RemoteQueryHistoryItem } from "../../../src/remote-queries/remote-query-history-item";
import { QueryStatus } from "../../../src/query-status";
export function createMockRemoteQueryHistoryItem({
date = new Date("2022-01-01T00:00:00.000Z"),
status = QueryStatus.InProgress,
failureReason = undefined,
resultCount = undefined,
repositoryCount = 0,
executionStartTime = date.getTime(),
userSpecifiedLabel = undefined,
}: {
date?: Date;
status?: QueryStatus;
failureReason?: string;
resultCount?: number;
repositoryCount?: number;
repositories?: string[];
executionStartTime?: number;
userSpecifiedLabel?: string;
}): RemoteQueryHistoryItem {
return {
t: "remote",
failureReason,
resultCount,
status,
completed: false,
queryId: nanoid(),
remoteQuery: {
queryName: "query-name",
queryFilePath: "query-file.ql",
queryText: "select 1",
language: "javascript",
controllerRepository: {
owner: "github",
name: "vscode-codeql-integration-tests",
},
executionStartTime,
actionsWorkflowRunId: 1,
repositoryCount,
},
userSpecifiedLabel,
};
}

View File

@@ -2,15 +2,12 @@ import { env } from "vscode";
import { QueryHistoryConfig } from "../../../../src/config";
import { HistoryItemLabelProvider } from "../../../../src/query-history/history-item-label-provider";
import { createMockLocalQueryInfo } from "../../../factories/query-history/local-query-history-item";
import { createMockRemoteQueryHistoryItem } from "../../../factories/query-history/remote-query-history-item";
import { QueryStatus } from "../../../../src/query-status";
describe("HistoryItemLabelProvider", () => {
let labelProvider: HistoryItemLabelProvider;
let config: QueryHistoryConfig;
const date = new Date("2022-01-01T00:00:00.000Z");
const dateStr = date.toLocaleString(env.language);
const executionStartTime = date.getTime();
const userSpecifiedLabel = "user-specified-name";
beforeEach(() => {
@@ -85,149 +82,4 @@ describe("HistoryItemLabelProvider", () => {
expect(labelProvider.getShortLabel(fqi2)).toBe("query-file.ql");
});
});
describe("remote queries", () => {
it("should interpolate query when user specified", () => {
const fqi = createMockRemoteQueryHistoryItem({ userSpecifiedLabel });
expect(labelProvider.getLabel(fqi)).toBe(userSpecifiedLabel);
fqi.userSpecifiedLabel = "%t %q %d %s %%";
expect(labelProvider.getLabel(fqi)).toBe(
`${dateStr} query-name (javascript) github/vscode-codeql-integration-tests in progress %`,
);
fqi.userSpecifiedLabel = "%t %q %d %s %%::%t %q %d %s %%";
expect(labelProvider.getLabel(fqi)).toBe(
`${dateStr} query-name (javascript) github/vscode-codeql-integration-tests in progress %::${dateStr} query-name (javascript) github/vscode-codeql-integration-tests in progress %`,
);
});
it("should interpolate query when not user-specified", () => {
const fqi = createMockRemoteQueryHistoryItem({
status: QueryStatus.Completed,
executionStartTime,
resultCount: 16,
});
expect(labelProvider.getLabel(fqi)).toBe(
"xxx query-name (javascript) xxx",
);
config.format = "%t %q %d %s %f %r %%";
expect(labelProvider.getLabel(fqi)).toBe(
`${dateStr} query-name (javascript) github/vscode-codeql-integration-tests completed query-file.ql (16 results) %`,
);
config.format = "%t %q %d %s %f %r %%::%t %q %d %s %f %r %%";
expect(labelProvider.getLabel(fqi)).toBe(
`${dateStr} query-name (javascript) github/vscode-codeql-integration-tests completed query-file.ql (16 results) %::${dateStr} query-name (javascript) github/vscode-codeql-integration-tests completed query-file.ql (16 results) %`,
);
});
it("should use number of repositories instead of controller repo if available", () => {
const fqi = createMockRemoteQueryHistoryItem({
status: QueryStatus.Completed,
executionStartTime,
resultCount: 16,
repositoryCount: 2,
});
config.format = "%t %q %d %s %f %r %%";
expect(labelProvider.getLabel(fqi)).toBe(
`${dateStr} query-name (javascript) 2 repositories completed query-file.ql (16 results) %`,
);
});
it("should get query short label", () => {
const fqi = createMockRemoteQueryHistoryItem({
status: QueryStatus.Completed,
executionStartTime,
userSpecifiedLabel,
});
// fall back on user specified if one exists.
expect(labelProvider.getShortLabel(fqi)).toBe("user-specified-name");
// use query name if no user-specified label exists
const fqi2 = createMockRemoteQueryHistoryItem({});
expect(labelProvider.getShortLabel(fqi2)).toBe("query-name");
});
describe("when results are present", () => {
it("should display results if there are any", () => {
const fqi = createMockRemoteQueryHistoryItem({
status: QueryStatus.Completed,
executionStartTime,
resultCount: 16,
repositoryCount: 2,
});
config.format = "%t %q %d %s %f %r %%";
expect(labelProvider.getLabel(fqi)).toBe(
`${dateStr} query-name (javascript) 2 repositories completed query-file.ql (16 results) %`,
);
});
});
describe("when results are not present", () => {
it("should skip displaying them", () => {
const fqi = createMockRemoteQueryHistoryItem({
status: QueryStatus.Completed,
executionStartTime,
resultCount: 0,
repositoryCount: 2,
});
config.format = "%t %q %d %s %f %r %%";
expect(labelProvider.getLabel(fqi)).toBe(
`${dateStr} query-name (javascript) 2 repositories completed query-file.ql %`,
);
});
});
describe("when extra whitespace is present in the middle of the label", () => {
it("should squash it down to a single whitespace", () => {
const fqi = createMockRemoteQueryHistoryItem({
status: QueryStatus.Completed,
executionStartTime,
resultCount: 0,
repositoryCount: 2,
});
config.format = "%t %q %d %s %f %r %%";
expect(labelProvider.getLabel(fqi)).toBe(
`${dateStr} query-name (javascript) 2 repositories completed query-file.ql %`,
);
});
});
describe("when extra whitespace is present at the start of the label", () => {
it("should squash it down to a single whitespace", () => {
const fqi = createMockRemoteQueryHistoryItem({
status: QueryStatus.Completed,
executionStartTime,
resultCount: 0,
repositoryCount: 2,
});
config.format = " %t %q %d %s %f %r %%";
expect(labelProvider.getLabel(fqi)).toBe(
` ${dateStr} query-name (javascript) 2 repositories completed query-file.ql %`,
);
});
});
describe("when extra whitespace is present at the end of the label", () => {
it("should squash it down to a single whitespace", () => {
const fqi = createMockRemoteQueryHistoryItem({
status: QueryStatus.Completed,
executionStartTime,
resultCount: 0,
repositoryCount: 2,
});
config.format = "%t %q %d %s %f %r %% ";
expect(labelProvider.getLabel(fqi)).toBe(
`${dateStr} query-name (javascript) 2 repositories completed query-file.ql % `,
);
});
});
});
});

View File

@@ -19,15 +19,11 @@ import {
createMockLocalQueryInfo,
createMockQueryWithResults,
} from "../../../factories/query-history/local-query-history-item";
import { createMockRemoteQueryHistoryItem } from "../../../factories/query-history/remote-query-history-item";
import { RemoteQueryHistoryItem } from "../../../../src/remote-queries/remote-query-history-item";
import { shuffleHistoryItems } from "../../utils/query-history-helpers";
import { createMockVariantAnalysisHistoryItem } from "../../../factories/query-history/variant-analysis-history-item";
import { VariantAnalysisHistoryItem } from "../../../../src/query-history/variant-analysis-history-item";
import { QueryStatus } from "../../../../src/query-status";
import { VariantAnalysisStatus } from "../../../../src/remote-queries/shared/variant-analysis";
import { Credentials } from "../../../../src/common/authentication";
import { createMockApp } from "../../../__mocks__/appMock";
import {
HistoryTreeDataProvider,
SortOrder,
@@ -46,7 +42,6 @@ describe("HistoryTreeDataProvider", () => {
let allHistory: QueryHistoryInfo[];
let localQueryHistory: LocalQueryInfo[];
let remoteQueryHistory: RemoteQueryHistoryItem[];
let variantAnalysisHistory: VariantAnalysisHistoryItem[];
let historyTreeDataProvider: HistoryTreeDataProvider;
@@ -102,12 +97,6 @@ describe("HistoryTreeDataProvider", () => {
// in progress
createMockLocalQueryInfo({ resultCount: 0 }),
];
remoteQueryHistory = [
createMockRemoteQueryHistoryItem({ status: QueryStatus.Completed }),
createMockRemoteQueryHistoryItem({ status: QueryStatus.Failed }),
createMockRemoteQueryHistoryItem({ status: QueryStatus.InProgress }),
createMockRemoteQueryHistoryItem({ status: QueryStatus.InProgress }),
];
variantAnalysisHistory = [
createMockVariantAnalysisHistoryItem({
historyItemStatus: QueryStatus.Completed,
@@ -128,7 +117,6 @@ describe("HistoryTreeDataProvider", () => {
];
allHistory = shuffleHistoryItems([
...localQueryHistory,
...remoteQueryHistory,
...variantAnalysisHistory,
]);
@@ -233,12 +221,6 @@ describe("HistoryTreeDataProvider", () => {
describe("sorting", () => {
const history = [
createMockRemoteQueryHistoryItem({
userSpecifiedLabel: "a",
executionStartTime: 2,
resultCount: 24,
status: QueryStatus.Completed,
}),
createMockLocalQueryInfo({
userSpecifiedLabel: "b",
startTime: new Date(10),
@@ -275,12 +257,6 @@ describe("HistoryTreeDataProvider", () => {
historyItemStatus: QueryStatus.Failed,
variantAnalysisStatus: VariantAnalysisStatus.Failed,
}),
createMockRemoteQueryHistoryItem({
userSpecifiedLabel: "h",
executionStartTime: 6,
resultCount: 5,
status: QueryStatus.InProgress,
}),
];
let treeDataProvider: HistoryTreeDataProvider;
@@ -309,14 +285,12 @@ describe("HistoryTreeDataProvider", () => {
it("should get children for date ascending", async () => {
const expected = [
history[4],
history[2],
history[5],
history[0],
history[3],
history[7],
history[6],
history[1],
history[2],
history[4],
history[3],
];
treeDataProvider.sortOrder = SortOrder.DateAsc;
@@ -326,14 +300,12 @@ describe("HistoryTreeDataProvider", () => {
it("should get children for date descending", async () => {
const expected = [
history[4],
history[2],
history[5],
history[0],
history[3],
history[7],
history[6],
history[1],
history[2],
history[4],
history[3],
].reverse();
treeDataProvider.sortOrder = SortOrder.DateDesc;
@@ -344,14 +316,12 @@ describe("HistoryTreeDataProvider", () => {
it("should get children for result count ascending", async () => {
const expected = [
history[7],
history[5],
history[4],
history[1],
history[0],
history[3],
history[6],
history[0],
history[2],
history[5],
history[1],
];
treeDataProvider.sortOrder = SortOrder.CountAsc;
@@ -362,14 +332,12 @@ describe("HistoryTreeDataProvider", () => {
it("should get children for result count descending", async () => {
const expected = [
history[7],
history[5],
history[4],
history[1],
history[0],
history[3],
history[6],
history[0],
history[2],
history[5],
history[1],
].reverse();
treeDataProvider.sortOrder = SortOrder.CountDesc;
@@ -395,12 +363,6 @@ describe("HistoryTreeDataProvider", () => {
historyItemStatus: QueryStatus.Completed,
variantAnalysisStatus: VariantAnalysisStatus.Failed,
}),
createMockRemoteQueryHistoryItem({
userSpecifiedLabel: "d",
resultCount: 0,
executionStartTime: 50,
status: QueryStatus.Completed,
}),
createMockVariantAnalysisHistoryItem({
userSpecifiedLabel: "e",
resultCount: 0,
@@ -438,12 +400,6 @@ describe("HistoryTreeDataProvider", () => {
historyItemStatus: QueryStatus.Completed,
variantAnalysisStatus: VariantAnalysisStatus.Failed,
}),
createMockRemoteQueryHistoryItem({
userSpecifiedLabel: "d",
resultCount: 0,
executionStartTime: 50,
status: QueryStatus.Completed,
}),
createMockVariantAnalysisHistoryItem({
userSpecifiedLabel: "e",
resultCount: 0,
@@ -463,12 +419,8 @@ describe("HistoryTreeDataProvider", () => {
});
});
async function createMockQueryHistory(
allHistory: QueryHistoryInfo[],
credentials?: Credentials,
) {
async function createMockQueryHistory(allHistory: QueryHistoryInfo[]) {
const qhm = new QueryHistoryManager(
createMockApp({ credentials }),
{} as QueryRunner,
{} as DatabaseManager,
localQueriesResultsViewStub,

View File

@@ -10,7 +10,6 @@ import { VariantAnalysisHistoryItem } from "../../../../src/query-history/varian
import { createMockVariantAnalysis } from "../../../factories/remote-queries/shared/variant-analysis";
import { createMockScannedRepos } from "../../../factories/remote-queries/shared/scanned-repositories";
import { createMockLocalQueryInfo } from "../../../factories/query-history/local-query-history-item";
import { createMockRemoteQueryHistoryItem } from "../../../factories/query-history/remote-query-history-item";
import {
VariantAnalysisRepoStatus,
VariantAnalysisStatus,
@@ -19,7 +18,6 @@ import {
describe("Query history info", () => {
const date = new Date("2022-01-01T00:00:00.000Z");
const localQueryHistoryItem = createMockLocalQueryInfo({ startTime: date });
const remoteQueryHistoryItem = createMockRemoteQueryHistoryItem({});
const variantAnalysisHistoryItem: VariantAnalysisHistoryItem = {
t: "variant-analysis",
status: QueryStatus.InProgress,
@@ -42,12 +40,6 @@ describe("Query history info", () => {
expect(queryName).toBe(localQueryHistoryItem.getQueryName());
});
it("should get the name for remote query history items", () => {
const queryName = getRawQueryName(remoteQueryHistoryItem);
expect(queryName).toBe(remoteQueryHistoryItem.remoteQuery.queryName);
});
it("should get the name for variant analysis history items", () => {
const queryName = getRawQueryName(variantAnalysisHistoryItem);
@@ -64,12 +56,6 @@ describe("Query history info", () => {
expect(historyItemId).toBe(localQueryHistoryItem.initialInfo.id);
});
it("should get the ID for remote query history items", () => {
const historyItemId = getQueryId(remoteQueryHistoryItem);
expect(historyItemId).toBe(remoteQueryHistoryItem.queryId);
});
it("should get the ID for variant analysis history items", () => {
const historyItemId = getQueryId(variantAnalysisHistoryItem);
@@ -86,12 +72,6 @@ describe("Query history info", () => {
expect(queryText).toBe(localQueryHistoryItem.initialInfo.queryText);
});
it("should get the query text for remote query history items", () => {
const queryText = getQueryText(remoteQueryHistoryItem);
expect(queryText).toBe(remoteQueryHistoryItem.remoteQuery.queryText);
});
it("should get the query text for variant analysis history items", () => {
const queryText = getQueryText(variantAnalysisHistoryItem);
@@ -102,23 +82,6 @@ describe("Query history info", () => {
});
describe("buildRepoLabel", () => {
describe("repo label for remote query history items", () => {
it("should return controller repo when `repositoryCount` is 0", () => {
const repoLabel = buildRepoLabel(remoteQueryHistoryItem);
const expectedRepoLabel = `${remoteQueryHistoryItem.remoteQuery.controllerRepository.owner}/${remoteQueryHistoryItem.remoteQuery.controllerRepository.name}`;
expect(repoLabel).toBe(expectedRepoLabel);
});
it("should return number of repositories when `repositoryCount` is non-zero", () => {
const remoteQueryHistoryItem2 = createMockRemoteQueryHistoryItem({
repositoryCount: 3,
});
const repoLabel2 = buildRepoLabel(remoteQueryHistoryItem2);
const expectedRepoLabel2 = "3 repositories";
expect(repoLabel2).toBe(expectedRepoLabel2);
});
});
describe("repo label for variant analysis history items", () => {
it("should return label when `totalScannedRepositoryCount` is 0", () => {
const variantAnalysisHistoryItem0: VariantAnalysisHistoryItem = {
@@ -159,18 +122,6 @@ describe("Query history info", () => {
});
describe("getActionsWorkflowRunUrl", () => {
it("should get the run url for remote query history items", () => {
const actionsWorkflowRunUrl = getActionsWorkflowRunUrl(
remoteQueryHistoryItem,
);
const remoteQuery = remoteQueryHistoryItem.remoteQuery;
const fullName = `${remoteQuery.controllerRepository.owner}/${remoteQuery.controllerRepository.name}`;
expect(actionsWorkflowRunUrl).toBe(
`https://github.com/${fullName}/actions/runs/${remoteQuery.actionsWorkflowRunId}`,
);
});
it("should get the run url for variant analysis history items", () => {
const actionsWorkflowRunUrl = getActionsWorkflowRunUrl(
variantAnalysisHistoryItem,

View File

@@ -20,20 +20,14 @@ import {
createMockLocalQueryInfo,
createMockQueryWithResults,
} from "../../../factories/query-history/local-query-history-item";
import { createMockRemoteQueryHistoryItem } from "../../../factories/query-history/remote-query-history-item";
import { RemoteQueryHistoryItem } from "../../../../src/remote-queries/remote-query-history-item";
import { shuffleHistoryItems } from "../../utils/query-history-helpers";
import { createMockVariantAnalysisHistoryItem } from "../../../factories/query-history/variant-analysis-history-item";
import { VariantAnalysisHistoryItem } from "../../../../src/query-history/variant-analysis-history-item";
import { QueryStatus } from "../../../../src/query-status";
import { VariantAnalysisStatus } from "../../../../src/remote-queries/shared/variant-analysis";
import * as ghActionsApiClient from "../../../../src/remote-queries/gh-api/gh-actions-api-client";
import { QuickPickItem, TextEditor } from "vscode";
import { WebviewReveal } from "../../../../src/interface-utils";
import * as helpers from "../../../../src/helpers";
import { testCredentialsWithStub } from "../../../factories/authentication";
import { Credentials } from "../../../../src/common/authentication";
import { createMockApp } from "../../../__mocks__/appMock";
describe("QueryHistoryManager", () => {
const mockExtensionLocation = join(tmpDir.name, "mock-extension-location");
@@ -59,7 +53,6 @@ describe("QueryHistoryManager", () => {
let allHistory: QueryHistoryInfo[];
let localQueryHistory: LocalQueryInfo[];
let remoteQueryHistory: RemoteQueryHistoryItem[];
let variantAnalysisHistory: VariantAnalysisHistoryItem[];
beforeEach(() => {
@@ -127,12 +120,6 @@ describe("QueryHistoryManager", () => {
// in progress
createMockLocalQueryInfo({ resultCount: 0 }),
];
remoteQueryHistory = [
createMockRemoteQueryHistoryItem({ status: QueryStatus.Completed }),
createMockRemoteQueryHistoryItem({ status: QueryStatus.Failed }),
createMockRemoteQueryHistoryItem({ status: QueryStatus.InProgress }),
createMockRemoteQueryHistoryItem({ status: QueryStatus.InProgress }),
];
variantAnalysisHistory = [
createMockVariantAnalysisHistoryItem({
historyItemStatus: QueryStatus.Completed,
@@ -153,7 +140,6 @@ describe("QueryHistoryManager", () => {
];
allHistory = shuffleHistoryItems([
...localQueryHistory,
...remoteQueryHistory,
...variantAnalysisHistory,
]);
});
@@ -709,24 +695,9 @@ describe("QueryHistoryManager", () => {
});
describe("handleCancel", () => {
let mockCancelRemoteQuery: jest.SpiedFunction<
typeof ghActionsApiClient.cancelRemoteQuery
>;
const getOctokitStub = jest.fn();
const mockCredentials = testCredentialsWithStub(getOctokitStub);
beforeEach(async () => {
mockCancelRemoteQuery = jest
.spyOn(ghActionsApiClient, "cancelRemoteQuery")
.mockResolvedValue();
});
describe("if the item is in progress", () => {
it("should cancel a single local query", async () => {
queryHistoryManager = await createMockQueryHistory(
localQueryHistory,
mockCredentials,
);
queryHistoryManager = await createMockQueryHistory(localQueryHistory);
// cancelling the selected item
const inProgress1 = localQueryHistory[4];
@@ -737,10 +708,7 @@ describe("QueryHistoryManager", () => {
});
it("should cancel multiple local queries", async () => {
queryHistoryManager = await createMockQueryHistory(
localQueryHistory,
mockCredentials,
);
queryHistoryManager = await createMockQueryHistory(localQueryHistory);
// cancelling the selected item
const inProgress1 = localQueryHistory[4];
@@ -757,51 +725,8 @@ describe("QueryHistoryManager", () => {
expect(cancelSpy2).toBeCalled();
});
it("should cancel a single remote query", async () => {
queryHistoryManager = await createMockQueryHistory(
localQueryHistory,
mockCredentials,
);
// cancelling the selected item
const inProgress1 = remoteQueryHistory[2];
await queryHistoryManager.handleCancel(inProgress1, [inProgress1]);
expect(mockCancelRemoteQuery).toBeCalledWith(
mockCredentials,
inProgress1.remoteQuery,
);
});
it("should cancel multiple remote queries", async () => {
queryHistoryManager = await createMockQueryHistory(
localQueryHistory,
mockCredentials,
);
// cancelling the selected item
const inProgress1 = remoteQueryHistory[2];
const inProgress2 = remoteQueryHistory[3];
await queryHistoryManager.handleCancel(inProgress1, [
inProgress1,
inProgress2,
]);
expect(mockCancelRemoteQuery).toBeCalledWith(
mockCredentials,
inProgress1.remoteQuery,
);
expect(mockCancelRemoteQuery).toBeCalledWith(
mockCredentials,
inProgress2.remoteQuery,
);
});
it("should cancel a single variant analysis", async () => {
queryHistoryManager = await createMockQueryHistory(
localQueryHistory,
mockCredentials,
);
queryHistoryManager = await createMockQueryHistory(localQueryHistory);
// cancelling the selected item
const inProgress1 = variantAnalysisHistory[1];
@@ -814,10 +739,7 @@ describe("QueryHistoryManager", () => {
});
it("should cancel multiple variant analyses", async () => {
queryHistoryManager = await createMockQueryHistory(
localQueryHistory,
mockCredentials,
);
queryHistoryManager = await createMockQueryHistory(localQueryHistory);
// cancelling the selected item
const inProgress1 = variantAnalysisHistory[1];
@@ -840,10 +762,7 @@ describe("QueryHistoryManager", () => {
describe("if the item is not in progress", () => {
it("should not cancel a single local query", async () => {
queryHistoryManager = await createMockQueryHistory(
localQueryHistory,
mockCredentials,
);
queryHistoryManager = await createMockQueryHistory(localQueryHistory);
// cancelling the selected item
const completed = localQueryHistory[0];
@@ -854,10 +773,7 @@ describe("QueryHistoryManager", () => {
});
it("should not cancel multiple local queries", async () => {
queryHistoryManager = await createMockQueryHistory(
localQueryHistory,
mockCredentials,
);
queryHistoryManager = await createMockQueryHistory(localQueryHistory);
// cancelling the selected item
const completed = localQueryHistory[0];
@@ -871,48 +787,8 @@ describe("QueryHistoryManager", () => {
expect(cancelSpy2).not.toBeCalledTimes(1);
});
it("should not cancel a single remote query", async () => {
queryHistoryManager = await createMockQueryHistory(
localQueryHistory,
mockCredentials,
);
// cancelling the selected item
const completed = remoteQueryHistory[0];
await queryHistoryManager.handleCancel(completed, [completed]);
expect(mockCancelRemoteQuery).not.toBeCalledWith(
mockCredentials,
completed.remoteQuery,
);
});
it("should not cancel multiple remote queries", async () => {
queryHistoryManager = await createMockQueryHistory(
localQueryHistory,
mockCredentials,
);
// cancelling the selected item
const completed = remoteQueryHistory[0];
const failed = remoteQueryHistory[1];
await queryHistoryManager.handleCancel(completed, [completed, failed]);
expect(mockCancelRemoteQuery).not.toBeCalledWith(
mockCredentials,
completed.remoteQuery,
);
expect(mockCancelRemoteQuery).not.toBeCalledWith(
mockCredentials,
failed.remoteQuery,
);
});
it("should not cancel a single variant analysis", async () => {
queryHistoryManager = await createMockQueryHistory(
localQueryHistory,
mockCredentials,
);
queryHistoryManager = await createMockQueryHistory(localQueryHistory);
// cancelling the selected item
const completedVariantAnalysis = variantAnalysisHistory[0];
@@ -927,10 +803,7 @@ describe("QueryHistoryManager", () => {
});
it("should not cancel multiple variant analyses", async () => {
queryHistoryManager = await createMockQueryHistory(
localQueryHistory,
mockCredentials,
);
queryHistoryManager = await createMockQueryHistory(localQueryHistory);
// cancelling the selected item
const completedVariantAnalysis = variantAnalysisHistory[0];
@@ -1272,12 +1145,8 @@ describe("QueryHistoryManager", () => {
});
});
async function createMockQueryHistory(
allHistory: QueryHistoryInfo[],
credentials?: Credentials,
) {
async function createMockQueryHistory(allHistory: QueryHistoryInfo[]) {
const qhm = new QueryHistoryManager(
createMockApp({ credentials }),
{} as QueryRunner,
{} as DatabaseManager,
localQueriesResultsViewStub,

View File

@@ -19,8 +19,6 @@ import { ResultsView } from "../../../../src/interface";
import { EvalLogViewer } from "../../../../src/eval-log-viewer";
import { QueryRunner } from "../../../../src/queryRunner";
import { VariantAnalysisManager } from "../../../../src/remote-queries/variant-analysis-manager";
import { App } from "../../../../src/common/app";
import { createMockApp } from "../../../__mocks__/appMock";
import { QueryHistoryManager } from "../../../../src/query-history/query-history-manager";
// set a higher timeout since recursive delete may take a while, expecially on Windows.
@@ -37,7 +35,6 @@ describe("Variant Analyses and QueryHistoryManager", () => {
/** noop */
};
let app: App;
let qhm: QueryHistoryManager;
let rawQueryHistory: any;
let disposables: DisposableBucket;
@@ -71,10 +68,7 @@ describe("Variant Analyses and QueryHistoryManager", () => {
join(STORAGE_DIR, "workspace-query-history.json"),
).queries;
app = createMockApp({});
qhm = new QueryHistoryManager(
app,
{} as QueryRunner,
{} as DatabaseManager,
localQueriesResultsViewStub,

View File

@@ -3,7 +3,7 @@ import {
serializeQueryHistory,
} from "../../../src/query-serialization";
import { join } from "path";
import { writeFileSync, mkdirpSync } from "fs-extra";
import { writeFileSync, mkdirpSync, writeFile } from "fs-extra";
import { LocalQueryInfo, InitialQueryInfo } from "../../../src/query-results";
import { QueryWithResults } from "../../../src/run-queries-shared";
import { DatabaseInfo } from "../../../src/pure/interface-types";
@@ -11,11 +11,10 @@ import { CancellationTokenSource, Uri } from "vscode";
import { tmpDir } from "../../../src/helpers";
import { QueryResultType } from "../../../src/pure/legacy-messages";
import { QueryInProgress } from "../../../src/legacy-query-server/run-queries";
import { RemoteQueryHistoryItem } from "../../../src/remote-queries/remote-query-history-item";
import { VariantAnalysisHistoryItem } from "../../../src/query-history/variant-analysis-history-item";
import { QueryHistoryInfo } from "../../../src/query-history/query-history-info";
import { createMockRemoteQueryHistoryItem } from "../../factories/query-history/remote-query-history-item";
import { createMockVariantAnalysisHistoryItem } from "../../factories/query-history/variant-analysis-history-item";
import { nanoid } from "nanoid";
describe("serialize and deserialize", () => {
let infoSuccessRaw: LocalQueryInfo;
@@ -24,13 +23,11 @@ describe("serialize and deserialize", () => {
let infoLateFailure: LocalQueryInfo;
let infoInProgress: LocalQueryInfo;
let remoteQuery1: RemoteQueryHistoryItem;
let remoteQuery2: RemoteQueryHistoryItem;
let variantAnalysis1: VariantAnalysisHistoryItem;
let variantAnalysis2: VariantAnalysisHistoryItem;
let allHistory: QueryHistoryInfo[];
let expectedHistory: QueryHistoryInfo[];
let queryPath: string;
let cnt = 0;
@@ -70,9 +67,6 @@ describe("serialize and deserialize", () => {
);
infoInProgress = createMockFullQueryInfo("e");
remoteQuery1 = createMockRemoteQueryHistoryItem({});
remoteQuery2 = createMockRemoteQueryHistoryItem({});
variantAnalysis1 = createMockVariantAnalysisHistoryItem({});
variantAnalysis2 = createMockVariantAnalysisHistoryItem({});
@@ -82,25 +76,21 @@ describe("serialize and deserialize", () => {
infoEarlyFailure,
infoLateFailure,
infoInProgress,
remoteQuery1,
remoteQuery2,
variantAnalysis1,
variantAnalysis2,
];
// the expected results only contains the history with completed queries
expectedHistory = [
infoSuccessRaw,
infoSuccessInterpreted,
infoLateFailure,
variantAnalysis1,
variantAnalysis2,
];
});
it("should serialize and deserialize query history", async () => {
// the expected results only contains the history with completed queries
const expectedHistory = [
infoSuccessRaw,
infoSuccessInterpreted,
infoLateFailure,
remoteQuery1,
remoteQuery2,
variantAnalysis1,
variantAnalysis2,
];
const allHistoryPath = join(tmpDir.name, "workspace-query-history.json");
// serialize and deserialize
@@ -137,6 +127,61 @@ describe("serialize and deserialize", () => {
expect(allHistoryActual.length).toEqual(expectedHistory.length);
});
it("should remove remote queries from the history", async () => {
const path = join(tmpDir.name, "query-history-with-remote.json");
await writeFile(
path,
JSON.stringify({
version: 2,
queries: [
...allHistory,
{
t: "remote",
status: "InProgress",
completed: false,
queryId: nanoid(),
remoteQuery: {
queryName: "query-name",
queryFilePath: "query-file.ql",
queryText: "select 1",
language: "javascript",
controllerRepository: {
owner: "github",
name: "vscode-codeql-integration-tests",
},
executionStartTime: Date.now(),
actionsWorkflowRunId: 1,
repositoryCount: 0,
},
},
{
t: "remote",
status: "Completed",
completed: true,
queryId: nanoid(),
remoteQuery: {
queryName: "query-name",
queryFilePath: "query-file.ql",
queryText: "select 1",
language: "javascript",
controllerRepository: {
owner: "github",
name: "vscode-codeql-integration-tests",
},
executionStartTime: Date.now(),
actionsWorkflowRunId: 1,
repositoryCount: 0,
},
},
],
}),
"utf8",
);
const actual = await deserializeQueryHistory(path);
expect(actual.length).toEqual(expectedHistory.length);
});
it("should handle an invalid query history version", async () => {
const badPath = join(tmpDir.name, "bad-query-history.json");
writeFileSync(