Cleanup and install pack dependencies

This commit is contained in:
Nora
2023-07-20 15:23:03 +00:00
parent f4da522953
commit 9fd6cb8c1f
4 changed files with 70 additions and 52 deletions

View File

@@ -6,12 +6,14 @@ import { QueryRunner } from "../query-server";
import { DatabaseItem } from "../databases/local-databases";
import { interpretResultsSarif } from "../query-results";
import { ProgressCallback } from "../common/vscode/progress";
import { Mode } from "./shared/mode";
type Options = {
cliServer: CodeQLCliServer;
queryRunner: QueryRunner;
databaseItem: DatabaseItem;
queryStorageDir: string;
queryDir: string;
progress: ProgressCallback;
};
@@ -23,6 +25,7 @@ export async function getAutoModelUsages({
queryRunner,
databaseItem,
queryStorageDir,
queryDir,
progress,
}: Options): Promise<UsageSnippetsBySignature> {
const maxStep = 1500;
@@ -32,11 +35,12 @@ export async function getAutoModelUsages({
// This will re-run the query that was already run when opening the data extensions editor. This
// might be unnecessary, but this makes it really easy to get the path to the BQRS file which we
// need to interpret the results.
const queryResult = await runQuery("applicationModeQuery", {
const queryResult = await runQuery(Mode.Application, {
cliServer,
queryRunner,
queryStorageDir,
databaseItem,
queryDir,
progress: (update) =>
progress({
maxStep,

View File

@@ -4,12 +4,23 @@ import { DataExtensionsEditorCommands } from "../common/commands";
import { CliVersionConstraint, CodeQLCliServer } from "../codeql-cli/cli";
import { QueryRunner } from "../query-server";
import { DatabaseManager } from "../databases/local-databases";
import { ensureDir } from "fs-extra";
import { ensureDir, writeFile } from "fs-extra";
import { join } from "path";
import { App } from "../common/app";
import { withProgress } from "../common/vscode/progress";
import { pickExtensionPack } from "./extension-pack-picker";
import { showAndLogErrorMessage } from "../common/logging";
import {
showAndLogErrorMessage,
showAndLogExceptionWithTelemetry,
} from "../common/logging";
import { dir } from "tmp-promise";
import { dump as dumpYaml } from "js-yaml";
import { fetchExternalApiQueries } from "./queries";
import { telemetryListener } from "../common/vscode/telemetry";
import { redactableError } from "../common/errors";
import { extLogger } from "../common/logging/vscode";
import { isQueryLanguage } from "../common/query-language";
import { Mode } from "./shared/mode";
const SUPPORTED_LANGUAGES: string[] = ["java", "csharp"];
@@ -99,13 +110,37 @@ export class DataExtensionsEditorModule {
return;
}
// TODO: Copy the files to a temporary directory and install pack dependencies
// Create new temporary directory for query files and pack dependencies
const queryDir = (await dir({ unsafeCleanup: true })).path;
// TODO: Write both the application mode and framework mode query
const queryFile = join(queryDir, "FetchExternalApis.ql");
await writeFile(queryFile, query[queryName], "utf8");
if (!isQueryLanguage(db.language)) {
void showAndLogExceptionWithTelemetry(
extLogger,
telemetryListener,
redactableError`Unsupported database language ${db.language}`,
);
return;
}
const query = fetchExternalApiQueries[db.language];
if (!query) {
void showAndLogExceptionWithTelemetry(
extLogger,
telemetryListener,
redactableError`No external API usage query found for language ${db.language}`,
);
return;
}
Object.values(Mode).map(async (mode) => {
const queryFile = join(
queryDir,
`FetchExternalApis${
mode.charAt(0).toUpperCase() + mode.slice(1)
}Mode.ql`,
);
await writeFile(queryFile, query[`${mode}ModeQuery`], "utf8");
});
if (query.dependencies) {
for (const [filename, contents] of Object.entries(
@@ -120,14 +155,15 @@ export class DataExtensionsEditorModule {
name: "codeql/external-api-usage",
version: "0.0.0",
dependencies: {
[`codeql/${databaseItem.language}-all`]: "*",
[`codeql/${db.language}-all`]: "*",
},
};
const qlpackFile = join(queryDir, "codeql-pack.yml");
await writeFile(qlpackFile, dumpYaml(syntheticQueryPack), "utf8");
// TODO: install pack dependencies in temporary file (`codeql pack install`)
// TODO: test dependency installation
await this.cliServer.packInstall(queryDir);
const view = new DataExtensionsEditorView(
this.ctx,

View File

@@ -249,19 +249,15 @@ export class DataExtensionsEditorView extends AbstractWebview<
async (progress) => {
try {
const cancellationTokenSource = new CancellationTokenSource();
const queryResult = await runQuery(
this.mode === Mode.Framework
? "frameworkModeQuery"
: "applicationModeQuery",
{
cliServer: this.cliServer,
queryRunner: this.queryRunner,
databaseItem: this.databaseItem,
queryStorageDir: this.queryStorageDir,
progress: (update) => progress({ ...update, maxStep: 1500 }),
token: cancellationTokenSource.token,
},
);
const queryResult = await runQuery(this.mode, {
cliServer: this.cliServer,
queryRunner: this.queryRunner,
databaseItem: this.databaseItem,
queryStorageDir: this.queryStorageDir,
queryDir: this.queryDir,
progress: (update) => progress({ ...update, maxStep: 1500 }),
token: cancellationTokenSource.token,
});
if (!queryResult) {
return;
}
@@ -433,6 +429,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
cliServer: this.cliServer,
queryRunner: this.queryRunner,
queryStorageDir: this.queryStorageDir,
queryDir: this.queryDir,
databaseItem: this.databaseItem,
progress: (update) => progress({ ...update, maxStep }),
});
@@ -513,6 +510,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
this.cliServer,
this.queryRunner,
this.queryStorageDir,
this.queryDir,
addedDatabase,
modelFile,
Mode.Framework,

View File

@@ -1,41 +1,36 @@
import { CoreCompletedQuery, QueryRunner } from "../query-server";
import { dir } from "tmp-promise";
import { writeFile } from "fs-extra";
import { dump as dumpYaml } from "js-yaml";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { extLogger } from "../common/logging/vscode";
import { showAndLogExceptionWithTelemetry, TeeLogger } from "../common/logging";
import { isQueryLanguage } from "../common/query-language";
import { CancellationToken } from "vscode";
import { CodeQLCliServer } from "../codeql-cli/cli";
import { DatabaseItem } from "../databases/local-databases";
import { ProgressCallback } from "../common/vscode/progress";
import { fetchExternalApiQueries } from "./queries";
import { QueryResultType } from "../query-server/new-messages";
import { join } from "path";
import { redactableError } from "../common/errors";
import { telemetryListener } from "../common/vscode/telemetry";
import { Query } from "./queries/query";
import { join } from "path";
type RunQueryOptions = {
cliServer: Pick<CodeQLCliServer, "resolveQlpacks">;
queryRunner: Pick<QueryRunner, "createQueryRun" | "logger">;
databaseItem: Pick<DatabaseItem, "contents" | "databaseUri" | "language">;
queryStorageDir: string;
queryDir: string;
progress: ProgressCallback;
token: CancellationToken;
};
export async function runQuery(
queryName: keyof Omit<Query, "dependencies">,
mode: string,
{
cliServer,
queryRunner,
databaseItem,
queryStorageDir,
progress,
queryDir,
progress,
token,
}: RunQueryOptions,
): Promise<CoreCompletedQuery | undefined> {
@@ -45,25 +40,6 @@ export async function runQuery(
// For a reference of what this should do in the future, see the previous implementation in
// https://github.com/github/vscode-codeql/blob/089d3566ef0bc67d9b7cc66e8fd6740b31c1c0b0/extensions/ql-vscode/src/data-extensions-editor/external-api-usage-query.ts#L33-L72
if (!isQueryLanguage(databaseItem.language)) {
void showAndLogExceptionWithTelemetry(
extLogger,
telemetryListener,
redactableError`Unsupported database language ${databaseItem.language}`,
);
return;
}
const query = fetchExternalApiQueries[databaseItem.language];
if (!query) {
void showAndLogExceptionWithTelemetry(
extLogger,
telemetryListener,
redactableError`No external API usage query found for language ${databaseItem.language}`,
);
return;
}
// TODO: install dependencies
const additionalPacks = getOnDiskWorkspaceFolders();
@@ -71,10 +47,14 @@ export async function runQuery(
await cliServer.resolveQlpacks(additionalPacks, true),
);
const queryFile = join(
queryDir,
`FetchExternalApis${mode.charAt(0).toUpperCase() + mode.slice(1)}Mode.ql`,
);
const queryRun = queryRunner.createQueryRun(
databaseItem.databaseUri.fsPath,
{
// TODO: select correct query file based on the `queryName` and `queryDir`
queryPath: queryFile,
quickEvalPosition: undefined,
quickEvalCountOnly: false,