name: Publish to npm

on:
  workflow_dispatch:
    inputs:
      dry_run:
        description: >
          Dry run — print the version and npm dist-tag that would be used; no commit or publish.
          Pick the branch to publish from with the "Use workflow from" dropdown.
          Non-default branches publish to the npm dist-tag `beta` (not `latest`).
        required: false
        default: false
        type: boolean
      skip_versioning:
        description: >
          Skip version bump — use the version already in the repo
          (e.g. retry after npm publish failed but the release commit is already pushed).
        required: false
        default: false
        type: boolean
      version_override:
        description: >
          Optional. Full semver to publish (e.g. 12.6.0-beta.2). Skips conventional bump when set.
          Leave empty for automatic versioning.
        required: false
        default: ''
        type: string

permissions:
  contents: write
  id-token: write

jobs:
  ci:
    uses: ./.github/workflows/build.yml

  version:
    needs: ci
    runs-on: ubuntu-latest
    timeout-minutes: 30
    outputs:
      version: ${{ steps.version.outputs.version }}
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          ref: ${{ github.ref }}
          fetch-depth: 0

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

      - name: Install dependencies
        if: ${{ !inputs.skip_versioning }}
        run: npm ci

      - name: Determine version bump
        id: bump
        if: ${{ !inputs.skip_versioning && inputs.version_override == '' }}
        working-directory: packages/blockly
        run: |
          RELEASE_TYPE=$(npx conventional-recommended-bump --preset conventionalcommits -t blockly-)
          echo "release_type=$RELEASE_TYPE" >> "$GITHUB_OUTPUT"
          echo "Recommended bump: $RELEASE_TYPE"

      - name: Apply version bump
        if: ${{ !inputs.skip_versioning }}
        working-directory: packages/blockly
        env:
          DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
          REF_NAME: ${{ github.ref_name }}
          RELEASE_TYPE: ${{ steps.bump.outputs.release_type }}
          VERSION_OVERRIDE: ${{ inputs.version_override }}
        run: |
          set -euo pipefail
          if [ -n "${VERSION_OVERRIDE}" ]; then
            npm version "${VERSION_OVERRIDE}" --no-git-tag-version
            exit 0
          fi
          if [ "${REF_NAME}" = "${DEFAULT_BRANCH}" ]; then
            npm version "${RELEASE_TYPE}" --no-git-tag-version
            exit 0
          fi
          VERSION=$(node -p "require('./package.json').version")
          if [[ "${VERSION}" == *"-beta."* ]]; then
            npm version prerelease --preid=beta --no-git-tag-version
          else
            case "${RELEASE_TYPE}" in
              major) npm version premajor --preid=beta --no-git-tag-version ;;
              minor) npm version preminor --preid=beta --no-git-tag-version ;;
              patch) npm version prepatch --preid=beta --no-git-tag-version ;;
              *)
                echo "::error title=Invalid release bump::conventional-recommended-bump returned '${RELEASE_TYPE}' (expected major, minor, or patch). Fix commits/tags or set version_override." >&2
                exit 1
                ;;
            esac
          fi

      - name: Read package version
        id: version
        working-directory: packages/blockly
        run: |
          VERSION=$(node -p "require('./package.json').version")
          echo "version=$VERSION" >> "$GITHUB_OUTPUT"
          echo "Version: $VERSION"

      - name: Dry run summary
        if: ${{ inputs.dry_run }}
        run: |
          DIST_TAG="${{ github.ref_name == github.event.repository.default_branch && 'latest' || 'beta' }}"
          echo "Dry run: would publish version ${{ steps.version.outputs.version }} to npm dist-tag: ${DIST_TAG}"
          if [ "${{ github.ref_name }}" != "${{ github.event.repository.default_branch }}" ]; then
            echo "GitHub release would be created as prerelease."
          fi

      - name: Upload versioned files
        if: ${{ !inputs.skip_versioning }}
        uses: actions/upload-artifact@v4
        with:
          name: versioned-files
          path: |
            packages/blockly/package.json
            package-lock.json

  publish:
    needs: version
    runs-on: ubuntu-latest
    if: ${{ !inputs.dry_run }}
    environment: release
    env:
      NPM_DIST_TAG: ${{ github.ref_name == github.event.repository.default_branch && 'latest' || 'beta' }}
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          ref: ${{ github.ref }}
          fetch-depth: 0
          ssh-key: ${{ secrets.DEPLOY_PRIVATE_KEY }}

      - name: Download versioned files
        if: ${{ !inputs.skip_versioning }}
        uses: actions/download-artifact@v4
        with:
          name: versioned-files

      - name: Commit and push version bump
        if: ${{ !inputs.skip_versioning }}
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
          git add packages/blockly/package.json package-lock.json
          git commit -m "release: v${{ needs.version.outputs.version }}"
          git push

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

      - name: Install dependencies
        run: npm ci

      - name: Build package
        working-directory: packages/blockly
        run: npm run package

      - name: Publish to npm
        working-directory: packages/blockly/dist
        run: npm publish --tag "${NPM_DIST_TAG}" --verbose

      - name: Create tarball
        working-directory: packages/blockly
        run: npm pack ./dist

      - name: Create GitHub release
        working-directory: packages/blockly
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          TARBALL="blockly-${{ needs.version.outputs.version }}.tgz"
          if [ "${{ github.ref_name }}" != "${{ github.event.repository.default_branch }}" ]; then
            gh release create "blockly-v${{ needs.version.outputs.version }}" "$TARBALL" \
              --repo "$GITHUB_REPOSITORY" \
              --title "blockly-v${{ needs.version.outputs.version }}" \
              --generate-notes \
              --prerelease
          else
            gh release create "blockly-v${{ needs.version.outputs.version }}" "$TARBALL" \
              --repo "$GITHUB_REPOSITORY" \
              --title "blockly-v${{ needs.version.outputs.version }}" \
              --generate-notes
          fi
