Note
This file is maintained by the foundry-python template and will be updated when you run mise run update_from_template.
For project-specific documentation, use README.md instead.
This guide provides comprehensive documentation for your Foundry-scaffolded project.
- Toolchain Overview
- Quick Start
- Service Connections
- Testing
- Code Quality
- CI/CD Workflows
- Pre-commit Hooks
- Task Reference
- Versioning & Releases
- Keeping Updated
- Troubleshooting
- Feedback
- Further Reading
This project was scaffolded using foundry-python with Copier, applying enterprise-grade operational excellence practices:
| Category | Tools |
|---|---|
| Code Quality | Ruff (linting), PyRight (type checking) |
| Git Hooks | pre-commit, detect-secrets, pygrep, Commitizen |
| Testing | pytest (parallel execution), Nox (matrix testing), Codecov (coverage) |
| CI/CD | GitHub Actions (workflows), act (local testing) |
| Security | SonarQube, pip-audit, trivy, Dependabot |
| Dependencies | Renovate (updates), pip-licenses (compliance) |
| Observability | Sentry (errors, tracing, profiling), BetterStack (uptime monitoring) |
| Documentation | SBOM generation (CycloneDX, SPDX), auto-generated attributions, dynamic badges |
| AI Assistance | GitHub Copilot (custom instructions), Claude Code (PR reviews) |
IMPORTANT: ALL service connections MUST be configured before proceeding. GitHub workflows will fail without them.
Complete the entire Service Connections section now.
mise run install
mise run testAll tests should pass. If not, run mise run install first.
git add .
git commit -m "chore: initial commit"Prerequisite: Create an empty repository at github.com/aignostics/foundry-python-core
git remote add origin git@github.com:aignostics/foundry-python-core.git
git push -u origin main| Service | Purpose |
|---|---|
| GitHub Settings | Security alerts, Dependabot |
| SonarCloud | Code quality analysis |
| Renovate | Dependency updates |
| CodeCov | Coverage reporting |
| Sentry | Error monitoring |
| Ox Security | Supply chain security |
| CodeQL | Security scanning |
| Claude Code CI | AI PR reviews |
| Slack | Release notifications |
Why: Ensures dependency vulnerability scanning is active.
Dependabot alerts and security updates are managed at the GitHub Enterprise level and enabled by default for all repositories. No manual configuration is needed.
- Go to https://github.com/aignostics/foundry-python-core/settings/security_analysis
- Verify Dependabot alerts is enabled (should be on by default via enterprise policy)
- Verify Dependabot security updates is enabled (should be on by default via enterprise policy)
- Do NOT enable Dependabot version updates (Renovate handles this)
- (Public repos only) Enable Private vulnerability reporting to allow external security researchers to report vulnerabilities privately
Verify: Security tab shows "Dependabot alerts enabled"
Why: Automated code quality and security analysis.
Note: Requires SonarCloud admin access. Ask your team lead if needed.
- Go to https://sonarcloud.io/projects/create, select your new repo and click "Set Up"
- Select Previous Code when prompted
- Go to https://sonarcloud.io/project/settings?id=aignostics_foundry-python-core and select "Administration > Analysis Method" in the left menu; disable Automatic Analysis
- To fix badges for private repositories:
- Go to https://sonarcloud.io/project/information?id=aignostics_foundry-python-core, scroll to the bottom of the "Badges" and select the
tokenvalue in the URL; replaceSONAR_BADGE_TOKENin your README.md with the generated token
- Go to https://sonarcloud.io/project/information?id=aignostics_foundry-python-core, scroll to the bottom of the "Badges" and select the
Verify: Quality Gate badge shows status in README after CI runs
Why: Automated dependency updates with smart grouping.
| Tool | Responsibility |
|---|---|
| Renovate | Version updates (Python, GitHub Actions), lock file maintenance |
| Dependabot | Security alerts and updates (including transitive dependencies) |
This separation ensures we get Renovate's superior update grouping and scheduling while retaining Dependabot's ability to detect and fix vulnerabilities in transitive dependencies.
- Go to https://developer.mend.io and sign in with your GitHub account
- Go to https://developer.mend.io/github/aignostics/foundry-python-core and click "Action > Run Renovate scan" to trigger the initial scan
- Renovate creates a Dependency Dashboard as an issue in your repository
Verify: Dependency Dashboard issue appears in your repository
Why: Code coverage tracking and PR comments.
CodeCov is automatically enabled for new repositories via organization-level configuration. No setup is required for coverage uploads.
Badge setup (for private repositories):
- Go to https://app.codecov.io/gh/aignostics/foundry-python-core/config/badge
- Under "Embed via API", copy the token value from the URL
- In your
README.md, replaceCODECOV_BADGE_TOKENwith the copied token
Verify: Coverage badge shows percentage in README after CI runs
Why: Error monitoring and performance profiling.
Sentry automatically scans code changes when you open PRs if organization-wide integration is configured. No additional setup required for basic functionality.
For advanced setup (error tracking, profiling), configure the Sentry DSN in your application.
Why: Supply chain security scanning.
Ox automatically scans code changes when you open PRs if organization-wide integration is configured. No additional setup required.
Why: Static analysis for security vulnerabilities (SQL injection, XSS, path traversal, etc.).
CodeQL is configured automatically via the included workflow files. No manual setup is required.
Schedule: Runs weekly on Tuesdays at 3:22 AM UTC
Verify: After first scheduled run, check Security tab → Code scanning alerts
Why: AI-powered PR reviews.
- Go to https://platform.claude.com/settings/keys
- Click "Create Key" and give it a descriptive name (e.g., "github-foundry-python-core")
- Copy the generated API key to your clipboard (you won't be able to see it again)
- Go to https://github.com/aignostics/foundry-python-core/settings/secrets/actions/new and create a new repository secret called
ANTHROPIC_API_KEY, pasting the key from your clipboard
Verify: Add the claude label to a PR to trigger AI review
Why: Better discoverability and branding.
- Go to https://github.com/aignostics/foundry-python-core
- Click on the cogs icon in the top right corner next to about
- Copy the description from the pyproject.toml file into the description field
- Copy up to 20 tags from the pyproject.toml file into the topics field
- Go to https://github.com/aignostics/foundry-python-core/settings and upload a social media image (e.g. logo.png) into the "Social preview" field
Every test MUST have a category marker. Tests without markers won't run in CI.
| Marker | Command | Purpose |
|---|---|---|
@pytest.mark.unit |
mise run test_unit |
Isolated tests, all dependencies mocked, must pass offline |
@pytest.mark.integration |
mise run test_integration |
Real local services (Docker), mocked external APIs |
@pytest.mark.e2e |
mise run test_e2e |
Real external services, full workflows |
@pytest.mark.scheduled |
mise run test_scheduled |
Tests run on schedule (also included in regular runs) |
@pytest.mark.sequential |
mise run test_sequential |
Tests excluded from parallel execution |
# By category
mise run test_unit # Fast, isolated (serial execution)
mise run test_integration # Real services (20% parallel)
mise run test_e2e # Full parallel
# All tests
mise run test # Runs unit → integration → e2e
# Specific test
pytest tests/path/to/test.py::test_function -vControlled by XDIST_WORKER_FACTOR environment variable:
| Test Type | Factor | Behavior |
|---|---|---|
| Unit | 0.0 | Serial (parallelization overhead > benefit) |
| Integration | 0.2 | 20% of logical CPUs |
| E2E | 1.0 | 100% of logical CPUs (I/O bound) |
- Goal: 100%
- Minimum: 85%
- Reports:
reports/coverage.xml,reports/coverage.md,reports/coverage_html/
pytest --collect-only -m "not unit and not integration and not e2e" -qmise run lint # Runs Ruff + PyRight| Tool | Mode | Purpose |
|---|---|---|
| Ruff | Format + Lint | Code style, 120 char limit, Google-style docstrings |
| PyRight | Strict | Type checking (all code) |
mise run audit # Runs all security checks| Tool | Purpose | Output |
|---|---|---|
| pip-audit | Vulnerability scanning | reports/pip-audit.json |
| pip-licenses | License compliance | reports/licenses.csv, reports/licenses.json |
| cyclonedx-py | CycloneDX SBOM | reports/sbom.json |
| trivy | SPDX SBOM + CVE scanning | reports/trivy-sbom.spdx.json |
| Workflow | Triggers | Purpose |
|---|---|---|
ci-cd.yml |
PR, push to main, version tags | Main pipeline: lint → audit → test → publish |
git-conventions.yml |
PR | Validates branch names, commit messages, and PR titles |
labels-sync.yml |
Push to main | Syncs GitHub labels from .github/labels.yml |
claude-code-automation-pr-review.yml |
PR with claude label |
AI-powered PR review |
audit-scheduled.yml |
Daily 6 AM UTC | Security audit with BetterStack heartbeat |
codeql-scheduled.yml |
Weekly (Tue 3:22 AM UTC) | CodeQL security scanning |
| Workflow | Purpose |
|---|---|
_lint.yml |
Ruff, PyRight |
_test.yml |
Unit, integration, E2E tests with coverage |
_audit.yml |
Security scanning and SBOM generation |
_package-publish.yml |
Build, document, publish to Artifact Registry, Slack notification |
_codeql.yml |
CodeQL analysis (Python + Actions) |
| Workflow | Schedule | Environment |
|---|---|---|
test-scheduled-staging-hourly.yml |
Hourly | Staging |
test-scheduled-staging-daily.yml |
Daily 12 PM UTC | Staging |
test-scheduled-production-hourly.yml |
Hourly | Production |
test-scheduled-production-daily.yml |
Daily 12 PM UTC | Production |
Add to commit message or PR labels:
| Skip Marker | Effect |
|---|---|
skip:test:unit |
Skip unit tests |
skip:test:integration |
Skip integration tests |
skip:test:e2e |
Skip E2E tests |
skip:test:all |
Skip all tests |
| Hook | Purpose |
|---|---|
| ruff | Format and lint code |
| pyright | Strict type checking |
| detect-secrets | Scan for exposed credentials |
| uv-lock | Keep uv.lock synchronized |
| check-toml, check-xml | Validate config file syntax |
| debug-statements | Find leftover debugger calls (pdb, breakpoint) |
| end-of-file-fixer | Ensure files end with newline |
| trailing-whitespace | Remove trailing whitespace |
| Hook | Purpose |
|---|---|
| docs | Generate ATTRIBUTIONS.md |
| test-unit | Run unit tests before push |
Uses Commitizen to enforce conventional commits:
type(scope): description
# Examples:
feat(api): add user authentication
fix(parser): handle edge case in date parsing
docs(readme): update installation instructions
chore(deps): update dependencies
mise run pre_commit_run_all # Run all hooks on entire codebaseSome tasks accept arguments. Use -- to separate mise options from task arguments:
mise run <task> -- <arguments>For example, to see help for the bump task:
mise run bump -- --helpTasks that accept arguments define them using mise's usage field, which provides built-in help and validation.
| Task | Description |
|---|---|
mise run install |
Sync all dependencies (uv sync --all-extras) + install pre-commit hooks |
mise run setup |
Post-generation environment setup |
mise run clean |
Remove all build artifacts and caches |
| Task | Description |
|---|---|
mise run lint |
Run Ruff, PyRight |
mise run audit |
Security scanning + SBOM generation |
mise run docs |
Generate ATTRIBUTIONS.md |
| Task | Description |
|---|---|
mise run test |
Run all tests (unit → integration → e2e) |
mise run test_unit |
Unit tests only (serial) |
mise run test_integration |
Integration tests (20% parallel) |
mise run test_e2e |
E2E tests (full parallel) |
mise run test_scheduled |
Scheduled tests only |
mise run test_sequential |
Non-parallelizable tests |
mise run test_coverage_reset |
Clear coverage data |
| Task | Description |
|---|---|
mise run bump |
Interactive version bump (accepts cz bump arguments) |
mise run update_from_template |
Update from Foundry template |
| Task | Description |
|---|---|
mise run all |
Full validation: lint + test + docs + audit |
mise run act |
Run GitHub Actions locally with act |
mise run pre_commit_run_all |
Run all pre-commit hooks on all files |
git switch main && git pull # Ensure you're on latest main
mise run docs # Regenerate documentation
mise run bump # Interactive: auto-detects bump type from commitsPass arguments to cz bump using --:
# Explicit increment type
mise run bump -- --increment patch
mise run bump -- --increment minor
mise run bump -- --increment major
# Pre-release versions
mise run bump -- --prerelease rc # e.g., 1.0.0 → 1.0.1-rc.0
mise run bump -- --increment major --prerelease rc # e.g., 1.0.0 → 2.0.0-rc.0
# Dry run (preview without changes)
mise run bump -- --dry-run
# See all options
mise run bump -- --helpThe mise run bump command:
- Bumps version using Commitizen
- Updates CHANGELOG.md
- Creates git tag
- Pushes to remote (triggers publish workflow)
Commits must follow the format for automatic changelog generation:
| Type | Version Bump | Example |
|---|---|---|
feat: |
Minor | feat(api): add user endpoint |
fix: |
Patch | fix(auth): handle expired tokens |
feat!: or BREAKING CHANGE: |
Major | feat!: redesign API response format |
docs:, chore:, refactor:, test: |
None | docs: update README |
Changelog inclusion: The following commit types appear in the generated changelog: feat, fix, refactor, perf, chore, docs. Other types (test, ci, style, build) are excluded from the changelog but still valid for commits.
mise run update_from_templateThis updates your project with the latest template improvements while preserving:
README.mdCHANGELOG.mdATTRIBUTIONS.mdlogo.png
Cause: Required services not configured.
Solution: Complete all sections in Service Connections.
Cause: Repository secrets not configured.
Solution: Add required secrets at https://github.com/aignostics/foundry-python-core/settings/secrets/actions:
GCP_WORKLOAD_IDENTITY_PROVIDERSONAR_TOKEN
Cause: Tests missing category marker.
Solution: Add @pytest.mark.unit, @pytest.mark.integration, or @pytest.mark.e2e to each test.
Cause: Code doesn't meet quality standards.
Solution: Many hooks auto-fix issues. Re-stage files and commit:
git add <fixed-files>
git commitCause: New code not covered by tests.
Solution: Add tests for new code, or verify new tests have category markers.
Cause: Message doesn't follow conventional commit format.
Solution: Use format type(scope): description. Valid types: feat, fix, docs, chore, refactor, test, perf, ci.
Happy to hear from you if you have any feedback on the DX/UX of using foundry-python.
Please reach out to us on Slack.
- README.md - Project documentation
- CODE_STYLE.md - Code style guide
- SECURITY.md - Security policy
- CONTRIBUTING.md - Contribution guidelines