Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Application
PROJECT_NAME=FastAPI Starter
API_VERSION=v1
DEBUG=false
ENVIRONMENT=development # development, staging, production

# Server
HOST=0.0.0.0
PORT=8000
RELOAD=false

# Database
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USER=postgres
DATABASE_PASSWORD=your_password_here
DATABASE_NAME=app_db
DATABASE_ECHO=false # SQL query logging
DATABASE_URL=postgresql+asyncpg://{DATABASE_USER}:{DATABASE_PASSWORD}@{DATABASE_HOST}:{DATABASE_PORT}/{DATABASE_NAME}
# Database Pool
DATABASE_POOL_SIZE=20
DATABASE_MAX_OVERFLOW=10
DATABASE_POOL_TIMEOUT=30
DATABASE_POOL_RECYCLE=3600

# Security
SECRET_KEY=your-secret-key-min-32-chars-long-change-in-production
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
REFRESH_TOKEN_EXPIRE_DAYS=7

# CORS
BACKEND_CORS_ORIGINS=["http://localhost:3000","http://localhost:8000","http://localhost:8080"]

# Rate Limiting
RATE_LIMIT_PER_MINUTE=60

# Logging
LOG_LEVEL=INFO # DEBUG, INFO, WARNING, ERROR, CRITICAL
LOG_FORMAT=json # json or text

# Redis (Optional)
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_DB=0
REDIS_PASSWORD=

# Sentry (Optional)
SENTRY_DSN=

# Email (Optional)
SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASSWORD=
SMTP_FROM=noreply@example.com

# AWS (Optional)
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=us-east-1
S3_BUCKET=
142 changes: 142 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: CI

on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]

jobs:
lint:
name: Lint & Format Check
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
cache: "pip"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ruff mypy

- name: Run Ruff linter
run: ruff check .

- name: Run Ruff formatter check
run: ruff format --check .

- name: Run MyPy type checker
run: mypy app/ --ignore-missing-imports
continue-on-error: true

test:
name: Test
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.13"]

steps:
- name: Check out code
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: |
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: Run tests
run: pytest -v --tb=short

- name: Upload coverage
if: matrix.python-version == '3.13'
uses: codecov/codecov-action@v4
with:
files: ./coverage.xml
fail_ci_if_error: false

security:
name: Security Scan
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
cache: "pip"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install safety bandit

- name: Run safety check
run: safety check --json || true
continue-on-error: true

- name: Run bandit security scan
run: bandit -r app/ -f json || true
continue-on-error: true

build:
name: Build & Validate
runs-on: ubuntu-latest
needs: [lint, test]
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
cache: "pip"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .

- name: Validate package build
run: |
pip install build
python -m build

- name: Test import
run: python -c "from app.main import create_app; print('Import successful')"

docker:
name: Docker Build
runs-on: ubuntu-latest
needs: [lint, test]
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: false
tags: fastapi-starter:test
cache-from: type=gha
cache-to: type=gha,mode=max
61 changes: 61 additions & 0 deletions .github/workflows/commitlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Commit Message Validation

on:
pull_request:
types: [opened, edited, synchronize, reopened]

jobs:
commitlint:
name: Validate Commit Messages
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install commitlint
run: |
npm install -g @commitlint/{cli,config-conventional}

- name: Create commitlint config
run: |
cat > commitlint.config.js << EOF
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'feat',
'fix',
'docs',
'style',
'refactor',
'perf',
'test',
'build',
'ci',
'chore',
'revert'
]
],
'subject-case': [0],
'subject-max-length': [2, 'always', 100]
}
};
EOF

- name: Validate PR commits
run: |
npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose

- name: Validate PR title
run: |
echo "${{ github.event.pull_request.title }}" | npx commitlint --verbose
52 changes: 52 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Code Coverage

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
coverage:
name: Generate Code Coverage
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
cache: "pip"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
pip install pytest-cov

- name: Run tests with coverage
run: |
pytest --cov=app --cov-report=xml --cov-report=html --cov-report=term

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false

- name: Upload coverage artifacts
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: htmlcov/

- name: Coverage comment
uses: py-cov-action/python-coverage-comment-action@v3
with:
GITHUB_TOKEN: ${{ github.token }}
MINIMUM_GREEN: 80
MINIMUM_ORANGE: 60
47 changes: 47 additions & 0 deletions .github/workflows/dependencies.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Dependency Update

on:
schedule:
# Run weekly on Monday at 9:00 AM UTC
- cron: "0 9 * * 1"
workflow_dispatch:

jobs:
dependency-update:
name: Check for Dependency Updates
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"

- name: Install pip-tools
run: |
python -m pip install --upgrade pip
pip install pip-tools pip-audit

- name: Check for outdated packages
run: pip list --outdated

- name: Security audit
run: pip-audit || true
continue-on-error: true

- name: Create issue for updates
if: success()
uses: actions/github-script@v7
with:
script: |
const title = 'Weekly Dependency Update Check';
const body = 'Automated dependency check completed. Please review outdated packages.';
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: title,
body: body,
labels: ['dependencies', 'automated']
});
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# add your production CI workflow here
Loading
Loading