CI/CD Pipeline
CI/CD Pipeline
Overview
This page documents the project’s real automation: a CI workflow that runs the same checks you run locally, a Docker image for deployment, pinned dependencies, and a workflow that publishes this documentation.
Pipeline Architecture
High-Level Flow
GitHub Actions Workflows
Workflow 1: CI
File: .github/workflows/ci.yml
What each step guards:
| Step | Guards |
|---|---|
ruff check . | lint rules (E, F, W, I, B, UP, SIM, C4, RUF), line length 100 |
ruff format --check . | consistent formatting |
mypy | strict = true over crypto_alarm/ |
unittest | alarm rules, monitor behavior, persistence |
The matrix runs the minimum supported Python (3.10, from requires-python) and the version used in Docker (3.12).
Workflow 2: Docs
File: .github/workflows/docs.yml
Builds the Hugo site and deploys it to GitHub Pages whenever docs/ changes on main (or when triggered manually). See GitHub Actions Setup for the details.
Testing Strategy
What the tests cover
tests/test_alarms.py: the pure rules (rules.py): input validation, target crossing, extremes, timeframe windowstests/test_monitor.py: a realMonitorwith a fake Binance client and an injected clock: adding pairs, trigger-once behavior, restart cooldown, stale prices, “since start” repeats, max/min reset, history sampling, persistence round trip, corrupt file handling
Why this design is testable
- Trigger logic lives in pure functions (no clocks, locks or I/O)
Monitortakes its Binance client, store and notifier as constructor argumentscheck_alarms(now)accepts the current time, so tests control the clock
Running locally
Code Quality Tools
All configuration is in pyproject.toml:
Fix formatting automatically with ruff format ..
Docker Configuration
Dockerfile
Design notes:
- Layer caching: dependencies are installed before the source is copied
--no-depsfor the app itself, becauserequirements.lockalready pinned everything- Runs as an unprivileged
appuser, which owns only the/datavolume - The health check calls
/healthz, which returns 503 when the Binance feed is down, so Docker marks the container unhealthy - One worker is not optional: state lives in the process
Docker Compose
Notification credentials and other settings go in a .env file next to docker-compose.yml (.env.example lists every variable). The file is optional.
Dependency Pinning
Version ranges live in pyproject.toml. Exact versions for Docker are pinned in requirements.lock:
Keep the two comment lines at the top of that file.
Documentation Publishing
Hugo Build Configuration
GitHub Pages Deployment
.github/workflows/docs.yml builds with Hugo 0.141.0 (extended) and publishes through actions/deploy-pages. The Relearn theme is vendored in docs/themes/hugo-theme-relearn, so no submodule checkout is needed.
Local Development Workflow
Run the checks CI runs
Run the app
Preview the docs
Security Best Practices
Secrets Management
- Notification tokens (
TELEGRAM_BOT_TOKEN,ALARM_WEBHOOK_URL) are read from the environment only, never committed .envis git-ignored;.env.examplecontains placeholders only- Logs never include request URLs, because Telegram’s URL embeds the bot token
Container Hardening
- Non-root user, slim base image, no build tools in the final image
- Port published on
127.0.0.1only, because the app has no authentication
Not Automated (Yet)
For accuracy, these are things the project does not currently do in CI:
- Publishing Docker images to a registry
- Release tagging and changelog generation
- Dependency update bots and vulnerability scanning
- Scheduled workflow runs
They would be natural additions (for example Dependabot for requirements.lock).
Troubleshooting CI/CD
Common Issues
ruff format --check fails
mypy reports errors only in CI
The Docker build can’t find a package
Next Steps
- See GitHub Actions Setup for the documentation workflow
- Check Implementations for architecture details