name: CI
on: workflow_call
permissions: {}
jobs:
  lint:
    name: Lint source files
    runs-on: ubuntu-latest
    permissions:
      contents: read # for actions/checkout
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          cache: npm
          node-version-file: '.node-version'

      - name: Install Dependencies
        run: npm ci --ignore-scripts

      - name: Lint ESLint
        run: npm run lint

      - name: Check Types
        run: npm run check:ts

      - name: Lint Prettier
        run: npm run prettier:check

      - name: Spellcheck
        run: npm run check:spelling

      - name: Lint GitHub Actions
        uses: docker://rhysd/actionlint:latest
        with:
          args: -color

  checkForCommonlyIgnoredFiles:
    name: Check for commonly ignored files
    runs-on: ubuntu-latest
    permissions:
      contents: read # for actions/checkout
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Check if commit contains files that should be ignored
        run: |
          git clone --depth 1 https://github.com/github/gitignore.git

          rm -f gitignore/Global/ModelSim.gitignore
          rm -f gitignore/Global/Images.gitignore
          cat gitignore/Node.gitignore gitignore/Global/*.gitignore > all.gitignore

          IGNORED_FILES=$(git ls-files --cached --ignored --exclude-from=all.gitignore)
          if  [[ "$IGNORED_FILES" != "" ]]; then
            echo -e "::error::Please remove these files:\n$IGNORED_FILES" | sed -z 's/\n/%0A/g'
            exit 1
          fi

  checkPackageLock:
    name: Check health of package-lock.json file
    runs-on: ubuntu-latest
    permissions:
      contents: read # for actions/checkout
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          cache: npm
          node-version-file: '.node-version'

      - name: Install Dependencies
        run: npm ci --ignore-scripts

      - name: Check that package-lock.json doesn't have conflicts
        run: npm ls --depth 999

      - name: Run npm install
        run: npm install --ignore-scripts --force --package-lock-only --engine-strict --strict-peer-deps

      - name: Check that package-lock.json is in sync with package.json
        run: git diff --exit-code package-lock.json

  integrationTests:
    name: Run integration tests
    runs-on: ubuntu-latest
    permissions:
      contents: read # for actions/checkout
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version-file: '.node-version'
          # We install bunch of packages during integration tests without locking them
          # so we skip cache action to not pollute cache for other jobs.

      - name: Install Dependencies
        run: npm ci --ignore-scripts

      - name: Run Integration Tests
        run: npm run check:integrations

  fuzz:
    name: Run fuzzing tests
    runs-on: ubuntu-latest
    permissions:
      contents: read # for actions/checkout
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          cache: npm
          node-version-file: '.node-version'

      - name: Install Dependencies
        run: npm ci --ignore-scripts

      - name: Run Tests
        run: npm run fuzzonly

  test:
    name: Run tests on Node v${{ matrix.node_version_to_setup }}
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node_version_to_setup: [22, 24, 25, 26]
    permissions:
      contents: read # for actions/checkout
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Setup Node.js v${{ matrix.node_version_to_setup }}
        uses: actions/setup-node@v6
        with:
          cache: npm
          node-version: ${{ matrix.node_version_to_setup }}

      - name: Install Dependencies
        run: npm ci --ignore-scripts

      - name: Run Tests with coverage
        run: npm run testonly:cover

  codeql:
    name: Run CodeQL security scan
    runs-on: ubuntu-latest
    permissions:
      contents: read # for actions/checkout
      security-events: write # for codeql-action
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Initialize CodeQL
        uses: github/codeql-action/init@v4
        with:
          languages: 'javascript, typescript'

      - name: Perform CodeQL analysis
        uses: github/codeql-action/analyze@v4

  build-npm-dist:
    name: Build 'npmDist' artifact
    runs-on: ubuntu-latest
    permissions:
      contents: read # for actions/checkout
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          cache: npm
          node-version-file: '.node-version'

      - name: Install Dependencies
        run: npm ci --ignore-scripts

      - name: Build NPM package
        run: npm run build:npm

      - name: Upload npmDist package
        uses: actions/upload-artifact@v7
        with:
          name: npmDist
          path: ./npmDist

  build-deno-dist:
    name: Build 'denoDist' artifact
    runs-on: ubuntu-latest
    permissions:
      contents: read # for actions/checkout
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          cache: npm
          node-version-file: '.node-version'

      - name: Install Dependencies
        run: npm ci --ignore-scripts

      - name: Build Deno package
        run: npm run build:deno

      - name: Upload denoDist package
        uses: actions/upload-artifact@v7
        with:
          name: denoDist
          path: ./denoDist

  check-deno-dist:
    name: Type check denoDist on Deno v${{ matrix.deno_version_to_setup }}
    needs: build-deno-dist
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        # Keep minors pinned to preserve backward-compat coverage; include v2.x
        # so CI also exercises the latest Deno release used for publishing.
        deno_version_to_setup: [2.4.x, 2.5.x, 2.6.x, 2.7.x, 2.8.x, v2.x]
    permissions:
      contents: read # for actions/download-artifact
    steps:
      - name: Download denoDist package
        uses: actions/download-artifact@v8
        with:
          name: denoDist
          path: ./denoDist

      - name: Setup Deno v${{ matrix.deno_version_to_setup }}
        uses: denoland/setup-deno@v2
        with:
          deno-version: ${{ matrix.deno_version_to_setup }}

      - name: Run denoDist package publish dry-run checks
        # `deno publish --dry-run` performs a number of checks including:
        # (a) type-checking package modules/public API,
        # (b) validating exports and module-graph resolution,
        # (c) validating the publish file set (gitignore + publish.exclude/include),
        # (d) validating package metadata/config, and
        # (e) enforcing JSR slow-types checks.
        working-directory: ./denoDist
        run: deno publish --dry-run