diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c60d0c2..84190e3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -134,6 +134,60 @@ jobs: name: test-report path: report.html + # The same reports, rendered and linkable. An artifact is a zip behind an authenticated + # download, so it cannot be linked from the readme; Pages can. Master only, and the site is + # public, which is what a public repository's CI output already is. + pages: + name: publish reports + needs: [summary, coverage] + if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deploy.outputs.page_url }} + + steps: + - uses: actions/download-artifact@v4 + with: + name: test-report + path: site/tests + + - uses: actions/download-artifact@v4 + with: + name: coverage-site + path: site/coverage + + - name: Landing page + shell: bash + run: | + mv site/tests/report.html site/tests/index.html + cat > site/index.html <<'HTML' + + + ImpromptuInterface — CI reports + +

ImpromptuInterface — CI reports

+

Generated by the latest master build.

+ +

Back to the repository

+ HTML + + - uses: actions/upload-pages-artifact@v3 + with: + path: site + + - id: deploy + uses: actions/deploy-pages@v4 + # Line and branch coverage of the library, through coverlet's MTP extension - the test exe # instruments itself, so there is no external collector. Restricted to the library, since # coverlet will instrument anything it can find sources for. @@ -169,7 +223,7 @@ jobs: dotnet tool install --global dotnet-reportgenerator-globaltool export PATH="$PATH:$HOME/.dotnet/tools" reportgenerator -reports:'coverage/coverage.cobertura.*.xml' -targetdir:coverage/report \ - -reporttypes:'Cobertura;MarkdownSummaryGithub' + -reporttypes:'Cobertura;MarkdownSummaryGithub;Html' cat coverage/report/SummaryGithub.md >> "$GITHUB_STEP_SUMMARY" - name: Upload coverage @@ -178,6 +232,64 @@ jobs: name: coverage path: coverage/report/Cobertura.xml + - name: Upload the browsable coverage report + uses: actions/upload-artifact@v4 + with: + name: coverage-site + path: coverage/report + + # After a green master run, rewrite the README's test and coverage badges from that run's own + # numbers, and commit only if one changed. [skip ci] so the badge commit starts no new run. + # No external badge service and no GitHub Pages: the shields URLs are static text in the + # README, and this edits them. + badges: + name: badges + needs: [build, wasm, coverage] + if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + name: results-ubuntu-latest + path: results + + - uses: actions/download-artifact@v4 + with: + name: coverage + path: coverage + + - name: Rewrite badges + shell: bash + run: | + set -e + tests=$(python3 - <<'PY' + import json, glob + d = json.load(open(glob.glob('results/**/net10.0.json', recursive=True)[0])) + print(sum(1 for a in d['Assemblies'] for f in a['Fixtures'] for t in f['Tests'] + for r in t['Results'] if r['Kind'] == 'Success')) + PY + ) + read line branch < <(python3 - <<'PY' + import glob, xml.etree.ElementTree as ET + t = ET.parse(glob.glob('coverage/**/Cobertura.xml', recursive=True)[0]).getroot() + print(round(float(t.get('line-rate')) * 100), round(float(t.get('branch-rate')) * 100)) + PY + ) + color() { if [ "$1" -ge 90 ]; then echo brightgreen; elif [ "$1" -ge 75 ]; then echo green; else echo yellow; fi; } + sed -i -E "s|tests-[0-9]+%20passed-[a-z]+|tests-${tests}%20passed-brightgreen|" Readme.md + sed -i -E "s|line%20coverage-[0-9]+%25-[a-z]+|line%20coverage-${line}%25-$(color $line)|" Readme.md + sed -i -E "s|branch%20coverage-[0-9]+%25-[a-z]+|branch%20coverage-${branch}%25-$(color $branch)|" Readme.md + git diff --quiet Readme.md && { echo "badges unchanged"; exit 0; } + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git commit -am "Readme: badges from the latest master run (${tests} tests, ${line}% line, ${branch}% branch) [skip ci]" + git push + publish: name: publish prerelease needs: [build, wasm] diff --git a/Readme.md b/Readme.md index 3418d2a..e4b1b22 100644 --- a/Readme.md +++ b/Readme.md @@ -1,14 +1,18 @@ net4.0/netstd2.0 framework to allow you to wrap any object (static or dynamic) with a static interface even though it didn't inherit from it. It does this by emitting cached dynamic binding code inside a proxy. -ImpromptuInterface is available Nuget [![NuGet](https://img.shields.io/nuget/dt/ImpromptuInterface.svg)](https://www.nuget.org/packages/ImpromptuInterface/) +[![build](https://github.com/ekonbenefits/impromptu-interface/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/ekonbenefits/impromptu-interface/actions/workflows/build.yml?query=branch%3Amaster) +[![Tests](https://img.shields.io/badge/tests-190%20passed-brightgreen.svg?style=flat)](https://github.com/ekonbenefits/impromptu-interface/actions/workflows/build.yml?query=branch%3Amaster) +[![Line coverage](https://img.shields.io/badge/line%20coverage-84%25-green.svg?style=flat)](https://github.com/ekonbenefits/impromptu-interface/actions/workflows/build.yml?query=branch%3Amaster) +[![Branch coverage](https://img.shields.io/badge/branch%20coverage-70%25-yellow.svg?style=flat)](https://github.com/ekonbenefits/impromptu-interface/actions/workflows/build.yml?query=branch%3Amaster) +[![NuGet](https://img.shields.io/nuget/dt/ImpromptuInterface.svg)](https://www.nuget.org/packages/ImpromptuInterface/) + +Available on [NuGet](https://www.nuget.org/packages/ImpromptuInterface/). One workflow covers +`net40`, `netstandard2.0` and `net10.0` on Windows, macOS and Linux, plus a browser-wasm leg. +From the latest master build: [test results](https://ekonbenefits.github.io/impromptu-interface/tests/) +and [coverage](https://ekonbenefits.github.io/impromptu-interface/coverage/). Every run also +carries its own per-platform table in the run summary. -Platform | Status --------- | ------ -NET4 (Win) | [![Build status](https://github.com/ekonbenefits/impromptu-interface/actions/workflows/dotnet48.yml/badge.svg)](https://github.com/ekonbenefits/impromptu-interface/actions/workflows/dotnet48.yml?query=branch%3Amaster) -NETSTD (Win/Mac/Linux) | [![Build status](https://github.com/ekonbenefits/impromptu-interface/actions/workflows/dotnet.yml/badge.svg)](https://github.com/ekonbenefits/impromptu-interface/actions/workflows/dotnet.yml?query=branch%3Amaster) - - Some of the features of `ImpromptuInterface` have been moved into another library called [Dynamitey](https://github.com/ekonbenefits/dynamitey), `ImpromptuInterface` depends on `Dynamitey`. `ImpromptuInterface.FSharp` has been spun off into [FSharp.Interop.Dynamic](https://github.com/fsprojects/FSharp.Interop.Dynamic) and also depends on `Dynamitey`.