name: Draft release

on:
  workflow_dispatch:
    inputs:
      versionBump:
        description: Version bump
        type: choice
        required: true
        default: patch
        options:
          - patch
          - minor
          - major
          - exact-version

      exactVersion:
        description: 'Exact version: (Only effective selecting "exact-version" as version bump)'
        required: false

description: |
  Run manually to prepare a draft release for the next version of the extension. The workflow will create a draft
  github release where the .vsix can be downloaded and manually tested before publishing. To release the version,
  publish the draft release, which will trigger the publish-release workflow.

permissions:
  contents: write

jobs:
  prepare-version:
    name: Prepare Version
    runs-on: ubuntu-latest
    outputs:
      release_tag: ${{ steps.set-version.outputs.release_tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          # NOTE: this is necessary to get the full history
          # and check if tags are already present
          fetch-depth: 0

      - name: Setup Node environment
        uses: ./.github/workflows/actions/setup-node-environment

      - name: Determine Next Version
        id: set-version
        shell: bash
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          VERSION_BUMP: ${{ github.event.inputs.versionBump }}
          EXACT_VERSION: ${{ github.event.inputs.exactVersion }}
        run: |
          set -e

          if [[ "$VERSION_BUMP" == "major" || "$VERSION_BUMP" == "minor" || "$VERSION_BUMP" == "patch" ]]; then
            PREV_VERSION_TAG=$(gh api repos/:owner/:repo/releases --jq '. | map(select(.draft == false)) | .[0] | .tag_name')
            PREV_VERSION=$(pnpm exec semver --coerce ${PREV_VERSION_TAG})

            NEXT_VERSION=$(pnpm exec semver -i "$VERSION_BUMP" "$PREV_VERSION")
          else
            NEXT_VERSION="$EXACT_VERSION"
          fi

          # Remove the 'v' prefix from NEXT_VERSION if it exists
          NEXT_VERSION="${NEXT_VERSION#v}"

          # Validates the version before using it
          pnpm exec semver v"${NEXT_VERSION}"

          pnpm version "${NEXT_VERSION}" --no-git-tag-version
          RELEASE_TAG="v${NEXT_VERSION}"
          echo "release_tag=${RELEASE_TAG}" >> "$GITHUB_OUTPUT"

          if git rev-parse "${RELEASE_TAG}" >/dev/null 2>&1; then
            echo "Error: Tag ${RELEASE_TAG} already existing"
            echo "If you are trying to re-create a draft release with this version, please delete the release and the tag first."
            echo "If this version has already been release consider using a different one."
            exit 1
          fi

      - name: Upload package.json
        uses: actions/upload-artifact@v4
        with:
          name: package-json
          path: package.json

  build-and-check:
    name: Build and Check
    needs: prepare-version
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node environment
        uses: ./.github/workflows/actions/setup-node-environment

      - name: Download package.json
        uses: actions/download-artifact@v4
        with:
          name: package-json

      - name: Set SEGMENT_KEY
        env:
          SEGMENT_KEY: ${{ secrets.SEGMENT_KEY_PROD }}
        run: |
          echo "SEGMENT_KEY=${SEGMENT_KEY}" >> $GITHUB_ENV
        shell: bash

      - name: Validate SEGMENT_KEY
        run: |
          if [ -z "${SEGMENT_KEY}" ]; then
            echo "SEGMENT_KEY is not set or is empty"
            exit 1
          fi
        shell: bash

      - name: Run Checks
        run: pnpm run check
        shell: bash

      - name: Build .vsix
        env:
          NODE_OPTIONS: "--require ./scripts/no-npm-list-fail.js --max_old_space_size=4096"
        run: |
          pnpm exec vsce package --githubBranch main
        shell: bash

      - name: Check .vsix filesize
        run: pnpm run check-vsix-size
        shell: bash

      - name: Upload .vsix for tests
        uses: actions/upload-artifact@v4
        with:
          name: vsix
          path: '*.vsix'

  test:
    name: Run Tests
    needs: build-and-check

    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
      fail-fast: false

    runs-on: ${{ matrix.os }}

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node environment
        uses: ./.github/workflows/actions/setup-node-environment

      - name: Run Tests
        env:
          NODE_OPTIONS: "--max_old_space_size=4096"
          MDB_IS_TEST: "true"
        run: |
          pnpm run test
        shell: bash

  test-install:
    name: Run Install Test
    needs: build-and-check

    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
      fail-fast: false

    runs-on: ${{ matrix.os }}

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node environment
        uses: ./.github/workflows/actions/setup-node-environment

      - name: Download .vsix
        uses: actions/download-artifact@v4
        with:
          name: vsix

      - name: Run VSIX Install Test
        env:
          RUNNER_OS: ${{ runner.os }}
        run: pnpm run test-install
        shell: bash

  test-snyk:
    name: Snyk Test
    needs: build-and-check
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node environment
        uses: ./.github/workflows/actions/setup-node-environment

      - name: Run Snyk Test
        shell: bash
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        run: |
          pnpm run snyk-test

      - name: Upload Snyk Report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: Snyk Report - ${{ github.run_id }}
          path: |
            .sbom/snyk-test-result.html
            .sbom/snyk-test-result.json

      - name: Generate Vulnerability Report (Fail on >= High)
        shell: bash
        run: |
          pnpm run generate-vulnerability-report > /dev/null

  create-draft-release:
    name: Create Draft Release
    needs: [prepare-version, test, test-install]

    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node environment
        uses: ./.github/workflows/actions/setup-node-environment

      - name: Download .vsix
        uses: actions/download-artifact@v4
        with:
          name: vsix

      - name: Sign .vsix
        env:
          ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
          ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
          GARASIGN_PASSWORD: ${{ secrets.GARASIGN_PASSWORD }}
          GARASIGN_USERNAME: ${{ secrets.GARASIGN_USERNAME }}
        run: |
          set -e
          FILE_TO_SIGN=$(find . -maxdepth 1 -name '*.vsix' -print -quit)
          if [ -z "$FILE_TO_SIGN" ]; then
            echo "Error: No .vsix file found in the current directory." >&2
            exit 1
          fi
          node scripts/sign-vsix.js "${FILE_TO_SIGN}"
          ls *.vsix.sig
        shell: bash

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: VSIX
          path: |
            *.vsix
            *.vsix.sig

      - name: Create Draft Release
        env:
          RELEASE_TAG: ${{ needs.prepare-version.outputs.release_tag }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          set -e
          echo Creating draft release for: "${RELEASE_TAG}"
          ls *.vsix
          ls *.vsix.sig

          gh release create "${RELEASE_TAG}" \
            --title "${RELEASE_TAG}" \
            --notes "Edit the release notes before publishing." \
            --target main \
            --draft \
            *.vsix \
            *.vsix.sig
        shell: bash
