name: Plugin Tests
on:
  pull_request:
    branches:
      - master
      - main
    paths:
      - 'packages/plugin-dev/**'
      - 'packages/plugin-api/**'
      - 'packages/vite-plugin/**'
      - '.github/workflows/plugin-tests.yml'
  workflow_dispatch:

permissions:
  contents: read

jobs:
  detect-changes:
    name: Detect plugin changes
    runs-on: ubuntu-latest
    outputs:
      plugins: ${{ steps.detect.outputs.plugins }}
      has-changes: ${{ steps.detect.outputs.has-changes }}
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v6
        with:
          persist-credentials: false
          fetch-depth: 0
      - id: detect
        env:
          BASE_SHA: ${{ github.event.pull_request.base.sha }}
          HEAD_SHA: ${{ github.event.pull_request.head.sha }}
          EVENT_NAME: ${{ github.event_name }}
        run: |
          set -euo pipefail
          # Plugins that have an `npm test` script configured.
          PLUGINS=(automations azure-devops-issue-provider caldav-calendar-provider clickup-issue-provider google-calendar-provider sync-md todoist-import)

          if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
            CHANGED=$(printf '%s\n' "${PLUGINS[@]}")
          else
            # Three-dot: changes on the PR branch only, ignoring commits that
            # landed on master after the PR forked.
            DIFF=$(git diff --name-only "$BASE_SHA...$HEAD_SHA")
            # Shared package change → run every plugin's tests.
            if printf '%s\n' "$DIFF" | grep -qE '^packages/(plugin-api|vite-plugin)/'; then
              CHANGED=$(printf '%s\n' "${PLUGINS[@]}")
            else
              CHANGED=""
              for p in "${PLUGINS[@]}"; do
                if printf '%s\n' "$DIFF" | grep -q "^packages/plugin-dev/$p/"; then
                  CHANGED="${CHANGED}${p}"$'\n'
                fi
              done
            fi
          fi

          JSON=$(printf '%s' "$CHANGED" | awk 'NF' | jq -R . | jq -sc .)
          echo "Plugins to test: $JSON"
          echo "plugins=$JSON" >> "$GITHUB_OUTPUT"
          if [ "$JSON" = "[]" ]; then
            echo 'has-changes=false' >> "$GITHUB_OUTPUT"
          else
            echo 'has-changes=true' >> "$GITHUB_OUTPUT"
          fi

  test:
    name: Test ${{ matrix.plugin }}
    needs: detect-changes
    if: needs.detect-changes.outputs.has-changes == 'true'
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        plugin: ${{ fromJson(needs.detect-changes.outputs.plugins) }}
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v6
        with:
          persist-credentials: false
      - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
        with:
          node-version: 22
      # work around for npm installs from git+https://github.com/johannesjo/J2M.git
      - name: Reconfigure git to use HTTP authentication
        run: >
          git config --global url."https://github.com/".insteadOf
          ssh://git@github.com/
      - name: Get npm cache directory
        id: npm-cache-dir
        run: echo "dir=$(npm config get cache)" >> "$GITHUB_OUTPUT"
      - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
        with:
          path: ${{ steps.npm-cache-dir.outputs.dir }}
          key: ${{ runner.os }}-node22-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node22-
      # Mirror ci.yml: use `npm i` here, not `npm ci`. The root lockfile uses
      # an `overrides.app-builder-lib.minimatch` pin that npm 10 (bundled with
      # Node 22) considers out-of-sync, while npm 11 accepts it. `npm i`
      # tolerates the drift without altering the lockfile on disk.
      - name: Install root dependencies
        run: npm i
      # Plugins consume @super-productivity/plugin-api and vite-plugin via file:
      # references that resolve to dist/. Build those before running plugin tests.
      - name: Build shared packages
        run: npm run build:packages
      - name: Install plugin dependencies
        working-directory: packages/plugin-dev/${{ matrix.plugin }}
        run: npm ci
      - name: Run plugin tests
        working-directory: packages/plugin-dev/${{ matrix.plugin }}
        run: npm test
