Skip to content

Commit 72a81f1

Browse files
wip
1 parent bf55db9 commit 72a81f1

9 files changed

Lines changed: 288 additions & 193 deletions

File tree

.github/workflows/pull_request.yml

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
name: Continuous Integration
22

3-
on: [pull_request, workflow_dispatch]
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
workflow_dispatch:
411

512
concurrency:
613
group: ${{ github.workflow }}-${{ github.ref }}
@@ -46,9 +53,6 @@ jobs:
4653
id: unit_tests
4754
continue-on-error: true
4855
env:
49-
CONDUCTOR_AUTH_KEY: ${{ secrets.CONDUCTOR_AUTH_KEY }}
50-
CONDUCTOR_AUTH_SECRET: ${{ secrets.CONDUCTOR_AUTH_SECRET }}
51-
CONDUCTOR_SERVER_URL: ${{ secrets.CONDUCTOR_SERVER_URL }}
5256
COVERAGE_FILE: ${{ env.COVERAGE_DIR }}/.coverage.unit
5357
run: |
5458
coverage run -m pytest tests/unit -v
@@ -57,9 +61,6 @@ jobs:
5761
id: bc_tests
5862
continue-on-error: true
5963
env:
60-
CONDUCTOR_AUTH_KEY: ${{ secrets.CONDUCTOR_AUTH_KEY }}
61-
CONDUCTOR_AUTH_SECRET: ${{ secrets.CONDUCTOR_AUTH_SECRET }}
62-
CONDUCTOR_SERVER_URL: ${{ secrets.CONDUCTOR_SERVER_URL }}
6364
COVERAGE_FILE: ${{ env.COVERAGE_DIR }}/.coverage.bc
6465
run: |
6566
coverage run -m pytest tests/backwardcompatibility -v
@@ -68,9 +69,6 @@ jobs:
6869
id: serdeser_tests
6970
continue-on-error: true
7071
env:
71-
CONDUCTOR_AUTH_KEY: ${{ secrets.CONDUCTOR_AUTH_KEY }}
72-
CONDUCTOR_AUTH_SECRET: ${{ secrets.CONDUCTOR_AUTH_SECRET }}
73-
CONDUCTOR_SERVER_URL: ${{ secrets.CONDUCTOR_SERVER_URL }}
7472
COVERAGE_FILE: ${{ env.COVERAGE_DIR }}/.coverage.serdeser
7573
run: |
7674
coverage run -m pytest tests/serdesertest -v
@@ -103,4 +101,30 @@ jobs:
103101

104102
- name: Check test results
105103
if: steps.unit_tests.outcome == 'failure' || steps.bc_tests.outcome == 'failure' || steps.serdeser_tests.outcome == 'failure' || steps.agent_base_import.outcome == 'failure'
106-
run: exit 1
104+
run: exit 1
105+
106+
integration-test:
107+
runs-on: ubuntu-latest
108+
timeout-minutes: 30
109+
env:
110+
CONDUCTOR_SERVER_URL: ${{ vars.SDKDEV_V5_SERVER_URL }}
111+
CONDUCTOR_AUTH_KEY: ${{ vars.SDKDEV_V5_AUTH_KEY }}
112+
CONDUCTOR_AUTH_SECRET: ${{ secrets.SDKDEV_V5_AUTH_SECRET }}
113+
steps:
114+
- name: Checkout code
115+
uses: actions/checkout@v4
116+
117+
- name: Set up Python
118+
uses: actions/setup-python@v5
119+
with:
120+
python-version: '3.12'
121+
cache: 'pip'
122+
123+
- name: Install dependencies
124+
run: |
125+
python -m pip install --upgrade pip
126+
pip install -e .
127+
pip install pytest
128+
129+
- name: Run integration tests
130+
run: bash scripts/run_integration_tests.sh

src/conductor/client/http/models/service_method.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class ServiceMethod:
1515
'input_type': 'str',
1616
'output_type': 'str',
1717
'request_params': 'list[RequestParam]',
18-
'example_input': 'dict'
18+
'example_input': 'object'
1919
}
2020

2121
attribute_map = {

src/conductor/client/http/models/upsert_user_request.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import re # noqa: F401
33
import six
44
from dataclasses import dataclass, field, InitVar
5-
from typing import List, Optional
5+
from typing import Dict, List, Optional
66
from enum import Enum
77

88

@@ -30,41 +30,50 @@ class UpsertUserRequest:
3030
name: InitVar[Optional[str]] = None
3131
roles: InitVar[Optional[List[str]]] = None
3232
groups: InitVar[Optional[List[str]]] = None
33+
contact_information: InitVar[Optional[Dict[str, str]]] = None
3334

3435
_name: str = field(default=None, init=False)
3536
_roles: List[str] = field(default=None, init=False)
3637
_groups: List[str] = field(default=None, init=False)
38+
_contact_information: Dict[str, str] = field(default=None, init=False)
3739

3840
swagger_types = {
3941
'name': 'str',
4042
'roles': 'list[str]',
41-
'groups': 'list[str]'
43+
'groups': 'list[str]',
44+
'contact_information': 'dict(str, str)'
4245
}
4346

4447
attribute_map = {
4548
'name': 'name',
4649
'roles': 'roles',
47-
'groups': 'groups'
50+
'groups': 'groups',
51+
'contact_information': 'contactInformation'
4852
}
4953

50-
def __init__(self, name=None, roles=None, groups=None): # noqa: E501
54+
def __init__(self, name=None, roles=None, groups=None, contact_information=None): # noqa: E501
5155
"""UpsertUserRequest - a model defined in Swagger""" # noqa: E501
5256
self._name = None
5357
self._roles = None
5458
self._groups = None
59+
self._contact_information = None
5560
self.discriminator = None
5661
self.name = name
5762
if roles is not None:
5863
self.roles = roles
5964
if groups is not None:
6065
self.groups = groups
66+
if contact_information is not None:
67+
self.contact_information = contact_information
6168

62-
def __post_init__(self, name, roles, groups):
69+
def __post_init__(self, name, roles, groups, contact_information):
6370
self.name = name
6471
if roles is not None:
6572
self.roles = roles
6673
if groups is not None:
6774
self.groups = groups
75+
if contact_information is not None:
76+
self.contact_information = contact_information
6877

6978
@property
7079
def name(self):
@@ -139,6 +148,29 @@ def groups(self, groups):
139148

140149
self._groups = groups
141150

151+
@property
152+
def contact_information(self):
153+
"""Gets the contact_information of this UpsertUserRequest. # noqa: E501
154+
155+
User's contact information, e.g. {"email": "user@example.com"} # noqa: E501
156+
157+
:return: The contact_information of this UpsertUserRequest. # noqa: E501
158+
:rtype: dict(str, str)
159+
"""
160+
return self._contact_information
161+
162+
@contact_information.setter
163+
def contact_information(self, contact_information):
164+
"""Sets the contact_information of this UpsertUserRequest.
165+
166+
User's contact information, e.g. {"email": "user@example.com"} # noqa: E501
167+
168+
:param contact_information: The contact_information of this UpsertUserRequest. # noqa: E501
169+
:type: dict(str, str)
170+
"""
171+
172+
self._contact_information = contact_information
173+
142174
def to_dict(self):
143175
"""Returns the model properties as a dict"""
144176
result = {}

tests/integration/README.md

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,36 @@ export CONDUCTOR_AUTH_SECRET="your-secret"
3838

3939
## Running Tests
4040

41+
### Run the CI suite locally (recommended)
42+
43+
Use the helper script to run exactly what CI runs (the `integration-test` job in
44+
[`.github/workflows/pull_request.yml`](../../.github/workflows/pull_request.yml)).
45+
It excludes the AI/agentic tests (which need a dedicated AI-enabled server) and
46+
the slow performance test, so you don't have to remember the `--ignore` flags:
47+
48+
```bash
49+
export CONDUCTOR_SERVER_URL="http://localhost:8080/api"
50+
# For Orkes / authenticated servers also set:
51+
# export CONDUCTOR_AUTH_KEY="your-key"
52+
# export CONDUCTOR_AUTH_SECRET="your-secret"
53+
54+
./scripts/run_integration_tests.sh
55+
56+
# Also run the performance test (test_update_task_v2_perf.py, ~1000 workflows,
57+
# several minutes):
58+
./scripts/run_integration_tests.sh --with-perf
59+
```
60+
61+
Any extra arguments pass straight through to pytest, which is handy for
62+
targeting a subset of tests or getting more detail on failures. See additional
63+
options and examples in the comments at the top of
64+
[`scripts/run_integration_tests.sh`](../../scripts/run_integration_tests.sh).
65+
4166
### Run All Integration Tests
4267

68+
This includes the AI/agentic tests, which require an AI-enabled server (see
69+
[Tests excluded by default](#tests-excluded-by-default) below):
70+
4371
```bash
4472
python3 -m pytest tests/integration/ -v -s
4573
```
@@ -442,46 +470,42 @@ To add more test scenarios:
442470

443471
---
444472

445-
## CI/CD Integration
473+
## Tests excluded by default
446474

447-
### GitHub Actions Example
475+
`scripts/run_integration_tests.sh` (and CI) skip a few tests by default.
448476

449-
```yaml
450-
name: Integration Tests
477+
**AI/agentic tests** need a dedicated AI-enabled server:
451478

452-
on: [push, pull_request]
479+
- `test_ai_task_types.py` and `test_ai_examples.py` hardcode
480+
`http://localhost:7001/api`.
481+
- `test_agentic_workflows.py` needs an `openai` LLM provider (model
482+
`gpt-4o-mini`) configured on the server.
453483

454-
jobs:
455-
integration:
456-
runs-on: ubuntu-latest
484+
Run them only against a suitably configured AI-enabled server, e.g.:
457485

458-
services:
459-
conductor:
460-
image: conductoross/conductor-standalone:3.15.0
461-
ports:
462-
- 8080:8080
463-
- 5000:5000
486+
```bash
487+
python3 -m pytest tests/integration/test_ai_task_types.py -v -s
488+
```
464489

465-
steps:
466-
- uses: actions/checkout@v2
490+
**Performance test** (`test_update_task_v2_perf.py`) submits ~1000 workflows and
491+
takes several minutes. Include it with the `--with-perf` flag:
467492

468-
- name: Set up Python
469-
uses: actions/setup-python@v2
470-
with:
471-
python-version: '3.9'
493+
```bash
494+
./scripts/run_integration_tests.sh --with-perf
495+
```
472496

473-
- name: Install dependencies
474-
run: pip install -e .
497+
---
498+
499+
## CI/CD Integration
475500

476-
- name: Wait for Conductor
477-
run: |
478-
timeout 60 bash -c 'until curl -f http://localhost:8080/api/health; do sleep 2; done'
501+
Integration tests run in CI via the `integration-test` job in
502+
[`.github/workflows/pull_request.yml`](../../.github/workflows/pull_request.yml)
503+
on pushes to `main`, PRs targeting `main`, and manual dispatch. The job invokes
504+
`scripts/run_integration_tests.sh` (excluding the AI tests and the performance
505+
test) and reads the server from the `SDKDEV_V5_*` repository variables/secret.
479506

480-
- name: Run integration tests
481-
env:
482-
CONDUCTOR_SERVER_URL: http://localhost:8080/api
483-
run: python3 -m pytest tests/integration/ -v -s
484-
```
507+
To reproduce the CI run locally, use the script documented in
508+
[Running Tests](#running-tests) above.
485509

486510
---
487511

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
from conductor.client.http.api.metadata_resource_api import MetadataResourceApi
22
from conductor.client.http.api_client import ApiClient
3+
from conductor.client.http.models.task_def import TaskDef
4+
5+
TASK_NAME = 'python_integration_test_task'
36

47

58
def test_async_method(api_client: ApiClient):
69
metadata_client = MetadataResourceApi(api_client)
10+
11+
# Ensure the task def exists so the async lookup has something to return,
12+
# regardless of test ordering.
13+
metadata_client.register_task_def(body=[TaskDef(name=TASK_NAME)])
14+
715
thread = metadata_client.get_task_def(
8-
async_req=True, tasktype='python_integration_test_task')
16+
async_req=True, tasktype=TASK_NAME)
917
thread.wait()
1018
assert thread.get() is not None

0 commit comments

Comments
 (0)