depfresh 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. depfresh-0.1.0/.github/workflows/ci.yml +74 -0
  2. depfresh-0.1.0/.github/workflows/publish.yml +53 -0
  3. depfresh-0.1.0/.gitignore +18 -0
  4. depfresh-0.1.0/CHANGELOG.md +43 -0
  5. depfresh-0.1.0/CLAUDE.md +109 -0
  6. depfresh-0.1.0/LICENSE +21 -0
  7. depfresh-0.1.0/PKG-INFO +276 -0
  8. depfresh-0.1.0/README.md +244 -0
  9. depfresh-0.1.0/SECURITY.md +31 -0
  10. depfresh-0.1.0/assets/logo-dark.svg +40 -0
  11. depfresh-0.1.0/assets/logo.svg +45 -0
  12. depfresh-0.1.0/pyproject.toml +76 -0
  13. depfresh-0.1.0/src/depfresh/__init__.py +45 -0
  14. depfresh-0.1.0/src/depfresh/audit.py +148 -0
  15. depfresh-0.1.0/src/depfresh/cli.py +172 -0
  16. depfresh-0.1.0/src/depfresh/constraints.py +176 -0
  17. depfresh-0.1.0/src/depfresh/exceptions.py +65 -0
  18. depfresh-0.1.0/src/depfresh/models.py +115 -0
  19. depfresh-0.1.0/src/depfresh/parsers/__init__.py +130 -0
  20. depfresh-0.1.0/src/depfresh/parsers/_base.py +54 -0
  21. depfresh-0.1.0/src/depfresh/parsers/_helpers.py +264 -0
  22. depfresh-0.1.0/src/depfresh/parsers/_pipfile.py +151 -0
  23. depfresh-0.1.0/src/depfresh/parsers/_pyproject.py +348 -0
  24. depfresh-0.1.0/src/depfresh/parsers/_requirements.py +228 -0
  25. depfresh-0.1.0/src/depfresh/py.typed +0 -0
  26. depfresh-0.1.0/src/depfresh/reports.py +463 -0
  27. depfresh-0.1.0/src/depfresh/upgrade.py +549 -0
  28. depfresh-0.1.0/src/depfresh/uv.py +220 -0
  29. depfresh-0.1.0/src/depfresh/verify.py +225 -0
  30. depfresh-0.1.0/tests/__init__.py +0 -0
  31. depfresh-0.1.0/tests/conftest.py +1 -0
  32. depfresh-0.1.0/tests/fixtures/sample_projects/01_requirements_simple/app.py +12 -0
  33. depfresh-0.1.0/tests/fixtures/sample_projects/01_requirements_simple/requirements.txt +2 -0
  34. depfresh-0.1.0/tests/fixtures/sample_projects/02_requirements_hashed/app.py +12 -0
  35. depfresh-0.1.0/tests/fixtures/sample_projects/02_requirements_hashed/requirements.txt +10 -0
  36. depfresh-0.1.0/tests/fixtures/sample_projects/03_requirements_in/app.py +12 -0
  37. depfresh-0.1.0/tests/fixtures/sample_projects/03_requirements_in/requirements.in +2 -0
  38. depfresh-0.1.0/tests/fixtures/sample_projects/04_pyproject_pep621/app.py +12 -0
  39. depfresh-0.1.0/tests/fixtures/sample_projects/04_pyproject_pep621/pyproject.toml +12 -0
  40. depfresh-0.1.0/tests/fixtures/sample_projects/05_pyproject_poetry/app.py +12 -0
  41. depfresh-0.1.0/tests/fixtures/sample_projects/05_pyproject_poetry/pyproject.toml +13 -0
  42. depfresh-0.1.0/tests/fixtures/sample_projects/06_pipfile/Pipfile +11 -0
  43. depfresh-0.1.0/tests/fixtures/sample_projects/06_pipfile/app.py +12 -0
  44. depfresh-0.1.0/tests/fixtures/sample_projects/07_pyproject_pep621_optional/app.py +10 -0
  45. depfresh-0.1.0/tests/fixtures/sample_projects/07_pyproject_pep621_optional/pyproject.toml +16 -0
  46. depfresh-0.1.0/tests/fixtures/sample_projects/08_pyproject_pep621_direct_ref/app.py +10 -0
  47. depfresh-0.1.0/tests/fixtures/sample_projects/08_pyproject_pep621_direct_ref/pyproject.toml +12 -0
  48. depfresh-0.1.0/tests/helpers.py +28 -0
  49. depfresh-0.1.0/tests/test_audit.py +252 -0
  50. depfresh-0.1.0/tests/test_cli.py +332 -0
  51. depfresh-0.1.0/tests/test_constraints.py +252 -0
  52. depfresh-0.1.0/tests/test_e2e.py +554 -0
  53. depfresh-0.1.0/tests/test_parsers.py +1128 -0
  54. depfresh-0.1.0/tests/test_reports.py +115 -0
  55. depfresh-0.1.0/tests/test_smoke.py +213 -0
  56. depfresh-0.1.0/tests/test_upgrade.py +572 -0
  57. depfresh-0.1.0/tests/test_uv.py +168 -0
  58. depfresh-0.1.0/tests/test_verify.py +117 -0
  59. depfresh-0.1.0/uv.lock +352 -0
@@ -0,0 +1,74 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ fail-fast: false
12
+ matrix:
13
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: ${{ matrix.python-version }}
21
+
22
+ - uses: astral-sh/setup-uv@v5
23
+
24
+ - name: Install project and dev dependencies
25
+ run: uv sync --extra dev
26
+
27
+ - name: Run tests
28
+ run: uv run pytest -q
29
+
30
+ quality:
31
+ runs-on: ubuntu-latest
32
+
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+
36
+ - uses: actions/setup-python@v5
37
+ with:
38
+ python-version: "3.11"
39
+
40
+ - uses: astral-sh/setup-uv@v5
41
+
42
+ - name: Install project and dev dependencies
43
+ run: uv sync --extra dev
44
+
45
+ - name: Lint
46
+ run: uv run ruff check src tests
47
+
48
+ - name: Type check
49
+ run: uv run mypy src
50
+
51
+ - name: Build distribution artifacts
52
+ run: uv build
53
+
54
+ - name: Verify package metadata
55
+ run: uv tool run twine check dist/*
56
+
57
+ smoke:
58
+ runs-on: ubuntu-latest
59
+ needs: [test, quality]
60
+
61
+ steps:
62
+ - uses: actions/checkout@v4
63
+
64
+ - uses: actions/setup-python@v5
65
+ with:
66
+ python-version: "3.12"
67
+
68
+ - uses: astral-sh/setup-uv@v5
69
+
70
+ - name: Install project and dev dependencies
71
+ run: uv sync --extra dev
72
+
73
+ - name: Run smoke tests (real uv + pip-audit)
74
+ run: uv run pytest -m smoke -v
@@ -0,0 +1,53 @@
1
+ name: Publish
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ release:
6
+ types: [published]
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.11"
18
+
19
+ - uses: astral-sh/setup-uv@v5
20
+
21
+ - name: Install project and dev dependencies
22
+ run: uv sync --extra dev
23
+
24
+ - name: Run release checks
25
+ run: |
26
+ uv run ruff check src tests
27
+ uv run mypy src
28
+ uv run pytest -q
29
+ uv build
30
+ uv tool run twine check dist/*
31
+
32
+ - name: Upload distribution artifacts
33
+ uses: actions/upload-artifact@v4
34
+ with:
35
+ name: dist
36
+ path: dist/
37
+
38
+ publish:
39
+ needs: build
40
+ runs-on: ubuntu-latest
41
+ if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
42
+ permissions:
43
+ id-token: write
44
+
45
+ steps:
46
+ - name: Download distribution artifacts
47
+ uses: actions/download-artifact@v4
48
+ with:
49
+ name: dist
50
+ path: dist/
51
+
52
+ - name: Publish to PyPI
53
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,18 @@
1
+ .DS_Store
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ .claude/
9
+ .venv*/
10
+ venv*/
11
+ .mypy_cache/
12
+ .pytest_cache/
13
+ .ruff_cache/
14
+ *.tmp
15
+ .tox/
16
+ htmlcov/
17
+ .coverage
18
+ reports/
@@ -0,0 +1,43 @@
1
+ # Changelog
2
+
3
+ All notable changes to depfresh will be documented here.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ---
9
+
10
+ ## [Unreleased]
11
+
12
+ ---
13
+
14
+ ## [0.1.0] — 2026-03-23
15
+
16
+ Initial public release.
17
+
18
+ ### Added
19
+
20
+ - **Six dependency formats** — `requirements.txt` (simple and hashed/pip-compile), `requirements.in`, `pyproject.toml` (PEP 621 and Poetry), `Pipfile`
21
+ - **Format-preserving writes** — extras, markers, comments and format-specific operators (Poetry `^`/`~`, PEP 508 extras) are kept intact
22
+ - **Pre- and post-upgrade vulnerability audit** via `pip-audit`
23
+ - **Remaining vulnerability diagnostics** — each unfixed CVE is classified with an actionable reason:
24
+ - Major upgrade required (use `--allow-major`)
25
+ - Pinned via `--keep-version`
26
+ - Major allowed but blocked by transitive conflict
27
+ - Within bounds but unresolvable
28
+ - No fix available upstream
29
+ - **Minor/patch-only upgrades by default** — major version crossing requires explicit opt-in via `--allow-major`
30
+ - **Selective major upgrades** — `--allow-major urllib3 cryptography` targets individual packages
31
+ - **Version pinning** — `--keep-version crewai litellm` preserves exact current versions
32
+ - **Dry-run mode** — `--dry-run` reports what would change without touching files
33
+ - **AST-based import verification** — checks that third-party imports still resolve after upgrade without executing any user code
34
+ - **PR-ready markdown report** and detailed log written per run
35
+ - **Public library API** — `upgrade()` and `audit_only()` functions for programmatic use
36
+ - **`--python`** flag to target a specific Python version for the upgrade venv
37
+ - **`--label`**, **`--dep-file`**, **`--format`**, **`--reports-dir`**, **`--venv`** options
38
+ - PEP 503 package name normalization throughout
39
+ - Custom exception hierarchy (`DepfreshError` and subclasses) for clean error handling
40
+ - Exit codes: `0` = clean, `1` = error, `2` = vulnerabilities remain
41
+
42
+ [Unreleased]: https://github.com/helios-sc/depfresh/compare/v0.1.0...HEAD
43
+ [0.1.0]: https://github.com/helios-sc/depfresh/releases/tag/v0.1.0
@@ -0,0 +1,109 @@
1
+ # CLAUDE.md — depfresh
2
+
3
+ ## What is depfresh?
4
+
5
+ A Python dependency upgrade and security audit tool. It combines **uv** (fast package manager) and **pip-audit** (CVE scanner) to upgrade dependencies to their latest safe versions, audit for vulnerabilities before and after, verify imports still resolve, and generate PR-ready markdown reports.
6
+
7
+ **Version:** 0.1.0 (Beta) · **License:** MIT · **Python:** 3.10+
8
+
9
+ ## Project layout
10
+
11
+ ```
12
+ src/depfresh/ # Source code
13
+ cli.py # CLI entry point (argparse)
14
+ upgrade.py # Core orchestration + public API
15
+ parsers.py # Format-aware dependency parsing (6 formats)
16
+ models.py # Dataclasses (Vulnerability, PackageChange, UpgradeResult, etc.)
17
+ constraints.py # Version constraint building, PEP 503 normalization, remaining vuln diagnostics
18
+ uv.py # uv binary discovery & venv management
19
+ audit.py # pip-audit integration
20
+ verify.py # AST-based import verification
21
+ reports.py # Log/markdown report generation
22
+ exceptions.py # Custom exceptions
23
+ tests/ # pytest test suite (mirrors src modules)
24
+ pyproject.toml # All project metadata and tool config
25
+ uv.lock # Locked dependencies
26
+ ```
27
+
28
+ ## Development setup
29
+
30
+ ```bash
31
+ uv venv && source .venv/bin/activate
32
+ uv pip install -e ".[dev]"
33
+ ```
34
+
35
+ Runtime requires the `uv` binary installed separately. Dev extras include pytest, ruff, and mypy.
36
+
37
+ ## Commands
38
+
39
+ ```bash
40
+ # Run tests
41
+ pytest
42
+
43
+ # Lint
44
+ ruff check src/ tests/
45
+
46
+ # Format
47
+ ruff format src/ tests/
48
+
49
+ # Type check
50
+ mypy src/
51
+ ```
52
+
53
+ ## Code style
54
+
55
+ - **Ruff** for linting and formatting — line length 100, rules: E, F, I, W, UP
56
+ - **mypy** strict mode — all functions and variables must be typed
57
+ - `from __future__ import annotations` in every module
58
+ - Google-style docstrings
59
+ - Target version: Python 3.10
60
+
61
+ ## Build & publish
62
+
63
+ Build system is **hatchling**. Entry point: `depfresh = depfresh.cli:main`.
64
+
65
+ ```bash
66
+ python -m build
67
+ ```
68
+
69
+ ## Test conventions
70
+
71
+ - pytest with class-based organization
72
+ - Fixtures: `tmp_path`, `capsys`, standard pytest built-ins
73
+ - Parameterized tests where appropriate
74
+ - Mocking for subprocess/external tool calls
75
+ - Test files mirror source modules: `test_cli.py`, `test_parsers.py`, etc.
76
+
77
+ ## Supported dependency formats
78
+
79
+ | Format | File | Detection order |
80
+ |--------|------|-----------------|
81
+ | Simple requirements | `requirements.txt` | 1st |
82
+ | Pip-compile (hashed) | `requirements.txt` | 1st (auto) |
83
+ | Requirements input | `requirements.in` | 2nd |
84
+ | PEP 621 | `pyproject.toml` | 3rd |
85
+ | Poetry | `pyproject.toml` | 3rd |
86
+ | Pipfile | `Pipfile` | 4th |
87
+
88
+ ## CLI usage
89
+
90
+ ```bash
91
+ depfresh /path/to/project
92
+ depfresh /path/to/project --dry-run
93
+ depfresh /path/to/project --allow-major urllib3 cryptography
94
+ depfresh /path/to/project --keep-version crewai litellm
95
+ depfresh /path/to/project --python 3.12 --reports-dir ./artifacts
96
+ ```
97
+
98
+ Exit codes: `0` = clean, `1` = error, `2` = vulnerabilities remain.
99
+
100
+ ## Remaining vulnerability diagnostics
101
+
102
+ When vulnerabilities remain after upgrade, `diagnose_remaining()` in `constraints.py` classifies each one:
103
+ - **Major upgrade required** — fix crosses a major version boundary (default constraints cap at `<major+1.0`)
104
+ - **Pinned via --keep-version** — user explicitly pinned the package
105
+ - **Major allowed but unresolved** — major was permitted but uv hit a transitive conflict
106
+ - **Within bounds but unresolved** — fix is within minor/patch bounds but couldn't resolve
107
+ - **No fix available** — upstream hasn't released a patched version
108
+
109
+ Results are stored in `UpgradeResult.remaining_reasons` (parallel list to `post_audit_vulns`) and shown in both log and markdown reports with a "Reason" column.
depfresh-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Helios Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,276 @@
1
+ Metadata-Version: 2.4
2
+ Name: depfresh
3
+ Version: 0.1.0
4
+ Summary: Upgrade Python dependencies to their latest safe versions and audit for vulnerabilities.
5
+ Project-URL: Homepage, https://github.com/helios-sc/depfresh
6
+ Project-URL: Repository, https://github.com/helios-sc/depfresh
7
+ Project-URL: Issues, https://github.com/helios-sc/depfresh/issues
8
+ Author-email: Helios Team <moises.nascimento@helios.sc>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: audit,dependencies,pip-audit,requirements,security,upgrade,uv,vulnerability
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Security
21
+ Classifier: Topic :: Software Development :: Build Tools
22
+ Classifier: Topic :: Software Development :: Quality Assurance
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: packaging>=23.0
25
+ Requires-Dist: tomli>=2.0; python_version < '3.11'
26
+ Requires-Dist: tomlkit>=0.12
27
+ Provides-Extra: dev
28
+ Requires-Dist: mypy; extra == 'dev'
29
+ Requires-Dist: pytest; extra == 'dev'
30
+ Requires-Dist: ruff; extra == 'dev'
31
+ Description-Content-Type: text/markdown
32
+
33
+ <picture>
34
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/helios-sc/depfresh/refs/heads/main/assets/logo-dark.svg">
35
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/helios-sc/depfresh/refs/heads/main/assets/logo.svg">
36
+ <img alt="depfresh" src="https://raw.githubusercontent.com/helios-sc/depfresh/refs/heads/main/assets/logo.svg" width="380">
37
+ </picture>
38
+
39
+ <br>
40
+
41
+ [![PyPI version](https://img.shields.io/pypi/v/depfresh)](https://pypi.org/project/depfresh/)
42
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)](https://python.org)
43
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
44
+
45
+ **One command to upgrade your Python dependencies, audit for CVEs, and prove it's safe.**
46
+
47
+ depfresh combines [uv](https://docs.astral.sh/uv/) and [pip-audit](https://github.com/pypa/pip-audit) into a single workflow — upgrade to the latest safe versions, scan for vulnerabilities before and after, verify imports still resolve, and generate a PR-ready markdown report.
48
+
49
+ ```bash
50
+ pip install depfresh
51
+ depfresh /path/to/project
52
+ ```
53
+
54
+ > **Prerequisites:** Python 3.10+ and [uv](https://docs.astral.sh/uv/). pip-audit is installed automatically.
55
+
56
+ ---
57
+
58
+ ## Why depfresh?
59
+
60
+ - **Tired of Dependabot/Renovate noise?** Get one deliberate upgrade pass with full context instead of 30 individual PRs
61
+ - **Need CVE auditing baked in?** Vulnerability scanning happens automatically, not as an afterthought
62
+ - **Want CI-ready reports?** Get dated markdown with tables, diffs, and checklists you can paste straight into a PR
63
+ - **Running multiple Python services?** Point depfresh at each one — locally, in CI, or on a cron schedule
64
+
65
+ ## How it works
66
+
67
+ ```
68
+ dependency file (auto-detected)
69
+ │
70
+ ▼
71
+ parse dependencies ──▶ create temp venv ──▶ install & audit (before)
72
+ │
73
+ build constraints (major bounds, pins, keep-version)
74
+ │
75
+ upgrade ──▶ freeze ──▶ verify imports (AST scan) ──▶ audit (after)
76
+ │
77
+ write reports ──▶ update dependency file ──▶ cleanup
78
+ ```
79
+
80
+ If resolution fails or the audit returns invalid output, depfresh aborts before updating anything. It fails closed — never generates a misleading clean result.
81
+
82
+ ## Features
83
+
84
+ | | |
85
+ |---|---|
86
+ | **Safe by default** | Minor/patch upgrades only, with opt-in per-package major bumps |
87
+ | **CVE scanning** | Pre- and post-upgrade vulnerability auditing via pip-audit |
88
+ | **Remaining vuln diagnostics** | Explains *why* each unfixed CVE couldn't be resolved |
89
+ | **Import verification** | AST-based scanning confirms third-party imports still resolve |
90
+ | **Selective control** | `--allow-major urllib3` / `--keep-version crewai` for fine-grained power |
91
+ | **Multi-format** | `requirements.txt`, `.in`, `pyproject.toml` (PEP 621 & Poetry), `Pipfile` |
92
+ | **Format-preserving** | Keeps exact pins, upper bounds, extras, and wildcards intact |
93
+ | **Zero footprint** | Temporary venv, cleans up after itself |
94
+ | **Fail-closed** | Aborts on resolver, hash, or audit failures |
95
+
96
+ ## Usage
97
+
98
+ ```bash
99
+ # Upgrade everything (minor/patch only) — auto-detects format
100
+ depfresh /path/to/project
101
+
102
+ # Preview without touching anything
103
+ depfresh /path/to/project --dry-run
104
+
105
+ # Allow major bumps for specific packages
106
+ depfresh /path/to/project --allow-major urllib3 cryptography
107
+
108
+ # Pin packages you don't want touched
109
+ depfresh /path/to/project --keep-version crewai litellm
110
+
111
+ # Include optional/dev groups for grouped formats
112
+ depfresh /path/to/project --dependency-scope all
113
+
114
+ # Run in CI with a specific Python and report dir
115
+ depfresh /path/to/project --python 3.12 --reports-dir ./artifacts
116
+ ```
117
+
118
+ <details>
119
+ <summary><strong>All CLI options</strong></summary>
120
+
121
+ | Option | Default | Description |
122
+ |--------|---------|-------------|
123
+ | `target_dir` | *(required)* | Directory containing the dependency file |
124
+ | `--label` | auto-derived | Report subfolder name |
125
+ | `--dep-file` | auto-detect | Dependency file name |
126
+ | `--format` | auto-detect | Force format: `requirements-simple`, `requirements-hashed`, `requirements-in`, `pyproject-pep621`, `pyproject-poetry`, `pipfile` |
127
+ | `--python` | `3.11` | Python version for the temp venv |
128
+ | `--dependency-scope` | `runtime` | `runtime` (main deps) or `all` (include optional/dev) |
129
+ | `--ignore-direct-references` | off | Skip git/path/url deps instead of failing |
130
+ | `--dry-run` | off | Preview without modifying files |
131
+ | `--allow-major [PKG ...]` | off | Allow major upgrades (all or named) |
132
+ | `--keep-version PKG [...]` | off | Pin packages to current version |
133
+ | `--reports-dir` | `./reports/` | Report output directory |
134
+ | `-v, --verbose` | off | Debug output |
135
+
136
+ **Exit codes:** `0` = clean, `1` = error, `2` = vulnerabilities remain.
137
+
138
+ </details>
139
+
140
+ ## Supported formats
141
+
142
+ | Format | File | Ecosystem |
143
+ |--------|------|-----------|
144
+ | Simple requirements | `requirements.txt` | pip, uv |
145
+ | Hashed requirements | `requirements.txt` | pip-compile, uv pip compile |
146
+ | Requirements input | `requirements.in` | pip-tools, uv pip compile |
147
+ | PEP 621 | `pyproject.toml` | uv, pdm, hatch, flit |
148
+ | Poetry | `pyproject.toml` | poetry |
149
+ | Pipfile | `Pipfile` | pipenv |
150
+
151
+ Auto-detection order: `requirements.txt` → `requirements.in` → `pyproject.toml` → `Pipfile`
152
+
153
+ ## Understanding remaining vulnerabilities
154
+
155
+ When CVEs remain after upgrade, depfresh diagnoses each one:
156
+
157
+ | Reason | What to do |
158
+ |--------|------------|
159
+ | **Requires major upgrade** | Re-run with `--allow-major <package>` |
160
+ | **Pinned via --keep-version** | Remove from `--keep-version` if the fix is needed |
161
+ | **Major allowed but unresolved** | Investigate transitive dependency conflicts |
162
+ | **Fix within constraints but unresolved** | Check for conflicting version requirements |
163
+ | **No fix available** | Monitor upstream for a patched release |
164
+
165
+ ## Python API
166
+
167
+ ```python
168
+ from depfresh import upgrade, audit_only
169
+
170
+ # Full upgrade workflow
171
+ result = upgrade(
172
+ "/path/to/project",
173
+ python="3.12",
174
+ allow_major=["urllib3"],
175
+ keep_version=["crewai"],
176
+ )
177
+
178
+ print(f"Upgraded {len(result.upgraded)} packages")
179
+ print(f"Vulns: {len(result.pre_audit_vulns)} → {len(result.post_audit_vulns)}")
180
+
181
+ for vuln, reason in zip(result.post_audit_vulns, result.remaining_reasons):
182
+ print(f" {vuln.package} {vuln.cve}: {reason}")
183
+
184
+ # Audit only — no modifications
185
+ result = audit_only("/path/to/project")
186
+ ```
187
+
188
+ <details>
189
+ <summary><strong>API reference</strong></summary>
190
+
191
+ ### `upgrade(target, **kwargs) -> UpgradeResult`
192
+
193
+ Full workflow: venv creation, install, audit, upgrade, import verification, reports.
194
+
195
+ | Parameter | Default | Description |
196
+ |-----------|---------|-------------|
197
+ | `target` | *(required)* | Directory containing dependency file |
198
+ | `label` | `None` | Report subfolder name |
199
+ | `dep_file` | `None` | Dependency filename |
200
+ | `fmt` | `None` | Force format string |
201
+ | `python` | `"3.11"` | Python version for the venv |
202
+ | `dependency_scope` | `"runtime"` | `"runtime"` or `"all"` |
203
+ | `ignore_direct_references` | `False` | Skip git/path/url deps |
204
+ | `dry_run` | `False` | Preview without writing |
205
+ | `allow_major` | `None` | `None` (minor/patch), `[]` (all), or `["pkg"]` |
206
+ | `keep_version` | `None` | Packages to pin at current version |
207
+ | `reports_dir` | `./reports/` | Report output directory |
208
+
209
+ ### `audit_only(target, **kwargs) -> UpgradeResult`
210
+
211
+ Vulnerability scan only. Same venv workflow, no file modifications.
212
+
213
+ ### `UpgradeResult`
214
+
215
+ | Field | Type | Description |
216
+ |-------|------|-------------|
217
+ | `upgraded` | `list[PackageChange]` | Packages that changed version |
218
+ | `new_deps` | `list[PackageChange]` | New transitive dependencies |
219
+ | `pre_audit_vulns` | `list[Vulnerability]` | CVEs before upgrade |
220
+ | `post_audit_vulns` | `list[Vulnerability]` | CVEs remaining after upgrade |
221
+ | `remaining_reasons` | `list[str]` | Why each post-upgrade CVE wasn't fixed |
222
+ | `import_check` | `ImportCheck` | Import verification results |
223
+ | `log_path` / `markdown_path` | `str` | Paths to generated reports |
224
+
225
+ </details>
226
+
227
+ ## CI / Automation
228
+
229
+ **GitHub Actions — weekly upgrade PR:**
230
+ ```yaml
231
+ - name: Upgrade dependencies
232
+ run: |
233
+ pip install depfresh
234
+ depfresh . --reports-dir ./artifacts --python 3.12
235
+ ```
236
+
237
+ **Cron job — audit only, alert on CVEs:**
238
+ ```python
239
+ from depfresh import audit_only
240
+
241
+ result = audit_only("/app")
242
+ if result.pre_audit_vulns:
243
+ send_alert(f"{len(result.pre_audit_vulns)} CVEs found")
244
+ ```
245
+
246
+ ## Current limitations
247
+
248
+ - `pyproject.toml`, Poetry, and `Pipfile` projects are analyzed through a synthesized requirements file — the install/audit environment approximates the native tool's resolver
249
+ - Operates on a single dependency file per run
250
+ - Import verification checks resolution, not runtime behavior — always run your test suite after upgrading
251
+ - Pip directives (`-r`, `-c`, `--index-url`) in requirements files are not followed
252
+
253
+ <details>
254
+ <summary><strong>Known edge cases</strong></summary>
255
+
256
+ - **PEP 440 epochs** (`1!2.0`): Not recognized by major-version extraction; packages are pinned exactly (conservative but safe)
257
+ - **Environment markers**: Preserved on write-back but not evaluated during dependency selection
258
+ - **Hybrid pyproject.toml** (PEP 621 + Poetry): PEP 621 is detected first; use `--format pyproject-poetry` to force Poetry handling
259
+ - **Private indexes**: Configure via `uv`'s native settings (`UV_INDEX_URL`, `uv.toml`), not via `--index-url` in requirements files
260
+
261
+ </details>
262
+
263
+ ## Contributing
264
+
265
+ ```bash
266
+ git clone https://github.com/helios-sc/depfresh.git && cd depfresh
267
+ uv venv && source .venv/bin/activate
268
+ uv pip install -e ".[dev]"
269
+ pytest && ruff check src/ && mypy src/
270
+ ```
271
+
272
+ Open an issue first for larger changes so we can discuss the approach.
273
+
274
+ ## License
275
+
276
+ MIT