/**
 * Vaspera Hardening GitHub Action
 *
 * Entry point for the GitHub Action that runs security scans
 * and posts results to PRs and Code Scanning.
 *
 * @module action
 */
import * as core from "@actions/core";
import * as github from "@actions/github";
import { join } from "path";
import { runAllScanners } from "../scanners/index.js";
import { exceedsThreshold } from "./types.js";
import { getChangedFiles, getFilesToScan, generateChangeSummary } from "./diff-mode.js";
import { generatePrComment, formatCommentBody, postPrComment } from "./pr-comment.js";
import { convertToSarif, writeSarifFile, uploadSarifToGitHub, getSarifFilePath } from "./sarif-upload.js";
/**
 * Parse action inputs
 */
function parseInputs() {
    const mode = core.getInput("mode");
    const failOn = core.getInput("fail-on");
    const uploadSarif = core.getBooleanInput("upload-sarif");
    const commentOnPr = core.getBooleanInput("comment-on-pr");
    const scanners = core.getInput("scanners").split(",").map((s) => s.trim()).filter(Boolean);
    const agents = core.getInput("agents").split(",").map((s) => s.trim()).filter(Boolean);
    const anthropicApiKey = core.getInput("anthropic-api-key") || undefined;
    const workingDirectory = core.getInput("working-directory") || ".";
    const configFile = core.getInput("config-file") || undefined;
    return {
        mode,
        failOn,
        uploadSarif,
        commentOnPr,
        scanners,
        agents,
        anthropicApiKey,
        workingDirectory,
        configFile,
    };
}
/**
 * Get GitHub context
 */
function getGitHubContext() {
    const ctx = github.context;
    return {
        owner: ctx.repo.owner,
        repo: ctx.repo.repo,
        sha: ctx.sha,
        ref: ctx.ref,
        eventName: ctx.eventName,
        pullRequest: ctx.payload.pull_request
            ? {
                number: ctx.payload.pull_request.number,
                base: {
                    sha: ctx.payload.pull_request.base.sha,
                    ref: ctx.payload.pull_request.base.ref,
                },
                head: {
                    sha: ctx.payload.pull_request.head.sha,
                    ref: ctx.payload.pull_request.head.ref,
                },
            }
            : undefined,
        workflow: ctx.workflow,
        runId: ctx.runId,
        runNumber: ctx.runNumber,
        actor: ctx.actor,
    };
}
/**
 * Set action outputs
 */
function setOutputs(outputs) {
    if (outputs.certificationId) {
        core.setOutput("certification-id", outputs.certificationId);
    }
    core.setOutput("total-findings", outputs.totalFindings);
    core.setOutput("critical-count", outputs.criticalCount);
    core.setOutput("high-count", outputs.highCount);
    core.setOutput("medium-count", outputs.mediumCount);
    core.setOutput("low-count", outputs.lowCount);
    if (outputs.sarifFile) {
        core.setOutput("sarif-file", outputs.sarifFile);
    }
    if (outputs.certificationLevel) {
        core.setOutput("certification-level", outputs.certificationLevel);
    }
    core.setOutput("scanner-summary", outputs.scannerSummary);
}
/**
 * Run the action
 */
async function run() {
    try {
        const inputs = parseInputs();
        const context = getGitHubContext();
        core.info(`Vaspera Hardening - Mode: ${inputs.mode}`);
        core.info(`Working directory: ${inputs.workingDirectory}`);
        core.info(`Event: ${context.eventName}`);
        // Resolve working directory
        const workspacePath = process.env.GITHUB_WORKSPACE || process.cwd();
        const projectPath = join(workspacePath, inputs.workingDirectory);
        // Get changed files if in diff mode
        let filesToScan;
        if (inputs.mode === "diff" && context.pullRequest) {
            const token = process.env.GITHUB_TOKEN;
            if (!token) {
                core.warning("GITHUB_TOKEN not set, falling back to full scan");
            }
            else {
                const octokit = github.getOctokit(token);
                const changedFiles = await getChangedFiles(octokit, context);
                filesToScan = getFilesToScan(changedFiles);
                core.info(`Changed files: ${changedFiles.length}`);
                core.info(`Files to scan: ${filesToScan.length}`);
                if (filesToScan.length === 0) {
                    core.info("No scannable files changed, skipping scan");
                    setOutputs({
                        totalFindings: 0,
                        criticalCount: 0,
                        highCount: 0,
                        mediumCount: 0,
                        lowCount: 0,
                        scannerSummary: "{}",
                    });
                    return;
                }
                core.startGroup("Changed Files Summary");
                core.info(generateChangeSummary(changedFiles));
                core.endGroup();
            }
        }
        // Build scanner options
        const scannerOptions = {
            semgrep: inputs.scanners.includes("semgrep"),
            dependencies: inputs.scanners.includes("dependencies"),
            secrets: inputs.scanners.includes("secrets"),
            typescript: inputs.scanners.includes("typescript"),
            include: filesToScan,
        };
        // Run scanners
        core.startGroup("Running Scanners");
        const scanResult = await runAllScanners(projectPath, scannerOptions);
        core.endGroup();
        // Log scanner results
        core.info(`Total findings: ${scanResult.totalFindings}`);
        core.info(`Critical: ${scanResult.bySeverity.critical}`);
        core.info(`High: ${scanResult.bySeverity.high}`);
        core.info(`Medium: ${scanResult.bySeverity.medium}`);
        core.info(`Low: ${scanResult.bySeverity.low}`);
        core.info(`Info: ${scanResult.bySeverity.info}`);
        // Generate SARIF and upload if enabled
        let sarifPath;
        if (inputs.uploadSarif) {
            core.startGroup("SARIF Generation");
            const sarif = convertToSarif(scanResult);
            sarifPath = getSarifFilePath(projectPath);
            await writeSarifFile(sarif, sarifPath);
            core.info(`SARIF written to: ${sarifPath}`);
            // Upload to GitHub Code Scanning
            const token = process.env.GITHUB_TOKEN;
            if (token) {
                try {
                    const octokit = github.getOctokit(token);
                    const uploadResult = await uploadSarifToGitHub(octokit, context, sarifPath);
                    core.info(`SARIF uploaded to Code Scanning (ID: ${uploadResult.id})`);
                }
                catch (error) {
                    core.warning(`Failed to upload SARIF: ${error instanceof Error ? error.message : String(error)}`);
                }
            }
            else {
                core.warning("GITHUB_TOKEN not set, skipping SARIF upload");
            }
            core.endGroup();
        }
        // Post PR comment if enabled
        if (inputs.commentOnPr && context.pullRequest) {
            core.startGroup("PR Comment");
            const token = process.env.GITHUB_TOKEN;
            if (token) {
                try {
                    const octokit = github.getOctokit(token);
                    const commentContent = generatePrComment(scanResult, context);
                    const commentBody = formatCommentBody(commentContent);
                    const result = await postPrComment(octokit, context, commentBody);
                    core.info(`Comment posted: ${result.url}`);
                }
                catch (error) {
                    core.warning(`Failed to post PR comment: ${error instanceof Error ? error.message : String(error)}`);
                }
            }
            else {
                core.warning("GITHUB_TOKEN not set, skipping PR comment");
            }
            core.endGroup();
        }
        // Set outputs
        const outputs = {
            totalFindings: scanResult.totalFindings,
            criticalCount: scanResult.bySeverity.critical,
            highCount: scanResult.bySeverity.high,
            mediumCount: scanResult.bySeverity.medium,
            lowCount: scanResult.bySeverity.low,
            sarifFile: sarifPath,
            scannerSummary: JSON.stringify({
                scanners: scanResult.scanners.map((s) => ({
                    name: s.scanner,
                    findings: s.findings.length,
                    success: s.success,
                    duration: s.duration,
                })),
                bySeverity: scanResult.bySeverity,
                totalDuration: scanResult.totalDuration,
            }),
        };
        setOutputs(outputs);
        // Check if we should fail the action
        if (exceedsThreshold(scanResult.bySeverity, inputs.failOn)) {
            core.setFailed(`Found ${scanResult.bySeverity[inputs.failOn] || 0}+ findings at ${inputs.failOn} severity or above`);
        }
    }
    catch (error) {
        core.setFailed(`Action failed: ${error instanceof Error ? error.message : String(error)}`);
    }
}
// Run the action
run();
//# sourceMappingURL=index.js.map