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.
- depfresh-0.1.0/.github/workflows/ci.yml +74 -0
- depfresh-0.1.0/.github/workflows/publish.yml +53 -0
- depfresh-0.1.0/.gitignore +18 -0
- depfresh-0.1.0/CHANGELOG.md +43 -0
- depfresh-0.1.0/CLAUDE.md +109 -0
- depfresh-0.1.0/LICENSE +21 -0
- depfresh-0.1.0/PKG-INFO +276 -0
- depfresh-0.1.0/README.md +244 -0
- depfresh-0.1.0/SECURITY.md +31 -0
- depfresh-0.1.0/assets/logo-dark.svg +40 -0
- depfresh-0.1.0/assets/logo.svg +45 -0
- depfresh-0.1.0/pyproject.toml +76 -0
- depfresh-0.1.0/src/depfresh/__init__.py +45 -0
- depfresh-0.1.0/src/depfresh/audit.py +148 -0
- depfresh-0.1.0/src/depfresh/cli.py +172 -0
- depfresh-0.1.0/src/depfresh/constraints.py +176 -0
- depfresh-0.1.0/src/depfresh/exceptions.py +65 -0
- depfresh-0.1.0/src/depfresh/models.py +115 -0
- depfresh-0.1.0/src/depfresh/parsers/__init__.py +130 -0
- depfresh-0.1.0/src/depfresh/parsers/_base.py +54 -0
- depfresh-0.1.0/src/depfresh/parsers/_helpers.py +264 -0
- depfresh-0.1.0/src/depfresh/parsers/_pipfile.py +151 -0
- depfresh-0.1.0/src/depfresh/parsers/_pyproject.py +348 -0
- depfresh-0.1.0/src/depfresh/parsers/_requirements.py +228 -0
- depfresh-0.1.0/src/depfresh/py.typed +0 -0
- depfresh-0.1.0/src/depfresh/reports.py +463 -0
- depfresh-0.1.0/src/depfresh/upgrade.py +549 -0
- depfresh-0.1.0/src/depfresh/uv.py +220 -0
- depfresh-0.1.0/src/depfresh/verify.py +225 -0
- depfresh-0.1.0/tests/__init__.py +0 -0
- depfresh-0.1.0/tests/conftest.py +1 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/01_requirements_simple/app.py +12 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/01_requirements_simple/requirements.txt +2 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/02_requirements_hashed/app.py +12 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/02_requirements_hashed/requirements.txt +10 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/03_requirements_in/app.py +12 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/03_requirements_in/requirements.in +2 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/04_pyproject_pep621/app.py +12 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/04_pyproject_pep621/pyproject.toml +12 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/05_pyproject_poetry/app.py +12 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/05_pyproject_poetry/pyproject.toml +13 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/06_pipfile/Pipfile +11 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/06_pipfile/app.py +12 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/07_pyproject_pep621_optional/app.py +10 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/07_pyproject_pep621_optional/pyproject.toml +16 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/08_pyproject_pep621_direct_ref/app.py +10 -0
- depfresh-0.1.0/tests/fixtures/sample_projects/08_pyproject_pep621_direct_ref/pyproject.toml +12 -0
- depfresh-0.1.0/tests/helpers.py +28 -0
- depfresh-0.1.0/tests/test_audit.py +252 -0
- depfresh-0.1.0/tests/test_cli.py +332 -0
- depfresh-0.1.0/tests/test_constraints.py +252 -0
- depfresh-0.1.0/tests/test_e2e.py +554 -0
- depfresh-0.1.0/tests/test_parsers.py +1128 -0
- depfresh-0.1.0/tests/test_reports.py +115 -0
- depfresh-0.1.0/tests/test_smoke.py +213 -0
- depfresh-0.1.0/tests/test_upgrade.py +572 -0
- depfresh-0.1.0/tests/test_uv.py +168 -0
- depfresh-0.1.0/tests/test_verify.py +117 -0
- 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,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
|
depfresh-0.1.0/CLAUDE.md
ADDED
|
@@ -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.
|
depfresh-0.1.0/PKG-INFO
ADDED
|
@@ -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
|
+
[](https://pypi.org/project/depfresh/)
|
|
42
|
+
[](https://python.org)
|
|
43
|
+
[](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
|