# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# This workflow checks out code, runs Codacy's Markdownlint engine only, and
# integrates the results with GitHub Advanced Security code scanning.
# For more information on the Codacy analysis action usage and
# parameters, see https://github.com/codacy/codacy-analysis-cli-action.
# For more information on Codacy Analysis CLI in general, see
# https://github.com/codacy/codacy-analysis-cli.

name: Codacy Markdownlint Scan

concurrency:
  # This concurrency group ensures that only one Codacy analysis runs at a time
  group: codacy-${{ github.ref_name }}
  cancel-in-progress: true

on:
  push:
    branches: ["main"]
  pull_request:
    # The branches below must be a subset of the branches above
    branches: ["main"]
  schedule:
    - cron: "42 0 * * 1"

permissions:
  contents: read

jobs:
  codacy-markdownlint-scan:
    permissions:
      # for actions/checkout to fetch code
      contents: read
      # for github/codeql-action/upload-sarif to upload SARIF results
      security-events: write
      # only required for a private repository by
      # github/codeql-action/upload-sarif to get the Action run status
      actions: read
    name: Codacy Markdownlint Scan
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      # Checkout the repository to the GitHub Actions runner
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

      - name: Set Codacy paths
        run: |
          set -euo pipefail
          echo "CODACY_WORKDIR=$RUNNER_TEMP/codacy-src" >> "$GITHUB_ENV"
          echo "CODACY_SARIF=$RUNNER_TEMP/results.sarif" >> "$GITHUB_ENV"

      - name: Prepare workspace copy without .git
        run: |
          set -euo pipefail
          mkdir -p "$CODACY_WORKDIR"
          rsync -a --delete --exclude '.git' ./ "$CODACY_WORKDIR/"

      # Execute Codacy Analysis CLI with a single tool. The Codacy GitHub App may
      # run curated PR-quality tools, but this SARIF workflow stays Markdownlint
      # only so maintainability checks are not mirrored into GitHub Code Scanning.
      - name: Run Codacy Analysis CLI
        # Cap Codacy runtime so a hung analyzer does not consume the full job timeout.
        timeout-minutes: 20
        uses: codacy/codacy-analysis-cli-action@562ee3e92b8e92df8b67e0a5ff8aa8e261919c08
        with:
          # Check https://github.com/codacy/codacy-analysis-cli#project-token
          # to get your project token from your Codacy repository.
          # You can also omit the token and run the tools that support
          # default configurations
          project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
          verbose: true
          directory: ${{ env.CODACY_WORKDIR }}
          output: ${{ env.CODACY_SARIF }}
          format: sarif
          tool: markdownlint
          skip-uncommitted-files-check: true
          # Adjust severity of non-security issues
          gh-code-scanning-compat: true
          # Force 0 exit code to allow SARIF file generation
          # This will handover control about PR rejection to the GitHub side
          max-allowed-issues: 2147483647

      - name: Split SARIF runs for upload
        run: |
          set -euo pipefail

          python3 <<'PY'
          import copy
          import json
          import os
          import re
          import sys
          from pathlib import Path

          source = Path(os.environ["CODACY_SARIF"])
          out_dir = Path(os.environ["RUNNER_TEMP"]) / "codacy-sarif"

          if not source.is_file() or source.stat().st_size == 0:
              sys.exit(f"Codacy did not produce a SARIF file at {source}")

          try:
              sarif = json.loads(source.read_text(encoding="utf-8"))
          except json.JSONDecodeError as exc:
              raise SystemExit(f"Codacy produced invalid SARIF JSON: {exc}") from exc

          runs = sarif.get("runs")
          if not isinstance(runs, list) or not runs:
              sys.exit("Codacy SARIF did not contain any runs to upload")

          out_dir.mkdir(parents=True, exist_ok=True)
          for stale in out_dir.glob("*.sarif"):
              stale.unlink()

          def slug(value: str) -> str:
              normalized = re.sub(r"[^A-Za-z0-9_.-]+", "-", value.strip().lower())
              return normalized.strip("-") or "unknown"

          seen_categories: dict[str, int] = {}
          for index, run in enumerate(runs, start=1):
              run_copy = copy.deepcopy(run)
              tool = run_copy.get("tool", {}).get("driver", {}).get("name")
              base_category = f"codacy-{slug(str(tool or f'run-{index}'))}"
              seen_categories[base_category] = seen_categories.get(base_category, 0) + 1
              suffix = seen_categories[base_category]
              category = base_category if suffix == 1 else f"{base_category}-{suffix}"

              automation = run_copy.get("automationDetails")
              if not isinstance(automation, dict):
                  automation = {}
              automation["id"] = category
              run_copy["automationDetails"] = automation

              split_sarif = {key: value for key, value in sarif.items() if key != "runs"}
              split_sarif.setdefault("$schema", "https://json.schemastore.org/sarif-2.1.0.json")
              split_sarif.setdefault("version", "2.1.0")
              split_sarif["runs"] = [run_copy]

              out_file = out_dir / f"{index:02d}-{category}.sarif"
              out_file.write_text(json.dumps(split_sarif, indent=2), encoding="utf-8")
              print(f"Wrote {out_file} with category {category}")

          with Path(os.environ["GITHUB_ENV"]).open("a", encoding="utf-8") as env_file:
              env_file.write(f"CODACY_SPLIT_SARIF_DIR={out_dir}\n")
          PY

      - name: Upload split SARIF files
        uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
        with:
          sarif_file: ${{ env.CODACY_SPLIT_SARIF_DIR }}
          wait-for-processing: true
