name: Publish packages to NPM

permissions:
  id-token: write
  contents: write
  pull-requests: write

on:
  workflow_dispatch:
    inputs:
      release_type:
        description: 'Release type: "minor" increments the minor version (e.g., 1.53.0 → 1.54.0), "patch" increments the patch version (e.g., 1.54.0 → 1.54.1), "next" publishes a pre-release version (e.g., 1.55.0-next.17).'
        required: true
        type: choice
        options:
          - 'minor'
          - 'patch'
          - 'next'
        default: 'next'
      is_patch_to_previous:
        description: 'Patch a previous release branch: Enable this to publish a patch to an older version branch (e.g., patching 1.53.x when 1.54.x is the latest). Must be used with release_type="patch". Leave disabled for publishing to the current latest or next version.'
        required: true
        type: boolean
        default: false
  schedule:
    - cron: "0 0 * * 1" # Publish next version (default) every monday at midnight

jobs:
  publish:
    name: Perform Publishing
    runs-on: ubuntu-22.04
    timeout-minutes: 60
    env:
      RELEASE_TYPE: ${{ inputs.release_type || 'next' }}
      IS_PATCH_TO_PREVIOUS: ${{ inputs.is_patch_to_previous || false }}
    steps:
      - name: Validate Inputs
        shell: bash
        run: |
          if [[ "${{ env.IS_PATCH_TO_PREVIOUS }}" == "true" && "${{ env.RELEASE_TYPE }}" != "patch" ]]; then
            echo "Error: When 'is_patch_to_previous' is enabled, release_type must be 'patch'"
            exit 1
          fi
          echo "Input validation passed"
          echo "Release type: ${{ env.RELEASE_TYPE }}"
          echo "Is patch to previous: ${{ env.IS_PATCH_TO_PREVIOUS }}"

      - name: Checkout
        uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
        with:
          # To fetch all history for all branches and tags.
          # Required for lerna to determine the version of the next package.
          fetch-depth: 0

      - name: Use Node.js 22.x
        uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # v3.8.2
        with:
          node-version: 22.x
          registry-url: "https://registry.npmjs.org"

      - name: Use Python 3.13
        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
        with:
          python-version: "3.13"

      - name: Install and build
        shell: bash
        run: |
          npm ci
          npm run build
        env:
          NODE_OPTIONS: --max_old_space_size=4096
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9

      - name: Publish to NPM (Latest)
        # We only publish minor or patch releases for the current version as latest, never for older patches or next versions.
        if: ${{ (env.RELEASE_TYPE == 'patch' || env.RELEASE_TYPE == 'minor') && env.IS_PATCH_TO_PREVIOUS == 'false' }}
        shell: bash
        run: |
          npm run publish:latest ${{ env.RELEASE_TYPE }}
          npm run publish:check
        env:
          NPM_CONFIG_PROVENANCE: "true"

      - name: Publish to NPM (Patch - To Previous Version)
        if: ${{ env.RELEASE_TYPE == 'patch' && env.IS_PATCH_TO_PREVIOUS == 'true' }}
        shell: bash
        run: |
          npm run publish:patch ${{ env.RELEASE_TYPE }}
          npm run publish:check
        env:
          NPM_CONFIG_PROVENANCE: "true"
      
      - name: Publish to NPM (Next)
        if: ${{ env.RELEASE_TYPE == 'next' }}
        shell: bash
        run: |
          npm run publish:next
        env:
          NPM_CONFIG_PROVENANCE: "true"

      - name: Submit PR for package updates
        if: ${{ env.RELEASE_TYPE != 'next' }}
        shell: bash
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # Configure git
          git config --local user.email "eclipse-theia-bot@eclipse.org"
          git config --local user.name "eclipse-theia-bot"

          # Get the version from lerna.json after publishing
          VERSION=$(node -p "require('./lerna.json').version")
          echo "Lerna Version: $VERSION"

          # First commit: Update packages/core/README.md
          if git diff --name-only | grep -q "packages/core/README.md"; then
            git add packages/core/README.md
            git commit -m "core: update re-exports for v${VERSION}"
            echo "First commit created for packages/core/README.md"
          else
            echo "No changes to packages/core/README.md"
          fi

          # Second commit: Add all other changes
          git add .
          if git diff --staged --quiet; then
            echo "No other changes to commit"
          else
            git commit -m "v${VERSION}"
            echo "Second commit created for remaining changes"
          fi

          # Submit PR
          if git log origin/${{ github.ref_name }}..HEAD | grep -q "commit"; then
            # Define PR body
            PR_BODY="Automated package updates for release v${VERSION}
            
            To complete the release:
            - Update all remaining package versions locally
            - Amend the commits with your author details (to ensure the ECA check passes)
            - Keep the commits split (the re-export commit on the readme needs to be separate)
            - Force push the branch
            - Verify that all checks pass, and then \`rebase and merge\`"
            
            # Create a new branch for the PR
            BRANCH_NAME="${{ github.ref_name }}-package-updates"
            git checkout -b "$BRANCH_NAME"
            git push origin "$BRANCH_NAME"

            # Create PR using GitHub CLI
            gh pr create \
              --title "Release v${VERSION} - Package updates" \
              --body "$PR_BODY" \
              --base "${{ github.ref_name }}" \
              --head "$BRANCH_NAME"

            echo "PR created for branch $BRANCH_NAME"
          else
            echo "No commits to push"
          fi
