name: build-release

on:
  workflow_dispatch:
  push:
    branches:
      - main

jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: write
    outputs:
      new_version: ${{ steps.version.outputs.version }}
      released: ${{ steps.version.outputs.released }}
    steps:
      - name: Repo checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Resolve version from package.json
        id: version
        run: |
          VERSION=$(jq -r .version package.json)
          echo "version=$VERSION" >> "$GITHUB_OUTPUT"
          if git rev-parse "v$VERSION" >/dev/null 2>&1; then
            echo "released=false" >> "$GITHUB_OUTPUT"
            echo "Tag v$VERSION already exists — skipping release."
          else
            echo "released=true" >> "$GITHUB_OUTPUT"
          fi

      # The generator writes a CHANGELOG.md section per version. Lift this
      # version's section out so the release body says what changed instead of
      # only linking a compare view. Missing or empty sections are not fatal:
      # the release still gets the auto-generated notes below.
      - name: Extract release notes for this version
        if: steps.version.outputs.released == 'true'
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          if [ -f CHANGELOG.md ]; then
            awk -v want="## v$VERSION " '
              index($0, want) == 1 { found = 1; next }
              found && /^## v/     { exit }
              found                { print }
            ' CHANGELOG.md > RELEASE_NOTES.md
          fi
          if [ ! -s RELEASE_NOTES.md ]; then
            echo "No CHANGELOG.md section for v$VERSION."
            : > RELEASE_NOTES.md
          fi
          cat RELEASE_NOTES.md

      - name: Create release
        if: steps.version.outputs.released == 'true'
        uses: ncipollo/release-action@v1
        with:
          tag: v${{ steps.version.outputs.version }}
          bodyFile: RELEASE_NOTES.md
          generateReleaseNotes: true

  publish-npmjs:
    runs-on: ubuntu-latest
    needs: [release]
    if: needs.release.outputs.released == 'true'
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '24.x'
          registry-url: 'https://registry.npmjs.org'

      - name: Update NPM
        run: npm install -g npm@latest

      - name: Install dependencies
        run: npm install

      - name: Publish package
        run: npm publish --provenance --access public

      # The package was published unscoped before moving to @hostinger. Republish
      # each release under the old name so existing installs keep updating.
      # Both names point their npm trusted publisher at this workflow file, which
      # is what the config keys on — the job/step it runs in is not part of it.
      # The name below is substituted by the generator, and is left empty for an
      # API that never had an unscoped package.
      - name: Publish legacy unscoped alias
        run: |
          LEGACY='hostinger-api-mcp'
          if [ -z "$LEGACY" ]; then
            echo "No legacy npm name configured — nothing to alias."
            exit 0
          fi
          jq --arg n "$LEGACY" '.name = $n' package.json > pkg.tmp && mv pkg.tmp package.json
          npm publish --provenance --access public

  release-github:
    runs-on: ubuntu-latest
    needs: [release]
    if: needs.release.outputs.released == 'true'
    permissions:
      contents: read
      id-token: write
      packages: write
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '24.x'
          registry-url: 'https://npm.pkg.github.com'
          scope: '@hostinger'

      - name: Install dependencies
        run: npm install

      - name: Publish package
        run: |
          sed -i 's+"name": ".*+"name": "@${{ github.repository }}",+gI' ./package.json
          npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  publish-mcp:
    runs-on: ubuntu-latest
    needs: [ release, publish-npmjs ]
    if: needs.release.outputs.released == 'true'
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Checkout repo
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '24.x'

      - name: Install MCP Publisher
        run: |
          curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
          chmod +x ./mcp-publisher

      - name: Login to MCP Registry using GitHub OIDC
        run: ./mcp-publisher login github-oidc

      # The registry validates that the npm version in server.json actually
      # exists, and npm says a fresh publish "may take a few minutes to become
      # available" — so this job reliably loses the race with the publish-npmjs
      # job it depends on and 400s with "version was not found (status: 404)".
      # Retry until npm catches up. The backoff totals ~7.5 minutes, well past
      # the propagation delays seen in practice (~3 minutes); if it is still
      # failing by then it is not a propagation problem and notify-failure
      # should page.
      - name: Publish to MCP Registry
        run: |
          for delay in 30 60 120 240 0; do
            if ./mcp-publisher publish; then
              exit 0
            fi
            if [ "$delay" -eq 0 ]; then
              break
            fi
            echo "Publish failed — npm may not have propagated yet. Retrying in ${delay}s."
            sleep "$delay"
          done
          echo "MCP registry publish still failing after all retries."
          exit 1

  notify-failure:
    needs: [release, publish-npmjs, release-github, publish-mcp]
    if: failure()
    runs-on: ubuntu-latest
    steps:
      - name: Notify Slack on release failure
        uses: slackapi/slack-github-action@v4.0.0
        with:
          errors: true
          webhook: ${{ secrets.PLATFORM_INCIDENT_SLACK_CHANNEL_WEBHOOK }}
          webhook-type: incoming-webhook
          payload: |
            text: ":rotating_light: Release failed in ${{ github.repository }}"
            blocks:
              - type: section
                text:
                  type: mrkdwn
                  text: |
                    :rotating_light: *Release failed:* `${{ github.repository }}`
                    *Commit:* <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}>
              - type: actions
                elements:
                  - type: button
                    text:
                      type: plain_text
                      text: "View failed run"
                    url: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
