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:
Elena Tanasoiu
2023-02-05 22:06:55 +00:00
parent a85281e365
commit 037596cfb4
2 changed files with 84 additions and 3 deletions

View File

@@ -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,

View File

@@ -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