name: Generate Performance Baseline

# Generate performance baselines for new releases
# Security: All GitHub context variables are passed through safe environment variables
# to prevent code injection attacks via malicious branch names or commit data
on:
  # Trigger on tag creation (releases)
  push:
    tags:
      - "v*"

  # Manual trigger (supports regenerating a baseline for an existing tag)
  workflow_dispatch:
    inputs:
      tag:
        description: "Tag to benchmark (e.g. v0.6.2)"
        required: true
        type: string

# Security: Define minimal required permissions
permissions:
  contents: read
  actions: read

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1
  # Seed search limit for both old (pre-v0.8) and current env var names.
  # Old tags read DELAUNAY_BENCH_SEED_SEARCH_LIMIT; current code reads
  # DELAUNAY_BENCH_DISCOVER_SEEDS_LIMIT. Setting both ensures backward
  # compatibility when generating baselines for older releases.
  DELAUNAY_BENCH_SEED_SEARCH_LIMIT: 256
  DELAUNAY_BENCH_DISCOVER_SEEDS_LIMIT: 256

jobs:
  generate-baseline:
    concurrency:
      group: generate-baseline-${{ github.ref }}
      cancel-in-progress: false
    runs-on: macos-15 # Use same runner as benchmark workflow for consistency
    timeout-minutes: 60

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0 # Full history for tag operations

      - name: Install Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@2b1f5e9b395427c92ee4e3331786ca3c37afe2d7 # v1.16.0
        with:
          cache: true
          # Toolchain from rust-toolchain.toml

      - name: Install uv (Python package manager)
        uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
        with:
          version: "latest"

      - name: Verify uv installation
        run: uv --version

      - name: Determine target tag
        id: tag_info
        env:
          INPUT_TAG: ${{ inputs.tag }}
          REF_TYPE: ${{ github.ref_type }}
          REF_NAME: ${{ github.ref_name }}
        run: |
          set -euo pipefail

          if [[ "${REF_TYPE}" = "tag" && -n "${REF_NAME}" ]]; then
            tag_name="${REF_NAME}"
          elif [[ -n "${INPUT_TAG}" ]]; then
            tag_name="${INPUT_TAG}"
          else
            echo "error: no tag provided. For workflow_dispatch you must provide inputs.tag" >&2
            exit 1
          fi

          if [[ ! "${tag_name}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then
            echo "error: tag must look like vX.Y.Z[-PRERELEASE][+BUILD] (got: '${tag_name}')" >&2
            exit 1
          fi

          echo "tag_name=${tag_name}" >> "$GITHUB_OUTPUT"

      - name: Checkout target tag (code under test)
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0
          ref: ${{ steps.tag_info.outputs.tag_name }}
          path: bench-target

      - name: Install target Rust toolchain (from tag)
        env:
          TAG_NAME: ${{ steps.tag_info.outputs.tag_name }}
        run: |
          set -euo pipefail

          channel="$(uv run python - <<'PY'
          from pathlib import Path
          import tomllib

          data = tomllib.loads(Path('bench-target/rust-toolchain.toml').read_text(encoding='utf-8'))
          print(data['toolchain']['channel'])
          PY
          )"

          echo "📌 Target tag: ${TAG_NAME}"
          echo "🦀 Installing Rust toolchain: ${channel}"

          rustup toolchain install "${channel}" --profile minimal

      - name: Generate performance baseline
        env:
          TAG_NAME: ${{ steps.tag_info.outputs.tag_name }}
        run: |
          set -euo pipefail

          echo "🚀 Generating performance baseline for tag ${TAG_NAME}"

          # Generate baseline using fixed tooling (this checkout) against the tag checkout.
          # Use --dev to match the comparison workflow's reduced Criterion settings;
          # benchmark-utils still runs the benchmark under Cargo's perf profile.
          uv run benchmark-utils generate-baseline \
            --project-root bench-target \
            --tag "${TAG_NAME}" \
            --dev

          echo "✅ Baseline generated successfully"

          # Display baseline summary
          uv run benchmark-utils display-summary \
            --baseline "bench-target/baseline-artifact/baseline_results.txt"

      - name: Prepare baseline artifact
        env:
          TAG_NAME: ${{ steps.tag_info.outputs.tag_name }}
          SAFE_RUN_ID: ${{ github.run_id }}
        run: |
          set -euo pipefail

          # Create metadata file in the target checkout so it is included in the uploaded artifact.
          uv run benchmark-utils create-metadata \
            --tag "${TAG_NAME}" \
            --output-dir "bench-target/baseline-artifact"

          # Extract the tag commit from the baseline file for human-readable logging.
          baseline_commit="$(uv run python - <<'PY'
          from pathlib import Path
          import re

          text = Path('bench-target/baseline-artifact/baseline_results.txt').read_text(
              encoding='utf-8',
              errors='replace',
          )
          m = re.search(r'^Git commit:\s*(\S+)', text, flags=re.MULTILINE)
          print(m.group(1) if m else 'unknown')
          PY
          )"
          echo "BASELINE_COMMIT=${baseline_commit}" >> "$GITHUB_ENV"

          echo "📦 Artifact contents:"
          ls -la bench-target/baseline-artifact/

      - name: Create safe artifact name
        id: safe_name
        env:
          TAG_NAME: ${{ steps.tag_info.outputs.tag_name }}
        run: uv run benchmark-utils sanitize-artifact-name --tag "$TAG_NAME"

      - name: Upload baseline artifact
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: ${{ steps.safe_name.outputs.artifact_name }}
          path: bench-target/baseline-artifact/
          retention-days: 90 # Keep baselines ~90 days (align with repo settings; adjust if needed)
          compression-level: 6 # Good balance of speed/compression

      - name: Display next steps
        env:
          TAG_NAME: ${{ steps.tag_info.outputs.tag_name }}
          SAFE_REF_TYPE: ${{ github.ref_type }}
        run: |
          set -euo pipefail

          echo "🎉 Performance baseline generated successfully!"
          echo ""
          echo "📋 Summary:"
          echo "  Tag: $TAG_NAME"
          echo "  Commit: ${BASELINE_COMMIT:-unknown}"
          echo "  Artifact: ${{ steps.safe_name.outputs.artifact_name }}"
          echo ""
          echo "🔄 The benchmark workflow will now use this baseline for:"
          echo "  • Pull request performance testing"
          echo "  • Main branch regression detection"
          echo "  • Manual performance comparisons"
          echo ""
          if [ "$SAFE_REF_TYPE" = "tag" ]; then
            echo "💡 This baseline is now available for tag $TAG_NAME"
          fi
