name: Close pending-release issues

on:
  push:
    branches: [master]

permissions:
  contents: read
  issues: write

env:
  NEXT_RELEASE_LABEL: pending-release

jobs:
  close:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: Close issues referenced by pushed commits
        shell: bash
        env:
          GH_TOKEN: ${{ secrets.KANGAL_GITHUB_TOKEN }}
        run: |
          set -euo pipefail

          echo "Using GitHub token for $(gh api user --jq .login)."

          BEFORE="${{ github.event.before }}"
          AFTER="${{ github.sha }}"
          ZERO_SHA="0000000000000000000000000000000000000000"

          if [ "$BEFORE" = "$ZERO_SHA" ]; then
            RANGE_ARGS=(-1 "$AFTER")
            echo "Scanning latest commit $AFTER for refs #<issue> lines."
          else
            RANGE_ARGS=("$BEFORE..$AFTER")
            echo "Scanning pushed commits in $BEFORE..$AFTER for refs #<issue> lines."
          fi

          mapfile -t ISSUES < <(
            git log --format=%b "${RANGE_ARGS[@]}" \
              | perl -ne 'print "$1\n" if /^\s*refs\s+#([0-9]+)\s*$/i' \
              | sort -nu
          )

          if [ "${#ISSUES[@]}" -eq 0 ]; then
            echo "No issue refs found."
            exit 0
          fi

          if ! gh api "repos/${GITHUB_REPOSITORY}/labels/${NEXT_RELEASE_LABEL}" >/dev/null 2>&1; then
            gh api -X POST "repos/${GITHUB_REPOSITORY}/labels" \
              -f name="$NEXT_RELEASE_LABEL" \
              -f color="5319E7" \
              -f description="Implemented on master and pending a published release." \
              >/dev/null \
              || gh api "repos/${GITHUB_REPOSITORY}/labels/${NEXT_RELEASE_LABEL}" >/dev/null
          fi

          PENDING_COMMENT_MARKER="<!-- herdr:pending-release -->"
          PENDING_COMMENT="${PENDING_COMMENT_MARKER}"$'\n'"Implemented on master and queued for the next release. This is not available in a published Herdr release yet."

          issue_has_comment_marker() {
            local issue="$1"
            local marker="$2"
            local comments
            if ! comments="$(gh api --paginate "repos/${GITHUB_REPOSITORY}/issues/${issue}/comments?per_page=100" --jq '.[].body')"; then
              echo "::warning::Could not read comments for issue #$issue."
              return 2
            fi
            grep -F -- "$marker" >/dev/null <<<"$comments"
          }

          for issue in "${ISSUES[@]}"; do
            echo "Checking #$issue"
            if ! data="$(gh api "repos/${GITHUB_REPOSITORY}/issues/${issue}")"; then
              echo "::warning::Could not read issue #$issue; skipping."
              continue
            fi

            if jq -e 'has("pull_request")' <<<"$data" >/dev/null; then
              echo "Skipping #$issue because it is a pull request."
              continue
            fi

            ISSUE_STATE="$(jq -r '.state' <<<"$data")"

            HAS_NEXT_RELEASE_LABEL="$(jq -r --arg label "$NEXT_RELEASE_LABEL" 'any(.labels[].name; . == $label)' <<<"$data")"
            if [ "$HAS_NEXT_RELEASE_LABEL" != "true" ]; then
              if ! gh issue edit "$issue" --repo "$GITHUB_REPOSITORY" --add-label "$NEXT_RELEASE_LABEL"; then
                echo "::warning::Could not label issue #$issue."
                continue
              fi
            fi

            MARKER_STATUS=0
            issue_has_comment_marker "$issue" "$PENDING_COMMENT_MARKER" || MARKER_STATUS="$?"
            if [ "$MARKER_STATUS" -eq 2 ]; then
              continue
            fi
            HAS_PENDING_COMMENT="false"
            if [ "$MARKER_STATUS" -eq 0 ]; then
              HAS_PENDING_COMMENT="true"
            fi

            if [ "$ISSUE_STATE" = "open" ]; then
              if [ "$HAS_PENDING_COMMENT" = "true" ]; then
                if ! gh issue close "$issue" --repo "$GITHUB_REPOSITORY" --reason completed; then
                  echo "::warning::Could not close issue #$issue."
                  continue
                fi
              elif ! gh issue close "$issue" --repo "$GITHUB_REPOSITORY" --reason completed --comment "$PENDING_COMMENT"; then
                echo "::warning::Could not close issue #$issue."
                continue
              fi
            elif [ "$HAS_PENDING_COMMENT" != "true" ]; then
              if ! gh issue comment "$issue" --repo "$GITHUB_REPOSITORY" --body "$PENDING_COMMENT"; then
                echo "::warning::Could not comment on closed issue #$issue."
                continue
              fi
            else
              echo "Skipping pending-release comment for #$issue because it already exists."
            fi
          done
