-
Notifications
You must be signed in to change notification settings - Fork 0
215 lines (183 loc) · 7.17 KB
/
ci-tests.yml
File metadata and controls
215 lines (183 loc) · 7.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
name: "CI: Tests"
run-name: "Tests: ${{ github.ref_name }}"
on:
push:
branches:
- main
- develop
- 'feature/**'
pull_request:
branches:
- main
- develop
- 'specification/**'
- 'implementation/**'
workflow_dispatch:
inputs:
force_run:
description: 'Force run all tests (ignore change detection)'
type: boolean
default: true
jobs:
test:
name: Run Tests
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # Required for Workload Identity Federation
env:
ENVIRONMENT: test
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check for testable changes
id: check
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
CHANGED_FILES=$(git diff --name-only $BASE_SHA $HEAD_SHA)
else
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || echo "")
fi
echo "Changed files:"
echo "$CHANGED_FILES"
# Check for Python changes outside plots/ (api, core, tests, automation)
# Plot implementations don't have unit tests
TESTABLE_CHANGES=$(echo "$CHANGED_FILES" | grep '\.py$' | grep -v '^plots/' || true)
# Also run tests if test configuration files change
CONFIG_CHANGES=$(echo "$CHANGED_FILES" | grep -E '^(pyproject\.toml|pytest\.ini|conftest\.py)$' || true)
# Force run on workflow_dispatch with force_run=true
if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ inputs.force_run }}" == "true" ]]; then
echo "Manual trigger with force_run=true, will run tests"
echo "should_test=true" >> $GITHUB_OUTPUT
elif [[ -n "$TESTABLE_CHANGES" ]]; then
echo "Found testable Python changes, will run tests"
echo "should_test=true" >> $GITHUB_OUTPUT
elif [[ -n "$CONFIG_CHANGES" ]]; then
echo "Found test config changes ($CONFIG_CHANGES), will run tests"
echo "should_test=true" >> $GITHUB_OUTPUT
else
echo "No testable changes (only plots/ or non-Python), skipping tests"
echo "should_test=false" >> $GITHUB_OUTPUT
fi
- name: Set up Python
if: steps.check.outputs.should_test == 'true'
uses: actions/setup-python@v6
with:
python-version: '3.14'
- name: Install uv
if: steps.check.outputs.should_test == 'true'
uses: astral-sh/setup-uv@v7
- name: Install dependencies
if: steps.check.outputs.should_test == 'true'
run: uv sync --extra test
- name: Authenticate to GCP
if: steps.check.outputs.should_test == 'true'
uses: google-github-actions/auth@v2
with:
project_id: anyplot
workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
- name: Start Cloud SQL Proxy
if: steps.check.outputs.should_test == 'true'
run: |
# Download Cloud SQL Proxy
curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.14.3/cloud-sql-proxy.linux.amd64
chmod +x cloud-sql-proxy
# Start proxy in background (localhost:5432 -> Cloud SQL)
./cloud-sql-proxy --port 5432 ${{ secrets.INSTANCE_CONNECTION_NAME }} &
# Wait for proxy to be ready
sleep 5
# Set DATABASE_URL for tests
echo "DATABASE_URL=postgresql+asyncpg://${{ secrets.DB_USER }}:${{ secrets.DB_PASS }}@localhost:5432/${{ secrets.DB_NAME }}" >> $GITHUB_ENV
- name: Run all tests with coverage
if: steps.check.outputs.should_test == 'true'
run: |
uv run pytest tests/unit tests/integration tests/e2e \
-v --tb=short \
--cov=core --cov=api --cov=automation --cov=agentic/workflows/modules \
--cov-report=term-missing \
--cov-report=xml
# Tests include:
# - Unit tests: Fast, mocked dependencies
# - Integration tests: SQLite in-memory for repository layer
# - E2E tests: Real PostgreSQL with separate 'test' database
- name: Upload coverage to GitHub Artifacts
if: steps.check.outputs.should_test == 'true' && always()
uses: actions/upload-artifact@v7
with:
name: coverage-report
path: coverage.xml
retention-days: 30
- name: Upload coverage to Codecov
if: steps.check.outputs.should_test == 'true'
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.xml
flags: backend
fail_ci_if_error: false
- name: Skip notice
if: steps.check.outputs.should_test == 'false'
run: echo "::notice::Tests skipped - no testable Python changes (only plots/ or non-Python files)"
test-frontend:
name: Run Frontend Tests
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check for frontend changes
id: check
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
CHANGED_FILES=$(git diff --name-only $BASE_SHA $HEAD_SHA)
else
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || echo "")
fi
echo "Changed files:"
echo "$CHANGED_FILES"
# Check for frontend changes
FRONTEND_CHANGES=$(echo "$CHANGED_FILES" | grep '^app/' || true)
# Force run on workflow_dispatch with force_run=true
if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ inputs.force_run }}" == "true" ]]; then
echo "Manual trigger with force_run=true, will run frontend tests"
echo "should_test=true" >> $GITHUB_OUTPUT
elif [[ -n "$FRONTEND_CHANGES" ]]; then
echo "Found frontend changes, will run tests"
echo "should_test=true" >> $GITHUB_OUTPUT
else
echo "No frontend changes, skipping frontend tests"
echo "should_test=false" >> $GITHUB_OUTPUT
fi
- name: Set up Node.js
if: steps.check.outputs.should_test == 'true'
uses: actions/setup-node@v6
with:
node-version: '24'
cache: 'yarn'
cache-dependency-path: app/yarn.lock
- name: Install dependencies
if: steps.check.outputs.should_test == 'true'
working-directory: app
run: yarn install --frozen-lockfile
- name: Run frontend tests with coverage
if: steps.check.outputs.should_test == 'true'
working-directory: app
run: yarn test --coverage
- name: Upload frontend coverage to Codecov
if: steps.check.outputs.should_test == 'true'
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./app/coverage/coverage-final.json
flags: frontend
fail_ci_if_error: false
- name: Skip notice
if: steps.check.outputs.should_test == 'false'
run: echo "::notice::Frontend tests skipped - no app/ changes"