Skip to content

Commit f217c5d

Browse files
committed
Initial commit
0 parents  commit f217c5d

File tree

169 files changed

+39765
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

169 files changed

+39765
-0
lines changed

.bandit

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Bandit configuration file
2+
# https://bandit.readthedocs.io/en/latest/config.html
3+
4+
# Skip B110 (try_except_pass) - we use this legitimately in cleanup code
5+
skips: [B110]
6+
7+
# Exclude test directories from security scanning
8+
exclude_dirs:
9+
- /tests
10+
- /examples
11+
12+
# We keep B101 (assert_used) to warn about potential issues with python -O

.github/workflows/ci-base.yml

Lines changed: 346 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,346 @@
1+
name: Base CI with Parallel Tests
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
run-integration-tests:
7+
description: 'Run integration tests'
8+
required: false
9+
type: boolean
10+
default: false
11+
run-full-suite:
12+
description: 'Run full test suite'
13+
required: false
14+
type: boolean
15+
default: false
16+
17+
jobs:
18+
lint:
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- uses: actions/checkout@v4
23+
24+
- name: Set up Python 3.12
25+
uses: actions/setup-python@v5
26+
with:
27+
python-version: '3.12'
28+
29+
- name: Install dependencies
30+
run: |
31+
python -m pip install --upgrade pip
32+
pip install -e ".[dev]"
33+
34+
- name: Run linting checks
35+
run: |
36+
echo "=== Running ruff ==="
37+
ruff check src/ tests/
38+
echo "=== Running black ==="
39+
black --check src/ tests/
40+
echo "=== Running isort ==="
41+
isort --check-only src/ tests/
42+
echo "=== Running mypy ==="
43+
mypy src/
44+
45+
security:
46+
runs-on: ubuntu-latest
47+
needs: lint
48+
49+
steps:
50+
- uses: actions/checkout@v4
51+
52+
- name: Set up Python 3.12
53+
uses: actions/setup-python@v5
54+
with:
55+
python-version: '3.12'
56+
57+
- name: Install security tools
58+
run: |
59+
python -m pip install --upgrade pip
60+
pip install bandit[toml] safety pip-audit
61+
62+
- name: Run Bandit security scan
63+
run: |
64+
echo "=== Running Bandit security scan ==="
65+
# Run bandit with config file and capture exit code
66+
bandit -c .bandit -r src/ -f json -o bandit-report.json || BANDIT_EXIT=$?
67+
# Show the detailed issues found
68+
echo "=== Bandit Detailed Results ==="
69+
bandit -c .bandit -r src/ -v || true
70+
# For low severity issues, we'll just warn but not fail
71+
if [ "${BANDIT_EXIT:-0}" -eq 1 ]; then
72+
echo "⚠️ Bandit found low-severity issues (see above)"
73+
# Check if there are medium or high severity issues
74+
if bandit -c .bandit -r src/ -lll &>/dev/null; then
75+
echo "✅ No medium or high severity issues found - continuing"
76+
exit 0
77+
else
78+
echo "❌ Medium or high severity issues found - failing"
79+
exit 1
80+
fi
81+
fi
82+
exit ${BANDIT_EXIT:-0}
83+
84+
- name: Check dependencies with Safety
85+
run: |
86+
echo "=== Checking dependencies with Safety ==="
87+
pip install -e ".[dev,test]"
88+
# Using the new 'scan' command as 'check' is deprecated
89+
safety scan --json || SAFETY_EXIT=$?
90+
# Safety scan exits with 64 if vulnerabilities found
91+
if [ "${SAFETY_EXIT:-0}" -eq 64 ]; then
92+
echo "❌ Vulnerabilities found in dependencies"
93+
exit 1
94+
fi
95+
96+
- name: Run pip-audit
97+
run: |
98+
echo "=== Running pip-audit ==="
99+
# Skip the local package as it's not on PyPI yet
100+
pip-audit --skip-editable
101+
102+
- name: Upload security reports
103+
uses: actions/upload-artifact@v4
104+
if: always()
105+
with:
106+
name: security-reports
107+
path: |
108+
bandit-report.json
109+
110+
unit-tests:
111+
runs-on: ubuntu-latest
112+
needs: lint
113+
114+
steps:
115+
- uses: actions/checkout@v4
116+
117+
- name: Set up Python 3.12
118+
uses: actions/setup-python@v5
119+
with:
120+
python-version: '3.12'
121+
122+
- name: Install dependencies
123+
run: |
124+
python -m pip install --upgrade pip
125+
pip install -e ".[test]"
126+
127+
- name: Run unit tests with coverage
128+
run: |
129+
pytest tests/unit/ -v --cov=async_cassandra --cov-report=html --cov-report=xml
130+
131+
# Coverage upload - disabled due to Codecov issues
132+
# - name: Upload coverage reports
133+
# uses: codecov/codecov-action@v4
134+
# with:
135+
# token: ${{ secrets.CODECOV_TOKEN }}
136+
# file: ./coverage.xml
137+
# flags: unittests
138+
# name: unit-tests
139+
# fail_ci_if_error: false
140+
# verbose: true
141+
142+
build:
143+
runs-on: ubuntu-latest
144+
needs: [lint, security, unit-tests]
145+
146+
steps:
147+
- uses: actions/checkout@v4
148+
149+
- name: Set up Python 3.12
150+
uses: actions/setup-python@v5
151+
with:
152+
python-version: '3.12'
153+
154+
- name: Install build dependencies
155+
run: |
156+
python -m pip install --upgrade pip
157+
pip install build twine
158+
159+
- name: Build package
160+
run: |
161+
echo "=== Building package ==="
162+
python -m build
163+
echo "=== Package contents ==="
164+
ls -la dist/
165+
166+
- name: Check package with twine
167+
run: |
168+
echo "=== Checking package metadata ==="
169+
twine check dist/*
170+
171+
- name: Display package info
172+
run: |
173+
echo "=== Wheel contents ==="
174+
python -m zipfile -l dist/*.whl | head -20
175+
echo "=== Package metadata ==="
176+
pip show --verbose async-cassandra || true
177+
178+
- name: Upload build artifacts
179+
uses: actions/upload-artifact@v4
180+
with:
181+
name: python-package-distributions
182+
path: dist/
183+
retention-days: 7
184+
185+
integration-tests:
186+
runs-on: ubuntu-latest
187+
needs: [lint, security, unit-tests]
188+
if: ${{ inputs.run-integration-tests || inputs.run-full-suite }}
189+
190+
strategy:
191+
fail-fast: false
192+
matrix:
193+
test-suite:
194+
- name: "Integration Tests"
195+
command: "pytest tests/integration -v -m 'not stress'"
196+
- name: "FastAPI Integration"
197+
command: "pytest tests/fastapi_integration -v"
198+
- name: "BDD Tests"
199+
command: "pytest tests/bdd -v"
200+
- name: "Example App"
201+
command: "cd examples/fastapi_app && pytest tests/ -v"
202+
203+
name: ${{ matrix.test-suite.name }}
204+
205+
services:
206+
cassandra:
207+
image: cassandra:5
208+
ports:
209+
- 9042:9042
210+
options: >-
211+
--health-cmd "nodetool status"
212+
--health-interval 30s
213+
--health-timeout 10s
214+
--health-retries 10
215+
--memory=4g
216+
--memory-reservation=4g
217+
env:
218+
CASSANDRA_CLUSTER_NAME: TestCluster
219+
CASSANDRA_DC: datacenter1
220+
CASSANDRA_ENDPOINT_SNITCH: SimpleSnitch
221+
HEAP_NEWSIZE: 512M
222+
MAX_HEAP_SIZE: 3G
223+
JVM_OPTS: "-XX:+UseG1GC -XX:G1RSetUpdatingPauseTimePercent=5 -XX:MaxGCPauseMillis=300"
224+
225+
steps:
226+
- uses: actions/checkout@v4
227+
228+
- name: Set up Python 3.12
229+
uses: actions/setup-python@v5
230+
with:
231+
python-version: '3.12'
232+
233+
- name: Install dependencies
234+
run: |
235+
python -m pip install --upgrade pip
236+
pip install -e ".[test,dev]"
237+
238+
- name: Verify Cassandra is ready
239+
run: |
240+
echo "Installing cqlsh to verify Cassandra..."
241+
pip install cqlsh
242+
echo "Testing Cassandra connection..."
243+
cqlsh localhost 9042 -e "DESC CLUSTER" | head -10
244+
echo "✅ Cassandra is ready and responding to CQL"
245+
246+
- name: Run ${{ matrix.test-suite.name }}
247+
env:
248+
CASSANDRA_HOST: localhost
249+
CASSANDRA_PORT: 9042
250+
run: |
251+
echo "=== Running ${{ matrix.test-suite.name }} ==="
252+
${{ matrix.test-suite.command }}
253+
254+
stress-tests:
255+
runs-on: ubuntu-latest
256+
needs: [lint, security, unit-tests]
257+
if: ${{ inputs.run-full-suite }}
258+
259+
strategy:
260+
fail-fast: false
261+
matrix:
262+
test-suite:
263+
- name: "Stress Tests"
264+
command: "pytest tests/integration -v -m stress"
265+
266+
name: ${{ matrix.test-suite.name }}
267+
268+
services:
269+
cassandra:
270+
image: cassandra:5
271+
ports:
272+
- 9042:9042
273+
options: >-
274+
--health-cmd "nodetool status"
275+
--health-interval 30s
276+
--health-timeout 10s
277+
--health-retries 10
278+
--memory=4g
279+
--memory-reservation=4g
280+
env:
281+
CASSANDRA_CLUSTER_NAME: TestCluster
282+
CASSANDRA_DC: datacenter1
283+
CASSANDRA_ENDPOINT_SNITCH: SimpleSnitch
284+
HEAP_NEWSIZE: 512M
285+
MAX_HEAP_SIZE: 3G
286+
JVM_OPTS: "-XX:+UseG1GC -XX:G1RSetUpdatingPauseTimePercent=5 -XX:MaxGCPauseMillis=300"
287+
288+
steps:
289+
- uses: actions/checkout@v4
290+
291+
- name: Set up Python 3.12
292+
uses: actions/setup-python@v5
293+
with:
294+
python-version: '3.12'
295+
296+
- name: Install dependencies
297+
run: |
298+
python -m pip install --upgrade pip
299+
pip install -e ".[test,dev]"
300+
301+
- name: Verify Cassandra is ready
302+
run: |
303+
echo "Installing cqlsh to verify Cassandra..."
304+
pip install cqlsh
305+
echo "Testing Cassandra connection..."
306+
cqlsh localhost 9042 -e "DESC CLUSTER" | head -10
307+
echo "✅ Cassandra is ready and responding to CQL"
308+
309+
- name: Run ${{ matrix.test-suite.name }}
310+
env:
311+
CASSANDRA_HOST: localhost
312+
CASSANDRA_PORT: 9042
313+
run: |
314+
echo "=== Running ${{ matrix.test-suite.name }} ==="
315+
${{ matrix.test-suite.command }}
316+
317+
test-summary:
318+
name: Test Summary
319+
runs-on: ubuntu-latest
320+
needs: [lint, security, unit-tests, build, integration-tests]
321+
if: always()
322+
steps:
323+
- name: Summary
324+
run: |
325+
echo "## Test Results Summary" >> $GITHUB_STEP_SUMMARY
326+
echo "" >> $GITHUB_STEP_SUMMARY
327+
echo "### Core Tests" >> $GITHUB_STEP_SUMMARY
328+
echo "- Lint: ${{ needs.lint.result }}" >> $GITHUB_STEP_SUMMARY
329+
echo "- Security: ${{ needs.security.result }}" >> $GITHUB_STEP_SUMMARY
330+
echo "- Unit Tests: ${{ needs.unit-tests.result }}" >> $GITHUB_STEP_SUMMARY
331+
echo "- Build: ${{ needs.build.result }}" >> $GITHUB_STEP_SUMMARY
332+
echo "" >> $GITHUB_STEP_SUMMARY
333+
echo "### Integration Tests" >> $GITHUB_STEP_SUMMARY
334+
echo "- Integration Tests: ${{ needs.integration-tests.result }}" >> $GITHUB_STEP_SUMMARY
335+
echo "" >> $GITHUB_STEP_SUMMARY
336+
337+
if [ "${{ needs.lint.result }}" != "success" ] || \
338+
[ "${{ needs.security.result }}" != "success" ] || \
339+
[ "${{ needs.unit-tests.result }}" != "success" ] || \
340+
[ "${{ needs.build.result }}" != "success" ] || \
341+
[ "${{ needs.integration-tests.result }}" != "success" ]; then
342+
echo "❌ Some tests failed" >> $GITHUB_STEP_SUMMARY
343+
exit 1
344+
else
345+
echo "✅ All tests passed" >> $GITHUB_STEP_SUMMARY
346+
fi

.github/workflows/main.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Main Branch CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths-ignore:
7+
- '**.md'
8+
- 'docs/**'
9+
- '.gitignore'
10+
- 'LICENSE'
11+
12+
jobs:
13+
ci:
14+
uses: ./.github/workflows/ci-base.yml
15+
with:
16+
run-integration-tests: true
17+
run-full-suite: false

.github/workflows/pr.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: PR CI
2+
3+
on:
4+
pull_request:
5+
branches: [ main ]
6+
paths-ignore:
7+
- '**.md'
8+
- 'docs/**'
9+
- '.gitignore'
10+
- 'LICENSE'
11+
12+
jobs:
13+
ci:
14+
uses: ./.github/workflows/ci-base.yml
15+
with:
16+
run-integration-tests: false
17+
run-full-suite: false

0 commit comments

Comments
 (0)