A production-ready FastAPI CRUD application with automated CI/CD pipelines
- β¨ Overview
- π― Key Features
- π Project Structure
- π οΈ Tech Stack
- βοΈ Installation
- π§ Configuration
βΆοΈ Running the App- π‘ API Usage
- π§ͺ Tests
- π CI/CD Pipeline
- πΊοΈ Roadmap
- π€ Contributing
- π License
- π Acknowledgements
This repository showcases a minimal, production-like FastAPI application with a complete Items CRUD system. It serves as a comprehensive reference for implementing robust CI/CD pipelines with semantic versioning and automation.
- π― FastAPI service with SQLModel models and PostgreSQL configuration
- ποΈ Clean architecture with separated business logic layer
- π€ Automated releases using python-semantic-release
- β Comprehensive CI checks: linting (ruff), testing (pytest), type checking (mypy)
- π Auto-deployed documentation via MkDocs
- π³ Docker support with helper scripts for builds
Perfect for: Learning semantic-release integration with Python and building reliable CI/CD pipelines that automate versioning, changelogs, and publishing.
|
|
|
|
.
βββ π§ .github/
β βββ workflows/
β βββ ci.yml # CI checks β lint, tests, docs
β βββ release.yml # Automated releases
β βββ cd.yml # Container builds & deployment
β
βββ π¦ app/
β βββ main.py # FastAPI application entry point
β βββ database.py # Database configuration
β βββ logging_config.py # Centralized logging
β βββ models/ # SQLModel data models
β βββ routes/ # API route handlers
β βββ schemas/ # Pydantic schemas
β βββ services/ # Business logic layer
β
βββ π docs/ # MkDocs documentation
βββ π§ͺ tests/ # Test suite (pytest)
βββ π scripts/ # Helper scripts
βββ π³ Dockerfile # Container definition
βββ π CHANGELOG.md # Auto-generated changelog
βββ βοΈ pyproject.toml # Project configuration
βββ π README.md # You are here!
Prerequisites: macOS/Linux with zsh. This project uses
uv(Astral) for fast dependency management.
git clone https://github.com/MichAdebayo/CI-CD-semantic-release.git
cd CI-CD-semantic-releasecurl -LsSf https://astral.sh/uv/install.sh | sh# Sync all dependencies to virtual environment
uv sync --dev# Copy example environment file
cp .env.example .env
# Edit with your values
# DATABASE_URL="SET_YOUR_DB_URL"
# DEBUG_MODE="SET_DEBUG_MODE"| Variable | Description | Required |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | β Production |
DEBUG_MODE |
Enable FastAPI debug mode | β Optional |
GITHUB_TOKEN |
Token for semantic-release | β CI/CD |
Configure these in your GitHub repository settings:
π€ GitHub App Configuration (Click to expand)
Required Secrets:
APP_IDβ GitHub App ID for release workflowAPP_PRIVATE_KEY_B64β Base64-encoded private keyDEPLOY_URLβ Render webhook URLGHCR_PAT/GHCR_USERβ Optional: manual GHCR credentials
Setup Steps:
- Navigate to GitHub β Settings β Developer settings β GitHub Apps
- Click New GitHub App
- Configure permissions:
contents: write,packages: write,actions: write - Generate a private key and encode it:
base64 -i private-key.pem | pbcopy - Add secrets to your repository
β οΈ Security Note: Never commit secrets to the repository. Use.env.examplewith placeholders only.
# FastAPI dev mode
uv run fastapi dev app/main.py
# Or with uvicorn directly
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000# Build image
./scripts/docker-build.sh myorg/items:latest
# Run container
docker run -p 8000:8000 \
--env DATABASE_URL="postgresql://..." \
myorg/items:latest- API Root: http://127.0.0.1:8000/
- Health Check: http://127.0.0.1:8000/health
- Interactive Docs: http://127.0.0.1:8000/docs
- ReDoc: http://127.0.0.1:8000/redoc
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Root endpoint |
GET |
/health |
Health check |
POST |
/items |
Create new item |
GET |
/items |
List all items |
GET |
/items/{id} |
Get item by ID |
PUT |
/items/{id} |
Update item |
DELETE |
/items/{id} |
Delete item |
Create Item
curl -X POST http://127.0.0.1:8000/items \
-H "Content-Type: application/json" \
-d '{"nom":"Keyboard","prix":49.99}'Get All Items
curl http://127.0.0.1:8000/itemsGet Single Item
curl http://127.0.0.1:8000/items/1Update Item
curl -X PUT http://127.0.0.1:8000/items/1 \
-H "Content-Type: application/json" \
-d '{"prix":59.99}'Delete Item
curl -X DELETE http://127.0.0.1:8000/items/1# Run all tests
uv run pytest -q
# With coverage
uv run pytest --cov=app tests/
# Verbose output
uv run pytest -vThe test suite includes:
- β Unit tests for models and service layer
- β Integration tests for API endpoints
- β Edge case handling and error scenarios
- β In-memory SQLite for fast test execution
graph LR
A[Push/PR] --> B[CI Workflow]
B --> C{Tests Pass?}
C -->|Yes| D[Release Workflow]
C -->|No| E[Fail]
D --> F{Main Branch?}
F -->|Yes| G[CD Workflow]
F -->|No| H[Dry Run]
G --> I[Build Docker]
I --> J[Push to GHCR]
J --> K[Security Scan]
K --> L[Deploy to Render]
| Workflow | Trigger | Actions |
|---|---|---|
CIci.yml |
Push/PR tomain, develop |
β’ Install dependencies β’ Run linting (ruff) β’ Execute tests (pytest) β’ Type check (mypy) β’ Deploy docs (MkDocs) β’ Trigger release workflow |
Releaserelease.yml |
Called by CI |
β’ Authenticate via GitHub App β’ Run semantic-release β’ Generate changelog β’ Create GitHub Release β’ Trigger CD workflow |
CDcd.yml |
Successful release |
β’ Prepare Docker tags β’ Build & push to GHCR β’ Run Trivy security scan β’ Trigger Render deployment |
| Branch | Purpose | Release Type |
|---|---|---|
main |
π Production | Stable releases + Deploy |
develop |
π§ͺ Development | Prereleases |
deploy/ci_cd |
π§ CI/CD Testing | CI/CD prereleases |
- GitHub App Token: Short-lived, scoped tokens for releases
- Least Privilege: Minimal permissions for each workflow
- Secret Management: All credentials in GitHub Secrets
- Vulnerability Scanning: Trivy scans on every image build
# Dry run (shows next version)
./scripts/release.sh
# Publish release (requires GITHUB_TOKEN)
GITHUB_TOKEN=ghp_... ./scripts/release.sh --publish --yes- π Add contract tests for API endpoints
- π¬ Add CI notifications (Slack/MS Teams)
- π Implement API authentication
- π Add monitoring and observability
Contributions are welcome! Here's how to get started:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Use conventional commits for semantic versioning
- Add tests for new functionality
- Run linting and formatting
- Submit a pull request with clear description
# Lint code
uv run ruff check app tests
# Format code
uv run ruff format app tests
# Run tests
uv run pytest -q
# Type check
uv run mypy appfeat: add new feature
fix: resolve bug
docs: update documentation
test: add test coverage
chore: maintenance tasks
This project is licensed under the MIT License - see the LICENSE file for details.
