Skip to content

refactor: replace Optional[X] with X | None for Python 3.10+ compatib… #9

refactor: replace Optional[X] with X | None for Python 3.10+ compatib…

refactor: replace Optional[X] with X | None for Python 3.10+ compatib… #9

Workflow file for this run

Check failure on line 1 in .github/workflows/ci-cd-pipeline.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/ci-cd-pipeline.yml

Invalid workflow file

(Line: 200, Col: 9): Unrecognized named-value: 'env'. Located at position 1 within expression: env.SONAR_TOKEN != '', (Line: 246, Col: 9): Unrecognized named-value: 'secrets'. Located at position 67 within expression: github.ref == 'refs/heads/main' && github.event_name == 'push' && secrets.RAILWAY_TOKEN != ''
name: "🚀 CI/CD Pipeline"
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
workflow_dispatch:
env:
PYTHON_VERSION: '3.11'
POETRY_VERSION: '1.8.0'
jobs:
conventional-commits:
name: "📝 Conventional Commits"
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
trivy-fs:
name: "🛡️ Trivy FS Scan"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Trivy filesystem scan (CRITICAL only)
uses: aquasecurity/trivy-action@0.20.0
with:
scan-type: 'fs'
scanners: 'vuln,secret,config'
ignore-unfixed: true
format: 'table'
severity: 'CRITICAL'
exit-code: '1'
vuln-type: 'os,library'
limit-severities-for-sarif: true
hide-progress: true
continue-on-error: false
code-quality:
name: "🎨 Code Quality"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install dependencies
run: |
pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: Run Ruff (linting)
run: ruff check app/ --output-format=github
- name: Run Ruff (formatting check)
run: ruff format --check app/
- name: Run Radon (complexity)
run: |
radon cc app/ -a -s -j > radon-cc.json || true
radon mi app/ -s -j > radon-mi.json || true
- name: Run Vulture (dead code)
run: vulture app/ --min-confidence 60 || true
- name: Run Interrogate (docstring coverage)
run: interrogate app/ --fail-under 80 || true
- name: Upload complexity reports
uses: actions/upload-artifact@v4
if: always()
with:
name: complexity-reports
path: radon-*.json
type-checking:
name: "🔍 Type Checking"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install dependencies
run: |
pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: Run MyPy
run: mypy app/ --junit-xml mypy-report.xml || true
- name: Upload MyPy report
uses: actions/upload-artifact@v4
if: always()
with:
name: mypy-report
path: mypy-report.xml
security:
name: "🔒 Security Scanning"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install dependencies
run: |
pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: Run Bandit
run: bandit -r app/ -c .bandit -f json -o bandit-report.json || true
- name: Run Safety
run: safety check --json > safety-report.json || true
- name: Run pip-audit
run: pip-audit --format json > pip-audit-report.json || true
- name: Run Semgrep
run: semgrep --config auto app/ --json > semgrep-report.json || true
- name: Upload security reports
uses: actions/upload-artifact@v4
if: always()
with:
name: security-reports
path: '*-report.json'
dependencies:
name: "📦 Dependency Analysis"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install dependencies
run: |
pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: Run pipdeptree
run: pipdeptree --json > pipdeptree.json
- name: Run deptry
run: deptry app/ --json-output deptry-report.json || true
- name: Upload dependency reports
uses: actions/upload-artifact@v4
if: always()
with:
name: dependency-reports
path: '*tree*.json'
test:
name: "🧪 Testing"
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install dependencies
run: |
pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: Run pytest with coverage
run: |
pytest --cov=app --cov-report=xml --cov-report=html --cov-report=term-missing --junitxml=test-results.xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
if: env.CODECOV_TOKEN != ''
with:
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-${{ matrix.python-version }}
path: |
test-results.xml
htmlcov/
sonarcloud:
name: "📊 SonarCloud Analysis"
runs-on: ubuntu-latest
needs: [test]
if: env.SONAR_TOKEN != ''
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download test results
uses: actions/download-artifact@v4
with:
name: test-results-3.11
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
docker:
name: "🐳 Docker Build"
runs-on: ubuntu-latest
needs: [code-quality, type-checking, security, test]
if: github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
if: github.event_name == 'push'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
if: github.event_name == 'push'
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ secrets.DOCKER_USERNAME }}/neurobank-fastapi:latest
${{ secrets.DOCKER_USERNAME }}/neurobank-fastapi:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
name: "🚂 Deploy to Railway"
runs-on: ubuntu-latest
needs: [docker]
if: github.ref == 'refs/heads/main' && github.event_name == 'push' && secrets.RAILWAY_TOKEN != ''
steps:
- uses: actions/checkout@v4
- name: Install Railway CLI
run: npm install -g @railway/cli
- name: Deploy to Railway
run: railway up --service neurobank-api
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}