name: Trivy Scan Result

on:
  workflow_run:
    workflows: ["Trivy Scan Trigger"]
    types:
      - completed

permissions:
  contents: read

jobs:
  trivy_scan:
    if: github.event.workflow_run.conclusion == 'success'
    runs-on: ubuntu-latest
    permissions:
      contents: write # Required to checkout the PR's head SHA.
    outputs:
      pr_number: ${{ steps.pr_context.outputs.pr_number }}
      
    steps:
      # For some reason with workflow_run.id, download-artifact does not work.
      # Github Docs explicity provide an example of using github-script to download artifacts.
      - name: 'Download artifact'
        uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
        with:
          script: |
            let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
               owner: context.repo.owner,
               repo: context.repo.repo,
               run_id: context.payload.workflow_run.id,
            });
            let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
              return artifact.name == "pr-context-for-scan"
            })[0];
            let download = await github.rest.actions.downloadArtifact({
               owner: context.repo.owner,
               repo: context.repo.repo,
               artifact_id: matchArtifact.id,
               archive_format: 'zip',
            });
            const fs = require('fs');
            fs.writeFileSync('pr-context-for-scan.zip', Buffer.from(download.data));

      - name: 'Unzip artifact to pr-context'
        run: unzip pr-context-for-scan.zip -d pr-context

      - name: Setup PR context
        id: pr_context
        run: |
          pr_number=$(cat pr-context/pr_number)
          echo "pr_number=$pr_number" >> $GITHUB_OUTPUT

      - name: Load K3s Image
        run: docker load -i pr-context/k3s.tar

      - name: Download Rancher's VEX Hub report
        run: curl -fsSO https://raw.githubusercontent.com/rancher/vexhub/refs/heads/main/reports/rancher.openvex.json

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
        with:
          image-ref: 'rancher/k3s:latest'
          format: 'table'
          severity: "HIGH,CRITICAL"
          output: "trivy-report.txt"
        env:
          TRIVY_VEX: rancher.openvex.json
          TRIVY_SHOW_SUPPRESSED: true
      
      - name: Upload Trivy Report
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: trivy-report
          path: trivy-report.txt  
          retention-days: 2
          if-no-files-found: error

  report_results:
    needs: trivy_scan
    if: always() # Run even if the scan fails.
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write # Required to post comments.
    
    steps:       
      - name: Download Trivy Report artifact
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
        if: needs.trivy_scan.result == 'success'
        with:
          name: trivy-report
          path: .

      - name: Add Trivy Report to PR
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GH_REPO: ${{ github.repository }}
          SCAN_RESULT: ${{ needs.trivy_scan.result }}
          PR_NUMBER: ${{ needs.trivy_scan.outputs.pr_number }}
        run: |
          if [[ "$SCAN_RESULT" == "failure" ]]; then
            gh issue comment $PR_NUMBER -b ":x: Trivy scan action failed, check logs :x:"
            exit 0
          fi

          if [ -s trivy-report.txt ] && [ -n "$(grep -v '^\s*$' trivy-report.txt)" ]; then
            echo '```' | cat - trivy-report.txt > temp && mv temp trivy-report.txt
            echo '```' >> trivy-report.txt
            gh issue comment $PR_NUMBER -F trivy-report.txt
          else
            echo ':star2: No High or Critical CVEs Found :star2:' > trivy-report.txt
            gh issue comment $PR_NUMBER -F trivy-report.txt
          fi

  remove_label:
    if: always() # Run even if the scan fails.
    needs: trivy_scan
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write # Required to remove labels from the PR.

    steps:
      - name: Remove 'scan-with-trivy' label
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GH_REPO: ${{ github.repository }}
          PR_NUMBER: ${{ needs.trivy_scan.outputs.pr_number }}
        run: |
          gh pr edit $PR_NUMBER --remove-label "scan-with-trivy"
