name: CI | Coverall Cyberia

on:
  push:
    branches: ['master', 'main']
  pull_request:
    branches: ['master', 'main']

jobs:
  test:
    name: Coverall Cyberia Test
    # Deliberately not the engine repository: two coverage workflows on one commit
    # are two Coveralls builds, and the badge then shows whichever landed last
    # rather than the tree's coverage. The engine is served by coverall.ci.yml.
    if: |
      github.actor != 'dependabot[bot]' &&
      (github.repository == 'underpostnet/engine-cyberia' ||
       github.repository == 'underpost/engine-cyberia' ||
       github.repository == 'underpostnet/engine-ghpkg-cyberia' ||
       github.repository == 'underpost/engine-ghpkg-cyberia' ||
       github.repository == 'underpostnet/engine-test-cyberia' ||
       github.repository == 'underpost/engine-test-cyberia')
    runs-on: ubuntu-latest
    container:
      image: quay.io/rockylinux/rockylinux:9
    steps:
      # Install git first. Checkout without git downloads an archive that has no .git.
      - name: Install required packages
        run: |
          dnf install -y sudo tar gzip bzip2 git bash
          dnf install -y curl --allowerasing

      - name: Clone repository
        uses: actions/checkout@v7

      # The checkout belongs to another user than the container root. Git refuses it without this.
      - name: Trust the checkout in git
        run: git config --global --add safe.directory '*'

      - name: Install Node.js
        run: |
          curl -fsSL https://rpm.nodesource.com/setup_24.x | bash -
          dnf install nodejs -y

      # gofmt formats the generated stat contract; the cyberia tier's contract
      # check fails without it on PATH.
      - name: Install Go
        run: dnf install -y golang

      # The database suites of the cyberia tier start a throwaway mongod
      # (test/support/mongod.js). Without one they skip, and the modules they drive count as uncovered.
      - name: Install the MongoDB server
        run: |
          curl -fsSL https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel93-8.0.14.tgz | tar -xz -C /opt
          echo "UNDERPOST_MONGOD_BIN=/opt/mongodb-linux-x86_64-rhel93-8.0.14/bin/mongod" >> "$GITHUB_ENV"

      - name: Install project dependencies
        run: npm install

      # The cyberia tier imports the modules its catalog pins (jimp, pngjs, ethers, ...),
      # which the engine manifest does not carry.
      - name: Install cyberia catalog dependencies
        run: node bin package dd-cyberia --install

      # A pull request runs what its change can break, and a push to the release
      # branch runs the whole platform: the selector comes from the canonical impact
      # model in `src/server/build/testing.js`, never from a path list of its own.
      - name: Resolve the test selection
        id: selection
        run: |
          if [ "${{ github.event_name }}" = "pull_request" ]; then
            git fetch --no-tags --depth=1 origin ${{ github.base_ref }}
            echo "suite=$(node bin test --changed origin/${{ github.base_ref }} --print)" >> "$GITHUB_OUTPUT"
          else
            echo "suite=underpost,ecosystem,object-layer,item-ledger:unit,cryptokoyn,cyberia" >> "$GITHUB_OUTPUT"
          fi

      # Set the COVERAGE_MIN repository variable to gate below the shipped
      # default while the suite is catching up to it.
      - name: Run tests and enforce coverage threshold
        run: COVERAGE_ENFORCE=1 node bin test ${{ steps.selection.outputs.suite }}
        env:
          COVERAGE_MIN: ${{ vars.COVERAGE_MIN }}

      # Stored even when the threshold step failed — that step still fails the
      # job, but without the report the badge freezes at the last passing build.
      - name: Store coverage report
        if: '!cancelled()'
        uses: actions/upload-artifact@v7
        with:
          name: coverall-cyberia-lcov
          path: ./coverage/lcov.info
          if-no-files-found: error

  upload:
    name: Upload Cyberia Coverage to Coveralls
    needs: test
    # Host runner, not the Rocky container the suite runs in: every step of the
    # Coveralls action declares `shell: bash`, which the runner execs inside the
    # job container and cannot resolve there.
    if: |
      !cancelled() &&
      github.actor != 'dependabot[bot]' &&
      (github.repository == 'underpostnet/engine-cyberia' ||
       github.repository == 'underpost/engine-cyberia' ||
       github.repository == 'underpostnet/engine-ghpkg-cyberia' ||
       github.repository == 'underpost/engine-ghpkg-cyberia' ||
       github.repository == 'underpostnet/engine-test-cyberia' ||
       github.repository == 'underpost/engine-test-cyberia')
    runs-on: ubuntu-latest
    steps:
      # Coveralls reads the commit and branch metadata from the checkout.
      - name: Clone repository
        uses: actions/checkout@v7

      - name: Restore coverage report
        uses: actions/download-artifact@v8
        with:
          name: coverall-cyberia-lcov
          path: ./coverage

      - name: Upload coverage to Coveralls
        uses: coverallsapp/github-action@v2
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          file: ./coverage/lcov.info
          format: lcov
          parallel: true
          fail-on-error: true

  finish:
    name: Finish Cyberia Coveralls build
    needs: upload
    # The build stays open until this webhook lands, so it runs on any upload
    # outcome rather than leaving a half-reported build behind.
    if: |
      !cancelled() &&
      github.actor != 'dependabot[bot]' &&
      (github.repository == 'underpostnet/engine-cyberia' ||
       github.repository == 'underpost/engine-cyberia' ||
       github.repository == 'underpostnet/engine-ghpkg-cyberia' ||
       github.repository == 'underpost/engine-ghpkg-cyberia' ||
       github.repository == 'underpostnet/engine-test-cyberia' ||
       github.repository == 'underpost/engine-test-cyberia')
    runs-on: ubuntu-latest
    steps:
      - name: Notify Coveralls Finished
        uses: coverallsapp/github-action@v2
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          parallel-finished: true
