suphm 0.3.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.
- suphm-0.3.0/.github/dependabot.yml +27 -0
- suphm-0.3.0/.github/workflows/ci.yml +46 -0
- suphm-0.3.0/.github/workflows/python-publish.yml +72 -0
- suphm-0.3.0/.gitignore +218 -0
- suphm-0.3.0/AUTHORS.md +9 -0
- suphm-0.3.0/CHANGELOG.md +295 -0
- suphm-0.3.0/CODE_OF_CONDUCT.md +133 -0
- suphm-0.3.0/CONTRIBUTING.md +147 -0
- suphm-0.3.0/LICENSE +661 -0
- suphm-0.3.0/PKG-INFO +265 -0
- suphm-0.3.0/README.md +224 -0
- suphm-0.3.0/docs/API_MIGRATION_GUIDE.md +202 -0
- suphm-0.3.0/docs/API_REFERENCE.md +304 -0
- suphm-0.3.0/docs/HEALTH_SCORE_CALCULATION.md +219 -0
- suphm-0.3.0/docs/METRICS_COMPARISON.md +552 -0
- suphm-0.3.0/docs/METRICS_SPECIFICATION.md +3986 -0
- suphm-0.3.0/docs/api-integrations.md +562 -0
- suphm-0.3.0/docs/commands.md +541 -0
- suphm-0.3.0/docs/getting-started.md +356 -0
- suphm-0.3.0/docs/github-token-setup.md +482 -0
- suphm-0.3.0/docs/serpapi-setup.md +466 -0
- suphm-0.3.0/pyproject.toml +90 -0
- suphm-0.3.0/src/suphm/__init__.py +3 -0
- suphm-0.3.0/src/suphm/analysis/__init__.py +5 -0
- suphm-0.3.0/src/suphm/analysis/pipeline.py +470 -0
- suphm-0.3.0/src/suphm/cache/__init__.py +5 -0
- suphm-0.3.0/src/suphm/cache/manager.py +567 -0
- suphm-0.3.0/src/suphm/cli.py +1369 -0
- suphm-0.3.0/src/suphm/config.py +276 -0
- suphm-0.3.0/src/suphm/core/__init__.py +6 -0
- suphm-0.3.0/src/suphm/core/git.py +373 -0
- suphm-0.3.0/src/suphm/core/http.py +529 -0
- suphm-0.3.0/src/suphm/discovery/__init__.py +6 -0
- suphm-0.3.0/src/suphm/discovery/purl.py +274 -0
- suphm-0.3.0/src/suphm/discovery/resolver.py +677 -0
- suphm-0.3.0/src/suphm/enrichment/__init__.py +5 -0
- suphm-0.3.0/src/suphm/enrichment/company.py +272 -0
- suphm-0.3.0/src/suphm/metrics/__init__.py +11 -0
- suphm-0.3.0/src/suphm/metrics/git.py +758 -0
- suphm-0.3.0/src/suphm/metrics/github.py +743 -0
- suphm-0.3.0/src/suphm/report/__init__.py +5 -0
- suphm-0.3.0/src/suphm/report/generator.py +469 -0
- suphm-0.3.0/src/suphm/scanner/__init__.py +5 -0
- suphm-0.3.0/src/suphm/scanner/tarball.py +636 -0
- suphm-0.3.0/src/suphm/scoring/__init__.py +11 -0
- suphm-0.3.0/src/suphm/scoring/burnout.py +464 -0
- suphm-0.3.0/src/suphm/scoring/health.py +797 -0
- suphm-0.3.0/tests/__init__.py +1 -0
- suphm-0.3.0/tests/conftest.py +220 -0
- suphm-0.3.0/tests/e2e/__init__.py +1 -0
- suphm-0.3.0/tests/e2e/test_workflows.py +375 -0
- suphm-0.3.0/tests/integration/__init__.py +1 -0
- suphm-0.3.0/tests/integration/test_cli.py +328 -0
- suphm-0.3.0/tests/unit/__init__.py +1 -0
- suphm-0.3.0/tests/unit/test_analysis.py +287 -0
- suphm-0.3.0/tests/unit/test_cache.py +310 -0
- suphm-0.3.0/tests/unit/test_cache_path_safety.py +79 -0
- suphm-0.3.0/tests/unit/test_config.py +251 -0
- suphm-0.3.0/tests/unit/test_discovery.py +231 -0
- suphm-0.3.0/tests/unit/test_enrichment.py +150 -0
- suphm-0.3.0/tests/unit/test_git_clone.py +250 -0
- suphm-0.3.0/tests/unit/test_git_metrics.py +274 -0
- suphm-0.3.0/tests/unit/test_github_collector_status.py +189 -0
- suphm-0.3.0/tests/unit/test_health_normalization.py +168 -0
- suphm-0.3.0/tests/unit/test_http.py +324 -0
- suphm-0.3.0/tests/unit/test_pipeline_resilience.py +108 -0
- suphm-0.3.0/tests/unit/test_report.py +336 -0
- suphm-0.3.0/tests/unit/test_scoring.py +221 -0
- suphm-0.3.0/tests/unit/test_tarball.py +240 -0
- suphm-0.3.0/tests/unit/test_tarball_security.py +214 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Keep GitHub Actions up to date so security patches in the actions
|
|
4
|
+
# themselves don't sit waiting for a human bump.
|
|
5
|
+
- package-ecosystem: github-actions
|
|
6
|
+
directory: /
|
|
7
|
+
schedule:
|
|
8
|
+
interval: weekly
|
|
9
|
+
commit-message:
|
|
10
|
+
prefix: "ci"
|
|
11
|
+
groups:
|
|
12
|
+
actions:
|
|
13
|
+
patterns: ["*"]
|
|
14
|
+
|
|
15
|
+
# Python dependencies in pyproject.toml. Grouped to avoid PR sprawl;
|
|
16
|
+
# weekly cadence so noise stays manageable.
|
|
17
|
+
- package-ecosystem: pip
|
|
18
|
+
directory: /
|
|
19
|
+
schedule:
|
|
20
|
+
interval: weekly
|
|
21
|
+
commit-message:
|
|
22
|
+
prefix: "deps"
|
|
23
|
+
groups:
|
|
24
|
+
production:
|
|
25
|
+
dependency-type: production
|
|
26
|
+
development:
|
|
27
|
+
dependency-type: development
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
# Allow python-publish.yml to reuse this workflow as the pre-publish test gate.
|
|
8
|
+
workflow_call:
|
|
9
|
+
|
|
10
|
+
# Cancel in-progress runs when a new push lands on the same branch/PR.
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
test:
|
|
20
|
+
name: test (py${{ matrix.python-version }})
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
strategy:
|
|
23
|
+
fail-fast: false
|
|
24
|
+
matrix:
|
|
25
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
26
|
+
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
31
|
+
uses: actions/setup-python@v5
|
|
32
|
+
with:
|
|
33
|
+
python-version: ${{ matrix.python-version }}
|
|
34
|
+
cache: pip
|
|
35
|
+
|
|
36
|
+
- name: Install dev dependencies
|
|
37
|
+
run: pip install -e ".[dev]"
|
|
38
|
+
|
|
39
|
+
- name: Lint (ruff)
|
|
40
|
+
run: ruff check src/ tests/
|
|
41
|
+
|
|
42
|
+
- name: Type-check (mypy)
|
|
43
|
+
run: mypy src/
|
|
44
|
+
|
|
45
|
+
- name: Tests (pytest)
|
|
46
|
+
run: pytest -q
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
# Two simultaneous releases would race on the same PyPI version.
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ${{ github.workflow }}-${{ github.event.release.tag_name }}
|
|
10
|
+
cancel-in-progress: false
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
test:
|
|
17
|
+
name: pre-publish tests
|
|
18
|
+
uses: ./.github/workflows/ci.yml
|
|
19
|
+
|
|
20
|
+
build:
|
|
21
|
+
name: build sdist + wheel
|
|
22
|
+
needs: test
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
|
|
28
|
+
- name: Set up Python
|
|
29
|
+
uses: actions/setup-python@v5
|
|
30
|
+
with:
|
|
31
|
+
# Pinned to a single supported version for reproducible builds.
|
|
32
|
+
# Bump intentionally; do not use "3.x" (would silently follow
|
|
33
|
+
# whatever the runner ships and could miss our 3.10 floor).
|
|
34
|
+
python-version: "3.12"
|
|
35
|
+
|
|
36
|
+
- name: Build distributions
|
|
37
|
+
run: |
|
|
38
|
+
python -m pip install --upgrade pip
|
|
39
|
+
python -m pip install build
|
|
40
|
+
python -m build
|
|
41
|
+
|
|
42
|
+
- name: Upload dist artifacts
|
|
43
|
+
uses: actions/upload-artifact@v4
|
|
44
|
+
with:
|
|
45
|
+
name: release-dists
|
|
46
|
+
path: dist/
|
|
47
|
+
|
|
48
|
+
publish:
|
|
49
|
+
name: publish to PyPI
|
|
50
|
+
needs: build
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
permissions:
|
|
53
|
+
# Trusted Publishing (OIDC) - no PyPI token required in repo secrets.
|
|
54
|
+
# PyPI side: configure a publisher pointing at SemClone/suphm with
|
|
55
|
+
# workflow=python-publish.yml and environment=pypi.
|
|
56
|
+
id-token: write
|
|
57
|
+
|
|
58
|
+
environment:
|
|
59
|
+
name: pypi
|
|
60
|
+
url: https://pypi.org/p/suphm
|
|
61
|
+
|
|
62
|
+
steps:
|
|
63
|
+
- name: Download dist artifacts
|
|
64
|
+
uses: actions/download-artifact@v4
|
|
65
|
+
with:
|
|
66
|
+
name: release-dists
|
|
67
|
+
path: dist/
|
|
68
|
+
|
|
69
|
+
- name: Publish to PyPI
|
|
70
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
71
|
+
with:
|
|
72
|
+
packages-dir: dist/
|
suphm-0.3.0/.gitignore
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
#poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
#pdm.lock
|
|
116
|
+
#pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
#pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# SageMath parsed files
|
|
135
|
+
*.sage.py
|
|
136
|
+
|
|
137
|
+
# Environments
|
|
138
|
+
.env
|
|
139
|
+
.envrc
|
|
140
|
+
.venv
|
|
141
|
+
env/
|
|
142
|
+
venv/
|
|
143
|
+
ENV/
|
|
144
|
+
env.bak/
|
|
145
|
+
venv.bak/
|
|
146
|
+
|
|
147
|
+
# Spyder project settings
|
|
148
|
+
.spyderproject
|
|
149
|
+
.spyproject
|
|
150
|
+
|
|
151
|
+
# Rope project settings
|
|
152
|
+
.ropeproject
|
|
153
|
+
|
|
154
|
+
# mkdocs documentation
|
|
155
|
+
/site
|
|
156
|
+
|
|
157
|
+
# mypy
|
|
158
|
+
.mypy_cache/
|
|
159
|
+
.dmypy.json
|
|
160
|
+
dmypy.json
|
|
161
|
+
|
|
162
|
+
# Pyre type checker
|
|
163
|
+
.pyre/
|
|
164
|
+
|
|
165
|
+
# pytype static type analyzer
|
|
166
|
+
.pytype/
|
|
167
|
+
|
|
168
|
+
# Cython debug symbols
|
|
169
|
+
cython_debug/
|
|
170
|
+
|
|
171
|
+
# PyCharm
|
|
172
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
173
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
174
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
175
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
176
|
+
#.idea/
|
|
177
|
+
|
|
178
|
+
# Abstra
|
|
179
|
+
# Abstra is an AI-powered process automation framework.
|
|
180
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
181
|
+
# Learn more at https://abstra.io/docs
|
|
182
|
+
.abstra/
|
|
183
|
+
|
|
184
|
+
# Visual Studio Code
|
|
185
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
186
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
188
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
189
|
+
# .vscode/
|
|
190
|
+
|
|
191
|
+
# Ruff stuff:
|
|
192
|
+
.ruff_cache/
|
|
193
|
+
|
|
194
|
+
# PyPI configuration file
|
|
195
|
+
.pypirc
|
|
196
|
+
|
|
197
|
+
# Cursor
|
|
198
|
+
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
|
199
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
200
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
201
|
+
.cursorignore
|
|
202
|
+
.cursorindexingignore
|
|
203
|
+
|
|
204
|
+
# Marimo
|
|
205
|
+
marimo/_static/
|
|
206
|
+
marimo/_lsp/
|
|
207
|
+
__marimo__/
|
|
208
|
+
|
|
209
|
+
# suphm-specific
|
|
210
|
+
# Local analysis output (regenerated on demand; not part of the source).
|
|
211
|
+
analysis_results/
|
|
212
|
+
# Local on-disk cache (default ~/.suphm/, but allow per-repo overrides).
|
|
213
|
+
.suphm/
|
|
214
|
+
# MagicMock paths created if a test accidentally treats a MagicMock as a Path.
|
|
215
|
+
MagicMock/
|
|
216
|
+
# Per-PURL output saved during ad-hoc testing.
|
|
217
|
+
*-result.json
|
|
218
|
+
*-analysis.json
|
suphm-0.3.0/AUTHORS.md
ADDED
suphm-0.3.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
## [0.3.0] - 2026-04-29
|
|
6
|
+
|
|
7
|
+
### Changed (BREAKING)
|
|
8
|
+
|
|
9
|
+
- **Project renamed** from `ccda-cli` to `suphm` (Supply Chain Health Metrics).
|
|
10
|
+
The repo also moved from `SemClone/ccda-cli` to `SemClone/suphm`.
|
|
11
|
+
- Python package: `ccda_cli` → `suphm`. All imports change.
|
|
12
|
+
```python
|
|
13
|
+
# before
|
|
14
|
+
from ccda_cli.metrics.git import GitMetricsAnalyzer
|
|
15
|
+
# after
|
|
16
|
+
from suphm.metrics.git import GitMetricsAnalyzer
|
|
17
|
+
```
|
|
18
|
+
- CLI entry point: `ccda-cli` → `suphm`. Update any scripts.
|
|
19
|
+
- Distribution name on PyPI: `ccda-cli` → `suphm` (new package; the old one
|
|
20
|
+
will not be updated further).
|
|
21
|
+
- Cache directory: `~/.ccda/` → `~/.suphm/`. Existing caches are not migrated;
|
|
22
|
+
delete the old directory or copy contents over manually.
|
|
23
|
+
- Project config file: `./ccda-config.yaml` → `./suphm-config.yaml`.
|
|
24
|
+
- Environment variables:
|
|
25
|
+
- `CCDA_GITHUB_TOKEN` → `SUPHM_GITHUB_TOKEN`
|
|
26
|
+
- `CCDA_SERPAPI_KEY` → `SUPHM_SERPAPI_KEY`
|
|
27
|
+
- `CCDA_CACHE_DIR` → `SUPHM_CACHE_DIR`
|
|
28
|
+
- `GITHUB_TOKEN` continues to work as a fallback.
|
|
29
|
+
- Repo-clone metadata file in cache: `.ccda-metadata.json` → `.suphm-metadata.json`.
|
|
30
|
+
Repos cloned by older versions will be re-cloned on first use.
|
|
31
|
+
|
|
32
|
+
## [0.2.2] - 2026-01-14
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- **Critical**: Fixed malformed GitHub URLs with `git+` prefix causing clone failures
|
|
37
|
+
- Discovery stage now properly normalizes GitHub URLs by stripping `git+` prefix
|
|
38
|
+
- Removes `.git` suffix and trailing paths (`/issues`, `/pulls`, `/wiki`, etc.)
|
|
39
|
+
- Replaces `git://` protocol with `https://`
|
|
40
|
+
- Affects all npm packages and potentially other ecosystems
|
|
41
|
+
- Missing metrics restored: Bus Factor, Pony Factor, Elephant Factor, Commit Activity, Contributor Retention, License Stability
|
|
42
|
+
- Now collecting all 10 health metrics instead of only 4 for affected packages
|
|
43
|
+
- Added `_normalize_github_url()` helper function in `discovery/resolver.py`
|
|
44
|
+
- Applied normalization to all repository URL assignments across all discovery sources
|
|
45
|
+
|
|
46
|
+
## [0.2.1] - 2026-01-13
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
|
|
50
|
+
- **Critical**: Fixed pkg:github package analysis failure with 'ecosystem' parameter error
|
|
51
|
+
- Fixed `_github_discovery_step` in `pipeline.py` passing invalid parameters to `DiscoveryResult`
|
|
52
|
+
- Removed non-existent `ecosystem` parameter
|
|
53
|
+
- Changed `github_url` to correct `repository_url` parameter
|
|
54
|
+
- Removed non-existent `success` parameter
|
|
55
|
+
- Changed `metadata` to correct `registry_data` parameter
|
|
56
|
+
- Added required `version` parameter
|
|
57
|
+
- GitHub packages like `pkg:github/hashicorp/terraform` now analyze successfully
|
|
58
|
+
|
|
59
|
+
## [0.2.0] - 2026-01-13
|
|
60
|
+
|
|
61
|
+
### Added
|
|
62
|
+
|
|
63
|
+
- **Phase 4 Metric A.6: Review Turnaround Time**
|
|
64
|
+
- New `avg_review_turnaround_hours` metric in pull request data
|
|
65
|
+
- New `median_review_turnaround_hours` metric in pull request data
|
|
66
|
+
- Track `prs_with_reviews` and `prs_without_reviews` counts
|
|
67
|
+
- Samples up to 50 recent PRs to calculate time from PR creation to first review
|
|
68
|
+
- Handles APPROVED, CHANGES_REQUESTED, and COMMENTED review states
|
|
69
|
+
|
|
70
|
+
- **Phase 4 Metric A.8: New Contributor Rate**
|
|
71
|
+
- New `new_contributors_count` metric in time window data (90d, 180d, 365d)
|
|
72
|
+
- New `new_contributors_per_month` metric showing monthly rate
|
|
73
|
+
- New `contributor_growth_rate` showing percentage of contributors who are new
|
|
74
|
+
- Tracks contributors whose first commit falls within each time window
|
|
75
|
+
|
|
76
|
+
### Changed
|
|
77
|
+
|
|
78
|
+
- Enhanced `PullRequestMetrics` dataclass with review turnaround fields
|
|
79
|
+
- Added `get_pull_reviews()` method to `GitHubClient` for fetching PR reviews
|
|
80
|
+
- Enhanced `TimeWindowMetrics` dataclass with new contributor rate fields
|
|
81
|
+
|
|
82
|
+
## [0.1.10] - 2026-01-12
|
|
83
|
+
|
|
84
|
+
### Fixed
|
|
85
|
+
|
|
86
|
+
- **Critical**: Fixed golang package GitHub metrics discovery
|
|
87
|
+
- Fixed `depsdev_ecosystem` property to handle "golang" vs "go" type mismatch
|
|
88
|
+
- Fixed `_discover_from_depsdev` to support both "go" and "golang" types
|
|
89
|
+
- Golang packages now correctly infer GitHub URL from package namespace
|
|
90
|
+
- Example: `pkg:golang/github.com/gin-gonic/gin` now discovers `https://github.com/gin-gonic/gin`
|
|
91
|
+
- Root cause: packageurl library returns `type="golang"` but code only checked for `"go"`
|
|
92
|
+
|
|
93
|
+
## [0.1.9] - 2026-01-12
|
|
94
|
+
|
|
95
|
+
### Changed
|
|
96
|
+
|
|
97
|
+
- Version bump to publish GitHub PURL support to PyPI
|
|
98
|
+
- No code changes from 0.1.8 (which included the GitHub PURL feature but was not published with it)
|
|
99
|
+
|
|
100
|
+
## [0.1.8] - 2026-01-12
|
|
101
|
+
|
|
102
|
+
### Added
|
|
103
|
+
|
|
104
|
+
- **Native pkg:github/* PURL support** for direct GitHub package analysis
|
|
105
|
+
- Early PURL detection in `AnalysisPipeline.analyze()` to identify GitHub packages
|
|
106
|
+
- New `_analyze_github_package()` method for specialized GitHub package analysis
|
|
107
|
+
- New `_github_discovery_step()` helper for minimal discovery without external API calls
|
|
108
|
+
- Direct GitHub API access for metrics collection (no tarball download required)
|
|
109
|
+
- Simplified 3-step pipeline for GitHub packages: Discovery → GitHub Metrics → Health Score
|
|
110
|
+
|
|
111
|
+
### Changed
|
|
112
|
+
|
|
113
|
+
- GitHub packages now skip package registry discovery (not needed for pkg:github/*)
|
|
114
|
+
- GitHub packages no longer require tarball download or git cloning
|
|
115
|
+
- Analysis time for GitHub packages reduced from ~80s to ~10s
|
|
116
|
+
|
|
117
|
+
### Fixed
|
|
118
|
+
|
|
119
|
+
- Analysis failures for GitHub PURLs like `pkg:github/hashicorp/terraform` and `pkg:github/actions/checkout`
|
|
120
|
+
- Unnecessary package registry lookups for GitHub-native packages
|
|
121
|
+
|
|
122
|
+
## [0.1.7] - 2026-01-05
|
|
123
|
+
|
|
124
|
+
### Fixed
|
|
125
|
+
|
|
126
|
+
- **Critical**: Fixed company affiliation enrichment silently failing
|
|
127
|
+
- Company enrichment was not working due to async/await execution context issue
|
|
128
|
+
- `_enrich_contributors()` was calling async code from within an executor thread
|
|
129
|
+
- Added proper event loop detection and thread-safe async execution
|
|
130
|
+
- Now correctly handles both standalone and executor-based execution contexts
|
|
131
|
+
- Company data now properly populates in metrics output
|
|
132
|
+
|
|
133
|
+
## [0.1.6] - 2026-01-05
|
|
134
|
+
|
|
135
|
+
### Added
|
|
136
|
+
|
|
137
|
+
- **Company affiliation enrichment** via GitHub API (optional, requires GitHub token)
|
|
138
|
+
- Automatically enriches contributor data with company information from GitHub user profiles
|
|
139
|
+
- Extracts GitHub usernames from commit emails (e.g., `username@users.noreply.github.com`)
|
|
140
|
+
- Fetches user profiles from GitHub API in batch to minimize API calls
|
|
141
|
+
- Caches user profiles for 30 days to avoid duplicate requests
|
|
142
|
+
- Normalizes company names using configurable mappings (e.g., "@google" → "Google")
|
|
143
|
+
- Respects GitHub API rate limits and degrades gracefully
|
|
144
|
+
- Falls back to email domain detection when API unavailable or rate limited
|
|
145
|
+
- Provides more accurate elephant factor and company distribution metrics
|
|
146
|
+
- New `CompanyEnricher` class in `ccda_cli.enrichment.company` module
|
|
147
|
+
- Configuration option `github.enrich_company_affiliation` (default: true when token provided)
|
|
148
|
+
- Comprehensive test suite for company enrichment (16 unit tests)
|
|
149
|
+
- Enhanced documentation in `docs/github-token-setup.md` with company enrichment examples
|
|
150
|
+
|
|
151
|
+
### Changed
|
|
152
|
+
|
|
153
|
+
- `GitMetricsAnalyzer` now accepts optional `github_token` parameter for enrichment
|
|
154
|
+
- Company detection now prioritizes GitHub API data over email domain mapping (when token available)
|
|
155
|
+
- Updated README.md to highlight company affiliation enrichment feature
|
|
156
|
+
|
|
157
|
+
## [0.1.5] - 2026-01-05
|
|
158
|
+
|
|
159
|
+
### Added
|
|
160
|
+
|
|
161
|
+
- **osslili as required dependency** for professional license detection
|
|
162
|
+
- Replaced brittle pattern-matching with osslili's Python API
|
|
163
|
+
- Accurate SPDX license identification with confidence scores
|
|
164
|
+
- Copyright statement extraction
|
|
165
|
+
- Support for all osslili detection methods (metadata, file analysis, keyword matching)
|
|
166
|
+
|
|
167
|
+
### Fixed
|
|
168
|
+
|
|
169
|
+
- **Critical**: Cargo package tarball scanning now works correctly
|
|
170
|
+
- Fixed `.crate` file download from crates.io (was downloading as `download` with no extension)
|
|
171
|
+
- Added `.crate` extension support to archive extraction
|
|
172
|
+
- Enhanced download URL detection to handle redirects properly (checks Content-Disposition header and final redirect URL)
|
|
173
|
+
- License file detection now works for all ecosystems
|
|
174
|
+
- Removed incomplete `LICENSE_PATTERNS` that missed common patterns like `LICENSE-MIT`, `LICENSE-APACHE`
|
|
175
|
+
- Now uses osslili for comprehensive license file discovery
|
|
176
|
+
- Relative path display in scan results (shows `serde-1.0.228/LICENSE-MIT` instead of full temp paths)
|
|
177
|
+
|
|
178
|
+
### Changed
|
|
179
|
+
|
|
180
|
+
- **Breaking**: osslili is now a required dependency (previously optional)
|
|
181
|
+
- **Breaking**: purl2src is now a required dependency (previously optional)
|
|
182
|
+
- Removed optional dependency groups `scanner` and `all`
|
|
183
|
+
- Tarball scanner completely refactored to use osslili Python API
|
|
184
|
+
- Deleted 200+ lines of brittle pattern-matching code
|
|
185
|
+
- Removed fallback license detection methods
|
|
186
|
+
- Scan method now always reports `osslili`
|
|
187
|
+
- Cleaned up unused code and imports from tarball scanner
|
|
188
|
+
|
|
189
|
+
### Removed
|
|
190
|
+
|
|
191
|
+
- Removed obsolete methods: `_check_tool`, `_resolve_command`, `_build_command`, `_run_external_tool`, `_run_osslili`, `_run_upmex`, `_apply_osslili_results`, `_apply_upmex_results`, `_analyze_license_file`
|
|
192
|
+
- Removed `LICENSE_PATTERNS` and `COPYRIGHT_PATTERNS` constants
|
|
193
|
+
- Removed support for external tool command-line integration (now uses Python APIs directly)
|
|
194
|
+
|
|
195
|
+
## [0.1.4] - 2026-01-04
|
|
196
|
+
|
|
197
|
+
### Added
|
|
198
|
+
|
|
199
|
+
- **purl2src integration** for automatic download URL discovery
|
|
200
|
+
- Integrated purl2src library as optional dependency
|
|
201
|
+
- Tarball scanner now auto-discovers download URLs from PURLs
|
|
202
|
+
- Fallback to PackageResolver if purl2src unavailable
|
|
203
|
+
- New optional dependency group: `scanner` and `all`
|
|
204
|
+
- Crates.io (Rust Cargo) package discovery integration
|
|
205
|
+
- Full metadata extraction from crates.io API
|
|
206
|
+
- Registry data snapshot including downloads, keywords, and categories
|
|
207
|
+
- Tarball URL resolution for package scanning
|
|
208
|
+
- Enhanced tarball scanner with external tool integration support
|
|
209
|
+
- Support for osslili and upmex external scanning tools
|
|
210
|
+
- Dynamic scan method tracking (builtin, osslili, upmex, or combined)
|
|
211
|
+
- Improved license detection and binary file analysis
|
|
212
|
+
|
|
213
|
+
### Fixed
|
|
214
|
+
|
|
215
|
+
- Test suite compatibility with Python 3.14
|
|
216
|
+
- Virtual environment setup and package installation workflow
|
|
217
|
+
|
|
218
|
+
## [0.1.3] - 2026-01-04
|
|
219
|
+
|
|
220
|
+
### Added
|
|
221
|
+
|
|
222
|
+
- Dynamic API sampling based on GitHub token authentication status
|
|
223
|
+
- Authenticated (5000 calls/hr): Fetches up to 5000 issues, 5000 PRs, 2000 closed issues
|
|
224
|
+
- Unauthenticated (60 calls/hr): Conservative limits of 300 items per category
|
|
225
|
+
- Sampling metadata in JSON output for transparency
|
|
226
|
+
- `_sampling` field in `IssueMetrics` showing sample size vs total count
|
|
227
|
+
- `_sampling` field in `PullRequestMetrics` with coverage information
|
|
228
|
+
- Coverage percentage indicator for quality assessment
|
|
229
|
+
|
|
230
|
+
### Fixed
|
|
231
|
+
|
|
232
|
+
- **Critical**: Metrics severely underreported due to hard-coded 300-item limit regardless of token
|
|
233
|
+
- Issue sample size increased from 300 to 5000 when authenticated (16x improvement)
|
|
234
|
+
- PR sample size increased from 300 to 5000 when authenticated (16x improvement)
|
|
235
|
+
- Unlabeled rate now calculated from proper sample size
|
|
236
|
+
- Unresponded rate now reflects larger sample for better accuracy
|
|
237
|
+
- Burnout score `issue_backlog` now uses adjusted full count instead of sampled count
|
|
238
|
+
- PR counts (open/merged/closed) now reflect comprehensive data instead of first 300 items
|
|
239
|
+
|
|
240
|
+
### Changed
|
|
241
|
+
|
|
242
|
+
- `IssueMetrics` dataclass now includes `sampled_open_count` and `sampled_closed_count` fields
|
|
243
|
+
- `PullRequestMetrics` dataclass now includes `sampled_count` field
|
|
244
|
+
- GitHub API collector now adapts page limits based on token availability
|
|
245
|
+
|
|
246
|
+
## [0.1.2] - 2026-01-04
|
|
247
|
+
|
|
248
|
+
### Fixed
|
|
249
|
+
|
|
250
|
+
- Use actual `open_issues_count` from GitHub repo API instead of sampled count (max 300)
|
|
251
|
+
- Subtract open PRs from issue count for accurate totals
|
|
252
|
+
- Fixes incorrect burnout score `issue_backlog` calculation
|
|
253
|
+
|
|
254
|
+
## [0.1.1] - 2026-01-04
|
|
255
|
+
|
|
256
|
+
### Added
|
|
257
|
+
|
|
258
|
+
- `chaoss_metrics` field to `HealthScoreResult` containing bus_factor, pony_factor, elephant_factor, and contributor_count
|
|
259
|
+
- `extended_metrics` field to `HealthScoreResult` containing commit_frequency, commits_per_day, pr_velocity, median_pr_merge_hours, branch_protected, and has_signed_releases
|
|
260
|
+
- Helper methods `_classify_frequency()` and `_classify_velocity()` for categorizing activity levels
|
|
261
|
+
|
|
262
|
+
### Fixed
|
|
263
|
+
|
|
264
|
+
- Dashboard template compatibility by exposing CHAOSS and extended metrics in health score output (#1)
|
|
265
|
+
|
|
266
|
+
## [0.1.0] - 2026-01-03
|
|
267
|
+
|
|
268
|
+
### Initial Release
|
|
269
|
+
|
|
270
|
+
First public release of ccda-cli - Supply Chain Security Metrics tool.
|
|
271
|
+
|
|
272
|
+
### Features
|
|
273
|
+
|
|
274
|
+
- Multi-ecosystem package analysis (npm, PyPI, Cargo, Maven, Go)
|
|
275
|
+
- Health score calculation (0-100) based on commit activity, contributor diversity, and community health
|
|
276
|
+
- Burnout score detection for maintainer sustainability risk assessment
|
|
277
|
+
- CHAOSS metrics computation (bus factor, pony factor, elephant factor)
|
|
278
|
+
- GitHub API integration for community health indicators (stars, forks, issues, PRs)
|
|
279
|
+
- Package tarball scanning for license compliance and binary detection
|
|
280
|
+
- Multiple discovery sources (deps.dev, ecosyste.ms, package registries, SerpAPI fallback)
|
|
281
|
+
- CLI commands: analyze, discover, cache management
|
|
282
|
+
- JSON output format for integration with other tools
|
|
283
|
+
- Comprehensive documentation and usage examples
|
|
284
|
+
|
|
285
|
+
### Documentation
|
|
286
|
+
|
|
287
|
+
- Complete README with installation and usage instructions
|
|
288
|
+
- Contribution guidelines (CONTRIBUTING.md)
|
|
289
|
+
- Code of Conduct (CODE_OF_CONDUCT.md)
|
|
290
|
+
- Authors and credits (AUTHORS.md)
|
|
291
|
+
- Detailed documentation for API integrations and configuration
|
|
292
|
+
|
|
293
|
+
### License
|
|
294
|
+
|
|
295
|
+
GNU Affero General Public License v3.0
|