Warn when workflow analyzes the same language twice

This commit is contained in:
Henry Mercer 2023-09-22 14:54:03 +01:00
parent 01b8760f90
commit d0c18ba23e
9 changed files with 576 additions and 281 deletions

38
lib/workflow.js generated
View file

@ -78,11 +78,43 @@ exports.WorkflowErrors = toCodedErrors({
MissingPushHook: `Please specify an on.push hook to analyze and see code scanning alerts from the default branch on the Security tab.`,
CheckoutWrongHead: `git checkout HEAD^2 is no longer necessary. Please remove this step as Code Scanning recommends analyzing the merge commit for best results.`,
});
function getWorkflowErrors(doc) {
async function getWorkflowErrors(doc, codeql) {
const errors = [];
const jobName = process.env.GITHUB_JOB;
if (jobName) {
const job = doc?.jobs?.[jobName];
if (job?.strategy?.matrix?.language) {
const matrixLanguages = job.strategy.matrix.language;
if (Array.isArray(matrixLanguages)) {
const resolveResult = await codeql.betterResolveLanguages();
if (resolveResult.aliases) {
const aliases = resolveResult.aliases;
// Map extractors to entries in the `language` matrix parameter. This will allow us to
// detect languages which are analyzed in more than one job.
const matrixLanguagesByExtractor = {};
for (const language of matrixLanguages) {
const extractorName = aliases[language] || language;
if (!matrixLanguagesByExtractor[extractorName]) {
matrixLanguagesByExtractor[extractorName] = [];
}
matrixLanguagesByExtractor[extractorName].push(language);
}
// Check for duplicate languages in the matrix
for (const [extractor, languages] of Object.entries(matrixLanguagesByExtractor)) {
if (languages.length > 1) {
errors.push({
message: `CodeQL language '${extractor}' is referenced by more than one entry in the ` +
`'language' matrix parameter for job '${jobName}'. This may result in duplicate alerts. ` +
`Please edit the 'language' matrix parameter to keep only one of the following: ${languages
.map((language) => `'${language}'`)
.join(", ")}.`,
code: "DuplicateLanguageInMatrix",
});
}
}
}
}
}
const steps = job?.steps;
if (Array.isArray(steps)) {
for (const step of steps) {
@ -127,7 +159,7 @@ function getWorkflowErrors(doc) {
return errors;
}
exports.getWorkflowErrors = getWorkflowErrors;
async function validateWorkflow(logger) {
async function validateWorkflow(codeql, logger) {
let workflow;
try {
workflow = await getWorkflow(logger);
@ -137,7 +169,7 @@ async function validateWorkflow(logger) {
}
let workflowErrors;
try {
workflowErrors = getWorkflowErrors(workflow);
workflowErrors = await getWorkflowErrors(workflow, codeql);
}
catch (e) {
return `error: getWorkflowErrors() failed: ${String(e)}`;