# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt

name: "Coverage"

on:
  # As currently structured, this adds too many jobs (checks?), so don't run it
  # on pull requests yet.
  push:
    branches:
      - master
      - "**/*metacov*"
  workflow_dispatch:

defaults:
  run:
    shell: bash

env:
  PIP_DISABLE_PIP_VERSION_CHECK: 1
  FORCE_COLOR: 1    # Get colored pytest output

permissions:
  contents: read

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

jobs:
  coverage:
    name: "${{ matrix.python-version }} on ${{ matrix.os }}"
    runs-on: "${{ matrix.os }}-${{ matrix.os-version || 'latest' }}"
    env:
      MATRIX_ID: "${{ matrix.python-version }}.${{ matrix.os }}"

    strategy:
      matrix:
        os:
          - ubuntu
          - macos
          - windows
        python-version:
          # When changing this list, be sure to check the [gh] list in
          # tox.ini so that tox will run properly. PYVERSIONS
          # Available versions:
          # https://github.com/actions/python-versions/blob/main/versions-manifest.json
          - "3.8"
          - "3.9"
          - "3.10"
          - "3.11"
          - "3.12"
          - "3.13"
          - "pypy-3.8"
          - "pypy-3.9"
          - "pypy-3.10"
        exclude:
          # Mac PyPy always takes the longest, and doesn't add anything.
          - os: macos
            python-version: "pypy-3.8"
          - os: macos
            python-version: "pypy-3.9"
          - os: macos
            python-version: "pypy-3.10"
          # Windows pypy 3.9 and 3.10 get stuck with PyPy 7.3.15.  I hope to
          # unstick them, but I don't want that to block all other progress, so
          # skip them for now.
          - os: windows
            python-version: "pypy-3.9"
          - os: windows
            python-version: "pypy-3.10"
        # If we need to tweak the os version we can do it with an include like
        # this:
        #  include:
        #    - python-version: "3.8"
        #      os: "macos"
        #      os-version: "13"

      # If one job fails, stop the whole thing.
      fail-fast: true

    steps:
      - name: "Check out the repo"
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: "Set up Python"
        uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
        with:
          python-version: "${{ matrix.python-version }}"
          allow-prereleases: true
          # At a certain point, installing dependencies failed on pypy 3.9 and
          # 3.10 on Windows.  Commenting out the cache here fixed it.  Someday
          # try using the cache again.
          #cache: pip
          #cache-dependency-path: 'requirements/*.pip'

      - name: "Show environment"
        run: |
          set -xe
          python -VV
          python -m site
          env

      - name: "Install dependencies"
        run: |
          echo matrix id: $MATRIX_ID
          set -xe
          python -VV
          python -m site
          python -m pip install -r requirements/tox.pip

      - name: "Run tox coverage for ${{ matrix.python-version }}"
        env:
          COVERAGE_COVERAGE: "yes"
          COVERAGE_CONTEXT: "${{ matrix.python-version }}.${{ matrix.os }}"
        run: |
          set -xe
          python -m tox

      - name: "Combine data"
        env:
          COVERAGE_RCFILE: "metacov.ini"
        run: |
          python -m coverage combine
          mv .metacov .metacov.$MATRIX_ID

      - name: "Upload coverage data"
        uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
        with:
          name: metacov-${{ env.MATRIX_ID }}
          path: .metacov.*

  combine:
    name: "Combine coverage data"
    needs: coverage
    runs-on: ubuntu-latest
    outputs:
      total: ${{ steps.total.outputs.total }}
    env:
      COVERAGE_RCFILE: "metacov.ini"

    steps:
      - name: "Check out the repo"
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: "Set up Python"
        uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
        with:
          python-version: "3.8" # Minimum of PYVERSIONS
          # At a certain point, installing dependencies failed on pypy 3.9 and
          # 3.10 on Windows.  Commenting out the cache here fixed it.  Someday
          # try using the cache again.
          #cache: pip
          #cache-dependency-path: 'requirements/*.pip'

      - name: "Show environment"
        run: |
          set -xe
          python -VV
          python -m site
          env | sort

      - name: "Install dependencies"
        run: |
          set -xe
          python -m pip install -e .
          python igor.py zip_mods

      - name: "Download coverage data"
        uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
        with:
          pattern: metacov-*
          merge-multiple: true

      - name: "Combine and report"
        id: combine
        env:
          COVERAGE_CONTEXT: "yes"
        run: |
          set -xe
          python igor.py combine_html

      - name: "Upload HTML report"
        uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
        with:
          name: html_report
          path: htmlcov

      - name: "Get total"
        id: total
        run: |
          echo "total=$(python -m coverage report --format=total)" >> $GITHUB_OUTPUT

  publish:
    name: "Publish coverage report"
    needs: combine
    runs-on: ubuntu-latest

    steps:
      - name: "Show environment"
        run: |
          set -xe
          env | sort

      - name: "Compute info for later steps"
        id: info
        run: |
          export SHA10=$(echo ${{ github.sha }} | cut -c 1-10)
          export SLUG=$(date +'%Y%m%d')_$SHA10
          export REPORT_DIR=reports/$SLUG/htmlcov
          export REF="${{ github.ref }}"
          echo "total=${{ needs.combine.outputs.total }}" >> $GITHUB_ENV
          echo "sha10=$SHA10" >> $GITHUB_ENV
          echo "slug=$SLUG" >> $GITHUB_ENV
          echo "report_dir=$REPORT_DIR" >> $GITHUB_ENV
          echo "url=https://htmlpreview.github.io/?https://github.com/nedbat/coverage-reports/blob/main/reports/$SLUG/htmlcov/index.html" >> $GITHUB_ENV
          echo "branch=${REF#refs/heads/}" >> $GITHUB_ENV

      - name: "Summarize"
        run: |
          echo '### Total coverage: ${{ env.total }}%' >> $GITHUB_STEP_SUMMARY

      - name: "Checkout reports repo"
        if: ${{ github.ref == 'refs/heads/master' }}
        run: |
          set -xe
          git clone --depth=1 --no-checkout https://${{ secrets.COVERAGE_REPORTS_TOKEN }}@github.com/nedbat/coverage-reports reports_repo
          cd reports_repo
          git sparse-checkout init --cone
          git sparse-checkout set --skip-checks '/*' '!/reports'
          git config user.name nedbat
          git config user.email ned@nedbatchelder.com
          git checkout main

      - name: "Download coverage HTML report"
        if: ${{ github.ref == 'refs/heads/master' }}
        uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
        with:
          name: html_report
          path: reports_repo/${{ env.report_dir }}

      - name: "Push to report repo"
        if: |
          github.repository_owner == 'nedbat'
          && github.ref == 'refs/heads/master'
        env:
          COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
        run: |
          set -xe
          # Make the redirect to the latest report.
          echo "<html><head>" > reports_repo/latest.html
          echo "<meta http-equiv='refresh' content='0;url=${{ env.url }}' />" >> reports_repo/latest.html
          echo "<body>Coverage report redirect..." >> reports_repo/latest.html
          # Make the commit message.
          echo "${{ env.total }}% - $COMMIT_MESSAGE" > commit.txt
          echo "" >> commit.txt
          echo "${{ env.url }}" >> commit.txt
          echo "${{ env.sha10 }}: ${{ env.branch }}" >> commit.txt
          # Commit.
          cd ./reports_repo
          git sparse-checkout set --skip-checks '/*' '${{ env.report_dir }}'
          rm ${{ env.report_dir }}/.gitignore
          git add ${{ env.report_dir }} latest.html
          git commit --file=../commit.txt
          git push
          echo '[${{ env.url }}](${{ env.url }})' >> $GITHUB_STEP_SUMMARY

      - name: "Create badge"
        if: |
          github.repository_owner == 'nedbat'
          && github.ref == 'refs/heads/master'
        # https://gist.githubusercontent.com/nedbat/8c6980f77988a327348f9b02bbaf67f5
        uses: schneegans/dynamic-badges-action@e9a478b16159b4d31420099ba146cdc50f134483 # v1.7.0
        with:
          auth: ${{ secrets.METACOV_GIST_SECRET }}
          gistID: 8c6980f77988a327348f9b02bbaf67f5
          filename: metacov.json
          label: Coverage
          message: ${{ env.total }}%
          minColorRange: 60
          maxColorRange: 95
          valColorRange: ${{ env.total }}
