Repository URL: https://feelpp.github.io/apt/
Public key: feelpp.gpg
This repository contains the feelpp-aptly-publisher tool for publishing Debian packages to the Feel++ APT repository using aptly and GitHub Pages, with full support for multi-component publications.
- Repository Structure
- Client Setup
- Publishing Packages
- Repository Cleanup
- Installation
- Development
- Testing
The APT repository is organized as follows:
-
Channels (prefixes):
stable/,testing/,pr/stable: Production-ready packagestesting: Pre-release packages for testingpr: Pull request builds for CI/CD
-
Distributions:
noble,jammy,focal,bookworm,bullseye, etc.- Ubuntu codenames (noble = 24.04, jammy = 22.04, etc.)
- Debian codenames (bookworm = 12, bullseye = 11, etc.)
-
Components (projects): Independent project namespaces
- Examples:
feelpp-project,mmg,parmmg,ktirio-urban-building,organ-on-chip - Each component can have multiple packages
- Components are isolated - updates to one don't affect others
- Examples:
Add the Feel++ APT repository to your system:
# Download and install the GPG key
curl -fsSL https://feelpp.github.io/apt/feelpp.gpg \
| sudo tee /usr/share/keyrings/feelpp.gpg >/dev/null
# Add the repository (example: stable channel, noble distribution, multiple components)
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/feelpp.gpg] \
https://feelpp.github.io/apt/stable noble mmg parmmg" \
| sudo tee /etc/apt/sources.list.d/feelpp-mmg.list
# Update package lists
sudo apt update
# Install packages
sudo apt install mmg libmmg5 libmmg-dev parmmg libparmmg5 libparmmg-devNote: Specify the components you need in the sources.list line. Available components can be found in the Release file.
- Install the publisher tool:
pip install feelpp-aptly-publisher
# or for development:
pip install -e .- Build your Debian packages:
# Your package building process, e.g.:
dpkg-buildpackage -us -uc -b- Publish to the repository:
feelpp-apt-publish \
--component my-project \
--channel stable \
--distro noble \
--debs /path/to/directory/with/debsThat's it! Your packages are now available at:
https://feelpp.github.io/apt/stable/dists/noble/my-project/
Stable (production releases):
feelpp-apt-publish --component mmg --channel stable --distro noble --debs ./debs/Testing (pre-release testing):
feelpp-apt-publish --component mmg --channel testing --distro noble --debs ./debs/PR (continuous integration):
feelpp-apt-publish --component mmg --channel pr --distro noble --debs ./debs/The publisher automatically preserves existing components when adding or updating a component. You don't need to do anything special!
Example scenario:
- Initial state: Repository has
component-aandcomponent-b - You publish
component-c:feelpp-apt-publish --component component-c --channel stable --distro noble --debs ./debs/
- Result: Repository now has
component-a,component-b, andcomponent-c
Updating an existing component:
# This will update component-a while preserving component-b and component-c
feelpp-apt-publish --component component-a --channel stable --distro noble --debs ./new-debs/How it works:
- The publisher reads the current Release file to detect existing components
- It creates temporary repositories for existing components from the pool
- It publishes all components together using aptly's multi-component support
- Both Release and InRelease files are updated consistently
feelpp-apt-publish --helpRequired options:
--component NAME: Component (project) name (will be normalized:My_Project→my-project)--distro NAME: Distribution codename (e.g.,noble,jammy,bookworm)
Optional options:
--channel NAME: Publication channel (default:stable, options:stable,testing,pr)--debs PATH: Directory containing .deb files (default: current directory)--pages-repo URL: GitHub Pages repository (default:https://github.com/feelpp/apt.git)--branch NAME: Git branch name (default:gh-pages)--sign: Enable GPG signing (default: disabled)--keyid ID: GPG key ID (required if --sign is used)--verbose: Enable verbose logging
Examples:
# Minimal example (uses defaults: stable channel, skip signing)
feelpp-apt-publish --component mmg --distro noble --debs ./debs/
# Full example with all options
feelpp-apt-publish \
--component my-project \
--distro noble \
--channel testing \
--debs /tmp/my-debs \
--verbose
# With GPG signing
feelpp-apt-publish \
--component mmg \
--distro noble \
--sign \
--keyid ABCD1234 \
--debs ./debs/The publisher includes tools for cleaning up old packages, particularly pre-release versions (alpha, beta, rc) that accumulate over time.
Analyze the repository to see what packages would be cleaned up:
# Analyze all channels
feelpp-apt-publish analyze --repo-path ./apt-repo
# Analyze specific channel
feelpp-apt-publish analyze --repo-path ./apt-repo --channels testing,pr
# Custom age limit (default: 90 days)
feelpp-apt-publish analyze --repo-path ./apt-repo --max-age-days 60
# Output as JSON for CI integration
feelpp-apt-publish analyze --repo-path ./apt-repo --json --output report.jsonActually delete old packages:
# Preview what would be deleted (default: dry-run mode)
feelpp-apt-publish cleanup --repo-path ./apt-repo
# Execute cleanup
feelpp-apt-publish cleanup --repo-path ./apt-repo --execute
# Cleanup with custom age limit
feelpp-apt-publish cleanup --repo-path ./apt-repo --execute --max-age-days 60
# Cleanup specific channels only
feelpp-apt-publish cleanup --repo-path ./apt-repo --execute --channels prConfigure how packages are retained using a policy file:
# Create a default policy configuration
feelpp-apt-publish init-policy --output retention-policy.json
# Use custom policy
feelpp-apt-publish cleanup --repo-path ./apt-repo --policy retention-policy.jsonDefault policy file: retention-policy.json
{
"prerelease_max_age_days": 90,
"max_versions_per_package": 0,
"channel_policies": {
"stable": {
"keep_prereleases": true,
"max_versions": 0
},
"testing": {
"keep_prereleases": false,
"max_versions": 5
},
"pr": {
"keep_prereleases": false,
"max_versions": 3,
"max_age_days": 30
}
},
"protected_components": [],
"protected_packages": []
}Policy Settings:
| Setting | Description | Default |
|---|---|---|
prerelease_max_age_days |
Max age for pre-release packages | 90 |
max_versions_per_package |
Keep N latest versions (0=unlimited) | 0 |
keep_prereleases |
Whether to keep pre-releases in channel | varies |
protected_components |
Components to never clean | [] |
protected_packages |
Package name patterns to never clean | [] |
The repository includes GitHub Actions workflows for automated cleanup:
Workflow: .github/workflows/cleanup-dry-run.yml
Runs weekly (Sunday 3 AM UTC) to analyze what could be cleaned:
# Manual trigger with custom settings
gh workflow run "Cleanup Analysis (Dry Run)" \
-f max-age-days=60 \
-f channel=testing \
-f include-stable-prereleases=falseWorkflow: .github/workflows/cleanup.yml
Runs monthly (1st of month, 4 AM UTC) to clean old pre-releases:
# Manual trigger
gh workflow run "Cleanup Old Packages" \
-f max-age-days=90 \
-f channel=all \
-f dry-run=false
# Preview mode (dry run)
gh workflow run "Cleanup Old Packages" \
-f dry-run=trueWorkflow: .github/workflows/cleanup-pr-channel.yml
Specifically cleans the PR channel (packages from closed PRs):
- Runs weekly (Monday 5 AM UTC)
- Removes packages older than 30 days
- Can be triggered when a PR is closed via
repository_dispatch
# Trigger cleanup for a specific closed PR
curl -X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
https://api.github.com/repos/feelpp/apt/dispatches \
-d '{"event_type":"pr-closed","client_payload":{"pr_number":"123"}}'Pre-release versions matching these patterns:
~alpha,~beta,~rc1,~pre,~dev~git,~svn,~bzr+git20231015,+svn1234alpha1,beta2,rc3
Version limits (when configured):
- Excess versions beyond
max_versionssetting - Oldest versions removed first (keeping newest)
Channel-specific defaults:
| Channel | Keep Pre-releases | Max Age | Max Versions |
|---|---|---|---|
| stable | Yes | - | unlimited |
| testing | No | 90 days | 5 |
| pr | No | 30 days | 3 |
pip install feelpp-aptly-publishergit clone https://github.com/feelpp/apt.git
cd apt
pip install -e .# Install with development dependencies
pip install -e ".[dev]"
# Or using the setup script
./setup-dev.sh# Run all tests
pytest
# Run only unit tests (fast)
pytest -m "not integration"
# Run integration tests (slower, tests actual publishing)
pytest -m integration
# Run with coverage
pytest --cov=feelpp_aptly_publisher --cov-report=html# Format code
black src/ tests/
# Lint
flake8 src/ tests/
# Type checking
mypy src/The repository includes comprehensive tests:
-
Unit tests (
tests/test_*.py): Fast tests for individual components- CLI argument parsing
- Component name normalization
- Publisher initialization
-
Integration tests (
tests/test_integration.py): Full workflow tests- Single component publishing
- Multi-component publishing (adding components)
- Updating existing components
- All three channels (stable, testing, pr)
- Channel independence
- Release/InRelease file consistency
Run the test suite:
# All tests
pytest -v
# Only integration tests
pytest -v -m integration
# Only unit tests (fast)
pytest -v -m "not integration"Problem: After publishing, packages install correctly but InRelease file doesn't list all components.
Solution: This was a bug in earlier versions. Update to feelpp-aptly-publisher >= 1.1.0 which fixes multi-component support.
Problem: Publishing a new component removes existing components from the repository.
Solution: Upgrade to version >= 1.1.0. The new version automatically detects and preserves all existing components.
Problem: Published package but apt update doesn't see it.
Checklist:
- Check that the component is listed in your sources.list
- Verify the component appears in the Release file:
curl -s https://feelpp.github.io/apt/stable/dists/noble/Release | grep Components - Check that packages exist:
curl -s https://feelpp.github.io/apt/stable/dists/noble/COMPONENT/binary-amd64/Packages
- Wait a few minutes for GitHub Pages to update (caching)
See CONTRIBUTING.md for development guidelines.
LGPL-3.0-or-later - see COPYING.LESSER
Feel++ Packaging Team contact@feelpp.org
Repository: https://github.com/feelpp/apt
Feel++ Project: https://www.feelpp.org