name: OpenWork Tests

on:
  pull_request:
    branches:
      - dev
  push:
    branches:
      - dev

permissions:
  contents: read

jobs:
  openwork-tests:
    runs-on: ${{ matrix.os }}

    strategy:
      fail-fast: false
      matrix:
        os: [blacksmith-4vcpu-ubuntu-2204, macos-14]

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Setup Node
        uses: actions/setup-node@v6
        with:
          node-version: 24

      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 11.4.0

      - name: Install OpenCode CLI
        shell: bash
        env:
          GITHUB_TOKEN: ${{ github.token }}
          OPENCODE_GITHUB_REPO: ${{ vars.OPENCODE_GITHUB_REPO || 'anomalyco/opencode' }}
        run: |
          set -euo pipefail

          repo="${OPENCODE_GITHUB_REPO:-anomalyco/opencode}"
          version="$(node -e "const fs=require('fs'); const parsed=JSON.parse(fs.readFileSync('constants.json','utf8')); process.stdout.write(String(parsed.opencodeVersion||'').trim().replace(/^v/,''));")"
          version="$(echo "$version" | tr -d '\r\n' | sed 's/^v//')"

          if [ -z "$version" ]; then
            echo "Unable to resolve OpenCode version from constants.json." >&2
            exit 1
          fi

          arch="$(uname -m)"
          case "${RUNNER_OS}" in
            Linux)
              if [ "$arch" = "aarch64" ] || [ "$arch" = "arm64" ]; then
                opencode_asset="opencode-linux-arm64.tar.gz"
              else
                opencode_asset="opencode-linux-x64-baseline.tar.gz"
              fi
              ;;
            macOS)
              if [ "$arch" = "arm64" ]; then
                opencode_asset="opencode-darwin-arm64.zip"
              else
                opencode_asset="opencode-darwin-x64-baseline.zip"
              fi
              ;;
            *)
              echo "Unsupported OS: ${RUNNER_OS}" >&2
              exit 1
              ;;
          esac

          url="https://github.com/${repo}/releases/download/v${version}/${opencode_asset}"
          tmp_dir="$RUNNER_TEMP/opencode"
          extract_dir="$tmp_dir/extracted"
          rm -rf "$tmp_dir"
          mkdir -p "$extract_dir"

          curl_headers=()
          if [ -n "${GITHUB_TOKEN:-}" ]; then
            curl_headers+=( -H "Authorization: Bearer ${GITHUB_TOKEN}" )
          fi

          curl -fsSL --retry 5 --retry-all-errors --retry-delay 2 "${curl_headers[@]}" -o "$tmp_dir/$opencode_asset" "$url"

          if [[ "$opencode_asset" == *.tar.gz ]]; then
            tar -xzf "$tmp_dir/$opencode_asset" -C "$extract_dir"
          else
            unzip -q "$tmp_dir/$opencode_asset" -d "$extract_dir"
          fi

          if [ -f "$extract_dir/opencode" ]; then
            bin_path="$extract_dir/opencode"
          elif [ -f "$extract_dir/opencode.exe" ]; then
            bin_path="$extract_dir/opencode.exe"
          else
            echo "OpenCode binary not found in archive" >&2
            ls -la "$extract_dir"
            exit 1
          fi

          install_dir="$HOME/.opencode/bin"
          mkdir -p "$install_dir"
          cp "$bin_path" "$install_dir/opencode"
          chmod 755 "$install_dir/opencode"
          echo "$install_dir" >> "$GITHUB_PATH"

      - name: Verify OpenCode
        run: opencode --version

      - name: Setup Bun
        uses: oven-sh/setup-bun@v2

      - name: Get pnpm store path
        id: pnpm-store
        shell: bash
        run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"

      - name: Cache pnpm store
        uses: actions/cache@v5
        continue-on-error: true
        with:
          path: ${{ steps.pnpm-store.outputs.path }}
          key: ${{ runner.os }}-pnpm-${{ hashFiles('pnpm-lock.yaml', 'evals/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pnpm-

      - name: Install dependencies
        run: pnpm install --frozen-lockfile --prefer-offline

      - name: Install eval workspace
        run: pnpm --dir evals install --frozen-lockfile --prefer-offline

      - name: Run eval spec lane
        run: pnpm --dir evals run spec

      - name: Run app unit tests
        run: pnpm --filter @openwork/app test

      - name: Run server unit tests
        run: pnpm --filter openwork-server test

      - name: Run desktop unit tests
        run: pnpm --filter @openwork/desktop test

      - name: Run eval runner unit tests
        run: pnpm test:eval-runner

      - name: Check outbound access manifest
        run: pnpm check:outbound-access

      - name: Typecheck Electron main against the IPC contract
        run: pnpm --filter @openwork/desktop typecheck:electron

      - name: Run e2e tests
        run: pnpm --filter @openwork/app test:e2e
