1- name : CI/CD Pipeline
1+ name : CI Pipeline
22
33on :
44 push :
77 branches : [ main, develop ]
88
99jobs :
10- setup :
11- runs-on : ubuntu-latest
12- outputs :
13- python-versions : ${{ steps.set-python-versions.outputs.matrix }}
14- steps :
15- - uses : actions/checkout@v4
16-
17- - name : Set up Python
18- uses : actions/setup-python@v4
19- with :
20- python-version : ' 3.11'
21-
22- - name : Extract Python versions from pyproject.toml
23- id : set-python-versions
24- run : |
25- python << EOF
26- import re
27- import json
28- import os
29-
30- with open('macro_agents/pyproject.toml', 'r') as f:
31- content = f.read()
32-
33- # Extract requires-python line
34- match = re.search(r'requires-python\s*=\s*["\']([^"\']+)["\']', content)
35- if match:
36- requirement = match.group(1)
37- print(f"Found requirement: {requirement}")
38-
39- # Parse version range (e.g., ">=3.9,<3.14")
40- min_version = None
41- max_version = None
42-
43- if '>=' in requirement:
44- min_match = re.search(r'>=(\d+\.\d+)', requirement)
45- if min_match:
46- min_version = min_match.group(1)
47- print(f"Min version: {min_version}")
48-
49- if '<' in requirement:
50- max_match = re.search(r'<(\d+\.\d+)', requirement)
51- if max_match:
52- max_version = max_match.group(1)
53- print(f"Max version: {max_version}")
54-
55- # Helper function to compare version strings
56- def version_compare(v1, v2):
57- """Compare two version strings. Returns -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2"""
58- parts1 = [int(x) for x in v1.split('.')]
59- parts2 = [int(x) for x in v2.split('.')]
60- # Pad shorter version with zeros
61- max_len = max(len(parts1), len(parts2))
62- parts1.extend([0] * (max_len - len(parts1)))
63- parts2.extend([0] * (max_len - len(parts2)))
64- if parts1 < parts2:
65- return -1
66- elif parts1 > parts2:
67- return 1
68- return 0
69-
70- # Generate list of supported versions
71- # Python versions: 3.9, 3.10, 3.11, 3.12, 3.13
72- all_versions = ['3.9', '3.10', '3.11', '3.12', '3.13']
73- supported = []
74-
75- for ver_str in all_versions:
76- # Check if version is within range: >= min and < max
77- if min_version and version_compare(ver_str, min_version) < 0:
78- continue # Skip if below minimum
79- if max_version and version_compare(ver_str, max_version) >= 0:
80- continue # Skip if at or above maximum
81- # Version is in range, add it
82- supported.append(ver_str)
83-
84- print(f"Supported versions: {supported}")
85-
86- # Output as JSON array for matrix
87- matrix_json = json.dumps(supported)
88- github_output = os.environ.get('GITHUB_OUTPUT', '/dev/stdout')
89- print(f"matrix={matrix_json}")
90- with open(github_output, 'a') as f:
91- f.write(f"matrix={matrix_json}\n")
92- else:
93- # Fallback to default versions
94- default = json.dumps(['3.9', '3.10', '3.11', '3.12'])
95- print(f"No requirement found, using default: {default}")
96- github_output = os.environ.get('GITHUB_OUTPUT', '/dev/stdout')
97- print(f"matrix={default}")
98- with open(github_output, 'a') as f:
99- f.write(f"matrix={default}\n")
100- EOF
101-
10210 test :
10311 runs-on : ubuntu-latest
104- needs : setup
105- strategy :
106- matrix :
107- python-version : ${{ fromJSON(needs.setup.outputs.python-versions) }}
108-
12+
10913 steps :
11014 - uses : actions/checkout@v4
11115
112- - name : Set up Python ${{ matrix.python-version }}
16+ - name : Set up Python 3.11
11317 uses : actions/setup-python@v4
11418 with :
115- python-version : ${{ matrix.python-version }}
19+ python-version : ' 3.11 '
11620
11721 - name : Install uv
11822 uses : astral-sh/setup-uv@v4
@@ -138,197 +42,19 @@ jobs:
13842 uv run ruff check .
13943 uv run ruff format --check .
14044
141- - name : Type check with mypy
142- run : |
143- cd macro_agents
144- uv run mypy . --ignore-missing-imports
145-
146- - name : Test with pytest
147- run : |
148- cd macro_agents
149- uv run pytest tests/ -v --cov=macro_agents --cov-report=xml --cov-report=html --junitxml=../pytest-results.xml
150- mv coverage.xml .. || true
151-
152- - name : Upload coverage to Codecov
153- uses : codecov/codecov-action@v4
154- with :
155- file : ./coverage.xml
156- flags : unittests
157- name : codecov-umbrella
158- fail_ci_if_error : false
159-
160- - name : Upload test results
161- uses : actions/upload-artifact@v4
162- if : always()
163- with :
164- name : pytest-results-${{ matrix.python-version }}
165- path : pytest-results.xml
166-
167- integration-test :
168- runs-on : ubuntu-latest
169- needs : test
170-
171- steps :
172- - uses : actions/checkout@v4
173-
174- - name : Set up Python 3.11
175- uses : actions/setup-python@v4
176- with :
177- python-version : 3.11
178-
179- - name : Install uv
180- uses : astral-sh/setup-uv@v4
181- with :
182- version : " latest"
183-
184- - name : Cache uv dependencies
185- uses : actions/cache@v4
186- with :
187- path : ~/.cache/uv
188- key : ${{ runner.os }}-uv-${{ hashFiles('macro_agents/pyproject.toml', 'macro_agents/uv.lock') }}
189- restore-keys : |
190- ${{ runner.os }}-uv-
191-
192- - name : Install dependencies with uv
193- run : |
194- cd macro_agents
195- uv sync --dev
196-
19745 - name : Test Dagster definitions
19846 run : |
19947 cd macro_agents
20048 uv run dg check defs
20149
202- - name : Test Dagster schedules
203- run : |
204- cd macro_agents
205- uv run dg schedule list
206- uv run dg sensor list
207-
208- - name : Test Dagster asset materialization (dry run)
209- run : |
210- cd macro_agents
211- uv run dg materialize --dry-run --select "*"
212-
213- - name : Test scheduled job execution (dry run)
214- run : |
215- cd macro_agents
216- uv run dg job execute --dry-run monthly_sector_analysis_job
217- uv run dg job execute --dry-run weekly_cycle_analysis_job
218- uv run dg job execute --dry-run weekly_allocation_job
219- uv run dg job execute --dry-run daily_monitoring_job
220-
22150 - name : Test DBT models
22251 run : |
22352 cd dbt_project
22453 dbt deps
22554 dbt compile
22655 dbt parse
227-
228- security-scan :
229- runs-on : ubuntu-latest
230- needs : test
23156
232- steps :
233- - uses : actions/checkout@v4
234-
235- - name : Set up Python 3.11
236- uses : actions/setup-python@v4
237- with :
238- python-version : 3.11
239-
240- - name : Install uv
241- uses : astral-sh/setup-uv@v4
242- with :
243- version : " latest"
244-
245- - name : Cache uv dependencies
246- uses : actions/cache@v4
247- with :
248- path : ~/.cache/uv
249- key : ${{ runner.os }}-uv-${{ hashFiles('macro_agents/pyproject.toml', 'macro_agents/uv.lock') }}
250- restore-keys : |
251- ${{ runner.os }}-uv-
252-
253- - name : Install dependencies with uv
254- run : |
255- cd macro_agents
256- uv sync --dev
257- uv pip install bandit safety
258-
259- - name : Security scan with bandit
260- run : |
261- cd macro_agents
262- uv run bandit -r . -f json -o ../bandit-report.json || true
263-
264- - name : Security scan with safety
265- run : |
266- cd macro_agents
267- uv run safety check --json --output ../safety-report.json || true
268-
269- - name : Upload security reports
270- uses : actions/upload-artifact@v4
271- if : always()
272- with :
273- name : security-reports
274- path : |
275- bandit-report.json
276- safety-report.json
277-
278- build :
279- runs-on : ubuntu-latest
280- needs : [test, integration-test, security-scan]
281- if : github.event_name == 'push' && github.ref == 'refs/heads/main'
282-
283- steps :
284- - uses : actions/checkout@v4
285-
286- - name : Set up Python 3.11
287- uses : actions/setup-python@v4
288- with :
289- python-version : 3.11
290-
291- - name : Install uv
292- uses : astral-sh/setup-uv@v4
293- with :
294- version : " latest"
295-
296- - name : Install build dependencies
297- run : |
298- uv pip install build twine
299-
300- - name : Build package
301- run : |
302- cd macro_agents
303- uv run python -m build
304-
305- - name : Check package
57+ - name : Test with pytest
30658 run : |
30759 cd macro_agents
308- uv run twine check dist/*
309-
310- - name : Upload build artifacts
311- uses : actions/upload-artifact@v4
312- with :
313- name : dist
314- path : macro_agents/dist/
315-
316- deploy :
317- runs-on : ubuntu-latest
318- needs : build
319- if : github.event_name == 'push' && github.ref == 'refs/heads/main'
320- environment : production
321-
322- steps :
323- - uses : actions/checkout@v4
324-
325- - name : Download build artifacts
326- uses : actions/download-artifact@v4
327- with :
328- name : dist
329- path : macro_agents/dist/
330-
331- - name : Deploy to production
332- run : |
333- echo "Deploying to production..."
334- # Add your deployment commands here
60+ uv run pytest tests/ -v
0 commit comments