name: Close issues ready for release

on:
  release:
    types: [published]

permissions:
  issues: write

concurrency:
  group: close-ready-for-release-${{ github.event.release.id || github.run_id }}
  cancel-in-progress: false

jobs:
  close-ready-for-release:
    runs-on: ubuntu-latest
    steps:
      - name: Comment and close labeled issues
        uses: actions/github-script@v7
        with:
          script: |
            const release = context.payload.release
            if (!release) {
              core.setFailed("No release payload found for this event.")
              return
            }

            if (release.draft) {
              core.notice("Release is a draft. Skipping issue closure.")
              return
            }

            if (release.prerelease) {
              core.notice("Release is a prerelease. Skipping issue closure.")
              return
            }

            const { owner, repo } = context.repo
            const tagName = release.tag_name
            const releaseUrl = release.html_url
            const marker = "<!-- fixed-in-release -->"
            const body = `${marker}\nThis has been fixed in ${tagName}, please see [the release](${releaseUrl}).`

            const labeledIssues = await github.paginate(
              github.rest.issues.listForRepo,
              {
                owner,
                repo,
                state: "open",
                labels: "ready for release",
                per_page: 100,
              }
            )

            const issues = labeledIssues.filter((issue) => !issue.pull_request)
            core.info(
              `Found ${issues.length} open issue(s) labeled "ready for release".`
            )

            const failures = []

            for (const issue of issues) {
              try {
                const comments = await github.paginate(
                  github.rest.issues.listComments,
                  {
                    owner,
                    repo,
                    issue_number: issue.number,
                    per_page: 100,
                  }
                )

                const existing = comments.find(
                  (comment) => comment.body && comment.body.includes(marker)
                )

                if (existing) {
                  await github.rest.issues.updateComment({
                    owner,
                    repo,
                    comment_id: existing.id,
                    body,
                  })
                } else {
                  await github.rest.issues.createComment({
                    owner,
                    repo,
                    issue_number: issue.number,
                    body,
                  })
                }

                await github.rest.issues.update({
                  owner,
                  repo,
                  issue_number: issue.number,
                  state: "closed",
                  state_reason: "completed",
                })
              } catch (error) {
                const message = error && error.message ? error.message : String(error)
                failures.push(`#${issue.number}: ${message}`)
              }
            }

            if (failures.length > 0) {
              core.setFailed(
                `Failed to update ${failures.length} issue(s): ${failures.join("; ")}`
              )
              return
            }

            core.info("Done. All labeled issues were commented and closed.")
