# weekly-activity Aggregate weekly activity across development platforms (Launchpad, GitHub, GitLab, Debian BTS) into a single text report. ## Usage ```bash # Launchpad (uses system keyring for OAuth; --anonymous for public data only) uv run weekly-activity launchpad uv run weekly-activity launchpad --anonymous # GitHub (uses GITHUB_TOKEN env var or `gh auth token`; anonymous works but rate-limited) uv run weekly-activity github uv run weekly-activity github --token ghp_xxx # 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 uv run weekly-activity gitlab --url https://salsa.debian.org uv run weekly-activity gitlab --url https://salsa.debian.org --token glpat-xxx # Debian BTS (bugs.debian.org; identify by the email used on bugs) uv run weekly-activity bts # Custom date range (ISO dates, UTC) uv run weekly-activity launchpad --since 2025-08-01 --until 2025-08-15 uv run weekly-activity github --since 2025-08-01 --until 2025-08-15 uv run weekly-activity gitlab --since 2025-08-01 --until 2025-08-15 uv run weekly-activity bts --since 2025-08-01 --until 2025-08-15 ``` ### GitLab instances Any GitLab instance works via `--url`. Token discovery order: 1. `--token` flag 2. env var named by `--token-env` 3. `_TOKEN` derived from the instance host (e.g. `SALSA_TOKEN` for `salsa.debian.org`) 4. `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 ```bash uv sync # install deps + dev tooling uv run ruff format src # format uv run ruff check src # lint uv run ty check # type check ``` ## 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)