Harvest add-on metadata from PyPI (by trove classifier) and npm into a normalised JSON snapshot — ships with a Plone/Volto profile.
Project description
addon-harvester
Harvests add-on/package metadata from PyPI (any trove classifier) and npm (search
queries) into one normalised JSON snapshot (index.json, schema_version 3) with a
0–100 health score per add-on. Std-lib only, no framework dependency. PyPI is enumerated
via the public BigQuery dataset (the only non-deprecated bulk API); XML-RPC browse and
the Simple index remain as fallbacks.
The search terms live in harvest.toml — point them at any ecosystem
("Framework :: Django", "Framework :: Zope", ...). The shipped default is the
Plone profile: Framework :: Plone plus npm queries for Volto/Aurora and
Nick add-ons (npm hits are tagged with their ecosystem
as category), with Plone-specific enrichments (version compat, add-on categories,
backend/frontend pairing) that simply stay empty for other ecosystems.
Docker (production, refresh every 4 h)
1. .env in the repo root:
BIGQUERY_PROJECT=my-gcp-project
GITHUB_TOKEN=ghp_... # optional: GitHub stars/last-commit enrichment
2. GCP service-account key at secrets/gcp-key.json (one-time):
gcloud iam service-accounts create harvester --project=$PROJECT
gcloud projects add-iam-policy-binding $PROJECT \
--member="serviceAccount:harvester@$PROJECT.iam.gserviceaccount.com" \
--role=roles/bigquery.jobUser
gcloud iam service-accounts keys create secrets/gcp-key.json \
--iam-account=harvester@$PROJECT.iam.gserviceaccount.com
3. Run:
docker compose up -d --build
docker compose logs -f harvester
The container harvests once at startup, then every 4 hours (docker/crontab), writing to
./data/index.json. Harvest flags live in HARVEST_ARGS in docker-compose.yml.
Without a key file the harvester falls back to the deprecated XML-RPC API.
Local development
make install # venv + package + dev extras (Python ≥ 3.14)
make test # pytest — offline, all network mocked
make lint # ruff
make harvest # full run (ARGS="--limit 20" to override)
For BigQuery enumeration locally, log in once with gcloud auth login and set
BIGQUERY_PROJECT in .env — tokens are minted automatically per run.
As a library (no I/O, snapshot returned in memory):
from addon_harvester import Harvester, HarvestOptions, write_snapshot
snapshot = Harvester(HarvestOptions(limit=20)).run()
write_snapshot(snapshot, "index.json")
Configuration
| Where | What |
|---|---|
harvest.toml |
search terms: PyPI trove classifiers + npm search queries (--classifier overrides the classifiers, --config for another file) |
.env |
BIGQUERY_PROJECT, GITHUB_TOKEN/GH_TOKEN, optional BIGQUERY_TOKEN |
python main.py --help |
all CLI flags (sources, limit, workers, output, ...) |
Every CLI run writes its full log to var/log/harvest-<timestamp>.log (newest 20 kept);
-v only controls console verbosity.
Architecture
src/addon_harvester/
├── harvester.py orchestration → snapshot (no I/O)
├── sources/ pypi (BigQuery → XML-RPC → Simple), npm, github enricher, bigquery client
├── normalizers/ raw registry document → TAddon
├── healthscore/ health score (rubric: healthscore/config.py)
└── http.py retrying JSON client with per-thread keep-alive · config.py · types.py
Each source implements list_packages / fetch_package / fetch_downloads /
normalize; HarvestBase.harvest() drives them identically. main.py is the CLI
wrapper, Makefile the task runner.
Release
make build # sdist + wheel into dist/
make publish # upload to PyPI (needs credentials)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file addon_harvester-1.1.0.tar.gz.
File metadata
- Download URL: addon_harvester-1.1.0.tar.gz
- Upload date:
- Size: 40.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4c830f0b7ac3344a905ee8c038eae194d3b1481b9ef2bc8c1d4dc8d96c43681e
|
|
| MD5 |
1fdc2594a1c08f400238698c576ed4e0
|
|
| BLAKE2b-256 |
e57bc227f7682890185b57a7bb01cfadd58fb74e6ae5c14fc7ccd0b28eb7b53b
|
Provenance
The following attestation bundles were made for addon_harvester-1.1.0.tar.gz:
Publisher:
release.yml on interaktivgmbh/addon-harvester
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
addon_harvester-1.1.0.tar.gz -
Subject digest:
4c830f0b7ac3344a905ee8c038eae194d3b1481b9ef2bc8c1d4dc8d96c43681e - Sigstore transparency entry: 1790043390
- Sigstore integration time:
-
Permalink:
interaktivgmbh/addon-harvester@8fa8b6b9fe2d957ccf242d565e56d6f484264c3c -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/interaktivgmbh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8fa8b6b9fe2d957ccf242d565e56d6f484264c3c -
Trigger Event:
push
-
Statement type:
File details
Details for the file addon_harvester-1.1.0-py3-none-any.whl.
File metadata
- Download URL: addon_harvester-1.1.0-py3-none-any.whl
- Upload date:
- Size: 35.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a11a783b7b75de3c5d1d53500ccf2c8a8e6e3612413b89de4777f137eb10bd6
|
|
| MD5 |
8f26e31e783f738001d04256cbafbbfe
|
|
| BLAKE2b-256 |
364b121ba52b36914787217ce7a1427140643bfd07a556f0c09d48db691e69ad
|
Provenance
The following attestation bundles were made for addon_harvester-1.1.0-py3-none-any.whl:
Publisher:
release.yml on interaktivgmbh/addon-harvester
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
addon_harvester-1.1.0-py3-none-any.whl -
Subject digest:
9a11a783b7b75de3c5d1d53500ccf2c8a8e6e3612413b89de4777f137eb10bd6 - Sigstore transparency entry: 1790043412
- Sigstore integration time:
-
Permalink:
interaktivgmbh/addon-harvester@8fa8b6b9fe2d957ccf242d565e56d6f484264c3c -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/interaktivgmbh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8fa8b6b9fe2d957ccf242d565e56d6f484264c3c -
Trigger Event:
push
-
Statement type: