mirror of
https://github.com/github/codeql-action.git
synced 2025-12-24 08:10:06 +08:00
Make getInputOrThrow throw when it can't find any calls to the Action
This created unexpected behavior with a workflow calling `codeql-action/analyze` locally. Therefore, be more conservative with parsing inputs from workflows and refuse to parse jobs that don't call the specified Action exactly once.
This commit is contained in:
26
lib/workflow.js
generated
26
lib/workflow.js
generated
@@ -264,25 +264,23 @@ function getStepsCallingAction(job, actionName) {
|
|||||||
* determine that no such input is passed to the Action.
|
* determine that no such input is passed to the Action.
|
||||||
*/
|
*/
|
||||||
function getInputOrThrow(workflow, jobName, actionName, inputName, matrixVars) {
|
function getInputOrThrow(workflow, jobName, actionName, inputName, matrixVars) {
|
||||||
|
var _a;
|
||||||
|
const preamble = `Could not get ${inputName} input to ${actionName} since`;
|
||||||
if (!workflow.jobs) {
|
if (!workflow.jobs) {
|
||||||
throw new Error(`Could not get ${inputName} input to ${actionName} since the workflow has no jobs.`);
|
throw new Error(`${preamble} the workflow has no jobs.`);
|
||||||
}
|
}
|
||||||
if (!workflow.jobs[jobName]) {
|
if (!workflow.jobs[jobName]) {
|
||||||
throw new Error(`Could not get ${inputName} input to ${actionName} since the workflow has no job named ${jobName}.`);
|
throw new Error(`${preamble} the workflow has no job named ${jobName}.`);
|
||||||
}
|
}
|
||||||
const inputs = getStepsCallingAction(workflow.jobs[jobName], actionName)
|
const stepsCallingAction = getStepsCallingAction(workflow.jobs[jobName], actionName);
|
||||||
.map((step) => { var _a; return (_a = step.with) === null || _a === void 0 ? void 0 : _a[inputName]; })
|
if (stepsCallingAction.length === 0) {
|
||||||
.filter((input) => input !== undefined)
|
throw new Error(`${preamble} the ${jobName} job does not call ${actionName}.`);
|
||||||
.map((input) => input);
|
|
||||||
if (inputs.length === 0) {
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
if (!inputs.every((input) => input === inputs[0])) {
|
else if (stepsCallingAction.length > 1) {
|
||||||
throw new Error(`Could not get ${inputName} input to ${actionName} since there were multiple steps calling ` +
|
throw new Error(`${preamble} the ${jobName} job calls ${actionName} multiple times.`);
|
||||||
`${actionName} with different values for ${inputName}.`);
|
|
||||||
}
|
}
|
||||||
let input = inputs[0];
|
let input = (_a = stepsCallingAction[0].with) === null || _a === void 0 ? void 0 : _a[inputName];
|
||||||
if (matrixVars !== undefined) {
|
if (input !== undefined && matrixVars !== undefined) {
|
||||||
// Make a basic attempt to substitute matrix variables
|
// Make a basic attempt to substitute matrix variables
|
||||||
// First normalize by removing whitespace
|
// First normalize by removing whitespace
|
||||||
input = input.replace(/\${{\s+/, "${{").replace(/\s+}}/, "}}");
|
input = input.replace(/\${{\s+/, "${{").replace(/\s+}}/, "}}");
|
||||||
@@ -290,7 +288,7 @@ function getInputOrThrow(workflow, jobName, actionName, inputName, matrixVars) {
|
|||||||
input = input.replace(`\${{matrix.${key}}}`, value);
|
input = input.replace(`\${{matrix.${key}}}`, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (input.includes("${{")) {
|
if (input !== undefined && input.includes("${{")) {
|
||||||
throw new Error(`Could not get ${inputName} input to ${actionName} since it contained an unrecognized dynamic value.`);
|
throw new Error(`Could not get ${inputName} input to ${actionName} since it contained an unrecognized dynamic value.`);
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
6
lib/workflow.test.js
generated
6
lib/workflow.test.js
generated
@@ -435,7 +435,7 @@ function errorCodes(actual, expected) {
|
|||||||
"an unrecognized dynamic value.",
|
"an unrecognized dynamic value.",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("getCategoryInputOrThrow throws error for workflow with multiple categories", (t) => {
|
(0, ava_1.default)("getCategoryInputOrThrow throws error for workflow with multiple calls to analyze", (t) => {
|
||||||
t.throws(() => (0, workflow_1.getCategoryInputOrThrow)(yaml.load(`
|
t.throws(() => (0, workflow_1.getCategoryInputOrThrow)(yaml.load(`
|
||||||
jobs:
|
jobs:
|
||||||
analysis:
|
analysis:
|
||||||
@@ -450,8 +450,8 @@ function errorCodes(actual, expected) {
|
|||||||
with:
|
with:
|
||||||
category: another-category
|
category: another-category
|
||||||
`), "analysis", {}), {
|
`), "analysis", {}), {
|
||||||
message: "Could not get category input to github/codeql-action/analyze since there were multiple steps " +
|
message: "Could not get category input to github/codeql-action/analyze since the analysis job " +
|
||||||
"calling github/codeql-action/analyze with different values for category.",
|
"calls github/codeql-action/analyze multiple times.",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
//# sourceMappingURL=workflow.test.js.map
|
//# sourceMappingURL=workflow.test.js.map
|
||||||
File diff suppressed because one or more lines are too long
@@ -646,7 +646,7 @@ test("getCategoryInputOrThrow throws error for workflow with dynamic category",
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("getCategoryInputOrThrow throws error for workflow with multiple categories", (t) => {
|
test("getCategoryInputOrThrow throws error for workflow with multiple calls to analyze", (t) => {
|
||||||
t.throws(
|
t.throws(
|
||||||
() =>
|
() =>
|
||||||
getCategoryInputOrThrow(
|
getCategoryInputOrThrow(
|
||||||
@@ -669,8 +669,8 @@ test("getCategoryInputOrThrow throws error for workflow with multiple categories
|
|||||||
),
|
),
|
||||||
{
|
{
|
||||||
message:
|
message:
|
||||||
"Could not get category input to github/codeql-action/analyze since there were multiple steps " +
|
"Could not get category input to github/codeql-action/analyze since the analysis job " +
|
||||||
"calling github/codeql-action/analyze with different values for category.",
|
"calls github/codeql-action/analyze multiple times.",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -327,35 +327,32 @@ function getInputOrThrow(
|
|||||||
inputName: string,
|
inputName: string,
|
||||||
matrixVars: { [key: string]: string } | undefined
|
matrixVars: { [key: string]: string } | undefined
|
||||||
) {
|
) {
|
||||||
|
const preamble = `Could not get ${inputName} input to ${actionName} since`;
|
||||||
if (!workflow.jobs) {
|
if (!workflow.jobs) {
|
||||||
throw new Error(
|
throw new Error(`${preamble} the workflow has no jobs.`);
|
||||||
`Could not get ${inputName} input to ${actionName} since the workflow has no jobs.`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (!workflow.jobs[jobName]) {
|
if (!workflow.jobs[jobName]) {
|
||||||
|
throw new Error(`${preamble} the workflow has no job named ${jobName}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const stepsCallingAction = getStepsCallingAction(
|
||||||
|
workflow.jobs[jobName],
|
||||||
|
actionName
|
||||||
|
);
|
||||||
|
|
||||||
|
if (stepsCallingAction.length === 0) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Could not get ${inputName} input to ${actionName} since the workflow has no job named ${jobName}.`
|
`${preamble} the ${jobName} job does not call ${actionName}.`
|
||||||
|
);
|
||||||
|
} else if (stepsCallingAction.length > 1) {
|
||||||
|
throw new Error(
|
||||||
|
`${preamble} the ${jobName} job calls ${actionName} multiple times.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputs = getStepsCallingAction(workflow.jobs[jobName], actionName)
|
let input = stepsCallingAction[0].with?.[inputName];
|
||||||
.map((step) => step.with?.[inputName])
|
|
||||||
.filter((input) => input !== undefined)
|
|
||||||
.map((input) => input!);
|
|
||||||
|
|
||||||
if (inputs.length === 0) {
|
if (input !== undefined && matrixVars !== undefined) {
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (!inputs.every((input) => input === inputs[0])) {
|
|
||||||
throw new Error(
|
|
||||||
`Could not get ${inputName} input to ${actionName} since there were multiple steps calling ` +
|
|
||||||
`${actionName} with different values for ${inputName}.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let input = inputs[0];
|
|
||||||
|
|
||||||
if (matrixVars !== undefined) {
|
|
||||||
// Make a basic attempt to substitute matrix variables
|
// Make a basic attempt to substitute matrix variables
|
||||||
// First normalize by removing whitespace
|
// First normalize by removing whitespace
|
||||||
input = input.replace(/\${{\s+/, "${{").replace(/\s+}}/, "}}");
|
input = input.replace(/\${{\s+/, "${{").replace(/\s+}}/, "}}");
|
||||||
@@ -363,8 +360,7 @@ function getInputOrThrow(
|
|||||||
input = input.replace(`\${{matrix.${key}}}`, value);
|
input = input.replace(`\${{matrix.${key}}}`, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (input !== undefined && input.includes("${{")) {
|
||||||
if (input.includes("${{")) {
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Could not get ${inputName} input to ${actionName} since it contained an unrecognized dynamic value.`
|
`Could not get ${inputName} input to ${actionName} since it contained an unrecognized dynamic value.`
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user