Skip to content

Commit 26c2031

Browse files
authored
Chore/ci consolidation (#105)
* chore: ignore VSCode workspace file * cleanup: remove duplicated CI workflows and stabilize pipeline * fix(security): remove hardcoded bind and rely on env host * feat(observability): add telemetry and test configuration * ci(railway): add automated docker build and deployment workflow * docs: cleanup deployment documentation * style: fix import order for isort/black * style: fix import order in app/main.py * fix(api): align root response with tests and harden settings * fix(security): remove hardcoded 0.0.0.0 default to satisfy bandit B104 * fix(api): align root endpoint response with tests (add features) * fix(api): stabilize root endpoint and logging lifecycle * fix(api): align root endpoint response with tests (add features) * fix(app): remove arguments from setup_logging (CodeQL) * fix(app): sort imports and finalize main app lifecycle * fix(lint): satisfy isort import order * fix(lint): satisfy isort 7 and CodeQL * chore(lint): configure isort to align with black * fix(backoffice): correct APIRouter import and routing * fix(core): stabilize app lifecycle, routing and logging * chore(lint): configure isort to align with black * feat(app): implement lifespan management and health check endpoints * fix: resolve architectural issues - cyclic imports and CodeQL errors - Refactor app/config.py to ONLY contain Settings class and get_settings() - Remove FastAPI app definition and lifespan (moved to main.py) - Remove router imports to break circular dependencies - Add pydantic extra='ignore' to handle extra env vars - Update app/utils/logging.py setup_logging() to accept ZERO arguments - Read LOG_LEVEL from environment internally - Fixes CodeQL error: 'Wrong number of arguments in call to setup_logging' - Refactor app/main.py as ONLY place for FastAPI app and lifespan - Define lifespan() with lazy settings import - Call setup_logging() with no arguments - Import routers directly (no circular dependencies) - Add timestamp to health check endpoint - Verify routers (operator, backoffice) don't import config or main Dependency flow: main.py -> config.py, routers (NEVER reverse) All tests pass (7/7 ✓) Black + isort formatting applied CodeQL circular import issues resolved * fix(tests): configure environment variables for CI tests - Add pytest-env configuration in pytest.ini with required vars: - API_KEY, SECRET_KEY for authentication tests - CORS_ORIGINS as JSON array format for pydantic-settings - ENVIRONMENT=testing for test environment - Update .env.test with proper test values - Use JSON format for list values: CORS_ORIGINS=["*"] Fixes test failure in CI: - ValueError: API_KEY environment variable is required - Tests now pass with mocked environment variables All tests pass locally: 7/7 ✓ * fix(ci): configure test environment variables properly - Move env vars from pytest.ini (unsupported) to CI workflow - Add environment variables directly in ci.yml test step: - API_KEY, SECRET_KEY, CORS_ORIGINS, ENVIRONMENT, etc. - Create app/tests/conftest.py for local testing: - Automatically sets test env vars if not present - Ensures consistent behavior between local and CI - Remove invalid 'env' section from pytest.ini - pytest-env plugin not needed anymore Fixes CI error: - "ERROR: Unknown config option: env" - Tests now have proper environment in both local and CI All tests pass: 7/7 ✓ * style: format conftest.py with black
1 parent d7f1756 commit 26c2031

File tree

17 files changed

+254
-929
lines changed

17 files changed

+254
-929
lines changed

.github/workflows/ci.yml

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,47 @@
1-
name: CI - Quality Checks
1+
name: CI Quality Gate
22

33
on:
44
pull_request:
5-
branches: [main]
5+
branches: [ main ]
66
push:
7-
branches:
8-
- "feature/**"
7+
branches: [ "feature/**" ]
98

109
jobs:
11-
quality-checks:
10+
quality:
1211
runs-on: ubuntu-latest
1312
strategy:
14-
fail-fast: false
1513
matrix:
16-
python-version: ["3.11", "3.12"]
14+
python-version: ["3.11"]
1715

1816
steps:
19-
- name: Checkout repository
20-
uses: actions/checkout@v4
17+
- uses: actions/checkout@v4
2118

22-
- name: Setup Python
23-
uses: actions/setup-python@v5
19+
- uses: actions/setup-python@v5
2420
with:
2521
python-version: ${{ matrix.python-version }}
2622

27-
- name: Get pip cache dir
28-
id: pip-cache
29-
run: |
30-
echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT
31-
32-
- name: Cache dependencies
33-
uses: actions/cache@v4
34-
with:
35-
path: ${{ steps.pip-cache.outputs.dir }}
36-
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/requirements.txt') }}
37-
restore-keys: |
38-
${{ runner.os }}-pip-${{ matrix.python-version }}-
39-
${{ runner.os }}-pip-
40-
41-
- name: Install dependencies and tools
23+
- name: Install dependencies
4224
run: |
4325
pip install --upgrade pip
4426
pip install -r requirements.txt
45-
pip install black isort autoflake bandit safety pytest pytest-asyncio pytest-cov
27+
pip install black isort bandit safety pytest pytest-asyncio pytest-cov
4628
47-
- name: Run linters
29+
- name: Lint
4830
run: |
49-
echo "--- Running Black ---"
5031
black --check app
51-
echo "--- Running isort ---"
5232
isort --check-only app
5333
54-
- name: Run security scans
34+
- name: Security scan
5535
run: |
56-
echo "--- Running Bandit ---"
5736
bandit -r app -ll
58-
echo "--- Running Safety ---"
5937
safety check -r requirements.txt || true
6038
61-
- name: Run unit tests
62-
run: pytest -q --disable-warnings --maxfail=1
39+
- name: Run tests
40+
env:
41+
API_KEY: test-api-key-12345678
42+
SECRET_KEY: test-secret-key-87654321
43+
CORS_ORIGINS: '["*"]'
44+
ENVIRONMENT: testing
45+
DEBUG: false
46+
LOG_LEVEL: INFO
47+
run: pytest -q --disable-warnings --maxfail=1

.github/workflows/deploy.yml

Lines changed: 12 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,38 @@
1-
name: CD - NeuroBank Deployment (Karpathy Edition)
1+
name: CD NeuroBank Deployment
22

33
on:
44
push:
5-
branches: [main]
5+
branches: [ main ]
66

77
jobs:
88
deploy:
9-
name: Build & Deploy
109
runs-on: ubuntu-latest
1110
permissions:
1211
contents: read
1312
packages: write
1413

1514
env:
1615
IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/neurobank:${{ github.sha }}
17-
SERVICE_ID: "REPLACE_ME" # <- luego pones el tuyo
1816
RAILWAY_API: https://backboard.railway.app/graphql
1917

2018
steps:
19+
- uses: actions/checkout@v4
2120

22-
- name: Checkout repository
23-
uses: actions/checkout@v4
24-
25-
# ============================================================
26-
# A — BUILD DOCKER IMAGE
27-
# ============================================================
28-
- name: Log in to GHCR
21+
- name: Login to GHCR
2922
run: |
30-
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io \
31-
echo "${{ secrets.GHCR_PAT }}" | docker login ghcr.io \
32-
-u "${{ github.actor }}" --password-stdin
23+
echo "${{ secrets.GHCR_PAT }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
3324
3425
- name: Build Docker image
35-
run: |
36-
echo "➜ Building Docker image: $IMAGE_NAME"
37-
docker build -t $IMAGE_NAME .
26+
run: docker build -t $IMAGE_NAME .
3827

39-
- name: Push Docker image to GHCR
40-
run: |
41-
echo "➜ Pushing image to GHCR..."
42-
docker push $IMAGE_NAME
28+
- name: Push Docker image
29+
run: docker push $IMAGE_NAME
4330

44-
# ============================================================
45-
# B — TRY RAILWAY CLI (NON-BLOCKING)
46-
# ============================================================
47-
- name: Try installing Railway CLI
48-
id: cli_install
31+
# Railway CLI (best-effort)
32+
- name: Try Railway CLI
4933
continue-on-error: true
50-
run: |
51-
echo "➜ Attempting Railway CLI install…"
52-
curl -fsSL https://railway.app/install.sh | sh
53-
if command -v railway > /dev/null; then
54-
echo "cli=true" >> $GITHUB_OUTPUT
55-
else
56-
echo "cli=false" >> $GITHUB_OUTPUT
57-
fi
58-
59-
- name: Deploy using Railway CLI
60-
if: steps.cli_install.outputs.cli == 'true'
6134
env:
6235
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
63-
continue-on-error: true
6436
run: |
65-
echo "➜ Railway CLI OK → Trying deploy…"
66-
railway up --ci || echo "⚠️ CLI deploy failed, continuing with API fallback"
67-
68-
# ============================================================
69-
# C — API FALLBACK DEPLOY (INFALIBLE)
70-
# ============================================================
71-
- name: Trigger Railway deployment via API (fallback)
72-
if: steps.cli_install.outputs.cli == 'false'
73-
env:
74-
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
75-
run: |
76-
echo "⚠️ CLI unavailable → Using API fallback mode."
77-
echo "➜ Deploying image: $IMAGE_NAME"
78-
79-
curl -X POST "$RAILWAY_API" \
80-
-H "Content-Type: application/json" \
81-
-H "Authorization: Bearer $RAILWAY_TOKEN" \
82-
-d "{
83-
\"query\": \"mutation { deployService(input: { serviceId: \\\"$SERVICE_ID\\\", image: \\\"$IMAGE_NAME\\\" }) { id } }\"
84-
}"
85-
86-
echo "✔ Deployment requested successfully via Railway API."
87-
88-
- name: Final status
89-
run: |
90-
echo ""
91-
echo "-------------------------------------------"
92-
echo " KARPATHY DEPLOY PIPELINE COMPLETED"
93-
echo "-------------------------------------------"
94-
echo "Image: $IMAGE_NAME"
95-
echo "Service: $SERVICE_ID"
96-
echo "If Railway falla → tú no fallas."
97-
echo "-------------------------------------------"
37+
curl -fsSL https://railway.app/install.sh | sh
38+
railway up || true
Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,27 @@
1-
name: docker-security
1+
name: Docker Security (Trivy)
22

33
on:
44
pull_request:
55
branches: [ main ]
6-
push:
7-
branches: [ main ]
86
workflow_dispatch:
97

108
jobs:
119
trivy:
12-
name: Trivy Security
1310
runs-on: ubuntu-latest
14-
1511
permissions:
1612
contents: read
1713
security-events: write
1814

1915
steps:
20-
- name: Checkout repository
21-
uses: actions/checkout@v6
16+
- uses: actions/checkout@v4
2217

23-
- name: Run Trivy vulnerability scanner (fs)
24-
uses: aquasecurity/[email protected]
18+
- uses: aquasecurity/[email protected]
2519
with:
26-
scan-type: "fs"
27-
format: "sarif"
28-
output: "trivy-results.sarif"
29-
severity: "CRITICAL,HIGH"
20+
scan-type: fs
21+
format: sarif
22+
output: trivy-results.sarif
23+
severity: CRITICAL,HIGH
3024

31-
- name: Upload SARIF results to GitHub Security
32-
uses: github/codeql-action/upload-sarif@v4
25+
- uses: github/codeql-action/upload-sarif@v4
3326
with:
3427
sarif_file: trivy-results.sarif

.github/workflows/lint.yml

Lines changed: 0 additions & 24 deletions
This file was deleted.

.github/workflows/security.yml

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,18 @@
1-
name: CI - Security Scan
1+
name: CI Security Scan
22

33
on:
44
pull_request:
5-
branches: [main]
6-
push:
7-
branches:
8-
- "feature/**"
5+
branches: [ main ]
96

107
jobs:
118
security:
129
runs-on: ubuntu-latest
13-
1410
steps:
1511
- uses: actions/checkout@v4
16-
17-
- name: Setup Python
18-
uses: actions/setup-python@v5
12+
- uses: actions/setup-python@v5
1913
with:
2014
python-version: "3.11"
2115

22-
- name: Install security tooling
23-
run: pip install bandit safety
24-
25-
- name: Run Bandit
26-
run: bandit -r app -ll
27-
28-
- name: Dependency vulnerability scan
29-
run: safety check -r requirements.txt || true
16+
- run: pip install bandit safety
17+
- run: bandit -r app -ll
18+
- run: safety check -r requirements.txt || true

.github/workflows/test.yml

Lines changed: 0 additions & 30 deletions
This file was deleted.

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.11.8
1+
3.12.3

DOCKER_FIX_DEPLOYED.md

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)