@@ -66,14 +66,40 @@ jobs:
6666          python-version : ${{ matrix.python-version }} 
6767          allow-prereleases : true 
6868
69-       - name : Test typing_extensions 
69+       - name : Install coverage 
70+         if : ${{ !startsWith(matrix.python-version, 'pypy') }} 
71+         run : | 
72+           # Be wary that this does not install typing_extensions in the future 
73+           pip install coverage 
74+ 
75+        - name : Test typing_extensions with coverage 
76+         if : ${{ !startsWith(matrix.python-version, 'pypy') }} 
77+         run : | 
78+           # Be wary of running `pip install` here, since it becomes easy for us to 
79+           # accidentally pick up typing_extensions as installed by a dependency 
80+           cd src 
81+           python --version  # just to make sure we're running the right one 
82+           # Run tests under coverage 
83+           export COVERAGE_FILE=.coverage_${{ matrix.python-version }} 
84+           python -m coverage run -m unittest test_typing_extensions.py 
85+        - name : Test typing_extensions no coverage on pypy 
86+         if : ${{ startsWith(matrix.python-version, 'pypy') }} 
7087        run : | 
7188          # Be wary of running `pip install` here, since it becomes easy for us to 
7289          # accidentally pick up typing_extensions as installed by a dependency 
7390          cd src 
7491          python --version  # just to make sure we're running the right one 
7592          python -m unittest test_typing_extensions.py 
7693
94+        - name : Archive code coverage results 
95+         id : archive-coverage 
96+         if : ${{ !startsWith(matrix.python-version, 'pypy') }} 
97+         uses : actions/upload-artifact@v4 
98+         with :
99+           name : .coverage_${{ matrix.python-version }} 
100+           path : ./src/.coverage* 
101+           include-hidden-files : true 
102+           compression-level : 0  #  no compression
77103      - name : Test CPython typing test suite 
78104        #  Test suite fails on PyPy even without typing_extensions
79105        if : ${{ !startsWith(matrix.python-version, 'pypy') }} 
82108          # Run the typing test suite from CPython with typing_extensions installed, 
83109          # because we monkeypatch typing under some circumstances. 
84110          python -c 'import typing_extensions; import test.__main__' test_typing -v 
111+      outputs :
112+       #  report if coverage was uploaded
113+       cov_uploaded : ${{ steps.archive-coverage.outputs.artifact-id }} 
85114
86115  create-issue-on-failure :
87116    name : Create an issue if daily tests failed 
@@ -111,3 +140,77 @@ jobs:
111140              title: `Daily tests failed on ${new Date().toDateString()}`, 
112141              body: "Runs listed here: https://github.com/python/typing_extensions/actions/workflows/ci.yml", 
113142            }) 
143+ 
144+    report-coverage :
145+     name : Report coverage 
146+ 
147+     runs-on : ubuntu-latest 
148+ 
149+     needs : [tests] 
150+ 
151+     permissions :
152+       pull-requests : write 
153+ 
154+     #  Job will run even if tests failed but only if at least one artifact was uploaded
155+     if : ${{ always() && needs.tests.outputs.cov_uploaded != '' }} 
156+ 
157+     steps :
158+       - uses : actions/checkout@v4 
159+         with :
160+           persist-credentials : false 
161+       - name : Set up Python 
162+         uses : actions/setup-python@v5 
163+         with :
164+           python-version : " 3" 
165+       - name : Download coverage artifacts 
166+         uses : actions/download-artifact@v4 
167+         with :
168+           pattern : .coverage_* 
169+           path : . 
170+           #  merge only when files are named differently
171+           merge-multiple : true 
172+       - name : Install dependencies 
173+         run : pip install coverage 
174+       - name : Combine coverage results 
175+         run : | 
176+           # List the files to see what we have 
177+           echo "Combining coverage files..." 
178+           ls -aR .coverage* 
179+           coverage combine .coverage* 
180+           echo "Creating coverage report..." 
181+           # Create a coverage report (console) 
182+           coverage report 
183+           # Create xml file for further processing 
184+           coverage xml 
185+ 
186+        #  For future use in case we want to add a PR comment for 3rd party PRs which requires
187+       #  a workflow with elevated PR write permissions. Move below steps into a separate job.
188+       - name : Archive code coverage report 
189+         uses : actions/upload-artifact@v4 
190+         with :
191+           name : coverage 
192+           path : coverage.xml 
193+ 
194+       - name : Code Coverage Report 
195+         uses : irongut/CodeCoverageSummary@51cc3a756ddcd398d447c044c02cb6aa83fdae95  #  v1.3.0
196+         with :
197+           filename : coverage.xml 
198+           badge : true 
199+           fail_below_min : true 
200+           format : markdown 
201+           hide_branch_rate : false 
202+           hide_complexity : true 
203+           indicators : true 
204+           output : both   #  console, file or both
205+           thresholds : ' 90 95' 
206+ 
207+       - name : Add Coverage PR Comment 
208+         uses : marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728   #  v2.9.3
209+         #  Create PR comment when the branch is on the repo, otherwise we lack PR write permissions
210+         #  -> need another workflow with access to secret token
211+         if : >- 
212+           github.event_name == 'pull_request' 
213+           && github.event.pull_request.head.repo.full_name == github.repository 
214+          with :
215+           recreate : true 
216+           path : code-coverage-results.md 
0 commit comments