# GitHub Release Monitor A CLI tool that tracks GitHub releases or tags from user-defined repositories and exposes them as a subscribable RSS feed. Some repositories (e.g., Zammad) only use git tags without creating GitHub releases — both modes are supported. ## Features - Track **releases** or **tags** per repository - SQLite storage with automatic deduplication - RSS 2.0 feed with markdown-stripped release notes - Built-in HTTP server for local feed access - Rate-limit-aware GitHub API client - Configurable via environment variables and CLI flags - Daemon mode for automatic background checks ## Installation ```bash pip install . ``` Or install in development mode: ```bash pip install -e . ``` ## Quick Start ```bash # Set your GitHub token (optional, increases rate limit from 60/h to 5000/h) export GH_TOKEN=your_token # Add repositories to track ghrel add golang/go # Track releases (default) ghrel add zammad/zammad --tags # Track tags # Fetch latest releases/tags ghrel check # List tracked repositories ghrel list # Start the RSS feed server ghrel serve ``` The RSS feed is available at `http://127.0.0.1:8080/feed.xml`. ## CLI Commands ``` ghrel # Main command ├── --version # Show version ├── --verbose / -v # Enable verbose/debug output ├── --quiet / -q # Suppress non-essential output ├── --db-path # Override database path ├── add [--tags] # Add a repository to track ├── remove # Remove a repository ├── update [--tags] [--release] # Update tracking mode ├── list # List all tracked repositories ├── check [--since N] # Fetch latest releases/tags ├── daemon [--interval 30m] # Run as background daemon └── serve [--port 8080] [--host 127.0.0.1] # Start HTTP server ``` ### `add [--tags]` Add a repository to track. Validates the format and pings the GitHub API to verify the repository exists. ```bash ghrel add golang/go # Track releases ghrel add zammad/zammad --tags # Track tags ``` ### `remove ` Remove a repository and its associated entries. ```bash ghrel remove golang/go ``` ### `update [--tags] [--release]` Update the tracking mode for an existing repository. ```bash ghrel update zammad/zammad --tags ghrel update zammad/zammad --release ``` ### `list` Display tracked repositories with entry counts and last check time. ``` REPO MODE ENTRIES LAST CHECKED golang/go release 12 2025-01-15 10:30 zammad/zammad tag 8 2025-01-15 10:30 ``` ### `check [--since N]` Fetch latest releases or tags for all tracked repositories. With `--since`, only fetch entries published in the last N hours (e.g., `--since 24h`). ```bash ghrel check # Fetch all new entries ghrel check --since 24h # Only entries from the last 24 hours ``` ### `serve [--port PORT] [--host HOST]` Start the HTTP server. ```bash ghrel serve # Default: 127.0.0.1:8080 ghrel serve --port 9090 --host 0.0.0.0 # Custom port and host ``` ### `daemon [--interval INTERVAL] [--pid-file PATH] [--since N]` Run as a background daemon that periodically checks all tracked repositories for new releases or tags. ```bash ghrel daemon # Default: 30m interval ghrel daemon --interval 1h # Check every hour ghrel daemon --interval 15m # Check every 15 minutes ghrel daemon --pid-file /run/ghrel.pid # Custom PID file ghrel daemon --since 24h # Only entries from last 24h ``` **Interval format**: `N` followed by `s` (seconds), `m` (minutes), `h` (hours), or `d` (days). The daemon writes a PID file for status checking and sends structured logs to stderr (suitable for systemd journal). It handles `SIGTERM` and `SIGINT` for graceful shutdown. #### Systemd Service Create `/etc/systemd/system/ghrel-daemon.service`: ```ini [Unit] Description=GitHub Release Monitor Daemon After=network.target [Service] Type=simple ExecStart=/usr/local/bin/ghrel daemon --interval 30m --pid-file /run/ghrel.pid Restart=on-failure RestartSec=10 Environment=GH_TOKEN=your_token_here [Install] WantedBy=multi-user.target ``` Enable and start: ```bash sudo systemctl daemon-reload sudo systemctl enable --now ghrel-daemon sudo systemctl status ghrel-daemon ``` View logs: ```bash journalctl -u ghrel-daemon -f ``` ``` ## Configuration | Setting | Default | Override | |---------------|----------------------------|-------------------| | `db_path` | `~/.config/ghrel/repos.db` | `--db-path` flag | | `gh_token` | `GH_TOKEN` env var | — | | `server_host` | `127.0.0.1` | `--host` flag | | `server_port` | `8080` | `--port` flag | ## RSS Feed The feed follows RSS 2.0 specification: - **Title**: `GitHub Release Monitor` - **Items**: Sorted by `published_at` (newest first), capped at 50 items - **Release entries**: Title from release name, description from markdown-stripped body (truncated at 300 characters) - **Tag entries**: Title from tag name, description as `Tag {tag_name}` ## Architecture ``` ┌──────────────────────────────────────────────────┐ │ CLI Interface │ │ (add, remove, update, list, check, serve) │ ├──────────────────────────────────────────────────┤ │ Core Logic │ │ ┌──────────────┐ ┌──────────────┐ ┌────────┐ │ │ │ config.py │ │ db.py │ │github.py│ │ │ │ (defaults, │ │ (sqlite3) │ │(httpx) │ │ │ │ env vars) │ │ │ │ │ │ │ └──────────────┘ └──────┬───────┘ └───┬────┘ │ │ │ │ │ │ ┌────────▼──────────────▼────┐ │ │ │ rss.py │ │ │ │ (xml.etree + markdown) │ │ │ └──────────────┬─────────────┘ │ │ │ │ │ ┌──────────────▼─────────────┐ │ │ │ server.py │ │ │ │ (http.server, stdlib) │ │ │ │ (/feed.xml endpoint) │ │ │ └─────────────────────────────┘ │ └──────────────────────────────────────────────────┘ ``` ## Testing ```bash pytest ``` ## Dependencies | Package | Purpose | |--------------|------------------------------------------| | `httpx` | HTTP client for GitHub API | | `markdown` | Convert markdown to HTML | | `bleach` | Strip HTML tags for plain text | | `pytest` | Testing framework | | `respx` | Mocking HTTP requests for tests | No heavy frameworks. `http.server` and `xml.etree.ElementTree` are stdlib.