Create skeleton QL pack if in CodeTour
We'd like to make it easier for a user going through the CodeQL Tour to write their queries. To help them along, we can generate skeleton QL packs once we know which database they're using, instead of expecting them to know how to create this themselves. We're then able to download the necessary dependencies for their CodeQL queries. This checks that we're running the CodeTour by looking for the `codeQL.codespacesTemplate` setting.
This commit is contained in:
@@ -9,6 +9,8 @@ import {
|
||||
showAndLogInformationMessage,
|
||||
isLikelyDatabaseRoot,
|
||||
showAndLogExceptionWithTelemetry,
|
||||
isFolderAlreadyInWorkspace,
|
||||
showBinaryChoiceDialog,
|
||||
} from "./helpers";
|
||||
import { ProgressCallback, withProgress } from "./commandRunner";
|
||||
import {
|
||||
@@ -23,6 +25,7 @@ import { asError, getErrorMessage } from "./pure/helpers-pure";
|
||||
import { QueryRunner } from "./queryRunner";
|
||||
import { pathsEqual } from "./pure/files";
|
||||
import { redactableError } from "./pure/errors";
|
||||
import { isCodespacesTemplate } from "./config";
|
||||
|
||||
/**
|
||||
* databases.ts
|
||||
@@ -621,9 +624,38 @@ export class DatabaseManager extends DisposableObject {
|
||||
await this.addDatabaseItem(progress, token, databaseItem);
|
||||
await this.addDatabaseSourceArchiveFolder(databaseItem);
|
||||
|
||||
if (isCodespacesTemplate()) {
|
||||
await this.createSkeletonPacks(databaseItem);
|
||||
}
|
||||
|
||||
return databaseItem;
|
||||
}
|
||||
|
||||
public async createSkeletonPacks(databaseItem: DatabaseItem) {
|
||||
if (databaseItem === undefined) {
|
||||
void this.logger.log(
|
||||
"Could not create QL pack as no database is selected. Please select a database.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (databaseItem.language == "") {
|
||||
void this.logger.log(
|
||||
"Could not create skeleton QL pack because the selected database's language is not set.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const folderName = `codeql-custom-queries-${databaseItem.language}`;
|
||||
if (isFolderAlreadyInWorkspace(folderName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await showBinaryChoiceDialog(
|
||||
"We've noticed you don't have QL packs downloaded to analyze this database. Can we set it up for you?",
|
||||
);
|
||||
}
|
||||
|
||||
private async reregisterDatabases(
|
||||
progress: ProgressCallback,
|
||||
token: vscode.CancellationToken,
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
} from "../../../src/archive-filesystem-provider";
|
||||
import { testDisposeHandler } from "../test-dispose-handler";
|
||||
import { QueryRunner } from "../../../src/queryRunner";
|
||||
import * as helpers from "../../../src/helpers";
|
||||
|
||||
describe("databases", () => {
|
||||
const MOCK_DB_OPTIONS: FullDatabaseOptions = {
|
||||
@@ -34,6 +35,11 @@ describe("databases", () => {
|
||||
let registerSpy: jest.Mock<Promise<void>, []>;
|
||||
let deregisterSpy: jest.Mock<Promise<void>, []>;
|
||||
let resolveDatabaseSpy: jest.Mock<Promise<DbInfo>, []>;
|
||||
let logSpy: jest.Mock<any, []>;
|
||||
|
||||
let showBinaryChoiceDialogSpy: jest.SpiedFunction<
|
||||
typeof helpers.showBinaryChoiceDialog
|
||||
>;
|
||||
|
||||
let dir: tmp.DirResult;
|
||||
|
||||
@@ -44,6 +50,13 @@ describe("databases", () => {
|
||||
registerSpy = jest.fn(() => Promise.resolve(undefined));
|
||||
deregisterSpy = jest.fn(() => Promise.resolve(undefined));
|
||||
resolveDatabaseSpy = jest.fn(() => Promise.resolve({} as DbInfo));
|
||||
logSpy = jest.fn(() => {
|
||||
/* */
|
||||
});
|
||||
|
||||
showBinaryChoiceDialogSpy = jest
|
||||
.spyOn(helpers, "showBinaryChoiceDialog")
|
||||
.mockResolvedValue(true);
|
||||
|
||||
databaseManager = new DatabaseManager(
|
||||
{
|
||||
@@ -66,9 +79,7 @@ describe("databases", () => {
|
||||
resolveDatabase: resolveDatabaseSpy,
|
||||
} as unknown as CodeQLCliServer,
|
||||
{
|
||||
log: () => {
|
||||
/**/
|
||||
},
|
||||
log: logSpy,
|
||||
} as unknown as Logger,
|
||||
);
|
||||
|
||||
@@ -574,6 +585,44 @@ describe("databases", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("createSkeletonPacks", () => {
|
||||
let mockDbItem: DatabaseItemImpl;
|
||||
|
||||
describe("when the language is set", () => {
|
||||
it("should offer the user to set up a skeleton QL pack", async () => {
|
||||
const options: FullDatabaseOptions = {
|
||||
dateAdded: 123,
|
||||
ignoreSourceArchive: false,
|
||||
language: "ruby",
|
||||
};
|
||||
mockDbItem = createMockDB(options);
|
||||
|
||||
await (databaseManager as any).createSkeletonPacks(mockDbItem);
|
||||
|
||||
expect(showBinaryChoiceDialogSpy).toBeCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the language is not set", () => {
|
||||
it("should fail gracefully", async () => {
|
||||
mockDbItem = createMockDB();
|
||||
await (databaseManager as any).createSkeletonPacks(mockDbItem);
|
||||
expect(logSpy).toHaveBeenCalledWith(
|
||||
"Could not create skeleton QL pack because the selected database's language is not set.",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the databaseItem is not set", () => {
|
||||
it("should fail gracefully", async () => {
|
||||
await (databaseManager as any).createSkeletonPacks(undefined);
|
||||
expect(logSpy).toHaveBeenCalledWith(
|
||||
"Could not create QL pack as no database is selected. Please select a database.",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createMockDB(
|
||||
mockDbOptions = MOCK_DB_OPTIONS,
|
||||
// source archive location must be a real(-ish) location since
|
||||
|
||||
Reference in New Issue
Block a user