Only allow scoped extension pack names

When packaging an extension pack, unscoped extension pack names are not
allowed and calling `codeql pack bundle` will fail with an error. This
command will be called when running a variant analysis, so these packs
will not work for a variant analysis.

To improve the user experience, we now only allow scoped extension pack
names. This means that the user will now have to enter a scope when
creating a new extension pack.
This commit is contained in:
Koen Vlaswinkel
2023-06-05 12:30:20 +02:00
parent af9af99f09
commit b0d45cefe9
2 changed files with 25 additions and 10 deletions

View File

@@ -19,7 +19,7 @@ const maxStep = 3;
const packNamePartRegex = /[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/; const packNamePartRegex = /[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
const packNameRegex = new RegExp( const packNameRegex = new RegExp(
`^(?:(?<scope>${packNamePartRegex.source})/)?(?<name>${packNamePartRegex.source})$`, `^(?<scope>${packNamePartRegex.source})/(?<name>${packNamePartRegex.source})$`,
); );
const packNameLength = 128; const packNameLength = 128;
@@ -246,11 +246,16 @@ async function pickNewExtensionPack(
return undefined; return undefined;
} }
let examplePackName = `${databaseItem.name}-extensions`;
if (!examplePackName.includes("/")) {
examplePackName = `pack/${examplePackName}`;
}
const packName = await window.showInputBox( const packName = await window.showInputBox(
{ {
title: "Create new extension pack", title: "Create new extension pack",
prompt: "Enter name of extension pack", prompt: "Enter name of extension pack",
placeHolder: `e.g. ${databaseItem.name}-extensions`, placeHolder: `e.g. ${examplePackName}`,
validateInput: async (value: string): Promise<string | undefined> => { validateInput: async (value: string): Promise<string | undefined> => {
if (!value) { if (!value) {
return "Pack name must not be empty"; return "Pack name must not be empty";
@@ -262,6 +267,10 @@ async function pickNewExtensionPack(
const matches = packNameRegex.exec(value); const matches = packNameRegex.exec(value);
if (!matches?.groups) { if (!matches?.groups) {
if (!value.includes("/")) {
return "Invalid package name: a pack name must contain a slash to separate the scope from the pack name";
}
return "Invalid package name: a pack name must contain only lowercase ASCII letters, ASCII digits, and hyphens"; return "Invalid package name: a pack name must contain only lowercase ASCII letters, ASCII digits, and hyphens";
} }
@@ -296,7 +305,7 @@ async function pickNewExtensionPack(
const extensionPack: ExtensionPack = { const extensionPack: ExtensionPack = {
path: packPath, path: packPath,
yamlPath: packYamlPath, yamlPath: packYamlPath,
name, name: packName,
version: "0.0.0", version: "0.0.0",
extensionTargets: { extensionTargets: {
[`codeql/${databaseItem.language}-all`]: "*", [`codeql/${databaseItem.language}-all`]: "*",

View File

@@ -232,7 +232,7 @@ describe("pickExtensionPackModelFile", () => {
label: "codeql-custom-queries-java", label: "codeql-custom-queries-java",
path: tmpDir.path, path: tmpDir.path,
} as QuickPickItem); } as QuickPickItem);
showInputBoxSpy.mockResolvedValueOnce("new-extension-pack"); showInputBoxSpy.mockResolvedValueOnce("pack/new-extension-pack");
showInputBoxSpy.mockResolvedValue("models/my-model.yml"); showInputBoxSpy.mockResolvedValue("models/my-model.yml");
expect( expect(
@@ -247,7 +247,7 @@ describe("pickExtensionPackModelFile", () => {
extensionPack: { extensionPack: {
path: newPackDir, path: newPackDir,
yamlPath: join(newPackDir, "codeql-pack.yml"), yamlPath: join(newPackDir, "codeql-pack.yml"),
name: "new-extension-pack", name: "pack/new-extension-pack",
version: "0.0.0", version: "0.0.0",
extensionTargets: { extensionTargets: {
"codeql/java-all": "*", "codeql/java-all": "*",
@@ -280,7 +280,7 @@ describe("pickExtensionPackModelFile", () => {
expect( expect(
loadYaml(await readFile(join(newPackDir, "codeql-pack.yml"), "utf8")), loadYaml(await readFile(join(newPackDir, "codeql-pack.yml"), "utf8")),
).toEqual({ ).toEqual({
name: "new-extension-pack", name: "pack/new-extension-pack",
version: "0.0.0", version: "0.0.0",
library: true, library: true,
extensionTargets: { extensionTargets: {
@@ -303,7 +303,7 @@ describe("pickExtensionPackModelFile", () => {
label: "codeql-custom-queries-java", label: "codeql-custom-queries-java",
path: tmpDir.path, path: tmpDir.path,
} as QuickPickItem); } as QuickPickItem);
showInputBoxSpy.mockResolvedValueOnce("new-extension-pack"); showInputBoxSpy.mockResolvedValueOnce("pack/new-extension-pack");
showInputBoxSpy.mockResolvedValue("models/my-model.yml"); showInputBoxSpy.mockResolvedValue("models/my-model.yml");
expect( expect(
@@ -321,7 +321,7 @@ describe("pickExtensionPackModelFile", () => {
extensionPack: { extensionPack: {
path: newPackDir, path: newPackDir,
yamlPath: join(newPackDir, "codeql-pack.yml"), yamlPath: join(newPackDir, "codeql-pack.yml"),
name: "new-extension-pack", name: "pack/new-extension-pack",
version: "0.0.0", version: "0.0.0",
extensionTargets: { extensionTargets: {
"codeql/csharp-all": "*", "codeql/csharp-all": "*",
@@ -354,7 +354,7 @@ describe("pickExtensionPackModelFile", () => {
expect( expect(
loadYaml(await readFile(join(newPackDir, "codeql-pack.yml"), "utf8")), loadYaml(await readFile(join(newPackDir, "codeql-pack.yml"), "utf8")),
).toEqual({ ).toEqual({
name: "new-extension-pack", name: "pack/new-extension-pack",
version: "0.0.0", version: "0.0.0",
library: true, library: true,
extensionTargets: { extensionTargets: {
@@ -806,6 +806,12 @@ describe("pickExtensionPackModelFile", () => {
"Invalid package name: a pack name must contain only lowercase ASCII letters, ASCII digits, and hyphens", "Invalid package name: a pack name must contain only lowercase ASCII letters, ASCII digits, and hyphens",
); );
expect(await validateFile("VSCODE")).toEqual( expect(await validateFile("VSCODE")).toEqual(
"Invalid package name: a pack name must contain a slash to separate the scope from the pack name",
);
expect(await validateFile("github/")).toEqual(
"Invalid package name: a pack name must contain only lowercase ASCII letters, ASCII digits, and hyphens",
);
expect(await validateFile("github/VSCODE")).toEqual(
"Invalid package name: a pack name must contain only lowercase ASCII letters, ASCII digits, and hyphens", "Invalid package name: a pack name must contain only lowercase ASCII letters, ASCII digits, and hyphens",
); );
expect(await validateFile("github/vscode-codeql-")).toEqual( expect(await validateFile("github/vscode-codeql-")).toEqual(
@@ -814,7 +820,7 @@ describe("pickExtensionPackModelFile", () => {
expect( expect(
await validateFile("github/vscode-codeql-extensions"), await validateFile("github/vscode-codeql-extensions"),
).toBeUndefined(); ).toBeUndefined();
expect(await validateFile("vscode-codeql-extensions")).toBeUndefined(); expect(await validateFile("pack/vscode-codeql-extensions")).toBeUndefined();
}); });
it("validates the file input", async () => { it("validates the file input", async () => {