name: CI

on:
  push:
    branches: ["main"]
  pull_request:
    branches:
      - main

jobs:
  format-rust:
    name: cargo fmt
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          components: rustfmt
      - uses: actions-rust-lang/rustfmt@v1
  lint-rust:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          components: clippy
      - run: cargo clippy --locked --tests
  test-rust:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          components: llvm-tools-preview
      - name: Install cargo-llvm-cov
        uses: taiki-e/install-action@cargo-llvm-cov
      - name: Install nexttest
        uses: taiki-e/install-action@nextest
      - name: Generate code coverage
        env:
          RUSTFLAGS: -D warnings
        run: |
          cargo llvm-cov --locked --no-report nextest --profile ci
          cargo llvm-cov report --locked --lcov --output-path lcov.txt
      - name: Upload coverage to Codecov
        if: github.event.pull_request.user.login != 'dependabot[bot]'
        uses: Wandalen/wretry.action@v3
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
        with:
          action: codecov/codecov-action@v4
          attempt_limit: 6
          attempt_delay: 10000
          with: |
            files: ./lcov.txt
            flags: unittests
            fail_ci_if_error: ${{ github.event_name == 'pull_request' }}
            verbose: true
      - name: Generate code coverage (wasm)
        env:
          RUSTFLAGS: -D warnings
        run: |
          cargo llvm-cov --locked --no-report nextest --profile ci --no-default-features --features wasm
          cargo llvm-cov report --locked --lcov --output-path lcov-wasm.txt
      - name: Upload coverage to Codecov
        if: github.event.pull_request.user.login != 'dependabot[bot]'
        uses: Wandalen/wretry.action@v3
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
        with:
          action: codecov/codecov-action@v4
          attempt_limit: 6
          attempt_delay: 10000
          with: |
            files: ./lcov-wasm.txt
            flags: wasm
            fail_ci_if_error: ${{ github.event_name == 'pull_request' }}
            verbose: true
  test-typescript:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
      - run: npm ci
        working-directory: packages/mpl-codemirror
      - run: npm test
        working-directory: packages/mpl-codemirror
  build-wasm:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          target: wasm32-unknown-unknown
      - run: cargo install --locked wasm-pack
      - uses: actions/setup-node@v6
      - name: Build wasm
        # --no-opt: wasm-pack's bundled wasm-opt crashes, and even system wasm-opt
        # increases gzipped size (our wasm-release profile already optimizes well).
        run: wasm-pack build --scope axiomhq --target web --profile wasm-release --no-opt --no-default-features --features wasm
      - run: npm install typescript
        working-directory: pkg
      - name: Check TypeScript types
        run: npx tsc --noEmit -t esnext mpl_lang.d.ts
        working-directory: pkg
      - name: Test wasm build against sample queries
        run: node tests/wasm/test-wasm.mjs
  build-playground:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          target: wasm32-unknown-unknown
      - run: cargo install --locked wasm-pack
      - uses: actions/setup-node@v6
      - name: Build wasm (playground)
        # --no-opt: wasm-pack's bundled wasm-opt crashes, and even system wasm-opt
        # increases gzipped size (our wasm-release profile already optimizes well).
        run: wasm-pack build extra/mpl-playground --scope axiomhq --target web --profile wasm-release --no-opt
      - run: npm install typescript
        working-directory: extra/mpl-playground/pkg
      - name: Check TypeScript types (playground)
        run: npx tsc --noEmit -t esnext mpl_playground.d.ts
        working-directory: extra/mpl-playground/pkg
      - name: Test playground build against sample queries
        run: node tests/wasm/test-playground.mjs
  # Mirrors the publish-npm build steps in .github/workflows/release.yaml up to
  # (but not including) `npm publish`. Catches drift between the codemirror
  # source's import names and the published `@axiomhq/mpl` package name on PRs,
  # so a name mismatch fails review instead of failing release after the tag is
  # already pushed (see PR #44 / v0.4.0).
  release-build-codemirror:
    name: release dry-run (mpl-codemirror build)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          target: wasm32-unknown-unknown
      - run: cargo install --locked wasm-pack
      - uses: actions/setup-node@v6
        with:
          node-version: "24"
      - name: Build WASM (release flags)
        run: wasm-pack build --out-name mpl --out-dir packages/mpl --scope axiomhq --target web --profile wasm-release --no-opt --features wasm
      - name: Apply release rename to packages/mpl/package.json
        # Must stay byte-identical to the equivalent step in release.yaml.
        run: |
          set -euo pipefail
          jq '
            .name = "@axiomhq/mpl"
            | .files = ["mpl.js", "mpl.d.ts", "mpl_bg.wasm", "mpl_bg.wasm.d.ts", "LICENSE-MIT", "LICENSE-APACHE"]
            | .repository.url = "git+https://github.com/axiomhq/mpl.git"
          ' packages/mpl/package.json > packages/mpl/package.json.tmp
          mv packages/mpl/package.json.tmp packages/mpl/package.json
      - name: Type-check WASM bindings
        working-directory: packages/mpl
        run: |
          npm install --no-save typescript
          npx tsc --noEmit -t esnext mpl.d.ts
      - name: Build mpl-codemirror (the step that fails on name drift)
        working-directory: packages/mpl-codemirror
        run: npm install && npm run build
