Skip to content

Commit cb58ff2

Browse files
committed
Introduce minimal CI/CD pipeline
1 parent 8422b0f commit cb58ff2

File tree

6 files changed

+387
-7
lines changed

6 files changed

+387
-7
lines changed

.github/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# CI/CD Pipeline
2+
3+
## Workflows
4+
5+
### CI (`ci.yml`)
6+
- **Code Quality**: Custom ruff script, MyPy, syntax validation
7+
- **Docker Build**: Image build and compose validation
8+
- **Runs on**: PRs and pushes to `main`
9+
10+
### Tests (`tests.yml`)
11+
- **Unit/Integration Tests**: Auto-detects and runs tests when they exist
12+
- **Runs on**: PRs and pushes to `main`
13+
14+
### Security (`security.yml`)
15+
- **Daily Scans**: Dependencies (Safety), code security (Bandit), secrets (TruffleHog), Docker (Trivy)
16+
- **Runs on**: Daily 2 AM UTC, PRs, pushes to `main`
17+
18+
### PR Check (`pr-check.yml`)
19+
- **Basic Validation**: Non-empty PR title/description, merge conflict check
20+
- **Runs on**: PRs to `main`
21+
22+
## Local Development
23+
24+
**Before pushing:**
25+
```bash
26+
./scripts/ruff_check_format_assets.sh
27+
```
28+
29+
**Optional checks:**
30+
```bash
31+
mypy src/ --ignore-missing-imports
32+
bandit -r src/
33+
```
34+
35+
## Requirements
36+
- Non-empty PR title/description
37+
- Pass code quality checks (ruff script must not make changes)
38+
- Docker must build successfully
39+
- No merge conflicts
40+
41+
## Tests
42+
Create test files in `tests/` directory - CI will auto-detect and run them.

.github/workflows/ci.yml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
branches: [ main ]
6+
push:
7+
branches: [ main ]
8+
9+
env:
10+
PYTHON_VERSION: "3.11"
11+
12+
jobs:
13+
# =============================================================================
14+
# CODE QUALITY & BUILD VALIDATION
15+
# =============================================================================
16+
code-quality:
17+
name: Code Quality & Build
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v4
22+
23+
- name: Set up Python
24+
uses: actions/setup-python@v4
25+
with:
26+
python-version: ${{ env.PYTHON_VERSION }}
27+
28+
- name: Cache dependencies
29+
uses: actions/cache@v3
30+
with:
31+
path: ~/.cache/pip
32+
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
33+
restore-keys: ${{ runner.os }}-pip-
34+
35+
- name: Install dependencies
36+
run: |
37+
python -m pip install --upgrade pip
38+
pip install ruff mypy tomli
39+
pip install pandas web3 tenacity
40+
41+
- name: Run code formatting and linting
42+
run: |
43+
chmod +x scripts/ruff_check_format_assets.sh
44+
./scripts/ruff_check_format_assets.sh
45+
46+
- name: Check for uncommitted changes
47+
run: |
48+
if ! git diff --quiet; then
49+
echo "Code formatting changes detected. Run ./scripts/ruff_check_format_assets.sh locally and commit changes."
50+
git diff --name-only
51+
exit 1
52+
fi
53+
54+
- name: Run type checking
55+
run: mypy src/ --ignore-missing-imports --no-strict-optional
56+
57+
- name: Validate Python syntax
58+
run: find src/ -name "*.py" -exec python -m py_compile {} \;
59+
60+
- name: Test critical imports
61+
run: |
62+
cd src
63+
python -c "
64+
import sys; sys.path.insert(0, '..')
65+
from src.utils.config_loader import load_config
66+
from src.utils.key_validator import validate_and_format_private_key
67+
print('Core modules import successfully')
68+
"
69+
70+
- name: Validate configuration
71+
run: |
72+
python -c "
73+
import tomli
74+
with open('config.toml.example', 'rb') as f:
75+
config = tomli.load(f)
76+
required = ['bigquery', 'blockchain', 'scheduling', 'secrets']
77+
for section in required:
78+
if section not in config:
79+
raise ValueError(f'Missing section: {section}')
80+
print('Configuration valid')
81+
"
82+
83+
# =============================================================================
84+
# DOCKER BUILD VALIDATION
85+
# =============================================================================
86+
docker-build:
87+
name: Docker Build
88+
runs-on: ubuntu-latest
89+
steps:
90+
- name: Checkout code
91+
uses: actions/checkout@v4
92+
93+
- name: Build and test Docker image
94+
run: |
95+
docker build -t service-quality-oracle:test .
96+
docker create --name test-container service-quality-oracle:test
97+
docker rm test-container
98+
99+
- name: Validate Docker Compose
100+
run: docker-compose config

.github/workflows/pr-check.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: PR Check
2+
3+
on:
4+
pull_request:
5+
branches: [ main ]
6+
7+
jobs:
8+
# =============================================================================
9+
# PR VALIDATION
10+
# =============================================================================
11+
pr-validation:
12+
name: PR Validation
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
with:
18+
fetch-depth: 0
19+
20+
- name: Validate PR requirements
21+
run: |
22+
PR_TITLE="${{ github.event.pull_request.title }}"
23+
if [[ ${#PR_TITLE} -lt 1 ]]; then
24+
echo "PR title cannot be empty"
25+
exit 1
26+
fi
27+
28+
PR_BODY="${{ github.event.pull_request.body }}"
29+
if [[ ${#PR_BODY} -lt 1 ]]; then
30+
echo "PR description cannot be empty"
31+
exit 1
32+
fi
33+
34+
- name: Analyze file changes
35+
run: |
36+
git diff --name-only origin/main...HEAD > changed_files.txt
37+
38+
if grep -q "\.github/workflows/" changed_files.txt; then
39+
echo "GitHub workflow files modified"
40+
fi
41+
42+
if grep -q "Dockerfile\|docker-compose" changed_files.txt; then
43+
echo "Docker configuration modified"
44+
fi
45+
46+
if grep -q "requirements.txt\|pyproject.toml" changed_files.txt; then
47+
echo "Dependencies modified"
48+
fi
49+
50+
- name: Check for merge conflicts
51+
run: |
52+
git config user.name "CI Bot"
53+
git config user.email "[email protected]"
54+
55+
if ! git merge-tree $(git merge-base HEAD origin/main) HEAD origin/main | grep -q "^<<<<<<< "; then
56+
echo "No merge conflicts detected"
57+
else
58+
echo "Merge conflicts detected - resolve before merging"
59+
exit 1
60+
fi

.github/workflows/security.yml

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
name: Security Scanning
2+
3+
on:
4+
schedule:
5+
# Run security scans daily at 2 AM UTC
6+
- cron: '0 2 * * *'
7+
pull_request:
8+
branches: [ main, develop ]
9+
push:
10+
branches: [ main ]
11+
12+
jobs:
13+
# =============================================================================
14+
# DEPENDENCY SCAN
15+
# =============================================================================
16+
dependency-scan:
17+
name: Dependency Scan
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v4
22+
23+
- name: Set up Python
24+
uses: actions/setup-python@v4
25+
with:
26+
python-version: "3.11"
27+
28+
- name: Scan dependencies
29+
run: |
30+
pip install safety
31+
safety check --file requirements.txt || echo "Vulnerabilities found - review required"
32+
33+
# =============================================================================
34+
# CODE SECURITY SCAN
35+
# =============================================================================
36+
code-security:
37+
name: Code Security
38+
runs-on: ubuntu-latest
39+
steps:
40+
- name: Checkout code
41+
uses: actions/checkout@v4
42+
43+
- name: Set up Python
44+
uses: actions/setup-python@v4
45+
with:
46+
python-version: "3.11"
47+
48+
- name: Run security analysis
49+
run: |
50+
pip install bandit
51+
bandit -r src/ || echo "Security issues found - review required"
52+
53+
# =============================================================================
54+
# SECRETS SCAN
55+
# =============================================================================
56+
secrets-scan:
57+
name: Secrets Scan
58+
runs-on: ubuntu-latest
59+
steps:
60+
- name: Checkout code
61+
uses: actions/checkout@v4
62+
63+
- name: Scan for secrets
64+
uses: trufflesecurity/trufflehog@main
65+
with:
66+
path: ./
67+
base: main
68+
head: HEAD
69+
extra_args: --only-verified
70+
71+
# =============================================================================
72+
# DOCKER SECURITY
73+
# =============================================================================
74+
docker-security:
75+
name: Docker Security
76+
runs-on: ubuntu-latest
77+
steps:
78+
- name: Checkout code
79+
uses: actions/checkout@v4
80+
81+
- name: Build and scan image
82+
run: docker build -t service-quality-oracle:security-scan .
83+
84+
- name: Run vulnerability scan
85+
uses: aquasecurity/trivy-action@master
86+
with:
87+
image-ref: 'service-quality-oracle:security-scan'
88+
format: 'table'

.github/workflows/tests.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: Test Suite
2+
3+
on:
4+
pull_request:
5+
branches: [ main ]
6+
push:
7+
branches: [ main ]
8+
9+
env:
10+
PYTHON_VERSION: "3.11"
11+
12+
jobs:
13+
# =============================================================================
14+
# UNIT TESTS
15+
# =============================================================================
16+
unit-tests:
17+
name: Unit Tests
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v4
22+
23+
- name: Set up Python
24+
uses: actions/setup-python@v4
25+
with:
26+
python-version: ${{ env.PYTHON_VERSION }}
27+
28+
- name: Install dependencies
29+
run: |
30+
python -m pip install --upgrade pip
31+
pip install -r requirements.txt
32+
pip install pytest pytest-cov pytest-mock
33+
34+
- name: Run tests
35+
run: |
36+
if [ -d "tests" ] && [ "$(find tests -name '*.py' -not -name '__init__.py' | wc -l)" -gt 0 ]; then
37+
echo "Running tests"
38+
pytest tests/ -v --cov=src --cov-report=term-missing
39+
else
40+
echo "No tests found - create files in tests/ directory to run tests"
41+
fi
42+
43+
# =============================================================================
44+
# INTEGRATION TESTS
45+
# =============================================================================
46+
integration-tests:
47+
name: Integration Tests
48+
runs-on: ubuntu-latest
49+
steps:
50+
- name: Checkout code
51+
uses: actions/checkout@v4
52+
53+
- name: Set up Python
54+
uses: actions/setup-python@v4
55+
with:
56+
python-version: ${{ env.PYTHON_VERSION }}
57+
58+
- name: Install dependencies
59+
run: |
60+
python -m pip install --upgrade pip
61+
pip install -r requirements.txt
62+
pip install pytest
63+
64+
- name: Validate Docker setup
65+
run: docker-compose config > /dev/null
66+
67+
- name: Run integration tests
68+
run: |
69+
if [ -d "tests/integration" ] && [ "$(find tests/integration -name '*.py' -not -name '__init__.py' | wc -l)" -gt 0 ]; then
70+
echo "Running integration tests"
71+
pytest tests/integration/ -v
72+
else
73+
echo "No integration tests found - create files in tests/integration/ directory"
74+
fi

0 commit comments

Comments
 (0)