name: "Releasing process"

on:
  push:
    tags:
      - "v*" # Only trigger on version tags (v1.0.0, v1.2.3, etc.)

# Minimal permissions at workflow level - each job specifies what it needs
permissions: {}

jobs:
  # Pre-release validation - verifies that CI checks already passed on main
  # Tests and linting run on every push to main (test.yml, lint.yml),
  # so we just verify they passed instead of re-running them.
  pre-release-checks:
    name: Pre-release validation
    runs-on: ubuntu-latest
    permissions:
      contents: read
      checks: read
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 2
          persist-credentials: false

      - name: Verify CI checks passed on main
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # The tag is created on the version bump commit (which skips CI).
          # CI tests ran on the parent commit — the actual code change.
          PARENT_SHA=$(git rev-parse HEAD~1)
          echo "Verifying CI status for commit: $PARENT_SHA"

          REQUIRED_CHECKS=("Test Summary" "Go Lint")

          for check_name in "${REQUIRED_CHECKS[@]}"; do
            echo ""
            echo "--- Checking: $check_name ---"
            PASSED=false

            # Poll for up to 10 minutes (20 × 30s) in case checks are still running
            for i in $(seq 1 20); do
              RESULT=$(gh api "repos/${{ github.repository }}/commits/${PARENT_SHA}/check-runs" \
                --jq "[.check_runs[] | select(.name == \"${check_name}\")] | first" 2>/dev/null)

              if [ -z "$RESULT" ] || [ "$RESULT" = "null" ]; then
                echo "⚠️  Check '$check_name' not found yet (attempt $i/20), waiting 30s..."
                sleep 30
                continue
              fi

              STATUS=$(echo "$RESULT" | jq -r '.status')
              CONCLUSION=$(echo "$RESULT" | jq -r '.conclusion')

              if [ "$STATUS" = "completed" ]; then
                if [ "$CONCLUSION" = "success" ]; then
                  echo "✅ $check_name passed"
                  PASSED=true
                  break
                else
                  echo "❌ $check_name failed (conclusion: $CONCLUSION)"
                  echo "Ensure all checks pass on main before releasing."
                  exit 1
                fi
              fi

              echo "⏳ $check_name in progress (attempt $i/20), waiting 30s..."
              sleep 30
            done

            if [ "$PASSED" != "true" ]; then
              echo "❌ Timed out waiting for '$check_name' to complete on commit $PARENT_SHA"
              exit 1
            fi
          done

          echo ""
          echo "✅ All required CI checks passed"

  # Build and release binaries
  build:
    name: Build and release
    needs: [pre-release-checks]
    runs-on: ubuntu-latest
    permissions:
      contents: write
      id-token: write
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: Set up tools
        uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4

      - name: Cache Go modules
        uses: actions/cache@v4
        with:
          path: |
            ~/go/pkg/mod
            ~/.cache/go-build
          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
          restore-keys: ${{ runner.os }}-go-

      - name: Generate GitHub App token for package managers
        uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
        id: app-token
        with:
          app-id: ${{ vars.APP_ID }}
          private-key: ${{ secrets.APP_PRIVATE_KEY }}
          owner: ${{ github.repository_owner }}
          repositories: homebrew-tap,scoop-bucket

      - name: Resolve previous semver tag
        id: prev_tag
        run: |
          # Ignore non-semver tags (e.g. "nightly") so they don't truncate the changelog.
          PREV=$(git tag --sort=-version:refname \
            | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \
            | grep -v "^${{ github.ref_name }}$" \
            | head -1)
          echo "tag=${PREV}" >> "$GITHUB_OUTPUT"
          echo "Previous semver tag: ${PREV}"

      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0
        with:
          distribution: goreleaser
          version: "v2.15.4"
          args: release --clean --timeout=60m
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GORELEASER_PREVIOUS_TAG: ${{ steps.prev_tag.outputs.tag }}
          AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
          TAP_GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}

  # Publish to NPM - must wait for GitHub Release to be created with binaries
  publish-npm:
    name: Publish to NPM
    needs: [build] # Wait for GitHub Release to be created with binaries
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: Setup Node.js
        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: "24.14.0"
          registry-url: "https://registry.npmjs.org"
          cache: "npm"
          cache-dependency-path: package-lock.json

      - name: Install dependencies
        run: npm ci --ignore-scripts

      - name: Publish to NPM
        run: npm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

  merge-schema-pr:
    name: Merge schema update PR
    needs: [publish-npm]
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - name: Generate GitHub App token
        uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
        id: app-token
        with:
          app-id: ${{ vars.APP_ID }}
          private-key: ${{ secrets.APP_PRIVATE_KEY }}
          owner: ${{ github.repository_owner }}
          repositories: website

      - name: Merge schema update PR
        env:
          GH_TOKEN: ${{ steps.app-token.outputs.token }}
        run: |
          BRANCH_NAME="chore/update-schema-from-cli"

          # Check if PR exists
          PR_NUMBER=$(gh pr list \
            --repo kubeasy-dev/website \
            --head "$BRANCH_NAME" \
            --base main \
            --json number \
            --jq '.[0].number')

          if [ -z "$PR_NUMBER" ]; then
            echo "No PR found for branch $BRANCH_NAME, skipping merge"
            exit 0
          fi

          echo "Found PR #$PR_NUMBER, merging..."

          # Merge the PR
          gh pr merge "$PR_NUMBER" \
            --repo kubeasy-dev/website \
            --squash \
            --delete-branch \
            --subject "chore: update challengeObjectives.ts from CLI" \
            --body "Auto-merged at kubeasy-cli release ${{ github.ref_name }}"
