Remove remote queries history item
This removes the remote queries history item as a supported history item. This allows us to delete almost all code related to remote queries except for the React view code which will be removed separately. In the query serialization code, we now ignore remote queries.
This commit is contained in:
@@ -652,7 +652,6 @@ async function activateWithInstalledDistribution(
|
||||
|
||||
void extLogger.log("Initializing query history.");
|
||||
const qhm = new QueryHistoryManager(
|
||||
app,
|
||||
qs,
|
||||
dbm,
|
||||
localQueryResultsView,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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[];
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { RemoteQuery } from "./remote-query";
|
||||
import { VariantAnalysis } from "./shared/variant-analysis";
|
||||
|
||||
export interface RemoteQuerySubmissionResult {
|
||||
queryDirPath?: string;
|
||||
query?: RemoteQuery;
|
||||
variantAnalysis?: VariantAnalysis;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
export type RemoteQueryWorkflowStatus =
|
||||
| "InProgress"
|
||||
| "CompletedSuccessfully"
|
||||
| "CompletedUnsuccessfully"
|
||||
| "Cancelled";
|
||||
|
||||
export interface RemoteQueryWorkflowResult {
|
||||
status: RemoteQueryWorkflowStatus;
|
||||
error?: string;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
export interface RemoteQueriesSubmission {
|
||||
ref: string;
|
||||
language: string;
|
||||
repositories?: string[];
|
||||
repositoryLists?: string[];
|
||||
repositoryOwners?: string[];
|
||||
queryPack: string;
|
||||
|
||||
controllerRepoId: number;
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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 % `,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user