A comprehensive, multi-platform release monitoring system that tracks software releases across different platforms and sends notifications when new versions are available. Built with Python and designed for reliability, extensibility, and ease of use.
# Clone the repository
git clone https://github.com/your-username/release-tracker.git
cd release-tracker
# Install dependencies
pip install -r requirements.txt
# Copy and configure the example config
cp config.example.yaml config.yaml
# Edit config.yaml with your settings
# Run the tracker
python main.py
${VAR}
placeholder expansionPlatform | Type | Authentication | Asset Support | Status |
---|---|---|---|---|
GitHub | Git Repository | Token (optional) | β | Stable |
GitLab | Git Repository | Token (optional) | β | Stable |
PyPI | Python Package | None | β | Stable |
APKMirror | Android APK | Token | β | Stable |
APKPure | Android APK | None | β | Stable |
F-Droid | Android APK | None | β | Stable |
# Clone the repository
git clone https://github.com/your-username/release-tracker.git
cd release-tracker
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
Create a .env
file for sensitive configuration:
# GitHub (optional, for higher rate limits)
GH_TOKEN=ghp_your_github_token
# GitLab (optional, for private repos)
GITLAB_TOKEN=glpat-your_gitlab_token
# Apprise notification URL
APPRISE_URL=discord://webhook_id/webhook_token
# Redis connection (if using external Redis)
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_DB=0
# AWS credentials (if loading config from S3)
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_REGION=us-east-1
The system uses YAML configuration files with support for environment variable expansion. Configuration can be loaded from:
config.yaml
(default)https://example.com/config.yaml
s3://bucket-name/config.yaml
# Platform-specific watchers
watchers:
github:
type: github
config:
token: "${GH_TOKEN}" # Optional, for higher rate limits
pypi:
type: pypi
config: {} # No authentication needed
# Repositories to monitor
repos:
- name: "Example GitHub Repo"
repo: "owner/repository"
watcher: github
config:
upload_assets: true
- name: "Python Package"
repo: "package-name"
watcher: pypi
config:
upload_assets: false
# State persistence
persistence:
type: redis
config:
host: "${REDIS_HOST:-redis}"
port: ${REDIS_PORT:-6379}
db: ${REDIS_DB:-0}
# Notification configuration
notifiers:
- type: apprise
config:
url: "${APPRISE_URL}"
format: "markdown" # or "text", "html"
# Global settings
upload_assets: false # Default for all repos
# docker-compose.yml
version: '3.8'
services:
release-tracker:
build: .
environment:
- CONFIG_SOURCE=config.yaml
- GH_TOKEN=${GH_TOKEN}
- APPRISE_URL=${APPRISE_URL}
volumes:
- ./config.yaml:/app/config.yaml
- ./downloads:/app/downloads
depends_on:
- redis
restart: unless-stopped
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis_data:/data
volumes:
redis_data:
Run with:
docker-compose up -d
# Build the image
docker build -t release-tracker .
# Run with Redis
docker run -d --name redis redis:7-alpine
docker run -d --name release-tracker \
--link redis:redis \
-v $(pwd)/config.yaml:/app/config.yaml \
-v $(pwd)/downloads:/app/downloads \
-e GH_TOKEN="$GH_TOKEN" \
-e APPRISE_URL="$APPRISE_URL" \
release-tracker
The Release Tracker supports both full checking mode and single repository mode via command-line interface.
python main.py
# Check a GitHub repository (explicit watcher)
python main.py -r microsoft/vscode -w github
# Check a repository configured in config.yaml (automatic watcher detection)
python main.py -r microsoft/vscode
# Check a PyPI package
python main.py -r django -w pypi
-r, --repo
: Repository identifier (format varies by platform)-w, --watcher
: Platform type (optional if repo is in config.yaml)--help
: Show help messageNote:
--watcher
is not provided, the tool looks for the repository in your config.yaml
file to determine the watcher typeconfig.yaml
fileFor detailed CLI documentation, see docs/CLI_USAGE.md.
Watchers are platform-specific components that fetch release information. Each watcher implements the same interface but handles different APIs and data formats.
Monitors GitHub repository releases using the GitHub REST API.
watchers:
github:
type: github
config:
token: "${GH_TOKEN}" # Optional, increases rate limits
base_url: "https://api.github.com" # Optional, for GitHub Enterprise
repos:
- name: "Docker"
repo: "docker/docker" # Format: owner/repository
watcher: github
config:
upload_assets: true
Features:
Monitors GitLab repository releases using the GitLab API.
watchers:
gitlab:
type: gitlab
config:
token: "${GITLAB_TOKEN}" # Optional, for private repos
base_url: "https://gitlab.com/api/v4" # Configurable for self-hosted
repos:
- name: "GitLab CE"
repo: "gitlab-org/gitlab" # Format: namespace/project
watcher: gitlab
Features:
Monitors Python package releases on the Python Package Index.
watchers:
pypi:
type: pypi
config: {} # No authentication required
repos:
- name: "Requests Library"
repo: "requests" # Just the package name
watcher: pypi
config:
upload_assets: true # Downloads .whl and .tar.gz files
Features:
Monitors Android app releases on APKMirror.
watchers:
apkmirror:
type: apkmirror
config:
auth_token: "${APKMIRROR_TOKEN}"
user_agent: "release-tracker"
api_url: "https://www.apkmirror.com/wp-json/apkm/v1/app_exists/"
repos:
- name: "WhatsApp"
repo: "com.whatsapp" # Android package name
watcher: apkmirror
Features:
Monitors Android app releases on APKPure using web scraping.
watchers:
apkpure:
type: apkpure
config:
user_agent: "Mozilla/5.0 (compatible; release-tracker)"
repos:
- name: "Telegram"
repo: "org.telegram.messenger" # Package identifier
watcher: apkpure
Features:
Monitors open-source Android app releases on F-Droid.
watchers:
fdroid:
type: fdroid
config:
base_url: "https://f-droid.org/en/packages/"
repo_url: "https://f-droid.org/repo/"
user_agent: "release-tracker"
repos:
- name: "Signal"
repo: "org.thoughtcrime.securesms" # F-Droid package ID
watcher: fdroid
Features:
Persistence backends store the last seen release version to prevent duplicate notifications.
persistence:
type: redis
config:
host: "localhost"
port: 6379
db: 0
password: "${REDIS_PASSWORD}" # Optional
Features:
persistence:
type: file
config:
path: "./releases.json"
Features:
The system uses Apprise for notifications, supporting 80+ services.
notifiers:
- type: apprise
config:
url: "${APPRISE_URL}"
format: "markdown" # Options: text, markdown, html
Popular notification services include:
discord://webhook_id/webhook_token
slack://token_a/token_b/token_c
tgram://bot_token/chat_id
mailto://user:[email protected]
pover://user@token
msteams://token_a/token_b/token_c
See the Apprise documentation for the complete list.
# Global asset download setting
upload_assets: false
# Force notifications (ignore duplicate checking)
# Controlled by FORCE_NOTIFY environment variable
repos:
- name: "Display Name" # Human-readable name
repo: "identifier" # Platform-specific identifier
watcher: "watcher_name" # Which watcher to use
config:
upload_assets: true # Override global setting
# Watcher-specific options can go here
Each watcher type has its own configuration schema:
watchers:
watcher_name:
type: "watcher_type"
config:
# Watcher-specific configuration
# See individual watcher documentation
The Release Tracker supports multiple environment variables for configuration and authentication. Hereβs a quick reference:
Variable | Description | Default |
---|---|---|
CONFIG_SOURCE |
Configuration file location | config.yaml |
FORCE_NOTIFY |
Force notifications even for seen releases | Not set |
GH_TOKEN |
GitHub personal access token | Not set |
GITLAB_TOKEN |
GitLab personal access token | Not set |
DOCKER_TOKEN |
Docker Hub authentication token | Not set |
APKMIRROR_TOKEN |
APKMirror API authentication token | Not set |
APPRISE_URL |
Apprise notification URL | Not set |
REDIS_HOST |
Redis server hostname | localhost |
REDIS_PORT |
Redis server port | 6379 |
REDIS_DB |
Redis database number | 0 |
REDIS_PASSWORD |
Redis authentication password | Not set |
AWS_ACCESS_KEY_ID |
AWS access key for S3 config | Not set |
AWS_SECRET_ACCESS_KEY |
AWS secret key for S3 config | Not set |
AWS_REGION |
AWS region for S3 config | Not set |
S3_ENDPOINT_URL |
Custom S3 endpoint (CloudFlare R2, MinIO) | Not set |
For detailed information, usage examples, and best practices, see Environment Variables Documentation.
watchers:
pypi:
type: pypi
config: {}
repos:
- {name: "Django", repo: "django", watcher: pypi}
- {name: "Flask", repo: "flask", watcher: pypi}
- {name: "Requests", repo: "requests", watcher: pypi}
- {name: "FastAPI", repo: "fastapi", watcher: pypi}
persistence:
type: redis
config: {host: redis, port: 6379, db: 0}
notifiers:
- type: apprise
config: {url: "${DISCORD_WEBHOOK}"}
format: markdown
watchers:
github:
type: github
config: {token: "${GH_TOKEN}"}
repos:
- {name: "Docker", repo: "docker/docker", watcher: github, config: {upload_assets: true}}
- {name: "Kubernetes", repo: "kubernetes/kubernetes", watcher: github}
- {name: "Terraform", repo: "hashicorp/terraform", watcher: github, config: {upload_assets: true}}
- {name: "VS Code", repo: "microsoft/vscode", watcher: github}
watchers:
fdroid:
type: fdroid
config: {}
apkpure:
type: apkpure
config: {}
repos:
- {name: "Signal", repo: "org.thoughtcrime.securesms", watcher: fdroid}
- {name: "Telegram", repo: "org.telegram.messenger", watcher: apkpure}
- {name: "Firefox", repo: "org.mozilla.firefox", watcher: fdroid}
For detailed information about specific topics, see the following documentation files:
watcher/your_platform.py
:from watcher.base import ReleaseAsset, ReleaseInfo, Watcher
class YourPlatformWatcher(Watcher):
def __init__(self, config=None):
# Initialize with platform-specific config
pass
def fetch_latest_release(self, repo_id: str) -> ReleaseInfo:
# Implement platform-specific logic
# Return ReleaseInfo with tag and assets
pass
utils.py
:from watcher.your_platform import YourPlatformWatcher
def build_watcher(watcher_type: str, config: dict[str, Any]) -> Watcher:
# ... existing watchers ...
if watcher_type == "your_platform":
return YourPlatformWatcher(config)
persistence/your_backend.py
:from persistence.base import PersistenceBackend
class YourBackend(PersistenceBackend):
def get_last_release(self, key: str) -> str | None:
# Implement retrieval logic
pass
def set_last_release(self, key: str, release: str) -> None:
# Implement storage logic
pass
utils.py
:def get_backend(config: dict[str, Any]) -> PersistenceBackend:
if config["type"] == "your_backend":
return YourBackend(**config["config"])
notifier/your_notifier.py
:from notifier.base import Notifier
class YourNotifier(Notifier):
def send(self, title: str, body: str, attachments: list = None) -> bool:
# Implement notification logic
# Return True on success, False on failure
pass
utils.py
:def get_notifier(config: dict[str, Any]) -> Notifier:
if config["type"] == "your_notifier":
return YourNotifier(config["config"])
Configuration not found:
# Check config file location
export CONFIG_SOURCE=/path/to/config.yaml
# Or use HTTP URL
export CONFIG_SOURCE=https://example.com/config.yaml
Redis connection failed:
# Check Redis status
redis-cli ping
# Verify connection settings in config
GitHub rate limiting:
# Add GitHub token to increase limits
export GH_TOKEN=ghp_your_token_here
Assets not downloading:
upload_assets: true
in repo configRun with verbose output:
python main.py --verbose
Force notifications (ignore seen releases):
FORCE_NOTIFY=1 python main.py
The application outputs detailed logs including:
git checkout -b feature/amazing-feature
ruff check . && ruff format .
git commit -m 'Add amazing feature'
git push origin feature/amazing-feature
# Install development dependencies
pip install -r requirements.txt
pip install ruff mypy pre-commit
# Set up pre-commit hooks
pre-commit install
# Run tests
python -m pytest
# Run linting
ruff check .
ruff format .
This project is licensed under the MIT License - see the LICENSE file for details.
Made with β€οΈ for developers who want to stay updated on their favorite software releases.