In the original flow for creating skeleton packs, we were starting out by choosing a database (e.g. github/codeql) and having the extension create the QL pack for us. At that point, we were storing the QL pack together with the database in the extension storage because we weren't interested in committing it to the repo. This means we weren't able to see it in the file explorer so in order to make it visible, we decided to push it as a top-level folder in the workspace. Hindsight is 20/20. Let's change this original flow by just creating the folder in the workspace storage instead of the extension storage (which will make it visible in the file explorer) and stop pushing it as an extra top level folder in the workspace. NB: For this flow, we exit early in the `createSkeletonPacks` method if the folder already exists so we don't need to check this again.
87 lines
2.4 KiB
TypeScript
87 lines
2.4 KiB
TypeScript
import { mkdir, writeFile } from "fs-extra";
|
|
import { dump } from "js-yaml";
|
|
import { join } from "path";
|
|
import { Uri } from "vscode";
|
|
import { CodeQLCliServer } from "./cli";
|
|
import { QueryLanguage } from "./common/query-language";
|
|
|
|
export class QlPackGenerator {
|
|
private readonly qlpackName: string;
|
|
private readonly qlpackVersion: string;
|
|
private readonly header: string;
|
|
private readonly qlpackFileName: string;
|
|
private readonly folderUri: Uri;
|
|
|
|
constructor(
|
|
private readonly folderName: string,
|
|
private readonly queryLanguage: QueryLanguage,
|
|
private readonly cliServer: CodeQLCliServer,
|
|
private readonly storagePath: string | undefined,
|
|
) {
|
|
if (this.storagePath === undefined) {
|
|
throw new Error("Workspace storage path is undefined");
|
|
}
|
|
this.qlpackName = `getting-started/codeql-extra-queries-${this.queryLanguage}`;
|
|
this.qlpackVersion = "1.0.0";
|
|
this.header = "# This is an automatically generated file.\n\n";
|
|
|
|
this.qlpackFileName = "codeql-pack.yml";
|
|
this.folderUri = Uri.file(join(this.storagePath, this.folderName));
|
|
}
|
|
|
|
public async generate() {
|
|
// create QL pack folder and add to workspace
|
|
await this.createWorkspaceFolder();
|
|
|
|
// create codeql-pack.yml
|
|
await this.createQlPackYaml();
|
|
|
|
// create example.ql
|
|
await this.createExampleQlFile();
|
|
|
|
// create codeql-pack.lock.yml
|
|
await this.createCodeqlPackLockYaml();
|
|
}
|
|
|
|
private async createWorkspaceFolder() {
|
|
await mkdir(this.folderUri.fsPath);
|
|
}
|
|
|
|
private async createQlPackYaml() {
|
|
const qlPackFilePath = join(this.folderUri.fsPath, this.qlpackFileName);
|
|
|
|
const qlPackYml = {
|
|
name: this.qlpackName,
|
|
version: this.qlpackVersion,
|
|
dependencies: {},
|
|
};
|
|
|
|
await writeFile(qlPackFilePath, this.header + dump(qlPackYml), "utf8");
|
|
}
|
|
|
|
public async createExampleQlFile(fileName = "example.ql") {
|
|
const exampleQlFilePath = join(this.folderUri.fsPath, fileName);
|
|
|
|
const exampleQl = `
|
|
/**
|
|
* This is an automatically generated file
|
|
* @name Hello world
|
|
* @kind problem
|
|
* @problem.severity warning
|
|
* @id ${this.queryLanguage}/example/hello-world
|
|
*/
|
|
|
|
import ${this.queryLanguage}
|
|
|
|
from File f
|
|
select f, "Hello, world!"
|
|
`.trim();
|
|
|
|
await writeFile(exampleQlFilePath, exampleQl, "utf8");
|
|
}
|
|
|
|
private async createCodeqlPackLockYaml() {
|
|
await this.cliServer.packAdd(this.folderUri.fsPath, this.queryLanguage);
|
|
}
|
|
}
|