name: Release

on:
  push:
    branches:
      {{#each branchPatterns}}
      - {{ . }}
      {{/each}}

permissions:
  contents: write
  pull-requests: write
  checks: write

jobs:
  release:
    outputs:
      pr: $\{{ steps.release.outputs.pr }}
      pr-branch: $\{{ steps.release.outputs.pr-branch }}
      pr-number: $\{{ steps.release.outputs.pr-number }}
      pr-sha: $\{{ steps.release.outputs.pr-sha }}
      releases: $\{{ steps.release.outputs.releases }}
      comment-id: $\{{ steps.create-comment.outputs.comment-id || steps.update-comment.outputs.comment-id }}
      check-id: $\{{ steps.create-check.outputs.check-id }}
    {{> jobYml jobName="Release" }}
      - name: Release Please
        id: release
        env:
          GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
        run: {{ rootNpxPath }} --offline template-oss-release-please --branch="$\{{ github.ref_name }}" --backport="{{ backport }}" --defaultTag="{{ defaultPublishTag }}"
      - name: Create Release Manager Comment Text
        if: steps.release.outputs.pr-number
        uses: actions/github-script@v7
        id: comment-text
        with:
          result-encoding: string
          script: |
            const { runId, repo: { owner, repo } } = context
            const { data: workflow } = await github.rest.actions.getWorkflowRun({ owner, repo, run_id: runId })
            return['## Release Manager', `Release workflow run: ${workflow.html_url}`].join('\n\n')
      - name: Find Release Manager Comment
        uses: peter-evans/find-comment@v2
        if: steps.release.outputs.pr-number
        id: found-comment
        with:
          issue-number: $\{{ steps.release.outputs.pr-number }}
          comment-author: 'github-actions[bot]'
          body-includes: '## Release Manager'
      - name: Create Release Manager Comment
        id: create-comment
        if: steps.release.outputs.pr-number && !steps.found-comment.outputs.comment-id
        uses: peter-evans/create-or-update-comment@v3
        with:
          issue-number: $\{{ steps.release.outputs.pr-number }}
          body: $\{{ steps.comment-text.outputs.result }}
      - name: Update Release Manager Comment
        id: update-comment
        if: steps.release.outputs.pr-number && steps.found-comment.outputs.comment-id
        uses: peter-evans/create-or-update-comment@v3
        with:
          comment-id: $\{{ steps.found-comment.outputs.comment-id }}
          body: $\{{ steps.comment-text.outputs.result }}
          edit-mode: 'replace'
      - name: Create Check
        id: create-check
        uses: ./.github/actions/create-check
        if: steps.release.outputs.pr-sha
        with:
          name: "Release"
          token: $\{{ secrets.GITHUB_TOKEN }}
          sha: $\{{ steps.release.outputs.pr-sha }}

  update:
    needs: release
    outputs:
      sha: $\{{ steps.commit.outputs.sha }}
      check-id: $\{{ steps.create-check.outputs.check-id }}
    {{> jobYml
      jobName="Update - Release"
      jobIf="needs.release.outputs.pr"
      jobCheckout=(obj ref="${{ needs.release.outputs.pr-branch }}" fetch-depth=0)
    }}
      - name: Create Release Manager Checklist Text
        id: comment-text
        env:
          GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
        run: {{ rootNpmPath }} exec --offline -- template-oss-release-manager --pr="$\{{ needs.release.outputs.pr-number }}" --backport="{{ backport }}" --defaultTag="{{ defaultPublishTag }}" {{~#if lockfile}} --lockfile{{/if}} {{~#if publish}} --publish{{/if}}
      - name: Append Release Manager Comment
        uses: peter-evans/create-or-update-comment@v3
        with:
          comment-id: $\{{ needs.release.outputs.comment-id }}
          body: $\{{ steps.comment-text.outputs.result }}
          edit-mode: 'append'
      - name: Run Post Pull Request Actions
        env:
          GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
        run: {{ rootNpmPath }} run rp-pull-request --ignore-scripts {{~#if allFlags}} {{ allFlags }}{{else}} --if-present{{/if}} -- --pr="$\{{ needs.release.outputs.pr-number }}" --commentId="$\{{ needs.release.outputs.comment-id }}"
      - name: Commit
        id: commit
        env:
          GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
        run: |
          git commit --all --amend --no-edit || true
          git push --force-with-lease
          echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
      - name: Create Check
        id: create-check
        uses: ./.github/actions/create-check
        with:
          name: "Update - Release"
          check-name: "Release"
          token: $\{{ secrets.GITHUB_TOKEN }}
          sha: $\{{ steps.commit.outputs.sha }}
      - name: Conclude Check
        uses: LouisBrunner/checks-action@v1.6.0
        with:
          token: $\{{ secrets.GITHUB_TOKEN }}
          conclusion: $\{{ job.status }}
          check_id: $\{{ needs.release.outputs.check-id }}

  ci:
    name: CI - Release
    needs: [release, update]
    if: needs.release.outputs.pr
    uses: ./.github/workflows/ci-release.yml
    with:
      ref: $\{{ needs.release.outputs.pr-branch }}
      check-sha: $\{{ needs.update.outputs.sha }}

  post-ci:
    needs: [release, update, ci]
    {{> jobYml jobName="Post CI - Release" jobIf="needs.release.outputs.pr && always()" jobSkipSetup=true }}
      - name: Get CI Conclusion
        id: conclusion
        run: |
          result=""
          if [[ "$\{{ contains(needs.*.result, 'failure') }}" == "true" ]]; then
            result="failure"
          elif [[ "$\{{ contains(needs.*.result, 'cancelled') }}" == "true" ]]; then
            result="cancelled"
          else
            result="success"
          fi
          echo "result=$result" >> $GITHUB_OUTPUT
      - name: Conclude Check
        uses: LouisBrunner/checks-action@v1.6.0
        with:
          token: $\{{ secrets.GITHUB_TOKEN }}
          conclusion: $\{{ steps.conclusion.outputs.result }}
          check_id: $\{{ needs.update.outputs.check-id }}

  post-release:
    needs: release
    outputs:
      comment-id: $\{{ steps.create-comment.outputs.comment-id }}
    {{> jobYml jobName="Post Release - Release" jobIf="needs.release.outputs.releases" jobSkipSetup=true  }}
      - name: Create Release PR Comment Text
        id: comment-text
        uses: actions/github-script@v7
        env:
          RELEASES: $\{{ needs.release.outputs.releases }}
        with:
          result-encoding: string
          script: |
            const releases = JSON.parse(process.env.RELEASES)
            const { runId, repo: { owner, repo } } = context
            const issue_number = releases[0].prNumber
            const runUrl = `https://github.com/${owner}/${repo}/actions/runs/${runId}`

            return [
              '## Release Workflow\n',
              ...releases.map(r => `- \`${r.pkgName}@${r.version}\` ${r.url}`),
              `- Workflow run: :arrows_counterclockwise: ${runUrl}`,
            ].join('\n')
      - name: Create Release PR Comment
        id: create-comment
        uses: peter-evans/create-or-update-comment@v3
        with:
          issue-number: $\{{ fromJSON(needs.release.outputs.releases)[0].prNumber }}
          body: $\{{ steps.comment-text.outputs.result }}

  release-integration:
    needs: release
    name: Release Integration
    if: needs.release.outputs.releases
    uses: ./.github/workflows/release-integration.yml
    {{#if publish}}
    permissions:
      contents: read
      id-token: write
    secrets:
      PUBLISH_TOKEN: $\{{ secrets.PUBLISH_TOKEN }}
    {{/if}}
    with:
      releases: $\{{ needs.release.outputs.releases }}

  post-release-integration:
    needs: [release, release-integration, post-release]
    {{> jobYml jobName="Post Release Integration - Release" jobIf="needs.release.outputs.releases && always()" jobSkipSetup=true }}
      - name: Get Post Release Conclusion
        id: conclusion
        run: |
          if [[ "$\{{ contains(needs.*.result, 'failure') }}" == "true" ]]; then
            result="x"
          elif [[ "$\{{ contains(needs.*.result, 'cancelled') }}" == "true" ]]; then
            result="heavy_multiplication_x"
          else
            result="white_check_mark"
          fi
          echo "result=$result" >> $GITHUB_OUTPUT
      - name: Find Release PR Comment
        uses: peter-evans/find-comment@v2
        id: found-comment
        with:
          issue-number: $\{{ fromJSON(needs.release.outputs.releases)[0].prNumber }}
          comment-author: 'github-actions[bot]'
          body-includes: '## Release Workflow'
      - name: Create Release PR Comment Text
        id: comment-text
        if: steps.found-comment.outputs.comment-id
        uses: actions/github-script@v7
        env:
          RESULT: $\{{ steps.conclusion.outputs.result }}
          BODY: $\{{ steps.found-comment.outputs.comment-body }}
        with:
          result-encoding: string
          script: |
            const { RESULT, BODY } = process.env
            const body = [BODY.replace(/(Workflow run: :)[a-z_]+(:)/, `$1${RESULT}$2`)]
            if (RESULT !== 'white_check_mark') {
              body.push(':rotating_light::rotating_light::rotating_light:')
              body.push([
                '{{ codeowner }}: The post-release workflow failed for this release.',
                'Manual steps may need to be taken after examining the workflow output.'
              ].join(' '))
              body.push(':rotating_light::rotating_light::rotating_light:')
            }
            return body.join('\n\n').trim()
      - name: Update Release PR Comment
        if: steps.comment-text.outputs.result
        uses: peter-evans/create-or-update-comment@v3
        with:
          comment-id: $\{{ steps.found-comment.outputs.comment-id }}
          body: $\{{ steps.comment-text.outputs.result }}
          edit-mode: 'replace'
            
