name: test
on:
  push:
    tags: ["v*"]
    branches: ["main", "mise"]
  pull_request:
    branches: ["main"]
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  CARGO_TERM_COLOR: always
  CARGO_INCREMENTAL: 0
  MISE_TRUSTED_CONFIG_PATHS: ${{ github.workspace }}
  MISE_EXPERIMENTAL: 1
  RUST_BACKTRACE: 1
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  NPM_CONFIG_FUND: false

permissions:
  pull-requests: write

jobs:
  unit:
    strategy:
      fail-fast: false
      matrix: { os: [ubuntu-latest, macos-latest] }
    runs-on: ${{ matrix.os }}
    timeout-minutes: 20
    steps:
      - uses: actions/checkout@v4
        with:
          repository: ${{ github.event.pull_request.head.repo.full_name }}
          ref: ${{ github.event.pull_request.head.ref }}
          token: ${{ secrets.RTX_GITHUB_BOT_TOKEN || github.token }}
      - uses: actions-rust-lang/setup-rust-toolchain@v1
        with: { toolchain: stable, components: rustfmt }
      - uses: taiki-e/install-action@v2
        with:
          tool: nextest,cargo-deny,cargo-msrv,cargo-machete,usage-cli
      - run: |
          cargo build --all-features
          echo "$PWD/target/debug" >> "$GITHUB_PATH"
      - run: npm i
      - name: cache mise
        uses: actions/cache@v4
        with:
          key: mise-tools-${{ matrix.os }}-${{ hashFiles('.mise.toml') }}
          restore-keys: mise-tools-${{ matrix.os }}
          path: |
            ~/.local/share/mise/installs
            ~/.local/share/mise/plugins
      - run: mise install
      - run: mise x -- cargo nextest run --all-features
      - run: cargo deny check
      - run: cargo msrv verify
      - run: cargo machete --with-metadata
      - run: ./scripts/test-standalone.sh
      - run: mise settings set experimental true
      - run: mise run render
      - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'jdx/mise'
        run: mise run lint-fix && git diff HEAD
      - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'jdx/mise'
        uses: EndBug/add-and-commit@v9
        with:
          push: true
          author_name: mise[bot]
          author_email: 123107610+mise-en-dev@users.noreply.github.com
      - uses: actions-rust-lang/rustfmt@v1
      - run: mise run lint

  nightly:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v4
        with:
          repository: ${{ github.event.pull_request.head.repo.full_name }}
          ref: ${{ github.event.pull_request.head.ref }}
          token: ${{ secrets.RTX_GITHUB_BOT_TOKEN || github.token }}
      - uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          { toolchain: nightly, components: "rustfmt, clippy", rustflags: "" }
      - run: |
          cargo build --all-features
          echo "$PWD/target/debug" >> "$GITHUB_PATH"
      - name: cache mise
        uses: actions/cache@v4
        with:
          key: mise-tools-ubuntu-latest-${{ hashFiles('.mise.toml') }}
          restore-keys: mise-tools-ubuntu-latest
          path: |
            ~/.local/share/mise/installs
            ~/.local/share/mise/plugins
      - run: mise install
      - run: mise run test:shuffle
      - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'jdx/mise'
        run: mise run lint-fix && git diff HEAD
      - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'jdx/mise'
        uses: EndBug/add-and-commit@v9
        with:
          push: true
          author_name: mise[bot]
          author_email: 123107610+mise-en-dev@users.noreply.github.com

  coverage:
    name: coverage-${{matrix.tranche}}
    #container: ghcr.io/jdx/mise:github-actions
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      fail-fast: false
      matrix:
        tranche: [0, 1, 2, 3]
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: coverage
          save-if: ${{ github.ref_name == 'main' && matrix.tranche == 0 }}
      - name: Install build and test dependencies
        run: |
          sudo apt-get update && sudo apt-get install \
            bison \
            build-essential \
            direnv \
            fd-find \
            fish \
            pipx \
            python3-venv \
            zsh
      - run: npm i
      - run: |
          mkdir -p "$HOME/.local/bin"
          ln -s "$(which fdfind)" "$HOME/.local/bin/fd"
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"
      - uses: taiki-e/install-action@v2
        with:
          tool: cargo-llvm-cov,mise,usage-cli
      - name: Test w/ coverage
        uses: nick-fields/retry@v3
        env:
          GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          RUST_BACKTRACE: "1"
          MISE_GITHUB_BOT_TOKEN: ${{ secrets.RTX_GITHUB_BOT_TOKEN }}
          MISE_EXPERIMENTAL: "1"
          TEST_TRANCHE: ${{matrix.tranche}}
          TEST_TRANCHE_COUNT: 4
          TEST_ALL: ${{github.ref_name == 'release' && '1' || '0'}}
        with:
          timeout_minutes: 30
          retry_wait_seconds: 30
          max_attempts: 2
          command: mise tasks run test:coverage
      - uses: actions/upload-artifact@v4
        with:
          name: coverage-${{matrix.tranche}}.lcov
          path: coverage-${{matrix.tranche}}.lcov
          if-no-files-found: error
  coverage-report:
    name: coverage-report
    runs-on: ubuntu-latest
    timeout-minutes: 10
    needs: coverage
    steps:
      - uses: actions/download-artifact@v4
        with:
          pattern: coverage-*.lcov
          path: .
          merge-multiple: true
      - run: |
          pip install lcov_cobertura
          npx lcov-result-merger 'coverage-*.lcov' coverage.lcov
          lcov_cobertura coverage.lcov --output coverage.xml
      - uses: codacy/codacy-coverage-reporter-action@v1
        continue-on-error: true
        with:
          project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
          coverage-reports: coverage.lcov
      - uses: irongut/CodeCoverageSummary@v1.3.0
        with:
          filename: coverage.xml
          badge: true
          format: markdown
          output: both
      - name: Add Coverage PR Comment
        uses: marocchino/sticky-pull-request-comment@v2
        if: github.event_name == 'pull_request'
        continue-on-error: true
        with:
          recreate: true
          path: code-coverage-results.md
  windows-unit:
    runs-on: windows-latest
    timeout-minutes: 20
    steps:
      - uses: actions/checkout@v4
      - uses: Swatinem/rust-cache@v2
      # TODO: enable when we can remove continue-on-error:
      # - name: cargo test
      #   uses: nick-fields/retry@v3
      #   with:
      #     timeout_minutes: 30
      #     retry_wait_seconds: 30
      #     max_attempts: 2
      #     command: cargo test
      - run: cargo test
        continue-on-error: true
  windows-e2e:
    runs-on: windows-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
      - uses: Swatinem/rust-cache@v2
      - run: cargo build
      - run: Add-Content $env:GITHUB_PATH "$PWD\target\debug"
      - name: e2e
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 30
          retry_wait_seconds: 30
          max_attempts: 2
          command: pwsh e2e-win\run_all.ps1
