name: Release

on:
  push:
    tags:
      - "v*"

env:
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

permissions:
  contents: write

jobs:
  release:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          submodules: true

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version-file: go.mod

      - name: Install gocyclo
        run: go install github.com/fzipp/gocyclo/cmd/gocyclo@v0.6.0

      - name: Install ineffassign
        run: go install github.com/gordonklaus/ineffassign@latest

      - name: Install misspell
        run: go install github.com/client9/misspell/cmd/misspell@v0.3.4

      - name: Add Go bin to PATH
        run: echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"

      - name: Run checks
        run: make ci

      - name: Ensure tag points to main
        run: |
          git fetch origin main
          tag_commit="$(git rev-parse "${GITHUB_REF}^{commit}")"
          main_commit="$(git rev-parse origin/main)"
          if [ "$tag_commit" != "$main_commit" ]; then
            echo "tag commit ($tag_commit) does not match origin/main ($main_commit)"
            exit 1
          fi

      # GoReleaser's nix publisher needs `nix-hash` on PATH to compute the
      # source hash for the generated flake; without Nix it skips the nix pipe
      # ("nix-hash is not available"). Install Nix before the release step so the
      # flake is published to dirstral/nix-user-repository.
      - name: Install Nix
        uses: cachix/install-nix-action@v30
        with:
          extra_nix_config: |
            experimental-features = nix-command flakes

      - name: GoReleaser release
        uses: goreleaser/goreleaser-action@v6
        with:
          distribution: goreleaser
          version: ~> v2
          args: release --clean
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
          # Required by the `nix:` publisher in .goreleaser.yaml to push the
          # generated flake to dirstral/nix-user-repository.
          NIX_USER_REPOSITORY_GITHUB_TOKEN: ${{ secrets.NIX_USER_REPOSITORY_GITHUB_TOKEN }}

      # GoReleaser auto-bumps the lean dir2mcp.rb but cannot regenerate
      # dir2mcp-full.rb (it carries hand-written docling install logic).
      # Open a PR on the tap that bumps version + tarball URLs + SHA256s
      # in dir2mcp-full.rb so the two formulas stay in lockstep.
      #
      # The step is idempotent so the workflow can be re-run for the same
      # tag (re-run from the Actions UI, retried after a transient
      # failure, or invoked twice while a tap CI re-run is pending):
      #   - if the bump branch already exists on the tap, we fetch and
      #     reset it to the new content rather than aborting on push;
      #   - if a PR for that branch is already open, we skip pr-create.
      - name: Bump dir2mcp-full formula on tap
        env:
          GH_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
        run: |
          set -euo pipefail
          VERSION="${GITHUB_REF_NAME#v}"
          BRANCH="auto/bump-full-v${VERSION}"

          if [ ! -f dist/checksums.txt ]; then
            echo "dist/checksums.txt missing — GoReleaser dist artefacts not where expected" >&2
            exit 1
          fi

          tap_dir="$RUNNER_TEMP/homebrew-tap"
          git clone \
            "https://x-access-token:${GH_TOKEN}@github.com/dirstral/homebrew-tap.git" \
            "$tap_dir"

          # Reuse the same identity GoReleaser uses for the lean-formula
          # commit so both updates show up under the same author.
          git -C "$tap_dir" config user.name "goreleaserbot"
          git -C "$tap_dir" config user.email "bot@goreleaser.com"

          # Re-use the existing remote branch when present so a re-run
          # updates it instead of failing on `git push` for a non-fast-
          # forward. The tap PR keeps the same head, so review history is
          # preserved.
          if git -C "$tap_dir" ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then
            echo "branch $BRANCH already exists on tap; will update it"
            git -C "$tap_dir" fetch origin "$BRANCH":"$BRANCH"
            git -C "$tap_dir" checkout "$BRANCH"
          else
            git -C "$tap_dir" checkout -b "$BRANCH"
          fi

          python3 scripts/bump_full_formula.py \
            --version "$VERSION" \
            --checksums dist/checksums.txt \
            --formula "$tap_dir/Formula/dir2mcp-full.rb"

          if git -C "$tap_dir" diff --quiet -- Formula/dir2mcp-full.rb; then
            echo "no formula changes — branch already matches target state" >&2
            exit 0
          fi

          git -C "$tap_dir" add Formula/dir2mcp-full.rb
          git -C "$tap_dir" commit -m "Bump dir2mcp-full to v${VERSION} (automated)"
          # --force-with-lease is safe because we just fetched origin/$BRANCH
          # above (or just created the branch); it protects against pushing
          # over a concurrent human edit on the same branch.
          git -C "$tap_dir" push --force-with-lease origin "$BRANCH"

          # Skip pr-create when an open PR already exists for this branch.
          # gh pr list --json number returns "[]" when none match.
          existing_pr="$(gh pr list \
            --repo dirstral/homebrew-tap \
            --head "$BRANCH" \
            --state open \
            --json number \
            --jq '.[0].number // empty')"
          if [ -n "$existing_pr" ]; then
            echo "PR #$existing_pr already open for $BRANCH; commit pushed, skipping pr-create"
            exit 0
          fi

          gh pr create \
            --repo dirstral/homebrew-tap \
            --base main \
            --head "$BRANCH" \
            --title "Bump dir2mcp-full to v${VERSION}" \
            --body "Automated bump from the dir2mcp v${VERSION} release.

          Mirrors the version, release-tarball URLs, and SHA256 fields in
          dir2mcp-full.rb without touching the docling install logic.
          Generated by .github/workflows/release.yml."
