CI/CD Integration
Docsfy already has strong automation building blocks for CI, but they are not yet wired into a repository-managed CI pipeline. The project currently relies on tox for tests and pre-commit for linting, typing, and secret scanning.
Warning: No CI workflow definitions are currently checked in (for example, no
.github/workflows,.gitlab-ci.yml, orJenkinsfile). Until a pipeline is added, enforcement depends on developers running checks locally.
Current Automation Posture
Test execution is defined in tox
skipsdist = true
envlist = ["unittests"]
[env.unittests]
deps = ["uv"]
commands = [["uv", "run", "--extra", "dev", "pytest", "-n", "auto", "tests"]]
- One tox environment exists:
unittests - Tests run with
pytest-xdist(-n auto) for parallel execution skipsdist = truemeans tox does not build/install the package before testing
Note: With
skipsdist = true, CI validates source-tree behavior but not wheel/sdist installability.
Python, pytest, and mypy defaults are centralized in pyproject.toml
[project]
requires-python = ">=3.12"
[project.optional-dependencies]
dev = ["pytest", "pytest-asyncio", "pytest-xdist", "httpx"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
pythonpath = ["src"]
[tool.mypy]
check_untyped_defs = true
disallow_any_generics = true
disallow_incomplete_defs = true
disallow_untyped_defs = true
no_implicit_optional = true
show_error_codes = true
warn_unused_ignores = true
strict_equality = true
extra_checks = true
warn_unused_configs = true
warn_redundant_casts = true
- CI runners should use Python 3.12+
- Async testing is first-class (
pytest-asyncio) - Mypy is configured in strict mode
Lint, formatting, typing, and security checks are encoded in .pre-commit-config.yaml
ci:
autofix_prs: false
autoupdate_commit_msg: "ci: [pre-commit.ci] pre-commit autoupdate"
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-added-large-files
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-merge-conflict
- id: check-symlinks
- id: detect-private-key
- id: mixed-line-ending
- id: debug-statements
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
- id: end-of-file-fixer
- id: check-ast
- id: check-builtin-literals
- id: check-toml
# flake8 retained for RedHatQE M511 plugin; ruff handles standard linting
- repo: https://github.com/PyCQA/flake8
rev: 7.3.0
hooks:
- id: flake8
args: [--config=.flake8]
additional_dependencies:
[git+https://github.com/RedHatQE/flake8-plugins.git, flake8-mutable]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.2
hooks:
- id: ruff
- id: ruff-format
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
- repo: https://github.com/gitleaks/gitleaks
rev: v8.30.0
hooks:
- id: gitleaks
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.19.1
hooks:
- id: mypy
exclude: (tests/)
ruff+ruff-formathandle general lint/format checksflake8is retained for ruleM511via plugindetect-secretsandgitleaksprovide layered secret scanningmypyruns as a hook and excludestests/
[flake8]
select=M511
[extend]
useDefault = true
[allowlist]
paths = [
'''tests/test_repository\.py''',
]
Warning: The flake8 hook intentionally pulls
RedHatQE/flake8-pluginsfrom Git, so CI reproducibility depends on that upstream repository state unless you pin a commit.
Deployment Readiness Signals Already in Code
The repo already contains deploy-friendly health checks in both app and container config:
@app.get("/health")
async def health() -> dict[str, str]:
return {"status": "ok"}
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
ENTRYPOINT ["uv", "run", "--no-sync", "uvicorn", "docsfy.main:app", "--host", "0.0.0.0", "--port", "8000"]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
Recommended Pipeline Stages
Use the existing repository configuration as the source of truth:
- Setup
- Use Python 3.12 runner
-
Install
pre-commit,tox, anduv -
Quality & Security Gate
- Run all hooks from
.pre-commit-config.yaml -
Enforces linting, formatting, type checks, and secret scanning
-
Test Gate
- Run tox
unittestsenv fromtox.toml -
Executes
pytest -n auto teststhroughuv -
Build Gate (main/release branches)
- Build container from
Dockerfile -
Preserves runtime assumptions already encoded in the image
-
Smoke Gate
- Start the built image and check
/health -
Fail fast before deployment if health probe fails
-
Deploy
- Deploy only after all prior gates succeed
Tip: Keep CI logic thin by reusing
tox.tomland.pre-commit-config.yamldirectly, instead of duplicating check logic in pipeline YAML.
Why This Works Well for Docsfy
Tests are already written to run without external AI services by mocking expensive/external operations:
with patch.dict(os.environ, {"ADMIN_KEY": TEST_ADMIN_KEY}):
get_settings.cache_clear()
await storage.init_db()
...
with (
patch("docsfy.main.check_ai_cli_available", return_value=(True, "")),
patch("docsfy.main.clone_repo", return_value=(tmp_path / "repo", "abc123")),
patch("docsfy.main.run_planner", return_value=sample_plan),
patch(
"docsfy.main.generate_all_pages",
return_value={"introduction": "# Intro\n\nWelcome!"},
),
):
...
This makes CI runs deterministic and suitable for pull-request validation without requiring real provider credentials.