name: Release on Crates and NPM

on:
  workflow_dispatch:
    inputs:
      ezno-version:
        description: "major/minor/patch or semver for Ezno (CLI)"
        required: false
        default: "none"
      ezno-checker-version:
        description: "major/minor/patch or semver for the type checker"
        required: false
        default: "none"
      ezno-parser-version:
        description: "major/minor/patch or semver for the parser"
        required: false
        default: "none"
      other-versions:
        description: "comma seperated 'name=version_argument' pairs"
        required: false
        default: "none"

concurrency: release-crate

env:
  CACHE_PATHS: |
    ~/.cargo/bin/
    ~/.cargo/registry/index/
    ~/.cargo/registry/cache/
    ~/.cargo/git/db/
    target/

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: ${{ env.CACHE_PATHS }}
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Set git credentials
        run: |
          git config user.name github-actions
          git config user.email github-actions@github.com

      - id: set-arguments
        run: |
          KEY_PAIR_ARGS="ezno=${{ inputs.ezno-version }},ezno-parser=${{ inputs.ezno-parser-version }},ezno-checker=${{ inputs.ezno-checker-version }},${{ inputs.other-versions }}"

          echo "::debug::$KEY_PAIR_ARGS"

          KEY_PAIR_ARGS_JSON=$(echo $KEY_PAIR_ARGS | jq --raw-input --compact-output 'split(",") | map(select(length > 0 and . != "none")) | map_values(split("=") | { (.[0]): .[1] }) | reduce .[] as $o ({}; . + $o)')

          echo "::debug::$KEY_PAIR_ARGS_JSON"

          echo "publish-json-args=$KEY_PAIR_ARGS_JSON" >> $GITHUB_OUTPUT
        shell: bash

      - id: get-sponsors
        run: |
          SPONSORS=$(
              gh api graphql -f query='{
                  user(login: "kaleidawave") {
                      sponsorshipsAsMaintainer(first: 100, activeOnly: false) {
                      edges {
                          node {
                          sponsor {
                              name, login
                          }
                          }
                      }
                      }
                  }
              }' -q '.data.user.sponsorshipsAsMaintainer.edges | map(.node.sponsor.name // .node.sponsor.login) | join(",")'
          )

          CONTRIBUTORS=$(
              gh pr list --state merged --json author | jq 'map(.author.name // .author.login) | unique | join(",")' --raw-output
          )

          echo "SPONSORS=$SPONSORS" >> $GITHUB_OUTPUT
          echo "CONTRIBUTORS=$CONTRIBUTORS" >> $GITHUB_OUTPUT

        shell: bash
        env:
          GH_TOKEN: ${{ github.token }}

      - name: Crates publish
        uses: kaleidawave/crates-release-gh-action@main
        id: release
        with:
          version: ${{ steps.set-arguments.outputs.publish-json-args }}
          crates-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        env:
          SPONSORS: ${{ steps.get-sponsors.outputs.SPONSORS }}
          CONTRIBUTORS: ${{ steps.get-sponsors.outputs.CONTRIBUTORS }}

      - name: Add WASM to rustup
        if: ${{ inputs.ezno-version != 'none' }}
        run: rustup target add wasm32-unknown-unknown

      - uses: brndnmtthws/rust-action-cargo-binstall@v1
        if: ${{ inputs.ezno-version != 'none' }}
        with:
          packages: wasm-pack@0.13.0

      - name: Set NPM package version & build
        id: set-npm-version
        if: ${{ inputs.ezno-version != 'none' }}
        run: |
          VERSION=$(echo '${{ steps.release.outputs.new-versions-json-object }}' | jq -r '.ezno')
          echo "new-ezno-version=${VERSION}" >> $GITHUB_OUTPUT
          npm ci
          npm version $VERSION
          npm run build-release

          # TODO temp check
          ls dist
        working-directory: src/js-cli-and-library
        env:
          SPONSORS: ${{ steps.get-sponsors.outputs.sponsors }}

      - name: NPM publish (CLI and library)
        if: ${{ inputs.ezno-version != 'none' }}
        uses: rxfork/npm-publish@v1
        with:
          token: ${{ secrets.NPM_REGISTRY_TOKEN }}
          package: src/js-cli-and-library/package.json
          
      - name: Update JS plugin version and dependencies
        if: ${{ inputs.ezno-version != 'none' }}
        run: |
          # Hopefully propagated in 20 seconds
          sleep 20
          npm ci
          npm install ezno@${{ steps.set-npm-version.outputs.new-ezno-version }}
          npm version ${{ steps.set-npm-version.outputs.new-ezno-version }}
        working-directory: src/js-based-plugin
        
      - name: NPM publish (plugin)
        uses: rxfork/npm-publish@v1
        with:
          token: ${{ secrets.NPM_REGISTRY_TOKEN }}
          package: src/js-based-plugin/package.json

      - name: Push updated manifests (Cargo.toml and package.json)
        run: |
          git add .
          git commit -m "Release: ${{ steps.release.outputs.new-versions-description }}"

          git config user.name "github-actions[bot]"
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
          
          # Create tags
          echo '${{ steps.release.outputs.new-versions }}' | jq -r '.[]' | while read -r update; do
            git tag "release/$update"
          done

          git push --tags origin main

      - name: Discord
        uses: dusmartijngames/discord-webhook-notify@master
        with:
          severity: info
          text: "Released version ${{ steps.release.outputs.new-versions-description }}"
          webhookUrl: ${{ secrets.DISCORD_WEBHOOK_ENDPOINT }}
