Skip to content

Commit d0fbbcc

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

7 files changed

Lines changed: 284 additions & 10 deletions

File tree

.github/workflows/test-packages.yml

Lines changed: 161 additions & 5 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-llamaindex
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-llamaindex
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-llamaindex
94+
path: packages/uipath-llamaindex/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-llamaindex
102+
path: packages/uipath-llamaindex/coverage.xml
103+
retention-days: 30
104+
84105
test-openai-agents:
85106
name: Test (uipath-openai-agents, ${{ 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-openai-agents
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-openai-agents
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-openai-agents
164+
path: packages/uipath-openai-agents/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-openai-agents
172+
path: packages/uipath-openai-agents/coverage.xml
173+
retention-days: 30
174+
133175
test-google-adk:
134176
name: Test (uipath-google-adk, ${{ matrix.python-version }}, ${{ matrix.os }})
135177
needs: detect-changed-packages
@@ -175,10 +217,31 @@ jobs:
175217
run: uv sync --all-extras --python ${{ matrix.python-version }}
176218

177219
- name: Run tests
178-
if: steps.check.outputs.skip != 'true'
220+
if: steps.check.outputs.skip != 'true' && !(matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13')
179221
working-directory: packages/uipath-google-adk
180222
run: uv run pytest
181223

224+
- name: Run tests with coverage
225+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
226+
working-directory: packages/uipath-google-adk
227+
run: uv run pytest --cov-report=xml --cov-report=html --tb=short
228+
229+
- name: Upload coverage HTML report
230+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && always()
231+
uses: actions/upload-artifact@v4
232+
with:
233+
name: coverage-html-uipath-google-adk
234+
path: packages/uipath-google-adk/htmlcov/
235+
retention-days: 30
236+
237+
- name: Upload coverage XML report
238+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && always()
239+
uses: actions/upload-artifact@v4
240+
with:
241+
name: coverage-xml-uipath-google-adk
242+
path: packages/uipath-google-adk/coverage.xml
243+
retention-days: 30
244+
182245
test-pydantic-ai:
183246
name: Test (uipath-pydantic-ai, ${{ matrix.python-version }}, ${{ matrix.os }})
184247
needs: detect-changed-packages
@@ -224,10 +287,31 @@ jobs:
224287
run: uv sync --all-extras --python ${{ matrix.python-version }}
225288

226289
- name: Run tests
227-
if: steps.check.outputs.skip != 'true'
290+
if: steps.check.outputs.skip != 'true' && !(matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13')
228291
working-directory: packages/uipath-pydantic-ai
229292
run: uv run pytest
230293

294+
- name: Run tests with coverage
295+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
296+
working-directory: packages/uipath-pydantic-ai
297+
run: uv run pytest --cov-report=xml --cov-report=html --tb=short
298+
299+
- name: Upload coverage HTML report
300+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && always()
301+
uses: actions/upload-artifact@v4
302+
with:
303+
name: coverage-html-uipath-pydantic-ai
304+
path: packages/uipath-pydantic-ai/htmlcov/
305+
retention-days: 30
306+
307+
- name: Upload coverage XML report
308+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && always()
309+
uses: actions/upload-artifact@v4
310+
with:
311+
name: coverage-xml-uipath-pydantic-ai
312+
path: packages/uipath-pydantic-ai/coverage.xml
313+
retention-days: 30
314+
231315
test-agent-framework:
232316
name: Test (uipath-agent-framework, ${{ matrix.python-version }}, ${{ matrix.os }})
233317
needs: detect-changed-packages
@@ -273,6 +357,78 @@ jobs:
273357
run: uv sync --all-extras --python ${{ matrix.python-version }}
274358

275359
- name: Run tests
276-
if: steps.check.outputs.skip != 'true'
360+
if: steps.check.outputs.skip != 'true' && !(matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13')
277361
working-directory: packages/uipath-agent-framework
278362
run: uv run pytest
363+
364+
- name: Run tests with coverage
365+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
366+
working-directory: packages/uipath-agent-framework
367+
run: uv run pytest --cov-report=xml --cov-report=html --tb=short
368+
369+
- name: Upload coverage HTML report
370+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && always()
371+
uses: actions/upload-artifact@v4
372+
with:
373+
name: coverage-html-uipath-agent-framework
374+
path: packages/uipath-agent-framework/htmlcov/
375+
retention-days: 30
376+
377+
- name: Upload coverage XML report
378+
if: steps.check.outputs.skip != 'true' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && always()
379+
uses: actions/upload-artifact@v4
380+
with:
381+
name: coverage-xml-uipath-agent-framework
382+
path: packages/uipath-agent-framework/coverage.xml
383+
retention-days: 30
384+
385+
sonarcloud:
386+
name: SonarCloud
387+
needs: [test-llamaindex, test-openai-agents, test-google-adk, test-pydantic-ai, test-agent-framework]
388+
runs-on: ubuntu-latest
389+
if: github.event_name == 'pull_request' && always() && needs.test-llamaindex.result != 'failure' && needs.test-openai-agents.result != 'failure' && needs.test-google-adk.result != 'failure' && needs.test-pydantic-ai.result != 'failure' && needs.test-agent-framework.result != 'failure'
390+
steps:
391+
- name: Checkout
392+
uses: actions/checkout@v4
393+
with:
394+
fetch-depth: 0
395+
396+
- name: Download uipath-llamaindex coverage
397+
uses: actions/download-artifact@v4
398+
continue-on-error: true
399+
with:
400+
name: coverage-xml-uipath-llamaindex
401+
path: packages/uipath-llamaindex
402+
403+
- name: Download uipath-openai-agents coverage
404+
uses: actions/download-artifact@v4
405+
continue-on-error: true
406+
with:
407+
name: coverage-xml-uipath-openai-agents
408+
path: packages/uipath-openai-agents
409+
410+
- name: Download uipath-google-adk coverage
411+
uses: actions/download-artifact@v4
412+
continue-on-error: true
413+
with:
414+
name: coverage-xml-uipath-google-adk
415+
path: packages/uipath-google-adk
416+
417+
- name: Download uipath-pydantic-ai coverage
418+
uses: actions/download-artifact@v4
419+
continue-on-error: true
420+
with:
421+
name: coverage-xml-uipath-pydantic-ai
422+
path: packages/uipath-pydantic-ai
423+
424+
- name: Download uipath-agent-framework coverage
425+
uses: actions/download-artifact@v4
426+
continue-on-error: true
427+
with:
428+
name: coverage-xml-uipath-agent-framework
429+
path: packages/uipath-agent-framework
430+
431+
- name: SonarCloud Scan
432+
uses: SonarSource/sonarqube-scan-action@2f77a1ec69fb1d595b06f35ab27e97605bdef703 # v5
433+
env:
434+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

packages/uipath-agent-framework/pyproject.toml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ ignore_errors = true
109109
[tool.pytest.ini_options]
110110
testpaths = ["tests"]
111111
python_files = "test_*.py"
112-
addopts = "-ra -q"
112+
addopts = "-ra -q --cov=src/uipath_agent_framework --cov-report=term-missing"
113113
asyncio_default_fixture_loop_scope = "function"
114114
asyncio_mode = "auto"
115115

@@ -121,3 +121,24 @@ name = "testpypi"
121121
url = "https://test.pypi.org/simple/"
122122
publish-url = "https://test.pypi.org/legacy/"
123123
explicit = true
124+
125+
[tool.coverage.run]
126+
source = ["src/uipath_agent_framework"]
127+
relative_files = true
128+
omit = [
129+
"*/tests/*",
130+
"*/__pycache__/*",
131+
"*/site-packages/*",
132+
"*/conftest.py",
133+
]
134+
135+
[tool.coverage.report]
136+
show_missing = true
137+
precision = 2
138+
exclude_lines = [
139+
"pragma: no cover",
140+
"def __repr__",
141+
"raise NotImplementedError",
142+
"if TYPE_CHECKING:",
143+
"@(abc\\.)?abstractmethod",
144+
]

packages/uipath-google-adk/pyproject.toml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ ignore_missing_imports = true
103103
[tool.pytest.ini_options]
104104
testpaths = ["tests"]
105105
python_files = "test_*.py"
106-
addopts = "-ra -q"
106+
addopts = "-ra -q --cov=src/uipath_google_adk --cov-report=term-missing"
107107
asyncio_default_fixture_loop_scope = "function"
108108
asyncio_mode = "auto"
109109

@@ -122,3 +122,24 @@ name = "testpypi"
122122
url = "https://test.pypi.org/simple/"
123123
publish-url = "https://test.pypi.org/legacy/"
124124
explicit = true
125+
126+
[tool.coverage.run]
127+
source = ["src/uipath_google_adk"]
128+
relative_files = true
129+
omit = [
130+
"*/tests/*",
131+
"*/__pycache__/*",
132+
"*/site-packages/*",
133+
"*/conftest.py",
134+
]
135+
136+
[tool.coverage.report]
137+
show_missing = true
138+
precision = 2
139+
exclude_lines = [
140+
"pragma: no cover",
141+
"def __repr__",
142+
"raise NotImplementedError",
143+
"if TYPE_CHECKING:",
144+
"@(abc\\.)?abstractmethod",
145+
]

packages/uipath-llamaindex/pyproject.toml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ disallow_untyped_defs = false
103103
[tool.pytest.ini_options]
104104
testpaths = ["tests"]
105105
python_files = "test_*.py"
106-
addopts = "-ra -q"
106+
addopts = "-ra -q --cov=src/uipath_llamaindex --cov-report=term-missing"
107107
asyncio_default_fixture_loop_scope = "function"
108108
asyncio_mode = "auto"
109109

@@ -112,3 +112,24 @@ name = "testpypi"
112112
url = "https://test.pypi.org/simple/"
113113
publish-url = "https://test.pypi.org/legacy/"
114114
explicit = true
115+
116+
[tool.coverage.run]
117+
source = ["src/uipath_llamaindex"]
118+
relative_files = true
119+
omit = [
120+
"*/tests/*",
121+
"*/__pycache__/*",
122+
"*/site-packages/*",
123+
"*/conftest.py",
124+
]
125+
126+
[tool.coverage.report]
127+
show_missing = true
128+
precision = 2
129+
exclude_lines = [
130+
"pragma: no cover",
131+
"def __repr__",
132+
"raise NotImplementedError",
133+
"if TYPE_CHECKING:",
134+
"@(abc\\.)?abstractmethod",
135+
]

packages/uipath-openai-agents/pyproject.toml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ ignore_errors = true
8989
[tool.pytest.ini_options]
9090
testpaths = ["tests"]
9191
python_files = "test_*.py"
92-
addopts = "-ra -q"
92+
addopts = "-ra -q --cov=src/uipath_openai_agents --cov-report=term-missing"
9393
asyncio_default_fixture_loop_scope = "function"
9494
asyncio_mode = "auto"
9595

@@ -98,3 +98,24 @@ name = "testpypi"
9898
url = "https://test.pypi.org/simple/"
9999
publish-url = "https://test.pypi.org/legacy/"
100100
explicit = true
101+
102+
[tool.coverage.run]
103+
source = ["src/uipath_openai_agents"]
104+
relative_files = true
105+
omit = [
106+
"*/tests/*",
107+
"*/__pycache__/*",
108+
"*/site-packages/*",
109+
"*/conftest.py",
110+
]
111+
112+
[tool.coverage.report]
113+
show_missing = true
114+
precision = 2
115+
exclude_lines = [
116+
"pragma: no cover",
117+
"def __repr__",
118+
"raise NotImplementedError",
119+
"if TYPE_CHECKING:",
120+
"@(abc\\.)?abstractmethod",
121+
]

packages/uipath-pydantic-ai/pyproject.toml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ ignore_errors = true
8686
[tool.pytest.ini_options]
8787
testpaths = ["tests"]
8888
python_files = "test_*.py"
89-
addopts = "-ra -q"
89+
addopts = "-ra -q --cov=src/uipath_pydantic_ai --cov-report=term-missing"
9090
asyncio_default_fixture_loop_scope = "function"
9191
asyncio_mode = "auto"
9292

@@ -95,3 +95,24 @@ name = "testpypi"
9595
url = "https://test.pypi.org/simple/"
9696
publish-url = "https://test.pypi.org/legacy/"
9797
explicit = true
98+
99+
[tool.coverage.run]
100+
source = ["src/uipath_pydantic_ai"]
101+
relative_files = true
102+
omit = [
103+
"*/tests/*",
104+
"*/__pycache__/*",
105+
"*/site-packages/*",
106+
"*/conftest.py",
107+
]
108+
109+
[tool.coverage.report]
110+
show_missing = true
111+
precision = 2
112+
exclude_lines = [
113+
"pragma: no cover",
114+
"def __repr__",
115+
"raise NotImplementedError",
116+
"if TYPE_CHECKING:",
117+
"@(abc\\.)?abstractmethod",
118+
]

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-integrations-python
2+
sonar.organization=ui
3+
sonar.host.url=https://sonarcloud.io
4+
5+
sonar.sources=packages/uipath-llamaindex/src,packages/uipath-openai-agents/src,packages/uipath-google-adk/src,packages/uipath-pydantic-ai/src,packages/uipath-agent-framework/src
6+
sonar.tests=packages/uipath-llamaindex/tests,packages/uipath-openai-agents/tests,packages/uipath-google-adk/tests,packages/uipath-pydantic-ai/tests,packages/uipath-agent-framework/tests
7+
8+
sonar.python.version=3.11,3.12,3.13
9+
sonar.python.coverage.reportPaths=packages/uipath-llamaindex/coverage.xml,packages/uipath-openai-agents/coverage.xml,packages/uipath-google-adk/coverage.xml,packages/uipath-pydantic-ai/coverage.xml,packages/uipath-agent-framework/coverage.xml
10+
11+
sonar.exclusions=**/samples/**,**/testcases/**,**/template/**
12+
13+
sonar.sourceEncoding=UTF-8

0 commit comments

Comments
 (0)