Skip to content

Commit de438f2

Browse files
committed
ci: add coverage report and sonarcloud scan on PRs
generate xml + html coverage on the ubuntu/3.13 matrix cell, upload as artifacts, and run a sonarcloud scan that imports all three packages coverage.xml so the quality gate "coverage on new code" works.
1 parent ed18224 commit de438f2

5 files changed

Lines changed: 171 additions & 13 deletions

File tree

.github/workflows/test-packages.yml

Lines changed: 103 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,31 @@ jobs:
7777
run: uv sync --all-extras --python ${{ matrix.python-version }}
7878

7979
- name: Run tests
80-
if: steps.check.outputs.skip != 'true'
80+
if: steps.check.outputs.skip != 'true' && !(matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13')
8181
working-directory: packages/uipath-core
8282
run: uv run pytest
8383

84+
- name: Run tests with coverage
85+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
86+
working-directory: packages/uipath-core
87+
run: uv run pytest --cov-report=xml --cov-report=html --tb=short
88+
89+
- name: Upload coverage HTML report
90+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && always()
91+
uses: actions/upload-artifact@v4
92+
with:
93+
name: coverage-html-uipath-core
94+
path: packages/uipath-core/htmlcov/
95+
retention-days: 30
96+
97+
- name: Upload coverage XML report
98+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && always()
99+
uses: actions/upload-artifact@v4
100+
with:
101+
name: coverage-xml-uipath-core
102+
path: packages/uipath-core/coverage.xml
103+
retention-days: 30
104+
84105
test-uipath-platform:
85106
name: Test (uipath-platform, ${{ matrix.python-version }}, ${{ matrix.os }})
86107
needs: detect-changed-packages
@@ -126,10 +147,31 @@ jobs:
126147
run: uv sync --all-extras --python ${{ matrix.python-version }}
127148

128149
- name: Run tests
129-
if: steps.check.outputs.skip != 'true'
150+
if: steps.check.outputs.skip != 'true' && !(matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13')
130151
working-directory: packages/uipath-platform
131152
run: uv run pytest
132153

154+
- name: Run tests with coverage
155+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
156+
working-directory: packages/uipath-platform
157+
run: uv run pytest --cov-report=xml --cov-report=html --tb=short
158+
159+
- name: Upload coverage HTML report
160+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && always()
161+
uses: actions/upload-artifact@v4
162+
with:
163+
name: coverage-html-uipath-platform
164+
path: packages/uipath-platform/htmlcov/
165+
retention-days: 30
166+
167+
- name: Upload coverage XML report
168+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && always()
169+
uses: actions/upload-artifact@v4
170+
with:
171+
name: coverage-xml-uipath-platform
172+
path: packages/uipath-platform/coverage.xml
173+
retention-days: 30
174+
133175
e2e-uipath-platform:
134176
name: E2E (uipath-platform, memory)
135177
needs: detect-changed-packages
@@ -225,12 +267,70 @@ jobs:
225267
run: uv sync --all-extras --python ${{ matrix.python-version }}
226268

227269
- name: Run tests
228-
if: steps.check.outputs.skip != 'true'
270+
if: steps.check.outputs.skip != 'true' && !(matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13')
229271
working-directory: packages/uipath
230272
run: uv run pytest
231273

274+
- name: Run tests with coverage
275+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
276+
working-directory: packages/uipath
277+
run: uv run pytest --cov-report=xml --cov-report=html --tb=short
278+
279+
- name: Upload coverage HTML report
280+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && always()
281+
uses: actions/upload-artifact@v4
282+
with:
283+
name: coverage-html-uipath
284+
path: packages/uipath/htmlcov/
285+
retention-days: 30
286+
287+
- name: Upload coverage XML report
288+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && always()
289+
uses: actions/upload-artifact@v4
290+
with:
291+
name: coverage-xml-uipath
292+
path: packages/uipath/coverage.xml
293+
retention-days: 30
294+
232295
continue-on-error: true
233296

297+
sonarcloud:
298+
name: SonarCloud
299+
needs: [test-uipath-core, test-uipath-platform, test-uipath]
300+
runs-on: ubuntu-latest
301+
if: github.event_name == 'pull_request' && always() && needs.test-uipath-core.result != 'failure' && needs.test-uipath-platform.result != 'failure' && needs.test-uipath.result != 'failure'
302+
steps:
303+
- name: Checkout
304+
uses: actions/checkout@v4
305+
with:
306+
fetch-depth: 0
307+
308+
- name: Download uipath-core coverage
309+
uses: actions/download-artifact@v4
310+
continue-on-error: true
311+
with:
312+
name: coverage-xml-uipath-core
313+
path: packages/uipath-core
314+
315+
- name: Download uipath-platform coverage
316+
uses: actions/download-artifact@v4
317+
continue-on-error: true
318+
with:
319+
name: coverage-xml-uipath-platform
320+
path: packages/uipath-platform
321+
322+
- name: Download uipath coverage
323+
uses: actions/download-artifact@v4
324+
continue-on-error: true
325+
with:
326+
name: coverage-xml-uipath
327+
path: packages/uipath
328+
329+
- name: SonarCloud Scan
330+
uses: SonarSource/sonarqube-scan-action@2f77a1ec69fb1d595b06f35ab27e97605bdef703 # v5
331+
env:
332+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
333+
234334
test-gate:
235335
name: Test
236336
needs: [test-uipath-core, test-uipath-platform, test-uipath, e2e-uipath-platform]

packages/uipath-core/pyproject.toml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,26 @@ addopts = "-ra -q --cov=src/uipath --cov-report=term-missing"
9999
asyncio_default_fixture_loop_scope = "function"
100100
asyncio_mode = "auto"
101101

102+
[tool.coverage.run]
103+
source = ["src/uipath"]
104+
relative_files = true
105+
omit = [
106+
"*/tests/*",
107+
"*/__pycache__/*",
108+
"*/site-packages/*",
109+
"*/conftest.py",
110+
]
111+
102112
[tool.coverage.report]
103113
show_missing = true
104-
105-
[tool.coverage.run]
106-
source = ["src"]
114+
precision = 2
115+
exclude_lines = [
116+
"pragma: no cover",
117+
"def __repr__",
118+
"raise NotImplementedError",
119+
"if TYPE_CHECKING:",
120+
"@(abc\\.)?abstractmethod",
121+
]
107122

108123
[[tool.uv.index]]
109124
name = "testpypi"

packages/uipath-platform/pyproject.toml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,26 @@ markers = [
105105
"e2e: end-to-end tests against real ECS/LLMOps (requires UIPATH_URL, UIPATH_ACCESS_TOKEN, UIPATH_FOLDER_KEY)",
106106
]
107107

108+
[tool.coverage.run]
109+
source = ["src/uipath"]
110+
relative_files = true
111+
omit = [
112+
"*/tests/*",
113+
"*/__pycache__/*",
114+
"*/site-packages/*",
115+
"*/conftest.py",
116+
]
117+
108118
[tool.coverage.report]
109119
show_missing = true
110-
111-
[tool.coverage.run]
112-
source = ["src"]
120+
precision = 2
121+
exclude_lines = [
122+
"pragma: no cover",
123+
"def __repr__",
124+
"raise NotImplementedError",
125+
"if TYPE_CHECKING:",
126+
"@(abc\\.)?abstractmethod",
127+
]
113128

114129
[tool.uv.sources]
115130
uipath-core = { path = "../uipath-core", editable = true }

packages/uipath/pyproject.toml

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,30 @@ warn_required_dynamic_aliases = true
137137
[tool.pytest.ini_options]
138138
testpaths = ["tests"]
139139
python_files = "test_*.py"
140-
addopts = "-ra -q --cov"
140+
addopts = "-ra -q --cov=src/uipath --cov-report=term-missing"
141141
asyncio_default_fixture_loop_scope = "function"
142142
asyncio_mode = "auto"
143143

144+
[tool.coverage.run]
145+
source = ["src/uipath"]
146+
relative_files = true
147+
omit = [
148+
"*/tests/*",
149+
"*/__pycache__/*",
150+
"*/site-packages/*",
151+
"*/conftest.py",
152+
]
153+
144154
[tool.coverage.report]
145155
show_missing = true
146-
147-
[tool.coverage.run]
148-
source = ["src"]
156+
precision = 2
157+
exclude_lines = [
158+
"pragma: no cover",
159+
"def __repr__",
160+
"raise NotImplementedError",
161+
"if TYPE_CHECKING:",
162+
"@(abc\\.)?abstractmethod",
163+
]
149164

150165
[tool.uv.sources]
151166
uipath-core = { path = "../uipath-core", editable = true }

sonar-project.properties

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
sonar.projectKey=UiPath_uipath-python
2+
sonar.organization=ui
3+
sonar.host.url=https://sonarcloud.io
4+
5+
sonar.sources=packages/uipath/src,packages/uipath-core/src,packages/uipath-platform/src
6+
sonar.tests=packages/uipath/tests,packages/uipath-core/tests,packages/uipath-platform/tests
7+
8+
sonar.python.version=3.11,3.12,3.13
9+
sonar.python.coverage.reportPaths=packages/uipath/coverage.xml,packages/uipath-core/coverage.xml,packages/uipath-platform/coverage.xml
10+
11+
sonar.exclusions=**/samples/**,**/testcases/**,**/template/**,**/_resources/**
12+
13+
sonar.sourceEncoding=UTF-8

0 commit comments

Comments
 (0)