From be98dd61018e41f37e107c3aa926966f635b2566 Mon Sep 17 00:00:00 2001 From: zacharyburnett Date: Tue, 24 Feb 2026 09:46:01 -0500 Subject: [PATCH] add option to generate test coverage report without codecov MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Stuart Mumford Co-authored-by: Clément Robert --- .github/workflows/test_tox.yml | 8 ++++++ .github/workflows/tox.yml | 50 ++++++++++++++++++++++++++++++++-- docs/source/tox.rst | 4 +-- pyproject.toml | 5 ++++ tools/tox_matrix.py | 13 +++++---- tox.ini | 5 ++++ 6 files changed, 75 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test_tox.yml b/.github/workflows/test_tox.yml index c7f7b809..f5174aa2 100644 --- a/.github/workflows/test_tox.yml +++ b/.github/workflows/test_tox.yml @@ -158,6 +158,14 @@ jobs: a/ cache-key: cache-${{ github.run_id }} + test_coverage_github: + uses: ./.github/workflows/tox.yml + with: + coverage: github + envs: | + - linux: py313-covcheck + - linux: py314-covcheck + test_artifact_upload: uses: ./.github/workflows/tox.yml with: diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 9884b1c1..c05bfc75 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -117,15 +117,13 @@ jobs: envs: name: Load tox environments runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.set-outputs.outputs.matrix }} steps: - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.12' - run: echo $TOX_MATRIX_SCRIPT | base64 --decode > tox_matrix.py env: - TOX_MATRIX_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJjbGljaz09OC4yLjEiLAojICAgICAicHl5YW1sPT02LjAuMiIsCiMgXQojIC8vLwppbXBvcnQganNvbgppbXBvcnQgb3MKaW1wb3J0IHJlCgppbXBvcnQgY2xpY2sKaW1wb3J0IHlhbWwKCgpAY2xpY2suY29tbWFuZCgpCkBjbGljay5vcHRpb24oIi0tZW52cyIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tbGlicmFyaWVzIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS1wb3NhcmdzIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS10b3hkZXBzIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS10b3hhcmdzIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS1weXRlc3QiLCBkZWZhdWx0PSJ0cnVlIikKQGNsaWNrLm9wdGlvbigiLS1weXRlc3QtcmVzdWx0cy1zdW1tYXJ5IiwgZGVmYXVsdD0iZmFsc2UiKQpAY2xpY2sub3B0aW9uKCItLWNvdmVyYWdlIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS1jb25kYSIsIGRlZmF1bHQ9ImF1dG8iKQpAY2xpY2sub3B0aW9uKCItLXNldGVudiIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tZGlzcGxheSIsIGRlZmF1bHQ9ImZhbHNlIikKQGNsaWNrLm9wdGlvbigiLS1jYWNoZS1wYXRoIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS1jYWNoZS1rZXkiLCBkZWZhdWx0PSIiKQpAY2xpY2sub3B0aW9uKCItLWNhY2hlLXJlc3RvcmUta2V5cyIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tYXJ0aWZhY3QtcGF0aCIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tcnVucy1vbiIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tZGVmYXVsdC1weXRob24iLCBkZWZhdWx0PSIiKQpAY2xpY2sub3B0aW9uKCItLXRpbWVvdXQtbWludXRlcyIsIGRlZmF1bHQ9IjM2MCIpCmRlZiBsb2FkX3RveF90YXJnZXRzKGVudnMsIGxpYnJhcmllcywgcG9zYXJncywgdG94ZGVwcywgdG94YXJncywgcHl0ZXN0LCBweXRlc3RfcmVzdWx0c19zdW1tYXJ5LAogICAgICAgICAgICAgICAgICAgICBjb3ZlcmFnZSwgY29uZGEsIHNldGVudiwgZGlzcGxheSwgY2FjaGVfcGF0aCwgY2FjaGVfa2V5LAogICAgICAgICAgICAgICAgICAgICBjYWNoZV9yZXN0b3JlX2tleXMsIGFydGlmYWN0X3BhdGgsIHJ1bnNfb24sIGRlZmF1bHRfcHl0aG9uLCB0aW1lb3V0X21pbnV0ZXMpOgogICAgIiIiU2NyaXB0IHRvIGxvYWQgdG94IHRhcmdldHMgZm9yIEdpdEh1YiBBY3Rpb25zIHdvcmtmbG93LiIiIgogICAgIyBMb2FkIGVudnMgY29uZmlnCiAgICBlbnZzID0geWFtbC5sb2FkKGVudnMsIExvYWRlcj15YW1sLkJhc2VMb2FkZXIpCiAgICBwcmludChqc29uLmR1bXBzKGVudnMsIGluZGVudD0yKSkKCiAgICAjIExvYWQgZ2xvYmFsIGxpYnJhcmllcyBjb25maWcKICAgIGdsb2JhbF9saWJyYXJpZXMgPSB7CiAgICAgICAgImJyZXciOiBbXSwKICAgICAgICAiYnJldy1jYXNrIjogW10sCiAgICAgICAgImFwdCI6IFtdLAogICAgICAgICJjaG9jbyI6IFtdLAogICAgfQogICAgbGlicmFyaWVzID0geWFtbC5sb2FkKGxpYnJhcmllcywgTG9hZGVyPXlhbWwuQmFzZUxvYWRlcikKICAgIGlmIGxpYnJhcmllcyBpcyBub3QgTm9uZToKICAgICAgICBnbG9iYWxfbGlicmFyaWVzLnVwZGF0ZShsaWJyYXJpZXMpCiAgICBwcmludChqc29uLmR1bXBzKGdsb2JhbF9saWJyYXJpZXMsIGluZGVudD0yKSkKCiAgICAjIERlZmF1bHQgaW1hZ2VzIHRvIHVzZSBmb3IgcnVubmVycwogICAgZGVmYXVsdF9ydW5zX29uID0gewogICAgICAgICJsaW51eCI6ICJ1YnVudHUtbGF0ZXN0IiwKICAgICAgICAibWFjb3MiOiAibWFjb3MtbGF0ZXN0IiwKICAgICAgICAid2luZG93cyI6ICJ3aW5kb3dzLWxhdGVzdCIsCiAgICB9CiAgICBjdXN0b21fcnVuc19vbiA9IHlhbWwubG9hZChydW5zX29uLCBMb2FkZXI9eWFtbC5CYXNlTG9hZGVyKQogICAgaWYgaXNpbnN0YW5jZShjdXN0b21fcnVuc19vbiwgZGljdCk6CiAgICAgICAgZGVmYXVsdF9ydW5zX29uLnVwZGF0ZShjdXN0b21fcnVuc19vbikKICAgIHByaW50KGpzb24uZHVtcHMoZGVmYXVsdF9ydW5zX29uLCBpbmRlbnQ9MikpCgogICAgIyBEZWZhdWx0IHN0cmluZyBwYXJhbWV0ZXJzIHdoaWNoIGNhbiBiZSBvdmVyd3JpdHRlbiBieSBlYWNoIGVudgogICAgc3RyaW5nX3BhcmFtZXRlcnMgPSB7CiAgICAgICAgInBvc2FyZ3MiOiBwb3NhcmdzLAogICAgICAgICJ0b3hkZXBzIjogdG94ZGVwcywKICAgICAgICAidG94YXJncyI6IHRveGFyZ3MsCiAgICAgICAgInB5dGVzdCI6IHB5dGVzdCwKICAgICAgICAicHl0ZXN0LXJlc3VsdHMtc3VtbWFyeSI6IHB5dGVzdF9yZXN1bHRzX3N1bW1hcnksCiAgICAgICAgImNvdmVyYWdlIjogY292ZXJhZ2UsCiAgICAgICAgImNvbmRhIjogY29uZGEsCiAgICAgICAgInNldGVudiI6IHNldGVudiwKICAgICAgICAiZGlzcGxheSI6IGRpc3BsYXksCiAgICAgICAgImNhY2hlLXBhdGgiOiBjYWNoZV9wYXRoLAogICAgICAgICJjYWNoZS1rZXkiOiBjYWNoZV9rZXksCiAgICAgICAgImNhY2hlLXJlc3RvcmUta2V5cyI6IGNhY2hlX3Jlc3RvcmVfa2V5cywKICAgICAgICAiYXJ0aWZhY3QtcGF0aCI6IGFydGlmYWN0X3BhdGgsCiAgICAgICAgInRpbWVvdXQtbWludXRlcyI6IHRpbWVvdXRfbWludXRlcywKICAgIH0KCiAgICAjIENyZWF0ZSBtYXRyaXgKICAgIG1hdHJpeCA9IHsiaW5jbHVkZSI6IFtdfQogICAgZm9yIGVudiBpbiBlbnZzOgogICAgICAgIG1hdHJpeFsiaW5jbHVkZSJdLmFwcGVuZChnZXRfbWF0cml4X2l0ZW0oCiAgICAgICAgICAgIGVudiwKICAgICAgICAgICAgZ2xvYmFsX2xpYnJhcmllcz1nbG9iYWxfbGlicmFyaWVzLAogICAgICAgICAgICBnbG9iYWxfc3RyaW5nX3BhcmFtZXRlcnM9c3RyaW5nX3BhcmFtZXRlcnMsCiAgICAgICAgICAgIHJ1bnNfb249ZGVmYXVsdF9ydW5zX29uLAogICAgICAgICAgICBkZWZhdWx0X3B5dGhvbj1kZWZhdWx0X3B5dGhvbiwKICAgICAgICApKQoKICAgICMgT3V0cHV0IG1hdHJpeAogICAgcHJpbnQoanNvbi5kdW1wcyhtYXRyaXgsIGluZGVudD0yKSkKICAgIHdpdGggb3Blbihvcy5lbnZpcm9uWyJHSVRIVUJfT1VUUFVUIl0sICJhIikgYXMgZjoKICAgICAgICBmLndyaXRlKGYibWF0cml4PXtqc29uLmR1bXBzKG1hdHJpeCl9XG4iKQoKCmRlZiBnZXRfbWF0cml4X2l0ZW0oZW52LCBnbG9iYWxfbGlicmFyaWVzLCBnbG9iYWxfc3RyaW5nX3BhcmFtZXRlcnMsCiAgICAgICAgICAgICAgICAgICAgcnVuc19vbiwgZGVmYXVsdF9weXRob24pOgoKICAgICMgZGVmaW5lIHNwZWMgZm9yIGVhY2ggbWF0cml4IGluY2x1ZGUgKCsgZ2xvYmFsX3N0cmluZ19wYXJhbWV0ZXJzKQogICAgaXRlbSA9IHsKICAgICAgICAib3MiOiBOb25lLAogICAgICAgICJ0b3hlbnYiOiBOb25lLAogICAgICAgICJweXRob25fdmVyc2lvbiI6IE5vbmUsCiAgICAgICAgIm5hbWUiOiBOb25lLAogICAgICAgICJweXRlc3RfZmxhZyI6IE5vbmUsCiAgICAgICAgImxpYnJhcmllc19icmV3IjogTm9uZSwKICAgICAgICAibGlicmFyaWVzX2JyZXdfY2FzayI6IE5vbmUsCiAgICAgICAgImxpYnJhcmllc19hcHQiOiBOb25lLAogICAgICAgICJsaWJyYXJpZXNfY2hvY28iOiBOb25lLAogICAgICAgICJjYWNoZS1wYXRoIjogTm9uZSwKICAgICAgICAiY2FjaGUta2V5IjogTm9uZSwKICAgICAgICAiY2FjaGUtcmVzdG9yZS1rZXlzIjogTm9uZSwKICAgICAgICAiYXJ0aWZhY3QtbmFtZSI6IE5vbmUsCiAgICAgICAgImFydGlmYWN0LXBhdGgiOiBOb25lLAogICAgICAgICJ0aW1lb3V0LW1pbnV0ZXMiOiBOb25lLAogICAgfQogICAgZm9yIHN0cmluZ19wYXJhbSwgZGVmYXVsdCBpbiBnbG9iYWxfc3RyaW5nX3BhcmFtZXRlcnMuaXRlbXMoKToKICAgICAgICBlbnZfdmFsdWUgPSBlbnYuZ2V0KHN0cmluZ19wYXJhbSkKICAgICAgICBpdGVtW3N0cmluZ19wYXJhbV0gPSBkZWZhdWx0IGlmIGVudl92YWx1ZSBpcyBOb25lIGVsc2UgZW52X3ZhbHVlCgogICAgIyBzZXQgb3MgYW5kIHRveGVudgogICAgZm9yIGssIHYgaW4gcnVuc19vbi5pdGVtcygpOgogICAgICAgIGlmIGsgaW4gZW52OgogICAgICAgICAgICBwbGF0Zm9ybSA9IGsKICAgICAgICAgICAgaXRlbVsib3MiXSA9IGVudi5nZXQoInJ1bnMtb24iLCB2KQogICAgICAgICAgICBpdGVtWyJ0b3hlbnYiXSA9IGVudltrXQogICAgYXNzZXJ0IGl0ZW1bIm9zIl0gaXMgbm90IE5vbmUgYW5kIGl0ZW1bInRveGVudiJdIGlzIG5vdCBOb25lCgogICAgIyBzZXQgcHl0aG9uX3ZlcnNpb24KICAgIHB5dGhvbl92ZXJzaW9uID0gZW52LmdldCgicHl0aG9uLXZlcnNpb24iKQogICAgbSA9IHJlLnNlYXJjaCgiXnB5KDJ8MykoWzAtOV0rdD8pIiwgaXRlbVsidG94ZW52Il0pCiAgICBpZiBweXRob25fdmVyc2lvbiBpcyBub3QgTm9uZToKICAgICAgICBpdGVtWyJweXRob25fdmVyc2lvbiJdID0gcHl0aG9uX3ZlcnNpb24KICAgIGVsaWYgbSBpcyBub3QgTm9uZToKICAgICAgICBtYWpvciwgbWlub3IgPSBtLmdyb3VwcygpCiAgICAgICAgaXRlbVsicHl0aG9uX3ZlcnNpb24iXSA9IGYie21ham9yfS57bWlub3J9IgogICAgZWxzZToKICAgICAgICBpdGVtWyJweXRob25fdmVyc2lvbiJdID0gZW52LmdldCgiZGVmYXVsdF9weXRob24iKSBvciBkZWZhdWx0X3B5dGhvbgoKICAgICMgc2V0IG5hbWUKICAgIGl0ZW1bIm5hbWUiXSA9IGVudi5nZXQoIm5hbWUiKSBvciBmJ3tpdGVtWyJ0b3hlbnYiXX0gKHtpdGVtWyJvcyJdfSknCgogICAgIyBzZXQgYXJ0aWZhY3QtbmFtZSAocmVwbGFjZSBpbnZhbGlkIHBhdGggY2hhcmFjdGVycykKICAgIGl0ZW1bImFydGlmYWN0LW5hbWUiXSA9IHJlLnN1YihyIltcXCAvOjw+fCo/XCInXSIsICItIiwgaXRlbVsibmFtZSJdKQogICAgaXRlbVsiYXJ0aWZhY3QtbmFtZSJdID0gcmUuc3ViKHIiLSsiLCAiLSIsIGl0ZW1bImFydGlmYWN0LW5hbWUiXSkKCiAgICAjIHNldCBweXRlc3RfZmxhZwogICAgaXRlbVsicHl0ZXN0X2ZsYWciXSA9ICIiCiAgICBzZXAgPSByIlxcIiBpZiBwbGF0Zm9ybSA9PSAid2luZG93cyIgZWxzZSAiLyIKICAgIGlmIGl0ZW1bInB5dGVzdCJdID09ICJ0cnVlIiBhbmQgImNvZGVjb3YiIGluIGl0ZW0uZ2V0KCJjb3ZlcmFnZSIsICIiKToKICAgICAgICBpdGVtWyJweXRlc3RfZmxhZyJdICs9ICgKICAgICAgICAgICAgcmYiLS1jb3YtcmVwb3J0PXhtbDoke3tHSVRIVUJfV09SS1NQQUNFfX17c2VwfWNvdmVyYWdlLnhtbCAiKQogICAgaWYgaXRlbVsicHl0ZXN0Il0gPT0gInRydWUiIGFuZCBpdGVtWyJweXRlc3QtcmVzdWx0cy1zdW1tYXJ5Il0gPT0gInRydWUiOgogICAgICAgIGl0ZW1bInB5dGVzdF9mbGFnIl0gKz0gcmYiLS1qdW5pdHhtbCAke3tHSVRIVUJfV09SS1NQQUNFfX17c2VwfXJlc3VsdHMueG1sICIKCiAgICAjIHNldCBsaWJyYXJpZXMKICAgIGVudl9saWJyYXJpZXMgPSBlbnYuZ2V0KCJsaWJyYXJpZXMiKQogICAgaWYgaXNpbnN0YW5jZShlbnZfbGlicmFyaWVzLCBzdHIpIGFuZCBsZW4oZW52X2xpYnJhcmllcy5zdHJpcCgpKSA9PSAwOgogICAgICAgIGVudl9saWJyYXJpZXMgPSB7fSAgIyBubyBsaWJyYXJpZXMgcmVxdWVzdGVkIGZvciBlbnZpcm9ubWVudAogICAgbGlicmFyaWVzID0gZ2xvYmFsX2xpYnJhcmllcyBpZiBlbnZfbGlicmFyaWVzIGlzIE5vbmUgZWxzZSBlbnZfbGlicmFyaWVzCiAgICBmb3IgbWFuYWdlciBpbiBbImJyZXciLCAiYnJld19jYXNrIiwgImFwdCIsICJjaG9jbyJdOgogICAgICAgIGl0ZW1bZiJsaWJyYXJpZXNfe21hbmFnZXJ9Il0gPSAiICIuam9pbihsaWJyYXJpZXMuZ2V0KG1hbmFnZXIsIFtdKSkKCiAgICAjIHNldCAiYXV0byIgY29uZGEgdmFsdWUKICAgIGlmIGl0ZW1bImNvbmRhIl0gPT0gImF1dG8iOgogICAgICAgIGl0ZW1bImNvbmRhIl0gPSAidHJ1ZSIgaWYgImNvbmRhIiBpbiBpdGVtWyJ0b3hlbnYiXSBlbHNlICJmYWxzZSIKCiAgICAjIGluamVjdCB0b3hkZXBzIGZvciBjb25kYQogICAgaWYgaXRlbVsiY29uZGEiXSA9PSAidHJ1ZSIgYW5kICJ0b3gtY29uZGEiIG5vdCBpbiBpdGVtWyJ0b3hkZXBzIl0ubG93ZXIoKToKICAgICAgICBpdGVtWyJ0b3hkZXBzIl0gPSAoInRveC1jb25kYSAiICsgaXRlbVsidG94ZGVwcyJdKS5zdHJpcCgpCgogICAgIyBtYWtlIHRpbWVvdXQtbWludXRlcyBhIG51bWJlcgogICAgaXRlbVsidGltZW91dC1taW51dGVzIl0gPSBpbnQoaXRlbVsidGltZW91dC1taW51dGVzIl0pCgogICAgIyB2ZXJpZnkgdmFsdWVzCiAgICBhc3NlcnQgaXRlbVsicHl0ZXN0Il0gaW4geyJ0cnVlIiwgImZhbHNlIn0KICAgIGFzc2VydCBpdGVtWyJjb25kYSJdIGluIHsidHJ1ZSIsICJmYWxzZSJ9CiAgICBhc3NlcnQgaXRlbVsiZGlzcGxheSJdIGluIHsidHJ1ZSIsICJmYWxzZSJ9CgogICAgcmV0dXJuIGl0ZW0KCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgbG9hZF90b3hfdGFyZ2V0cygpCg== + TOX_MATRIX_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJjbGljaz09OC4yLjEiLAojICAgICAicHl5YW1sPT02LjAuMiIsCiMgXQojIC8vLwppbXBvcnQganNvbgppbXBvcnQgb3MKaW1wb3J0IHJlCgppbXBvcnQgY2xpY2sKaW1wb3J0IHlhbWwKCgpAY2xpY2suY29tbWFuZCgpCkBjbGljay5vcHRpb24oIi0tZW52cyIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tbGlicmFyaWVzIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS1wb3NhcmdzIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS10b3hkZXBzIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS10b3hhcmdzIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS1weXRlc3QiLCBkZWZhdWx0PSJ0cnVlIikKQGNsaWNrLm9wdGlvbigiLS1weXRlc3QtcmVzdWx0cy1zdW1tYXJ5IiwgZGVmYXVsdD0iZmFsc2UiKQpAY2xpY2sub3B0aW9uKCItLWNvdmVyYWdlIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS1jb25kYSIsIGRlZmF1bHQ9ImF1dG8iKQpAY2xpY2sub3B0aW9uKCItLXNldGVudiIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tZGlzcGxheSIsIGRlZmF1bHQ9ImZhbHNlIikKQGNsaWNrLm9wdGlvbigiLS1jYWNoZS1wYXRoIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS1jYWNoZS1rZXkiLCBkZWZhdWx0PSIiKQpAY2xpY2sub3B0aW9uKCItLWNhY2hlLXJlc3RvcmUta2V5cyIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tYXJ0aWZhY3QtcGF0aCIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tcnVucy1vbiIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tZGVmYXVsdC1weXRob24iLCBkZWZhdWx0PSIiKQpAY2xpY2sub3B0aW9uKCItLXRpbWVvdXQtbWludXRlcyIsIGRlZmF1bHQ9IjM2MCIpCmRlZiBsb2FkX3RveF90YXJnZXRzKGVudnMsIGxpYnJhcmllcywgcG9zYXJncywgdG94ZGVwcywgdG94YXJncywgcHl0ZXN0LCBweXRlc3RfcmVzdWx0c19zdW1tYXJ5LAogICAgICAgICAgICAgICAgICAgICBjb3ZlcmFnZSwgY29uZGEsIHNldGVudiwgZGlzcGxheSwgY2FjaGVfcGF0aCwgY2FjaGVfa2V5LAogICAgICAgICAgICAgICAgICAgICBjYWNoZV9yZXN0b3JlX2tleXMsIGFydGlmYWN0X3BhdGgsIHJ1bnNfb24sIGRlZmF1bHRfcHl0aG9uLCB0aW1lb3V0X21pbnV0ZXMpOgogICAgIiIiU2NyaXB0IHRvIGxvYWQgdG94IHRhcmdldHMgZm9yIEdpdEh1YiBBY3Rpb25zIHdvcmtmbG93LiIiIgogICAgIyBMb2FkIGVudnMgY29uZmlnCiAgICBlbnZzID0geWFtbC5sb2FkKGVudnMsIExvYWRlcj15YW1sLkJhc2VMb2FkZXIpCiAgICBwcmludChqc29uLmR1bXBzKGVudnMsIGluZGVudD0yKSkKCiAgICAjIExvYWQgZ2xvYmFsIGxpYnJhcmllcyBjb25maWcKICAgIGdsb2JhbF9saWJyYXJpZXMgPSB7CiAgICAgICAgImJyZXciOiBbXSwKICAgICAgICAiYnJldy1jYXNrIjogW10sCiAgICAgICAgImFwdCI6IFtdLAogICAgICAgICJjaG9jbyI6IFtdLAogICAgfQogICAgbGlicmFyaWVzID0geWFtbC5sb2FkKGxpYnJhcmllcywgTG9hZGVyPXlhbWwuQmFzZUxvYWRlcikKICAgIGlmIGxpYnJhcmllcyBpcyBub3QgTm9uZToKICAgICAgICBnbG9iYWxfbGlicmFyaWVzLnVwZGF0ZShsaWJyYXJpZXMpCiAgICBwcmludChqc29uLmR1bXBzKGdsb2JhbF9saWJyYXJpZXMsIGluZGVudD0yKSkKCiAgICAjIERlZmF1bHQgaW1hZ2VzIHRvIHVzZSBmb3IgcnVubmVycwogICAgZGVmYXVsdF9ydW5zX29uID0gewogICAgICAgICJsaW51eCI6ICJ1YnVudHUtbGF0ZXN0IiwKICAgICAgICAibWFjb3MiOiAibWFjb3MtbGF0ZXN0IiwKICAgICAgICAid2luZG93cyI6ICJ3aW5kb3dzLWxhdGVzdCIsCiAgICB9CiAgICBjdXN0b21fcnVuc19vbiA9IHlhbWwubG9hZChydW5zX29uLCBMb2FkZXI9eWFtbC5CYXNlTG9hZGVyKQogICAgaWYgaXNpbnN0YW5jZShjdXN0b21fcnVuc19vbiwgZGljdCk6CiAgICAgICAgZGVmYXVsdF9ydW5zX29uLnVwZGF0ZShjdXN0b21fcnVuc19vbikKICAgIHByaW50KGpzb24uZHVtcHMoZGVmYXVsdF9ydW5zX29uLCBpbmRlbnQ9MikpCgogICAgIyBEZWZhdWx0IHN0cmluZyBwYXJhbWV0ZXJzIHdoaWNoIGNhbiBiZSBvdmVyd3JpdHRlbiBieSBlYWNoIGVudgogICAgc3RyaW5nX3BhcmFtZXRlcnMgPSB7CiAgICAgICAgInBvc2FyZ3MiOiBwb3NhcmdzLAogICAgICAgICJ0b3hkZXBzIjogdG94ZGVwcywKICAgICAgICAidG94YXJncyI6IHRveGFyZ3MsCiAgICAgICAgInB5dGVzdCI6IHB5dGVzdCwKICAgICAgICAicHl0ZXN0LXJlc3VsdHMtc3VtbWFyeSI6IHB5dGVzdF9yZXN1bHRzX3N1bW1hcnksCiAgICAgICAgImNvdmVyYWdlIjogY292ZXJhZ2UsCiAgICAgICAgImNvbmRhIjogY29uZGEsCiAgICAgICAgInNldGVudiI6IHNldGVudiwKICAgICAgICAiZGlzcGxheSI6IGRpc3BsYXksCiAgICAgICAgImNhY2hlLXBhdGgiOiBjYWNoZV9wYXRoLAogICAgICAgICJjYWNoZS1rZXkiOiBjYWNoZV9rZXksCiAgICAgICAgImNhY2hlLXJlc3RvcmUta2V5cyI6IGNhY2hlX3Jlc3RvcmVfa2V5cywKICAgICAgICAiYXJ0aWZhY3QtcGF0aCI6IGFydGlmYWN0X3BhdGgsCiAgICAgICAgInRpbWVvdXQtbWludXRlcyI6IHRpbWVvdXRfbWludXRlcywKICAgIH0KCiAgICAjIENyZWF0ZSBtYXRyaXgKICAgIG1hdHJpeCA9IHsiaW5jbHVkZSI6IFtdfQogICAgZm9yIGVudiBpbiBlbnZzOgogICAgICAgIG1hdHJpeFsiaW5jbHVkZSJdLmFwcGVuZChnZXRfbWF0cml4X2l0ZW0oCiAgICAgICAgICAgIGVudiwKICAgICAgICAgICAgZ2xvYmFsX2xpYnJhcmllcz1nbG9iYWxfbGlicmFyaWVzLAogICAgICAgICAgICBnbG9iYWxfc3RyaW5nX3BhcmFtZXRlcnM9c3RyaW5nX3BhcmFtZXRlcnMsCiAgICAgICAgICAgIHJ1bnNfb249ZGVmYXVsdF9ydW5zX29uLAogICAgICAgICAgICBkZWZhdWx0X3B5dGhvbj1kZWZhdWx0X3B5dGhvbiwKICAgICAgICApKQoKICAgICMgT3V0cHV0IG1hdHJpeAogICAgcHJpbnQoanNvbi5kdW1wcyhtYXRyaXgsIGluZGVudD0yKSkKICAgIHdpdGggb3Blbihvcy5lbnZpcm9uWyJHSVRIVUJfT1VUUFVUIl0sICJhIikgYXMgZjoKICAgICAgICBmLndyaXRlKGYibWF0cml4PXtqc29uLmR1bXBzKG1hdHJpeCl9XG4iKQoKCmRlZiBnZXRfbWF0cml4X2l0ZW0oZW52LCBnbG9iYWxfbGlicmFyaWVzLCBnbG9iYWxfc3RyaW5nX3BhcmFtZXRlcnMsCiAgICAgICAgICAgICAgICAgICAgcnVuc19vbiwgZGVmYXVsdF9weXRob24pOgoKICAgICMgZGVmaW5lIHNwZWMgZm9yIGVhY2ggbWF0cml4IGluY2x1ZGUgKCsgZ2xvYmFsX3N0cmluZ19wYXJhbWV0ZXJzKQogICAgaXRlbSA9IHsKICAgICAgICAib3MiOiBOb25lLAogICAgICAgICJ0b3hlbnYiOiBOb25lLAogICAgICAgICJweXRob25fdmVyc2lvbiI6IE5vbmUsCiAgICAgICAgIm5hbWUiOiBOb25lLAogICAgICAgICJweXRlc3RfZmxhZyI6IE5vbmUsCiAgICAgICAgImxpYnJhcmllc19icmV3IjogTm9uZSwKICAgICAgICAibGlicmFyaWVzX2JyZXdfY2FzayI6IE5vbmUsCiAgICAgICAgImxpYnJhcmllc19hcHQiOiBOb25lLAogICAgICAgICJsaWJyYXJpZXNfY2hvY28iOiBOb25lLAogICAgICAgICJjYWNoZS1wYXRoIjogTm9uZSwKICAgICAgICAiY2FjaGUta2V5IjogTm9uZSwKICAgICAgICAiY2FjaGUtcmVzdG9yZS1rZXlzIjogTm9uZSwKICAgICAgICAiYXJ0aWZhY3QtbmFtZSI6IE5vbmUsCiAgICAgICAgImFydGlmYWN0LXBhdGgiOiBOb25lLAogICAgICAgICJ0aW1lb3V0LW1pbnV0ZXMiOiBOb25lLAogICAgfQogICAgZm9yIHN0cmluZ19wYXJhbSwgZGVmYXVsdCBpbiBnbG9iYWxfc3RyaW5nX3BhcmFtZXRlcnMuaXRlbXMoKToKICAgICAgICBlbnZfdmFsdWUgPSBlbnYuZ2V0KHN0cmluZ19wYXJhbSkKICAgICAgICBpdGVtW3N0cmluZ19wYXJhbV0gPSBkZWZhdWx0IGlmIGVudl92YWx1ZSBpcyBOb25lIGVsc2UgZW52X3ZhbHVlCgogICAgIyBzZXQgb3MgYW5kIHRveGVudgogICAgZm9yIGssIHYgaW4gcnVuc19vbi5pdGVtcygpOgogICAgICAgIGlmIGsgaW4gZW52OgogICAgICAgICAgICBwbGF0Zm9ybSA9IGsKICAgICAgICAgICAgaXRlbVsib3MiXSA9IGVudi5nZXQoInJ1bnMtb24iLCB2KQogICAgICAgICAgICBpdGVtWyJ0b3hlbnYiXSA9IGVudltrXQogICAgYXNzZXJ0IGl0ZW1bIm9zIl0gaXMgbm90IE5vbmUgYW5kIGl0ZW1bInRveGVudiJdIGlzIG5vdCBOb25lCgogICAgIyBzZXQgcHl0aG9uX3ZlcnNpb24KICAgIHB5dGhvbl92ZXJzaW9uID0gZW52LmdldCgicHl0aG9uLXZlcnNpb24iKQogICAgbSA9IHJlLnNlYXJjaCgiXnB5KDJ8MykoWzAtOV0rdD8pIiwgaXRlbVsidG94ZW52Il0pCiAgICBpZiBweXRob25fdmVyc2lvbiBpcyBub3QgTm9uZToKICAgICAgICBpdGVtWyJweXRob25fdmVyc2lvbiJdID0gcHl0aG9uX3ZlcnNpb24KICAgIGVsaWYgbSBpcyBub3QgTm9uZToKICAgICAgICBtYWpvciwgbWlub3IgPSBtLmdyb3VwcygpCiAgICAgICAgaXRlbVsicHl0aG9uX3ZlcnNpb24iXSA9IGYie21ham9yfS57bWlub3J9IgogICAgZWxzZToKICAgICAgICBpdGVtWyJweXRob25fdmVyc2lvbiJdID0gZW52LmdldCgiZGVmYXVsdF9weXRob24iKSBvciBkZWZhdWx0X3B5dGhvbgoKICAgICMgc2V0IG5hbWUKICAgIGl0ZW1bIm5hbWUiXSA9IGVudi5nZXQoIm5hbWUiKSBvciBmJ3tpdGVtWyJ0b3hlbnYiXX0gKHtpdGVtWyJvcyJdfSknCgogICAgIyBzZXQgYXJ0aWZhY3QtbmFtZSAocmVwbGFjZSBpbnZhbGlkIHBhdGggY2hhcmFjdGVycykKICAgIGl0ZW1bImFydGlmYWN0LW5hbWUiXSA9IHJlLnN1YihyIltcXCAvOjw+fCo/XCInXSIsICItIiwgaXRlbVsibmFtZSJdKQogICAgaXRlbVsiYXJ0aWZhY3QtbmFtZSJdID0gcmUuc3ViKHIiLSsiLCAiLSIsIGl0ZW1bImFydGlmYWN0LW5hbWUiXSkKCiAgICAjIHNldCBweXRlc3RfZmxhZwogICAgaXRlbVsicHl0ZXN0X2ZsYWciXSA9ICIiCiAgICBzZXAgPSByIlxcIiBpZiBwbGF0Zm9ybSA9PSAid2luZG93cyIgZWxzZSAiLyIKICAgIGlmIGl0ZW1bInB5dGVzdCJdID09ICJ0cnVlIjoKICAgICAgICBpZiAiY29kZWNvdiIgaW4gaXRlbS5nZXQoImNvdmVyYWdlIiwgIiIpOgogICAgICAgICAgICBpdGVtWyJweXRlc3RfZmxhZyJdICs9ICgKICAgICAgICAgICAgICAgIHJmIi0tY292IC0tY292LXJlcG9ydD14bWw6JHt7R0lUSFVCX1dPUktTUEFDRX19e3NlcH1jb3ZlcmFnZS54bWwgIgogICAgICAgICAgICApCgogICAgICAgIGlmIGl0ZW1bInB5dGVzdC1yZXN1bHRzLXN1bW1hcnkiXSA9PSAidHJ1ZSI6CiAgICAgICAgICAgIGl0ZW1bInB5dGVzdF9mbGFnIl0gKz0gcmYiLS1qdW5pdHhtbCAke3tHSVRIVUJfV09SS1NQQUNFfX17c2VwfXJlc3VsdHMueG1sICIKCiAgICAjIHNldCBsaWJyYXJpZXMKICAgIGVudl9saWJyYXJpZXMgPSBlbnYuZ2V0KCJsaWJyYXJpZXMiKQogICAgaWYgaXNpbnN0YW5jZShlbnZfbGlicmFyaWVzLCBzdHIpIGFuZCBsZW4oZW52X2xpYnJhcmllcy5zdHJpcCgpKSA9PSAwOgogICAgICAgIGVudl9saWJyYXJpZXMgPSB7fSAgIyBubyBsaWJyYXJpZXMgcmVxdWVzdGVkIGZvciBlbnZpcm9ubWVudAogICAgbGlicmFyaWVzID0gZ2xvYmFsX2xpYnJhcmllcyBpZiBlbnZfbGlicmFyaWVzIGlzIE5vbmUgZWxzZSBlbnZfbGlicmFyaWVzCiAgICBmb3IgbWFuYWdlciBpbiBbImJyZXciLCAiYnJld19jYXNrIiwgImFwdCIsICJjaG9jbyJdOgogICAgICAgIGl0ZW1bZiJsaWJyYXJpZXNfe21hbmFnZXJ9Il0gPSAiICIuam9pbihsaWJyYXJpZXMuZ2V0KG1hbmFnZXIsIFtdKSkKCiAgICAjIHNldCAiYXV0byIgY29uZGEgdmFsdWUKICAgIGlmIGl0ZW1bImNvbmRhIl0gPT0gImF1dG8iOgogICAgICAgIGl0ZW1bImNvbmRhIl0gPSAidHJ1ZSIgaWYgImNvbmRhIiBpbiBpdGVtWyJ0b3hlbnYiXSBlbHNlICJmYWxzZSIKCiAgICAjIGluamVjdCB0b3hkZXBzIGZvciBjb25kYQogICAgaWYgaXRlbVsiY29uZGEiXSA9PSAidHJ1ZSIgYW5kICJ0b3gtY29uZGEiIG5vdCBpbiBpdGVtWyJ0b3hkZXBzIl0ubG93ZXIoKToKICAgICAgICBpdGVtWyJ0b3hkZXBzIl0gPSAoInRveC1jb25kYSAiICsgaXRlbVsidG94ZGVwcyJdKS5zdHJpcCgpCgogICAgIyBtYWtlIHRpbWVvdXQtbWludXRlcyBhIG51bWJlcgogICAgaXRlbVsidGltZW91dC1taW51dGVzIl0gPSBpbnQoaXRlbVsidGltZW91dC1taW51dGVzIl0pCgogICAgIyB2ZXJpZnkgdmFsdWVzCiAgICBhc3NlcnQgaXRlbVsicHl0ZXN0Il0gaW4geyJ0cnVlIiwgImZhbHNlIn0KICAgIGFzc2VydCBpdGVtWyJjb25kYSJdIGluIHsidHJ1ZSIsICJmYWxzZSJ9CiAgICBhc3NlcnQgaXRlbVsiZGlzcGxheSJdIGluIHsidHJ1ZSIsICJmYWxzZSJ9CgogICAgcmV0dXJuIGl0ZW0KCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgbG9hZF90b3hfdGFyZ2V0cygpCg== - run: cat tox_matrix.py - id: set-outputs run: | @@ -141,6 +139,8 @@ jobs: --runs-on "${{ inputs.runs-on }}" --default-python "${{ inputs.default_python }}" \ --timeout-minutes "${{ inputs.timeout-minutes }}" shell: sh + outputs: + matrix: ${{ steps.set-outputs.outputs.matrix }} tox: name: ${{ matrix.name }} @@ -236,3 +236,47 @@ jobs: uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 with: token: ${{ secrets.CODECOV_TOKEN }} + + - name: Upload coverage data to GitHub + id: upload-coverage-gh + if: ${{ (success() || failure()) && contains(matrix.coverage, 'github') && matrix.pytest == 'true' }} + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + with: + name: coverage-data-${{ github.run_id }}-${{ runner.os }}-${{ runner.arch }}-${{ matrix.toxenv }} + path: .coverage.* + if-no-files-found: error + include-hidden-files: true + outputs: + coverage-gh: ${{ steps.upload-coverage-gh.outputs.artifact-id }} + + report_overall_test_coverage: + needs: [ tox ] + if: needs.tox.outputs.coverage-gh + name: report overall test coverage + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + lfs: true + submodules: ${{ inputs.submodules }} + ref: ${{ inputs.checkout_ref }} + - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + with: + pattern: coverage-data-${{ github.run_id }}-* + merge-multiple: true + + - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + with: + python-version: "3.12" + - name: generate coverage report + run: | + python -Im pip install 'pip>=25.1' + python -Im pip install --group covcheck + python -Im coverage combine + python -Im coverage report -i -m --format=markdown >> $GITHUB_STEP_SUMMARY + - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + with: + name: coverage-report-${{ hashFiles('.coverage') }} + path: .coverage + if-no-files-found: error + include-hidden-files: true diff --git a/docs/source/tox.rst b/docs/source/tox.rst index f6edcb01..b61e49e4 100644 --- a/docs/source/tox.rst +++ b/docs/source/tox.rst @@ -164,8 +164,8 @@ This option has no effect if ``pytest`` is ``false``. coverage ^^^^^^^^ -A space separated list of coverage providers to upload to. Currently -only ``codecov`` is supported. Default is to not upload coverage +A space separated list of coverage providers to upload to, either +``codecov`` or ``github``. Default is to not upload coverage reports. See also, ``CODECOV_TOKEN`` secret. diff --git a/pyproject.toml b/pyproject.toml index 5dda3f19..aa6ac868 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,11 @@ concurrency = [ "pytest-repeat>=0.9.3", "pytest-run-parallel>=0.4.4", ] +covcheck = [ + "coverage[toml] ; python_version < '3.11'", + "coverage>=7.11.3", + "pytest-cov>=7.0.0", +] test = [ "hypothesis>=6.113.0", "pytest>=8.3.5", diff --git a/tools/tox_matrix.py b/tools/tox_matrix.py index f10a1a83..76c3f1a2 100644 --- a/tools/tox_matrix.py +++ b/tools/tox_matrix.py @@ -152,11 +152,14 @@ def get_matrix_item(env, global_libraries, global_string_parameters, # set pytest_flag item["pytest_flag"] = "" sep = r"\\" if platform == "windows" else "/" - if item["pytest"] == "true" and "codecov" in item.get("coverage", ""): - item["pytest_flag"] += ( - rf"--cov-report=xml:${{GITHUB_WORKSPACE}}{sep}coverage.xml ") - if item["pytest"] == "true" and item["pytest-results-summary"] == "true": - item["pytest_flag"] += rf"--junitxml ${{GITHUB_WORKSPACE}}{sep}results.xml " + if item["pytest"] == "true": + if "codecov" in item.get("coverage", ""): + item["pytest_flag"] += ( + rf"--cov --cov-report=xml:${{GITHUB_WORKSPACE}}{sep}coverage.xml " + ) + + if item["pytest-results-summary"] == "true": + item["pytest_flag"] += rf"--junitxml ${{GITHUB_WORKSPACE}}{sep}results.xml " # set libraries env_libraries = env.get("libraries") diff --git a/tox.ini b/tox.ini index dd2e56e8..cfe6b406 100644 --- a/tox.ini +++ b/tox.ini @@ -7,6 +7,7 @@ envlist = py{,py}3{10,13}-python_version libraries cache-{setup,verify} + covcheck [testenv] allowlist_externals = @@ -17,6 +18,9 @@ allowlist_externals = bash rolldice which +dependency_groups = + covcheck: covcheck + covcheck: test skip_install = true passenv = MY_VAR commands = @@ -48,6 +52,7 @@ commands = artifact-upload: bash -c "echo 'hello world' > test.txt" # Verify that freethreaded builds are using freethreaded interpreter py313t: python -c "import sys; assert 'free-threading' in sys.version" + covcheck: coverage run --parallel-mode -m pytest --pyargs test_package {posargs} [testenv:pep8] description = verify pep8