mirror of
https://github.com/github/codeql-action.git
synced 2026-10-03 17:41:28 +00:00
Support old and new formats
This commit is contained in:
23
lib/entry-points.js
generated
23
lib/entry-points.js
generated
@@ -151053,7 +151053,7 @@ function getInvalidConfigFileMessage(configFile, messages) {
|
||||
}
|
||||
function getConfigFileRepoFormatInvalidMessage(configFile) {
|
||||
let error3 = `The configuration file "${configFile}" is not a supported remote file reference.`;
|
||||
error3 += " Expected format [<owner>/]<repository>[/<file-path>][@<ref>]";
|
||||
error3 += " Expected format [<owner>/]<repository>[@<ref>][:<file-path>]";
|
||||
return error3;
|
||||
}
|
||||
function getConfigFileFormatInvalidMessage(configFile) {
|
||||
@@ -151447,9 +151447,28 @@ function getDefaultOwner(env) {
|
||||
}
|
||||
return nwoParts[0].trim();
|
||||
}
|
||||
var OLD_REMOTE_ADDRESS_FORMAT = new RegExp(
|
||||
"(?<owner>[^/]+)/(?<repo>[^/]+)/(?<path>[^@]+)@(?<ref>.*)"
|
||||
);
|
||||
function parseOldRemoteFileAddress(input) {
|
||||
const pieces = OLD_REMOTE_ADDRESS_FORMAT.exec(input);
|
||||
if (pieces?.groups === void 0 || pieces.length < 5) {
|
||||
return new Failure(void 0);
|
||||
}
|
||||
return new Success({
|
||||
owner: pieces.groups.owner.trim(),
|
||||
repo: pieces.groups.repo.trim(),
|
||||
path: pieces.groups.path.trim(),
|
||||
ref: pieces.groups.ref.trim()
|
||||
});
|
||||
}
|
||||
function parseRemoteFileAddress(env, configFile) {
|
||||
const oldFormatAddressResult = parseOldRemoteFileAddress(configFile);
|
||||
if (oldFormatAddressResult.isSuccess()) {
|
||||
return oldFormatAddressResult.value;
|
||||
}
|
||||
const format = new RegExp(
|
||||
"^((?<owner>[^/]+)/)?(?<repo>[^/@]+)(/(?<path>[^@]+))?(@(?<ref>.*))?$"
|
||||
"^((?<owner>[^:@/]+)/)?(?<repo>[^:@/]+)(@(?<ref>[^:]+))?(:(?<path>.+))?$"
|
||||
);
|
||||
const pieces = format.exec(configFile.trim());
|
||||
const repo = pieces?.groups?.repo?.trim();
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
test("parseRemoteFileAddress accepts full remote addresses", async (t) => {
|
||||
const env = getTestEnv();
|
||||
|
||||
// Old format.
|
||||
t.deepEqual(parseRemoteFileAddress(env, "owner/repo/path@ref"), {
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
@@ -86,6 +87,79 @@ test("parseRemoteFileAddress accepts full remote addresses", async (t) => {
|
||||
ref: "ref/feature",
|
||||
} satisfies RemoteFileAddress,
|
||||
);
|
||||
|
||||
// New format.
|
||||
t.deepEqual(parseRemoteFileAddress(env, "owner/repo@ref:path"), {
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
path: "path",
|
||||
ref: "ref",
|
||||
} satisfies RemoteFileAddress);
|
||||
|
||||
t.deepEqual(parseRemoteFileAddress(env, "owner /repo@ref:path"), {
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
path: "path",
|
||||
ref: "ref",
|
||||
} satisfies RemoteFileAddress);
|
||||
|
||||
t.deepEqual(parseRemoteFileAddress(env, "owner/ repo@ref:path"), {
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
path: "path",
|
||||
ref: "ref",
|
||||
} satisfies RemoteFileAddress);
|
||||
|
||||
t.deepEqual(parseRemoteFileAddress(env, "owner/repo @ref:path"), {
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
path: "path",
|
||||
ref: "ref",
|
||||
} satisfies RemoteFileAddress);
|
||||
|
||||
t.deepEqual(parseRemoteFileAddress(env, "owner/repo@ ref:path"), {
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
path: "path",
|
||||
ref: "ref",
|
||||
} satisfies RemoteFileAddress);
|
||||
|
||||
t.deepEqual(parseRemoteFileAddress(env, "owner/repo@ref :path"), {
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
path: "path",
|
||||
ref: "ref",
|
||||
} satisfies RemoteFileAddress);
|
||||
|
||||
t.deepEqual(parseRemoteFileAddress(env, "owner/repo@ref: path"), {
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
path: "path",
|
||||
ref: "ref",
|
||||
} satisfies RemoteFileAddress);
|
||||
|
||||
t.deepEqual(
|
||||
parseRemoteFileAddress(env, "owner/repo@ref/feature:path/to/codeql.yml"),
|
||||
{
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
path: "path/to/codeql.yml",
|
||||
ref: "ref/feature",
|
||||
} satisfies RemoteFileAddress,
|
||||
);
|
||||
|
||||
t.deepEqual(
|
||||
parseRemoteFileAddress(
|
||||
env,
|
||||
" owner/repo@ref/feature:path/to/codeql.yml ",
|
||||
),
|
||||
{
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
path: "path/to/codeql.yml",
|
||||
ref: "ref/feature",
|
||||
} satisfies RemoteFileAddress,
|
||||
);
|
||||
});
|
||||
|
||||
test("parseRemoteFileAddress accepts remote address without an owner", async (t) => {
|
||||
@@ -96,6 +170,13 @@ test("parseRemoteFileAddress accepts remote address without an owner", async (t)
|
||||
.withArgs(ActionsEnvVars.GITHUB_REPOSITORY)
|
||||
.returns(`${owner}/current-repo`);
|
||||
|
||||
t.deepEqual(parseRemoteFileAddress(env, "repo@ref:path.yml"), {
|
||||
owner,
|
||||
repo: "repo",
|
||||
path: "path.yml",
|
||||
ref: "ref",
|
||||
} satisfies RemoteFileAddress);
|
||||
|
||||
t.deepEqual(parseRemoteFileAddress(env, "repo@ref"), {
|
||||
owner,
|
||||
repo: "repo",
|
||||
@@ -103,6 +184,13 @@ test("parseRemoteFileAddress accepts remote address without an owner", async (t)
|
||||
ref: "ref",
|
||||
} satisfies RemoteFileAddress);
|
||||
|
||||
t.deepEqual(parseRemoteFileAddress(env, "repo:path.yml"), {
|
||||
owner,
|
||||
repo: "repo",
|
||||
path: "path.yml",
|
||||
ref: DEFAULT_CONFIG_FILE_REF,
|
||||
} satisfies RemoteFileAddress);
|
||||
|
||||
t.deepEqual(parseRemoteFileAddress(env, "repo"), {
|
||||
owner,
|
||||
repo: "repo",
|
||||
@@ -142,14 +230,7 @@ test("parseRemoteFileAddress accepts remote address without a path", async (t) =
|
||||
test("parseRemoteFileAddress accepts remote address without a ref", async (t) => {
|
||||
const env = getTestEnv();
|
||||
|
||||
t.deepEqual(parseRemoteFileAddress(env, "owner/repo/path"), {
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
path: "path",
|
||||
ref: DEFAULT_CONFIG_FILE_REF,
|
||||
} satisfies RemoteFileAddress);
|
||||
|
||||
t.deepEqual(parseRemoteFileAddress(env, "owner/repo/path@"), {
|
||||
t.deepEqual(parseRemoteFileAddress(env, "owner/repo:path"), {
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
path: "path",
|
||||
@@ -171,10 +252,43 @@ test("parseRemoteFileAddress rejects invalid values", async (t) => {
|
||||
t.throws(() => parseRemoteFileAddress(env, "repo//absolute"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, "repo:/absolute"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, "/repo@ref"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, " /repo@ref"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, "repo@"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, "repo:"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, "repo/"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, "/repo"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, ":path"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, "@ref"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, "@ref:path"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, "owner/@ref:path"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, "owner/@ref"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
t.throws(() => parseRemoteFileAddress(env, "owner/:path"), {
|
||||
instanceOf: ConfigurationError,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ActionsEnvVars } from "../actions-util";
|
||||
import { Env } from "../environment";
|
||||
import * as errorMessages from "../error-messages";
|
||||
import { ConfigurationError } from "../util";
|
||||
import { ConfigurationError, Failure, Result, Success } from "../util";
|
||||
|
||||
/** Represents remote file addresses. */
|
||||
export interface RemoteFileAddress {
|
||||
@@ -37,6 +37,38 @@ function getDefaultOwner(env: Env): string {
|
||||
return nwoParts[0].trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* The old remote address format that's always been supported for the `config-file` input.
|
||||
* All the components are required. Unchanged from the previous implementation.
|
||||
*/
|
||||
const OLD_REMOTE_ADDRESS_FORMAT = new RegExp(
|
||||
"(?<owner>[^/]+)/(?<repo>[^/]+)/(?<path>[^@]+)@(?<ref>.*)",
|
||||
);
|
||||
|
||||
/**
|
||||
* Attempts to parse `input` as a `RemoteFileAddress` using the old format.
|
||||
*
|
||||
* @param input The input to try and parse.
|
||||
* @returns A `RemoteFileAddress` value if successful or `undefined` otherwise.
|
||||
*/
|
||||
function parseOldRemoteFileAddress(
|
||||
input: string,
|
||||
): Result<RemoteFileAddress, undefined> {
|
||||
const pieces = OLD_REMOTE_ADDRESS_FORMAT.exec(input);
|
||||
|
||||
// 5 = 4 groups + the whole expression
|
||||
if (pieces?.groups === undefined || pieces.length < 5) {
|
||||
return new Failure(undefined);
|
||||
}
|
||||
|
||||
return new Success({
|
||||
owner: pieces.groups.owner.trim(),
|
||||
repo: pieces.groups.repo.trim(),
|
||||
path: pieces.groups.path.trim(),
|
||||
ref: pieces.groups.ref.trim(),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to parse `configFile` into an array of `RemoteFileAddress` components.
|
||||
*
|
||||
@@ -49,9 +81,17 @@ export function parseRemoteFileAddress(
|
||||
env: Env,
|
||||
configFile: string,
|
||||
): RemoteFileAddress {
|
||||
// Try to parse the input using the old format. If successful, return the
|
||||
// resulting `RemoteFileAddress`. Otherwise, continue using the new format.
|
||||
const oldFormatAddressResult = parseOldRemoteFileAddress(configFile);
|
||||
|
||||
if (oldFormatAddressResult.isSuccess()) {
|
||||
return oldFormatAddressResult.value;
|
||||
}
|
||||
|
||||
// retrieve the various parts of the config location, and ensure they're present
|
||||
const format = new RegExp(
|
||||
"^((?<owner>[^/]+)/)?(?<repo>[^/@]+)(/(?<path>[^@]+))?(@(?<ref>.*))?$",
|
||||
"^((?<owner>[^:@/]+)/)?(?<repo>[^:@/]+)(@(?<ref>[^:]+))?(:(?<path>.+))?$",
|
||||
);
|
||||
const pieces = format.exec(configFile.trim());
|
||||
|
||||
@@ -59,6 +99,9 @@ export function parseRemoteFileAddress(
|
||||
|
||||
// Check that the regular expression matched and that we have at least the repo name.
|
||||
if (!pieces?.groups || !repo || repo.length === 0) {
|
||||
// Neither the old format nor the new format worked. Throw an error that
|
||||
// explains the format we accept. We only mention the new format, since that's
|
||||
// what we want to be used going forward.
|
||||
throw new ConfigurationError(
|
||||
errorMessages.getConfigFileRepoFormatInvalidMessage(configFile),
|
||||
);
|
||||
|
||||
@@ -34,7 +34,7 @@ export function getConfigFileRepoFormatInvalidMessage(
|
||||
configFile: string,
|
||||
): string {
|
||||
let error = `The configuration file "${configFile}" is not a supported remote file reference.`;
|
||||
error += " Expected format [<owner>/]<repository>[/<file-path>][@<ref>]";
|
||||
error += " Expected format [<owner>/]<repository>[@<ref>][:<file-path>]";
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user