2026-02-21 02:54:49 -05:00
|
|
|
import * as core from '@actions/core';
|
|
|
|
|
import GovulncheckRunner from './lib/govulncheck.js';
|
|
|
|
|
import VulnerabilityParser from './lib/parser.js';
|
|
|
|
|
import AnnotationCreator from './lib/annotator.js';
|
|
|
|
|
import SummaryGenerator from './lib/summary.js';
|
|
|
|
|
import { fileURLToPath } from 'url';
|
2025-06-06 23:41:03 -04:00
|
|
|
|
|
|
|
|
async function run(dependencies = {}) {
|
|
|
|
|
// Allow dependency injection for testing
|
2026-02-21 02:54:49 -05:00
|
|
|
const coreLib = dependencies.core || core;
|
2025-06-06 23:41:03 -04:00
|
|
|
const govulncheck = dependencies.govulncheck || new GovulncheckRunner();
|
|
|
|
|
const parser = dependencies.parser || new VulnerabilityParser();
|
2026-02-21 02:54:49 -05:00
|
|
|
const annotator = dependencies.annotator || new AnnotationCreator(coreLib);
|
|
|
|
|
const summaryGenerator = dependencies.summaryGenerator || new SummaryGenerator(coreLib);
|
2025-06-06 23:41:03 -04:00
|
|
|
|
|
|
|
|
try {
|
2026-02-21 02:54:49 -05:00
|
|
|
const workingDirectory = coreLib.getInput('working-directory');
|
2025-06-06 23:41:03 -04:00
|
|
|
|
|
|
|
|
// Change to working directory
|
|
|
|
|
if (workingDirectory !== '.') {
|
2026-02-21 02:54:49 -05:00
|
|
|
coreLib.info(`Changing working directory to: ${workingDirectory}`);
|
2025-06-06 23:41:03 -04:00
|
|
|
process.chdir(workingDirectory);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-07 00:19:52 -04:00
|
|
|
// Install govulncheck if necessary.
|
2025-06-06 23:41:03 -04:00
|
|
|
await govulncheck.install();
|
|
|
|
|
|
|
|
|
|
// Run govulncheck with JSON output
|
2026-02-21 02:54:49 -05:00
|
|
|
coreLib.info('Running govulncheck...');
|
2025-06-06 23:50:57 -04:00
|
|
|
const { output, errorOutput } = await govulncheck.run();
|
2025-06-06 23:41:03 -04:00
|
|
|
|
|
|
|
|
if (errorOutput) {
|
2026-02-21 02:54:49 -05:00
|
|
|
coreLib.warning(`govulncheck stderr: ${errorOutput}`);
|
|
|
|
|
|
2025-06-07 02:08:43 -04:00
|
|
|
// Check for critical errors that indicate govulncheck couldn't run properly
|
2026-02-21 02:54:49 -05:00
|
|
|
if (
|
|
|
|
|
errorOutput.includes('missing go.sum entry') ||
|
|
|
|
|
errorOutput.includes('could not import') ||
|
|
|
|
|
errorOutput.includes('invalid package name')
|
|
|
|
|
) {
|
|
|
|
|
throw new Error(
|
|
|
|
|
`govulncheck failed due to missing dependencies. Please run 'go mod tidy' to update go.mod and go.sum files.\n\nError: ${errorOutput}`
|
|
|
|
|
);
|
2025-06-07 02:08:43 -04:00
|
|
|
}
|
2025-06-06 23:41:03 -04:00
|
|
|
}
|
|
|
|
|
|
2025-06-06 23:58:11 -04:00
|
|
|
// Log raw output for debugging
|
2026-02-21 02:54:49 -05:00
|
|
|
coreLib.info(`Raw govulncheck output length: ${output.length} characters`);
|
2025-06-06 23:58:11 -04:00
|
|
|
if (output.length < 5000) {
|
2026-02-21 02:54:49 -05:00
|
|
|
coreLib.info(`Raw output: ${output}`);
|
2025-06-06 23:58:11 -04:00
|
|
|
} else {
|
2026-02-21 02:54:49 -05:00
|
|
|
coreLib.info(`Raw output (first 1000 chars): ${output.substring(0, 1000)}...`);
|
2025-06-06 23:58:11 -04:00
|
|
|
}
|
|
|
|
|
|
2025-06-06 23:41:03 -04:00
|
|
|
// Parse JSON output
|
|
|
|
|
const vulnerabilities = parser.parse(output);
|
|
|
|
|
|
|
|
|
|
// Create annotations
|
2025-06-07 00:58:11 -04:00
|
|
|
await annotator.createAnnotations(vulnerabilities, parser, workingDirectory);
|
2026-02-21 02:54:49 -05:00
|
|
|
|
2025-06-07 00:58:11 -04:00
|
|
|
// Generate workflow summary
|
|
|
|
|
await summaryGenerator.generateSummary(vulnerabilities, parser, workingDirectory);
|
2025-06-06 23:41:03 -04:00
|
|
|
|
|
|
|
|
// Set outputs
|
|
|
|
|
const hasVulnerabilities = vulnerabilities.length > 0;
|
2026-02-21 02:54:49 -05:00
|
|
|
coreLib.setOutput('vulnerabilities-found', hasVulnerabilities.toString());
|
|
|
|
|
coreLib.setOutput('vulnerability-count', vulnerabilities.length.toString());
|
2025-06-06 23:41:03 -04:00
|
|
|
|
|
|
|
|
if (hasVulnerabilities) {
|
2026-02-21 02:54:49 -05:00
|
|
|
coreLib.warning(`Found ${vulnerabilities.length} vulnerabilities`);
|
2025-06-06 23:41:03 -04:00
|
|
|
} else {
|
2026-02-21 02:54:49 -05:00
|
|
|
coreLib.info('No vulnerabilities found');
|
2025-06-06 23:41:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return { vulnerabilities, hasVulnerabilities };
|
|
|
|
|
} catch (error) {
|
2026-02-21 02:54:49 -05:00
|
|
|
coreLib.setFailed(error.message);
|
2025-06-06 23:41:03 -04:00
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only run if this is the main module
|
2026-02-21 02:54:49 -05:00
|
|
|
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
2025-06-06 23:41:03 -04:00
|
|
|
run();
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-21 02:54:49 -05:00
|
|
|
export { run };
|