|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project |
| 6 | + |
| 7 | +**lastversion** — CLI tool and Python library that finds the latest stable release version of software projects across multiple hosting platforms (GitHub, GitLab, PyPI, Bitbucket, SourceForge, WordPress, etc.). Used heavily in RPM build automation and CI/CD pipelines. |
| 8 | + |
| 9 | +## Development Setup |
| 10 | + |
| 11 | +- **Virtualenv:** `~/.virtualenvs/lastversion/` |
| 12 | +- **Secrets:** Source `~/.secrets` before running tests (contains `GITHUB_API_TOKEN` and other API tokens) |
| 13 | + |
| 14 | +## Common Commands |
| 15 | + |
| 16 | +```bash |
| 17 | +# Run all tests (sources secrets, activates venv, parallel execution with 10min timeout) |
| 18 | +make test |
| 19 | + |
| 20 | +# Run a single test |
| 21 | +source ~/.secrets && ~/.virtualenvs/lastversion/bin/python -m pytest tests/test_github.py::test_function_name -v |
| 22 | + |
| 23 | +# Lint |
| 24 | +~/.virtualenvs/lastversion/bin/python -m flake8 src tests |
| 25 | +~/.virtualenvs/lastversion/bin/python -m pylint src tests |
| 26 | + |
| 27 | +# Security scan |
| 28 | +~/.virtualenvs/lastversion/bin/python -m bandit -c pyproject.toml -r src/lastversion |
| 29 | + |
| 30 | +# Release (CI auto-publishes to PyPI on GitHub release creation) |
| 31 | +# 1. Bump __version__ in src/lastversion/__about__.py |
| 32 | +# 2. Commit: git commit -m "chore(release): X.Y.Z" |
| 33 | +# 3. Tag: git tag -s vX.Y.Z -m "vX.Y.Z" |
| 34 | +# 4. Push: git push origin master && git push origin vX.Y.Z |
| 35 | +# 5. Create release: gh release create vX.Y.Z --title "vX.Y.Z" --notes "..." |
| 36 | +# CI workflow pythonpublish.yml handles PyPI upload automatically. |
| 37 | +# Do NOT use `make publish` or manual `twine upload`. |
| 38 | +make publish # backup only, prefer CI |
| 39 | + |
| 40 | +# Build single binary |
| 41 | +make one-file |
| 42 | +``` |
| 43 | + |
| 44 | +## Architecture |
| 45 | + |
| 46 | +### Repository Holder Pattern |
| 47 | + |
| 48 | +Core abstraction: `BaseProjectHolder` (in `src/lastversion/repo_holders/base.py`) is the abstract base class for all hosting platform adapters. Each adapter lives in `src/lastversion/repo_holders/` and implements release discovery for its platform. |
| 49 | + |
| 50 | +`HolderFactory` (`holder_factory.py`) maintains an ordered registry of adapters and selects the appropriate one based on the input URL/name. Detection order matters — adapters are tried in registration order. |
| 51 | + |
| 52 | +### Key Modules |
| 53 | + |
| 54 | +- **`lastversion.py`** — Core logic: `latest()`, `has_update()`, `check_version()` entry points |
| 55 | +- **`cli.py`** — CLI argument parsing, all subcommands (get, download, extract, install, update-spec, etc.) |
| 56 | +- **`version.py`** — `Version` class extending `packaging.Version` with normalization for messy real-world version strings (dashed versions, Java-style, pre-release variants) |
| 57 | +- **`cache.py`** — Dual-level caching: HTTP-level (CacheControl/ETag) + release-data-level (File or Redis backend) with PID-based file locking |
| 58 | +- **`config.py`** — Platform-aware config singleton (`~/.config/lastversion/lastversion.yml` on Linux, `~/Library/Application Support/lastversion/lastversion.yml` on macOS) |
| 59 | + |
| 60 | +### GitHub Adapter (`repo_holders/github.py`) |
| 61 | + |
| 62 | +Most complex adapter. Uses GraphQL API with REST fallback. Handles rate limiting, API tokens (`GITHUB_API_TOKEN`/`GITHUB_TOKEN` env vars), commit-based version extraction, and release note parsing. |
| 63 | + |
| 64 | +### RPM Spec Integration |
| 65 | + |
| 66 | +`update-spec` command parses `.spec` files for `%{upstream_github}`, `%global lastversion_repo`, and `%global lastversion_*` directives to determine repo and version constraints. |
| 67 | + |
| 68 | +## Testing |
| 69 | + |
| 70 | +- **Framework:** pytest with pytest-xdist (parallel: `-n auto`) |
| 71 | +- **CI matrix:** Python 3.6, 3.9, 3.13 |
| 72 | +- Tests include live API calls — require valid API tokens |
| 73 | +- Test files mirror the module structure: `test_github.py`, `test_gitlab.py`, `test_pypi.py`, etc. |
| 74 | +- Helper utilities in `tests/helpers.py` |
| 75 | + |
| 76 | +## Linting |
| 77 | + |
| 78 | +- **flake8:** max-line-length=120, select C,E,F,W,B,B950, ignore E203/E501/E704 (configured in `setup.cfg`) |
| 79 | +- **bandit:** security scanning configured in `pyproject.toml` |
| 80 | +- **pre-commit:** ruff, flake8, black, isort, bandit — all at line-length 120 |
| 81 | + |
| 82 | +## Code Style |
| 83 | + |
| 84 | +- **Docstrings:** Google-style on all new/modified functions. First line: one-sentence imperative summary ending with a period. Include Args, Returns, Raises sections with type info even if type hints exist. Document coroutine behavior where relevant. |
| 85 | +- **Interpreter:** Always use `~/.virtualenvs/lastversion/bin/python` — never bare `python` or `pytest`. |
| 86 | +- **PRs:** Must include docstrings for new/modified functions. Must update `.cursor/rules/` if adding new modules or architectural changes. |
| 87 | + |
| 88 | +## Python Compatibility |
| 89 | + |
| 90 | +Supports Python 3.6+. Conditional dependencies exist for `cachecontrol` and `urllib3` based on Python version (see `setup.py`). |
0 commit comments