name: Release

# This workflow handles latest, beta, and alpha releases:
# - Latest: Triggered by GitHub releases (tag vX.Y.Z)
# - Beta: Triggered by pushes to beta-X.Y.Z branches
# - Alpha: Triggered by pushes to alpha-X.Y.Z branches

on:
  release:
    types: [released]
  push:
    branches:
      - beta-*.*.*
      - alpha-*.*.*
  workflow_dispatch:

permissions:
  id-token: write
  contents: write

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  determine-release-type:
    name: Determine Release Type
    runs-on: ubuntu-latest
    if: ${{ github.repository == 'homebridge/hap-client' }}
    outputs:
      release_type: ${{ steps.release-type.outputs.type }}
      npm_tag: ${{ steps.release-type.outputs.tag }}
      version: ${{ steps.get_version.outputs.version }}
    steps:
      - name: Determine release type
        id: release-type
        run: |
          if [[ "${{ github.event_name }}" == "release" ]]; then
            echo "type=latest" >> $GITHUB_OUTPUT
            echo "tag=latest" >> $GITHUB_OUTPUT
          elif [[ "${{ github.ref }}" == refs/heads/beta-* ]]; then
            echo "type=beta" >> $GITHUB_OUTPUT
            echo "tag=beta" >> $GITHUB_OUTPUT
          elif [[ "${{ github.ref }}" == refs/heads/alpha-* ]]; then
            echo "type=alpha" >> $GITHUB_OUTPUT
            echo "tag=alpha" >> $GITHUB_OUTPUT
          else
            echo "type=none" >> $GITHUB_OUTPUT
            echo "tag=none" >> $GITHUB_OUTPUT
            echo "No valid release type detected - skipping publish"
          fi

      - name: Get Release Tag (Latest Only)
        if: steps.release-type.outputs.type == 'latest'
        id: get_version
        uses: jannemattila/get-version-from-tag@v3

      - name: Tag Info (Latest Only)
        if: steps.release-type.outputs.type == 'latest'
        run: |
          echo "Release Tag: ${{github.ref}}"
          echo "Latest Tag: ${{ steps.get_version.outputs.version }}"

      - name: Tag Info Matches (Latest Only)
        if: steps.release-type.outputs.type == 'latest' && endsWith(github.ref, steps.get_version.outputs.version)
        run: |
          echo Latest Tag matches Release tag

      - name: Tag Info Doesn't Match (Latest Only)
        if: steps.release-type.outputs.type == 'latest' && !endsWith(github.ref, steps.get_version.outputs.version)
        run: |
          echo Latest Tag does not matches Release tag
          exit 1

  build_and_test_latest:
    needs: determine-release-type
    name: Build and Test ${{ needs.determine-release-type.outputs.version }}
    if: needs.determine-release-type.outputs.release_type == 'latest'
    uses: homebridge/.github/.github/workflows/nodejs-build-and-test.yml@latest
    with:
      enable_coverage: true
      install_cmd: npm ci
    secrets:
      token: ${{ secrets.GITHUB_TOKEN }}

  build_and_test_beta:
    needs: determine-release-type
    name: Build and Test (Beta)
    if: needs.determine-release-type.outputs.release_type == 'beta'
    uses: homebridge/.github/.github/workflows/nodejs-build-and-test.yml@latest
    with:
      enable_coverage: false
      install_cmd: npm ci
    secrets:
      token: ${{ secrets.GITHUB_TOKEN }}

  publish:
    needs: [determine-release-type, build_and_test_latest, build_and_test_beta]
    if: |
      always() &&
      needs.determine-release-type.outputs.release_type != 'none' &&
      (needs.determine-release-type.outputs.release_type == 'alpha' ||
       needs.build_and_test_latest.result == 'success' ||
       needs.build_and_test_latest.result == 'skipped') &&
      (needs.build_and_test_beta.result == 'success' ||
       needs.build_and_test_beta.result == 'skipped')
    name: Publish to npm (${{ needs.determine-release-type.outputs.npm_tag }})
    runs-on: ubuntu-latest
    outputs:
      npm_version: ${{ steps.get-published-version.outputs.version }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24
          registry-url: 'https://registry.npmjs.org'

      - name: Upgrade npm for OIDC support
        run: npm install -g npm@latest

      - name: Install dependencies
        run: npm ci

      - name: Handle prerelease versioning
        if: needs.determine-release-type.outputs.release_type == 'beta' || needs.determine-release-type.outputs.release_type == 'alpha'
        run: |
          # Download versioning script from homebridge/.github
          mkdir -p .github
          wget -q https://raw.githubusercontent.com/homebridge/.github/latest/.github/npm-version-script-esm.js -O .github/npm-version-script-esm.js

          # Run the script to set base version
          node .github/npm-version-script-esm.js ${{ github.ref }} ${{ needs.determine-release-type.outputs.release_type }}

          # Add prerelease suffix
          npm version pre --preid=${{ needs.determine-release-type.outputs.release_type }} --no-git-tag-version

      - name: Build
        run: npm run build

      - name: Publish to npm with OIDC
        run: npm publish --tag ${{ needs.determine-release-type.outputs.npm_tag }} --provenance --access public

      - name: Get published version
        id: get-published-version
        run: |
          VERSION=$(node -p "require('./package.json').version")
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "Published version: $VERSION"

  pre-release:
    needs: [determine-release-type, publish]
    name: Create GitHub Pre-Release
    if: |
      always() &&
      needs.publish.result == 'success' &&
      github.repository == 'homebridge/hap-client' &&
      (needs.determine-release-type.outputs.release_type == 'beta' || needs.determine-release-type.outputs.release_type == 'alpha')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Create nightly release
        id: create_release
        uses: viperproject/create-nightly-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: v${{ needs.publish.outputs.npm_version }}
          release_name: v${{ needs.publish.outputs.npm_version }}
          body: |
            v${{ needs.publish.outputs.npm_version }}
          keep_num: 5
          keep_tags: false
