Skip to content

Commit 77604ee

Browse files
committed
ci: cross-test all integrations against locally-built uipath wheels
1 parent 82f8e54 commit 77604ee

3 files changed

Lines changed: 332 additions & 173 deletions

File tree

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
name: uipath - Test Integrations
2+
3+
on:
4+
pull_request:
5+
types: [ opened, synchronize, reopened, labeled ]
6+
7+
jobs:
8+
build-wheels:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
12+
if: contains(github.event.pull_request.labels.*.name, 'test:uipath-integrations')
13+
steps:
14+
- name: Checkout uipath-python
15+
uses: actions/checkout@v4
16+
17+
- name: Setup uv
18+
uses: astral-sh/setup-uv@v5
19+
20+
- name: Setup Python
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: "3.12"
24+
25+
- name: Build uipath-core package
26+
working-directory: packages/uipath-core
27+
run: uv build
28+
29+
- name: Build uipath-platform package
30+
working-directory: packages/uipath-platform
31+
run: uv build
32+
33+
- name: Build uipath package
34+
working-directory: packages/uipath
35+
run: uv build
36+
37+
- name: Upload wheels
38+
uses: actions/upload-artifact@v4
39+
with:
40+
name: uipath-wheels
41+
path: packages/*/dist/*.whl
42+
43+
discover-packages:
44+
needs: [build-wheels]
45+
runs-on: ubuntu-latest
46+
permissions:
47+
contents: read
48+
outputs:
49+
packages: ${{ steps.discover.outputs.packages }}
50+
steps:
51+
- name: Checkout uipath-integrations-python
52+
uses: actions/checkout@v4
53+
with:
54+
repository: 'UiPath/uipath-integrations-python'
55+
path: 'uipath-integrations-python'
56+
57+
- name: Discover packages
58+
id: discover
59+
working-directory: uipath-integrations-python
60+
run: |
61+
# Find every package directory under packages/ that has a pyproject.toml
62+
package_dirs=$(find packages -maxdepth 2 -name pyproject.toml -printf '%h\n' | sed 's|^packages/||' | sort)
63+
64+
echo "Found integration packages:"
65+
echo "$package_dirs"
66+
67+
packages_json=$(echo "$package_dirs" | jq -R -s -c 'split("\n")[:-1]')
68+
echo "packages=$packages_json" >> $GITHUB_OUTPUT
69+
70+
test-package:
71+
needs: [build-wheels, discover-packages]
72+
runs-on: ${{ matrix.os }}
73+
strategy:
74+
fail-fast: false
75+
matrix:
76+
package: ${{ fromJson(needs.discover-packages.outputs.packages) }}
77+
python-version: [ "3.11", "3.12", "3.13" ]
78+
os: [ ubuntu-latest, windows-latest ]
79+
80+
name: "${{ matrix.package }} / py${{ matrix.python-version }} / ${{ matrix.os }}"
81+
permissions:
82+
contents: read
83+
84+
steps:
85+
- name: Setup uv
86+
uses: astral-sh/setup-uv@v5
87+
88+
- name: Setup Python
89+
uses: actions/setup-python@v5
90+
with:
91+
python-version: ${{ matrix.python-version }}
92+
93+
- name: Download wheels
94+
uses: actions/download-artifact@v4
95+
with:
96+
name: uipath-wheels
97+
path: wheels
98+
99+
- name: Checkout uipath-integrations-python
100+
uses: actions/checkout@v4
101+
with:
102+
repository: 'UiPath/uipath-integrations-python'
103+
path: 'uipath-integrations-python'
104+
105+
- name: Update uipath packages
106+
shell: bash
107+
working-directory: uipath-integrations-python/packages/${{ matrix.package }}
108+
run: |
109+
uv add ../../../wheels/uipath-core/dist/*.whl --dev
110+
uv add ../../../wheels/uipath-platform/dist/*.whl --dev
111+
uv add ../../../wheels/uipath/dist/*.whl --dev
112+
113+
- name: Install dependencies and run tests
114+
shell: bash
115+
working-directory: uipath-integrations-python/packages/${{ matrix.package }}
116+
run: |
117+
uv sync
118+
if [ -d tests ]; then
119+
uv run pytest
120+
else
121+
echo "No tests directory found in ${{ matrix.package }}, skipping pytest"
122+
fi
123+
124+
discover-testcases:
125+
needs: [test-package, discover-packages]
126+
runs-on: ubuntu-latest
127+
permissions:
128+
contents: read
129+
outputs:
130+
matrix: ${{ steps.discover.outputs.matrix }}
131+
has_testcases: ${{ steps.discover.outputs.has_testcases }}
132+
steps:
133+
- name: Checkout uipath-integrations-python
134+
uses: actions/checkout@v4
135+
with:
136+
repository: 'UiPath/uipath-integrations-python'
137+
path: 'uipath-integrations-python'
138+
139+
- name: Discover testcases across packages
140+
id: discover
141+
working-directory: uipath-integrations-python
142+
run: |
143+
# For each package with a testcases/ directory, list its testcase folders
144+
# and emit one matrix entry per (package, testcase) pair.
145+
entries="[]"
146+
for pkg_dir in packages/*/; do
147+
pkg=$(basename "$pkg_dir")
148+
tc_dir="$pkg_dir/testcases"
149+
if [ ! -d "$tc_dir" ]; then
150+
continue
151+
fi
152+
testcases=$(find "$tc_dir" -maxdepth 1 -type d -name "*-*" -printf '%f\n' | sort)
153+
if [ -z "$testcases" ]; then
154+
continue
155+
fi
156+
for tc in $testcases; do
157+
entries=$(echo "$entries" | jq --arg p "$pkg" --arg t "$tc" '. + [{package: $p, testcase: $t}]')
158+
done
159+
done
160+
161+
echo "Discovered testcase matrix:"
162+
echo "$entries" | jq .
163+
164+
count=$(echo "$entries" | jq 'length')
165+
if [ "$count" -eq 0 ]; then
166+
echo "has_testcases=false" >> $GITHUB_OUTPUT
167+
echo "matrix=[]" >> $GITHUB_OUTPUT
168+
else
169+
echo "has_testcases=true" >> $GITHUB_OUTPUT
170+
echo "matrix=$(echo "$entries" | jq -c .)" >> $GITHUB_OUTPUT
171+
fi
172+
173+
run-integration-tests:
174+
needs: [build-wheels, discover-testcases]
175+
if: needs.discover-testcases.outputs.has_testcases == 'true'
176+
runs-on: ubuntu-latest
177+
container:
178+
image: ghcr.io/astral-sh/uv:python3.12-bookworm
179+
env:
180+
UIPATH_JOB_KEY: "3a03d5cb-fa21-4021-894d-a8e2eda0afe0"
181+
UIPATH_TRACING_ENABLED: false
182+
permissions:
183+
contents: read
184+
strategy:
185+
fail-fast: false
186+
matrix:
187+
include: ${{ fromJson(needs.discover-testcases.outputs.matrix) }}
188+
environment: [alpha, staging] # temporary disable [cloud]
189+
190+
name: "${{ matrix.package }} / ${{ matrix.testcase }} / ${{ matrix.environment }}"
191+
192+
steps:
193+
- name: Download wheels
194+
uses: actions/download-artifact@v4
195+
with:
196+
name: uipath-wheels
197+
path: wheels
198+
199+
- name: Checkout uipath-integrations-python
200+
uses: actions/checkout@v4
201+
with:
202+
repository: 'UiPath/uipath-integrations-python'
203+
path: 'uipath-integrations-python'
204+
205+
- name: Update uipath packages
206+
shell: bash
207+
working-directory: uipath-integrations-python/packages/${{ matrix.package }}
208+
run: |
209+
uv add ../../../wheels/uipath-core/dist/*.whl
210+
uv add ../../../wheels/uipath-platform/dist/*.whl
211+
uv add ../../../wheels/uipath/dist/*.whl
212+
213+
- name: Install dependencies
214+
working-directory: uipath-integrations-python/packages/${{ matrix.package }}
215+
run: uv sync
216+
217+
- name: Run testcase
218+
env:
219+
CLIENT_ID: ${{ matrix.environment == 'alpha' && secrets.ALPHA_TEST_CLIENT_ID || matrix.environment == 'staging' && secrets.STAGING_TEST_CLIENT_ID || matrix.environment == 'cloud' && secrets.CLOUD_TEST_CLIENT_ID }}
220+
CLIENT_SECRET: ${{ matrix.environment == 'alpha' && secrets.ALPHA_TEST_CLIENT_SECRET || matrix.environment == 'staging' && secrets.STAGING_TEST_CLIENT_SECRET || matrix.environment == 'cloud' && secrets.CLOUD_TEST_CLIENT_SECRET }}
221+
BASE_URL: ${{ matrix.environment == 'alpha' && secrets.ALPHA_BASE_URL || matrix.environment == 'staging' && secrets.STAGING_BASE_URL || matrix.environment == 'cloud' && secrets.CLOUD_BASE_URL }}
222+
UV_PYTHON: "3.12"
223+
working-directory: uipath-integrations-python/packages/${{ matrix.package }}/testcases/${{ matrix.testcase }}
224+
run: |
225+
echo "Package: ${{ matrix.package }}"
226+
echo "Testcase: ${{ matrix.testcase }}"
227+
echo "Environment: ${{ matrix.environment }}"
228+
229+
bash run.sh
230+
bash ../common/validate_output.sh
231+
232+
notify-on-failure:
233+
needs: [test-package, run-integration-tests]
234+
if: always() && contains(github.event.pull_request.labels.*.name, 'test:uipath-integrations') && (needs.test-package.result == 'failure' || needs.run-integration-tests.result == 'failure')
235+
runs-on: ubuntu-latest
236+
permissions:
237+
pull-requests: write
238+
steps:
239+
- name: Comment on PR
240+
uses: actions/github-script@v7
241+
with:
242+
script: |
243+
const marker = '<!-- cross-test-failure:uipath-integrations -->';
244+
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
245+
const body = [
246+
marker,
247+
'## :rotating_light: **Heads up: `uipath-integrations` cross-tests are FAILING** :rotating_light:',
248+
'',
249+
'Your changes may break one or more integrations in **[`uipath-integrations-python`](https://github.com/UiPath/uipath-integrations-python)**:',
250+
'',
251+
'- `uipath-openai-agents`',
252+
'- `uipath-google-adk`',
253+
'- `uipath-agent-framework`',
254+
'- `uipath-llamaindex`',
255+
'- `uipath-pydantic-ai`',
256+
'',
257+
'> :warning: **These checks are NOT enforced by branch protection rules.** Please review the failures before merging.',
258+
'',
259+
`**:mag: [Inspect the failed run →](${runUrl})**`,
260+
].join('\n');
261+
262+
// Delete any prior failure comments for this workflow so the new
263+
// one always lands at the bottom of the PR conversation.
264+
const { data: comments } = await github.rest.issues.listComments({
265+
owner: context.repo.owner,
266+
repo: context.repo.repo,
267+
issue_number: context.issue.number,
268+
});
269+
for (const c of comments) {
270+
if (c.body && c.body.includes(marker)) {
271+
await github.rest.issues.deleteComment({
272+
owner: context.repo.owner,
273+
repo: context.repo.repo,
274+
comment_id: c.id,
275+
});
276+
}
277+
}
278+
279+
await github.rest.issues.createComment({
280+
owner: context.repo.owner,
281+
repo: context.repo.repo,
282+
issue_number: context.issue.number,
283+
body,
284+
});

.github/workflows/test-uipath-langchain.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,51 @@ jobs:
175175
# Execute the testcase run script directly
176176
bash run.sh
177177
bash ../common/validate_output.sh
178+
179+
notify-on-failure:
180+
needs: [test-uipath-langchain, run-uipath-langchain-integration-tests]
181+
if: always() && contains(github.event.pull_request.labels.*.name, 'test:uipath-langchain') && (needs.test-uipath-langchain.result == 'failure' || needs.run-uipath-langchain-integration-tests.result == 'failure')
182+
runs-on: ubuntu-latest
183+
permissions:
184+
pull-requests: write
185+
steps:
186+
- name: Comment on PR
187+
uses: actions/github-script@v7
188+
with:
189+
script: |
190+
const marker = '<!-- cross-test-failure:uipath-langchain -->';
191+
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
192+
const body = [
193+
marker,
194+
'## :rotating_light: **Heads up: `uipath-langchain` cross-tests are FAILING** :rotating_light:',
195+
'',
196+
'Your changes may break the **[`uipath-langchain-python`](https://github.com/UiPath/uipath-langchain-python)** integration.',
197+
'',
198+
'> :warning: **These checks are NOT enforced by branch protection rules.** Please review the failures before merging.',
199+
'',
200+
`**:mag: [Inspect the failed run →](${runUrl})**`,
201+
].join('\n');
202+
203+
// Delete any prior failure comments for this workflow so the new
204+
// one always lands at the bottom of the PR conversation.
205+
const { data: comments } = await github.rest.issues.listComments({
206+
owner: context.repo.owner,
207+
repo: context.repo.repo,
208+
issue_number: context.issue.number,
209+
});
210+
for (const c of comments) {
211+
if (c.body && c.body.includes(marker)) {
212+
await github.rest.issues.deleteComment({
213+
owner: context.repo.owner,
214+
repo: context.repo.repo,
215+
comment_id: c.id,
216+
});
217+
}
218+
}
219+
220+
await github.rest.issues.createComment({
221+
owner: context.repo.owner,
222+
repo: context.repo.repo,
223+
issue_number: context.issue.number,
224+
body,
225+
});

0 commit comments

Comments
 (0)