name: Github Actions

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

      - name: Use Node.js
        uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
        with:
          node-version: lts/*
          cache: yarn

      - run: yarn --frozen-lockfile

      - name: Cache prettier result
        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
        with:
          path: ./node_modules/.cache/prettier/.prettier-cache
          key: lint-prettier-${{ runner.os }}-node-${{ hashFiles('**/yarn.lock', '**/.prettierrc.js') }}
          restore-keys: lint-prettier-

      - name: Cache eslint result
        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
        with:
          path: .eslintcache
          key: lint-eslint-${{ runner.os }}-node-${{ hashFiles('**/yarn.lock', '**/eslint.config.mjs') }}
          restore-keys: lint-eslint-

      - name: Cache cspell result
        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
        with:
          path: .cspellcache
          key: lint-cspell-${{ runner.os }}-node-${{ hashFiles('**/yarn.lock', '**/cspell.json') }}
          restore-keys: lint-cspell-

      - run: yarn lint

      - name: Validate types using old typescript version
        run: |
          yarn upgrade typescript@5.0 @types/node@20
          yarn --frozen-lockfile
          yarn validate:types

  validate-legacy-node:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

      - name: Use Node.js 10.x
        uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
        with:
          node-version: 10.x
          cache: yarn

      # Remove `devDependencies` from `package.json` to avoid `yarn install` compatibility error
      - run: node -e "const content = require('./package.json');delete content.devDependencies;require('fs').writeFileSync('package.json', JSON.stringify(content, null, 2));"

      - run: yarn install --production --frozen-lockfile

  benchmark:
    strategy:
      fail-fast: false
      matrix:
        shard: [1/4, 2/4, 3/4, 4/4]
    runs-on: ubuntu-latest
    permissions:
      issues: write
      pull-requests: write
    steps:
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
        with:
          fetch-tags: true
          fetch-depth: 0

      - name: Use Node.js
        uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
        with:
          node-version: lts/*
          cache: yarn

      - run: yarn --frozen-lockfile

      - run: yarn link --frozen-lockfile || true

      - run: yarn link webpack --frozen-lockfile

      - name: Run benchmarks
        uses: CodSpeedHQ/action@6b43a0cd438f6ca5ad26f9ed03ed159ed2df7da9 # v4.1.1
        with:
          run: yarn benchmark --ci
          mode: "instrumentation"
          token: ${{ secrets.CODSPEED_TOKEN }}
        env:
          LAST_COMMIT: 1
          NEGATIVE_FILTER: on-schedule
          SHARD: ${{ matrix.shard }}

  basic:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

      - name: Use Node.js
        uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
        with:
          node-version: lts/*
          cache: yarn

      - run: yarn --frozen-lockfile

      - run: yarn link --frozen-lockfile || true

      - run: yarn link webpack --frozen-lockfile

      - run: yarn test:basic --ci

  unit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

      - name: Use Node.js
        uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
        with:
          node-version: lts/*
          cache: yarn

      - run: yarn --frozen-lockfile

      - run: yarn link --frozen-lockfile || true

      - run: yarn link webpack --frozen-lockfile

      - name: Cache jest result
        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
        with:
          path: .jest-cache
          key: jest-unit-${{ env.GITHUB_SHA }}
          restore-keys: jest-unit-${{ hashFiles('**/yarn.lock', '**/jest.config.js') }}

      - run: yarn cover:unit --ci --cacheDirectory .jest-cache

      - name: Codecov
        uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
        with:
          flags: unit
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

  integration:
    needs: basic
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [10.x, 20.x, 22.x, 24.x]
        part: [a, b]
        include:
          # Test with main branches of webpack dependencies
          - os: ubuntu-latest
            node-version: lts/*
            part: a
            use_main_branches: 1
          - os: ubuntu-latest
            node-version: lts/*
            part: b
            use_main_branches: 1
          # Test on old Node.js versions
          - os: ubuntu-latest
            node-version: 18.x
            part: a
          - os: ubuntu-latest
            node-version: 16.x
            part: a
          - os: ubuntu-latest
            node-version: 14.x
            part: a
          - os: ubuntu-latest
            node-version: 12.x
            part: a
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

      - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
        id: calculate_architecture
        with:
          result-encoding: string
          script: |
            if ('${{ matrix.os }}' === 'macos-latest' && '${{ matrix['node-version'] }}' === '10.x') {
              return "x64"
            } else {
              return ''
            }

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
        with:
          node-version: ${{ matrix.node-version }}
          architecture: ${{ steps.calculate_architecture.outputs.result }}
          cache: yarn

      # Install old `jest` version and deps for legacy node versions
      - run: |
          yarn upgrade jest@^27.5.0 jest-circus@^27.5.0 jest-cli@^27.5.0 jest-diff@^27.5.0 jest-environment-node@^27.5.0 jest-junit@^13.0.0 @types/jest@^27.4.0 pretty-format@^27.0.2 husky@^8.0.3 lint-staged@^13.2.1 cspell@^6.31.1 open-cli@^7.2.0 coffee-loader@^1.0.0 babel-loader@^8.1.0 style-loader@^2.0.0 css-loader@^5.0.1 less-loader@^8.1.1 mini-css-extract-plugin@^1.6.1 nyc@^15.1.0 memfs@4.14.0 --ignore-engines
          yarn --frozen-lockfile --ignore-engines
        if: matrix.node-version == '10.x' || matrix.node-version == '12.x' || matrix.node-version == '14.x'

      - run: |
          yarn upgrade jest@^27.5.0 jest-circus@^27.5.0 jest-cli@^27.5.0 jest-diff@^27.5.0 jest-environment-node@^27.5.0 jest-junit@^13.0.0 @types/jest@^27.4.0 pretty-format@^27.0.2 husky@^8.0.3 lint-staged@^13.2.1 nyc@^15.1.0 coffee-loader@1.0.0 babel-loader@^8.1.0 style-loader@^2.0.0 css-loader@^5.0.1 less-loader@^8.1.1 mini-css-extract-plugin@^1.6.1 --ignore-engines
          yarn --frozen-lockfile
        if: matrix.node-version == '16.x'

      - run: |
          yarn upgrade cspell@^8.8.4 lint-staged@^15.2.5 --ignore-engines
          yarn --frozen-lockfile
        if: matrix.node-version == '18.x'

      # Install main version of our deps
      - run: yarn upgrade enhanced-resolve@webpack/enhanced-resolve#main loader-runner@webpack/loader-runner#main webpack-sources@webpack/webpack-sources#main watchpack@webpack/watchpack#main tapable@webpack/tapable#main
        if: matrix.use_main_branches == '1'

      # Install dependencies for LTS node versions
      - run: yarn --frozen-lockfile
        if: matrix.node-version != '10.x' && matrix.node-version != '12.x' && matrix.node-version != '14.x' && matrix.node-version != '16.x'

      - run: yarn link --frozen-lockfile || true

      - run: yarn link webpack --frozen-lockfile

      - name: Cache jest result
        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
        with:
          path: .jest-cache
          key: jest-integration-${{ env.GITHUB_SHA }}
          restore-keys: jest-integration-${{ hashFiles('**/yarn.lock', '**/jest.config.js') }}

      - run: yarn cover:integration:${{ matrix.part }} --ci --cacheDirectory .jest-cache || yarn cover:integration:${{ matrix.part }} --ci --cacheDirectory .jest-cache -f

      - run: yarn cover:merge

      - name: Codecov
        uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
        with:
          flags: integration
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
