The runner's system CPython 3.12.3 satisfies the '3.12' request, so uv kept using it and PyInstaller failed: system python is built without libpython3.x.so. Set UV_PYTHON_PREFERENCE=only-managed and install the managed interpreter explicitly.
weekly-activity
Aggregate weekly activity across development platforms (Launchpad, GitHub, GitLab, Debian BTS) into a single text report.
Usage
# Launchpad (uses system keyring for OAuth; --anonymous for public data only)
uv run weekly-activity launchpad <username>
uv run weekly-activity launchpad --anonymous <username>
# GitHub (uses GITHUB_TOKEN env var or `gh auth token`; anonymous works but rate-limited)
uv run weekly-activity github <username>
uv run weekly-activity github --token ghp_xxx <username>
# GitLab (gitlab.com by default; any self-hosted instance via --url, e.g. Debian Salsa;
# uses GITLAB_TOKEN / SALSA_TOKEN env vars, anonymous works but rate-limited)
uv run weekly-activity gitlab <username>
uv run weekly-activity gitlab --url https://salsa.debian.org <username>
uv run weekly-activity gitlab --url https://salsa.debian.org --token glpat-xxx <username>
# Debian BTS (bugs.debian.org; identify by the email used on bugs)
uv run weekly-activity bts <email>
# Custom date range (ISO dates, UTC)
uv run weekly-activity launchpad --since 2025-08-01 --until 2025-08-15 <username>
uv run weekly-activity github --since 2025-08-01 --until 2025-08-15 <username>
uv run weekly-activity gitlab --since 2025-08-01 --until 2025-08-15 <username>
uv run weekly-activity bts --since 2025-08-01 --until 2025-08-15 <email>
GitLab instances
Any GitLab instance works via --url. Token discovery order:
--tokenflag- env var named by
--token-env <HOST>_TOKENderived from the instance host (e.g.SALSA_TOKENforsalsa.debian.org)GITLAB_TOKEN
What it reports
| Section | Launchpad | GitHub | GitLab | Debian BTS |
|---|---|---|---|---|
| Merge proposals / PRs authored | getMergeProposals (created in range) |
/search/issues (author: + type:pr) |
/merge_requests (author_id, created range) |
— |
| Review requests received | getRequestedReviews (filtered by date_review_requested) |
/search/issues (reviewed-by: + type:pr) |
— | — |
| Reviews performed | getRequestedReviews (filtered by date_reviewed) |
(same query) | events (action=approved) |
— |
| Issues / Bugs | searchTasks (reporter, commenter, assignee) |
/search/issues (author, commenter, assignee) |
/issues (author_id, assignee_id) |
get_bugs (submitter) + get_status (created in range) |
| Bugs owned, updated | — | — | — | get_bugs (owner) + get_status (log_modified) |
| Repositories modified | git_repositories.getRepositories (modified_since_date) |
/users/{user}/repos (filtered by pushed_at) |
— (covered by push events) | — |
| Commits pushed | — (not in Launchpad REST API) | /repos/{owner}/{repo}/commits (per active repo) |
events (action=pushed) |
— |
Default time window
Rolling 7 days ending today (inclusive). Override with --since / --until (ISO dates, UTC).
Architecture
src/weekly_activity/
model.py ActivityReport, Section, last_week_window
report.py format_report() — source-agnostic text renderer
cli.py subcommand dispatch (launchpad | github | gitlab | bts)
sources/
__init__.py ActivitySource protocol
launchpad.py LaunchpadSource (launchpadlib)
github.py GitHubSource (httpx)
gitlab.py GitLabSource (httpx, REST v4 — gitlab.com or self-hosted)
debian_bts.py DebianBtsSource (python-debianbts SOAP)
Each source implements ActivitySource — a name and a collect(username, since, until) -> ActivityReport method. Sources keep their own dataclasses internally; the shared contract is Section (title + pre-formatted lines) and ActivityReport (metadata + sections + warnings). The report formatter (report.py) is source-agnostic.
Per-query failures (rate limits, server timeouts) are caught per-section — a failing endpoint records a warning and degrades to an empty section rather than killing the whole report.
Development
uv sync # install deps + dev tooling
uv run ruff format src # format
uv run ruff check src # lint
uv run ty check # type check
CI / releases
Gitea Actions (.gitea/workflows/ci.yml) runs two jobs:
- check — format, lint, and type check on every push to
main - release — on
v*tags: builds a standalone Linux executable with PyInstaller, smoke-tests it, creates a Gitea release, and uploads the binary as an asset
Cut a release with:
git tag vX.Y.Z && git push origin vX.Y.Z
Dependencies
- launchpadlib — Launchpad REST API client
- httpx — GitHub & GitLab REST API client
- python-debianbts — Debian BTS SOAP client
- ruff — format + lint (dev)
- ty — type check (dev)