# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Planned
- Production GitHub Actions workflows for package deployment (Phase 7)
- REST API server (optional, low priority)
- Removal of deprecated bash scripts (scheduled for v0.6.0)


## [0.5.0] - 2025-11-17

### Added
- **Enhanced `list` command**:
	- Repository grouping by codename with tree-like display
	- Component display under each codename (without codename suffix)
	- `--stats` flag to show package count and repository size
	- Better visual representation with emoji (📦)
	- More informative output for repository overview
- **New `AptlyManager` method**:
	- `get_repo_stats()` - retrieves package count and disk space usage
	- Calculates size by scanning `.deb` files in `public/pool` directory

### Changed
- Refactored `list_repos` function for reduced complexity:
	- Extracted `_list_packages_in_component()` helper function
	- Extracted `_display_repositories_grouped()` helper function
	- Improved code maintainability and readability
- Updated integration tests to match new list command output format

### Tests
- Added 8 new unit tests for `get_repo_stats()` method
- Added 5 new unit tests for enhanced `list` command
- Updated integration tests for new output format
- Total test count: 354 tests passing
- Coverage maintained: ~79%

### Fixed
- Integration tests updated to work with new grouped list output
- Code quality issues: E501 (line length), C901 (complexity)


## [0.4.0] - 2025-11-14

### Added
- **Release management commands**:
	- `debrepomanager release add <codename>` - Add new distribution release
	- `debrepomanager release remove <codename>` - Remove old distribution release
	- Auto-creation of components (jethome-tools, jethome-{codename}, jethome-armbian)
	- Activity check before removal (nginx logs)
	- Backup support with configurable directory
	- Dual format symlinks integration
- **Environment isolation**:
	- `--environment stable|beta|test` option for package addition
	- Auto-component generation from package directory basename
	- Support for publish_prefix (stable='', beta='beta', test='test')
	- Parallel stable/beta/test repository operation
- **Documentation**:
	- `QUICK_START.md` - 5-minute getting started guide
	- `docs/CHEATSHEET.md` - Command reference
	- `docs/WORKFLOWS.md` - Common usage scenarios
	- `docs/MIGRATION.md` - Migration guide from bash scripts

### Changed
- Bash scripts (repoadd, add-release, remove-release) moved to `scripts/legacy/`
- Bash scripts now emit deprecation warnings
- Bash scripts are thin wrappers calling Python CLI
- Updated README with new commands and features

### Tests
- Added 273+ new unit tests for release management
- Added integration tests with real aptly operations
- Added real APT installation tests in Docker containers
- Total test count: 341 tests passing
- Coverage: 79.53%

### Deprecated
- `scripts/repoadd` - Use `debrepomanager add --environment` instead
- `scripts/add-release.sh` - Use `debrepomanager release add` instead
- `scripts/remove-release.sh` - Use `debrepomanager release remove` instead
- All deprecated scripts will be removed in v0.5.0

### Fixed
- Improved error handling in release operations
- Better validation of codenames and components

## [0.3.7] - 2025-11-13

### Added
- **fix-symlinks CLI command**: Check and fix dual format symlinks
  - `debrepomanager fix-symlinks` - scan and fix all symlinks
  - `--check-only` mode for verification without changes
  - `--codename` and `--component` filters
  - Detailed status reporting with emojis
  - 11 comprehensive unit tests
- **Release lifecycle management scripts**:
  - `add-release.sh` - Add new distribution releases (Debian Trixie, Ubuntu Oracular)
  - `remove-release.sh` - Remove EOL releases with backup support
  - `update-nginx-codenames.sh` - Auto-update nginx config with available codenames
  - Activity monitoring before removal
  - Automatic backup creation
  - Safe with confirmations
- **Scripts distribution via pip**:
  - All scripts install to `/usr/local/share/debrepomanager/scripts/`
  - Docs install to `/usr/local/share/debrepomanager/docs/`
  - Examples install to `/usr/local/share/debrepomanager/examples/`
  - MANIFEST.in for proper package distribution
- **Old format APT support via nginx**:
  - Nginx rewrite rules for legacy URL format
  - Both formats work simultaneously
  - Example configs in `examples/nginx-repo.conf`
  - Dynamic codenames list in `examples/repo-codenames.conf`
- **Documentation**:
  - `RELEASE_LIFECYCLE.md` - Complete release management guide
  - `NGINX_OLD_FORMAT.md` - Nginx configuration for old format support
  - Updated DUAL_FORMAT.md with nginx recommendations
  - Updated NGINX_MULTI_ENV.md with rewrite rules

### Changed
- **delete-repo command**: Added `--yes` as alias for `--confirm`
- **Dual format symlinks**: Simplified to work with nginx rewrite
- **aptly.py**: Corrected publish paths for empty publish_prefix

### Fixed
- **Dual format symlink paths**: Now correctly points to `/{codename}/dists/{component}/`
- **fix-symlinks scanning**: Properly detects published repositories

### Technical
- Total tests: 315 unit + 16 integration scenarios
- Coverage: 80.91%
- Integration tests for release lifecycle (11 scenarios)
- Old format APT tested end-to-end
- All tests passing in CI/CD

### Architecture Notes
- Old format APT (`deb http://site codename component`) requires nginx rewrite
- Symlinks alone insufficient due to "main" component and isolated pools
- Solution: nginx rewrite + dynamic codenames configuration
- Fully automated via add/remove-release scripts

## [0.3.6] - 2025-11-13

### Added
- **Environment isolation with --publish-prefix**
  - New CLI option: `--publish-prefix <prefix>` for beta/test environments
  - ENV variable: `REPOMANAGER_PUBLISH_PREFIX`
  - Single config for all environments (as designed!)
  - stable: publishes to `/opt/repo/public/trixie/`
  - beta: publishes to `/opt/repo/public/beta/trixie/`
  - test: publishes to `/opt/repo/public/test/trixie/`

### Changed
- **repoadd script now supports environment isolation**
  - `./repoadd stable ...` - no prefix
  - `./repoadd beta ...` - automatically adds `--publish-prefix beta`
  - `./repoadd test ...` - automatically adds `--publish-prefix test`
  - Reverted wrong config-{env}.yaml selection from PR #41

### Fixed
- **Dual format symlinks paths corrected**
  - Fixed new_path to include component directory
  - aptly creates: `/{prefix}/{component}/dists/{component}/`
  - Symlinks now point to correct location
- **Real APT tests use stable environment**
  - Tests now pass with correct URL format

### Technical
- config.py: Added `publish_prefix` property
- aptly.py: Use publish_prefix in publish/delete/symlinks
- cli.py: Added `--publish-prefix` global option
- scripts/repoadd: Auto-select prefix based on environment
- All tests passing: 304 passed, 80.50% coverage

## [0.3.5] - 2025-11-13

### Changed
- **CI/CD Architecture refactored to unified workflow**
  - Merged `tests.yml` and `publish-pypi.yml` into `tests-and-release.yml`
  - PyPI publication now REQUIRES all tests to pass
  - Eliminated critical gap: previously PyPI published without checking tests

### Fixed
- **CRITICAL**: PyPI publication without test validation
  - Old: `publish-pypi.yml` ran on release WITHOUT waiting for tests
  - New: `publish-pypi` job has `needs: [test, lint, security, integration, real-apt-tests, build]`
  - Impossible to publish broken code to PyPI

### Technical
- Unified workflow with conditional jobs
- `if: github.event_name == 'release'` for PyPI job
- All tests run on push/PR/release/workflow_dispatch
- PyPI only on release AND only if all tests passed
- No code duplication between workflows

## [0.3.4] - 2025-11-13

### Changed
- **Cursor rules refactored to v0.3.3**
  - Updated all version references from v0.2.0 to v0.3.3
  - Added new modules documentation (gpg_rotation.py, retention.py)
  - Updated test counts (263 → 304) and coverage (92.98% → 80.62%)

### Fixed
- **local-aptly.mdc**: Updated publish examples with correct FileSystemPublishEndpoints syntax
  - Fixed prefix format (codename only, not codename/component)
  - Added filesystem:public: endpoint documentation
  - Removed outdated publish patterns

### Added
- **local-testing.mdc**: Real APT E2E testing strategy documentation
  - 4 comprehensive test scenarios documented
  - nginx + apt-get validation patterns
  - Test matrix (2 codenames × 3 components = 6 repos)
- **CI/CD**: Real APT Tests job added to tests.yml workflow

### Technical
- Total cursor rules: 8 local + 10 shared = 18 files
- All rules validated against current codebase
- Globs tested against tracked files
- No outdated examples remaining

## [0.3.3] - 2025-11-11

### Note
- This release contains the same fixes as v0.3.2
- v0.3.2 was published to PyPI with incorrect code (before PR #33 merge)
- v0.3.3 is the correct release with all fixes from PR #33
- **Use v0.3.3, not v0.3.2!**

### Fixed
- Same as v0.3.2 (see below)

### Added
- Same as v0.3.2 (see below)

## [0.3.2] - 2025-11-11

### Fixed
- **CRITICAL: FileSystemPublishEndpoints now works correctly**
  - PR #31 added FileSystemPublishEndpoints but it didn't work - files still published to wrong location
  - Fixed endpoint syntax: use named endpoint `filesystem:public:` instead of empty endpoint
  - Fixed prefix: use only `codename` instead of `codename/component`
  - Fixed delete_repo: updated to use same endpoint format
  - Files now correctly published to `/opt/repo/public/{codename}/` ✅
  - Previously published to `/opt/repo/{codename}/public/` ❌

### Added
- **Real APT integration tests with nginx**
  - Full end-to-end test that validates entire workflow
  - Scenario 1: Install package v1.0.0 via `apt-get install`
  - Scenario 2: Upgrade package to v2.0.0 via `apt-get upgrade`
  - Scenario 3: Multi-codename isolation (bookworm vs noble)
  - Scenario 4: Multi-component isolation (jethome-tools, jethome-bookworm, jethome-desktop)
  - Tests validate: 2 codenames × 3 components = 6 independent repositories
  - Proves multi-root architecture works as designed
  - New command: `make test-real-apt`

### Technical
- `aptly.py`: Updated `_create_aptly_config()` to use named endpoint "public"
- `aptly.py`: Updated `_publish_snapshot()` to use `filesystem:public:{codename}` prefix
- `aptly.py`: Updated `delete_repo()` to use same endpoint format
- `tests/integration/test_real_apt.sh`: Comprehensive integration test (277 lines)
- `tests/integration/Dockerfile.realtest`: Docker environment with nginx
- Total tests: 304 passed
- Coverage: 80.62%
- Integration tests: 4 scenarios, all passed

## [0.3.1] - 2025-11-11

### Fixed
- **Config path consistency**: Corrected all paths to use `debrepomanager` (not `repomanager`)
  - System config: `/etc/debrepomanager/config.yaml` (was `/etc/repomanager/`)
  - User config: `~/.debrepomanager/config.yaml` (was `~/.repomanager/`)
  - Local config: `./config.yaml` (was `./repomanager.yaml` - simpler!)
- **repoadd script**: Now uses auto-detection (finds `./config.yaml` in current directory)
  - Removed hardcoded `/etc/repomanager/config.yaml` default
  - Uses debrepomanager auto-detection by default
  - Set `REPOMANAGER_CONFIG` env var to override
- **Documentation**: Updated all config path references in docs
- **Tests**: Updated test_config_v02.py for new paths

### Technical
- Consistent naming throughout: `debrepomanager` everywhere
- Local config now just `config.yaml` (easier to use)
- Total tests: 304 passed
- Coverage: 80.61%

## [0.3.0] - 2025-11-11

### Fixed
- **Retention Policy max_age_days now works!**: Upload date tracking implemented
  - Uses file modification time from aptly pool directory
  - Works for ALL packages (new and existing)
  - No additional metadata tracking needed
  - Acceptable performance for monthly cleanup operations
  - Fallback to datetime.now() if file not found

### Technical
- `retention._get_package_upload_date()` reads mtime from pool files
- Simple implementation using existing data
- No sync issues with metadata
- Total tests: 304
- Coverage: 80.76%

## [0.2.1] - 2025-11-11

### Added
- **GPG Key Rotation (Phase 9)**: Zero-downtime GPG key rotation
  - `debrepomanager rotate-gpg-key` command for safe key rotation
  - Automatic rollback on publish failure (prevents data loss)
  - Grace period support (manual process, both keys valid)
  - Rollback capability with `--rollback --old-key-id`
  - Verification mode with `--verify-only`
  - Client migration script: `scripts/migrate-gpg-key.sh`
  - Auto-detects system (Debian/Ubuntu/RedHat)
  - Comprehensive documentation in `docs/GPG_ROTATION.md`
  - 16 tests with 88% coverage for gpg_rotation.py

### Security
- **Critical safety features in GPG rotation**:
  - Automatic rollback if new key publish fails
  - Repository stays published except disaster scenario
  - CRITICAL error alerts if both publish attempts fail
  - Pre-validation of new key before rotation starts
  - Proper exception chaining for troubleshooting

### Technical
- Total tests: 304 (+16 GPG rotation tests)
- Coverage: 81.43%
- New module: `debrepomanager/gpg_rotation.py` (116 lines, 88% coverage)

## [0.2.0] - 2025-11-11

### Added
- **Retention Policy Engine**: Automatic cleanup of old package versions
  - `debrepomanager cleanup` command for package retention management
  - Configurable policies: `min_versions`, `max_age_days`, `keep_latest`, `delete_last_aged_version`
  - Per-component policy overrides
  - Safety features: `keep_latest` protects newest versions, `delete_last_aged_version` prevents complete removal
  - Dry-run mode by default (use `--apply` to actually remove packages)
  - Debian version comparison using `python-debian`
  - Comprehensive test suite (26 tests covering all scenarios)
  - Batch removal support to handle large package sets efficiently
  - ⚠️  Limitation: max_age_days not functional (upload_date tracking TODO for v0.3)
- **repoadd script**: Simplified upload script for stable/beta/test environments
  - Automatic repository creation if not exists
  - Component name auto-detection from directory name
  - **Optional explicit component parameter** - 4th argument to override auto-detection
  - Support for environment-specific configurations
  - DRY_RUN mode for testing
  - Comprehensive error handling and validation
  - Color-coded output for better readability
- **Integration tests for repoadd**: Full test suite with Docker
  - 12 integration tests covering all scenarios
  - Tests for auto-component and explicit component modes
  - Tests for all environments (stable/beta/test)
  - Dry-run mode testing
- **Environment-specific configurations**:
  - `config-stable.yaml.example` for production
  - `config-beta.yaml.example` for pre-release
  - `config-test.yaml.example` for testing
- **Documentation**:
  - `REPOADD_SCRIPT.md` - Complete usage guide
  - `NGINX_MULTI_ENV.md` - Nginx configuration for multi-environment setup
  - `scripts/README.md` - Scripts directory documentation
- **Test script**: `test_repoadd.sh` for validation

## [0.1.3] - 2025-11-03

### Changed
- **Generic example URLs**: All `repo.jethome.ru` replaced with `repo.site.com`
  - Makes documentation deployment-agnostic
  - Users can substitute their own domain
  - Generic placeholder for examples

### Technical
- Version bump to 0.1.3
- 150+ URL references updated
- No code changes, documentation only

## [0.1.2] - 2025-11-03

### Changed
- **Documentation translated to English**
  - README.md: Complete English translation for PyPI
  - Primary language: English (for international audience)
  - Russian documentation preserved in docs/ru/ (future)

### Technical
- Version bump to 0.1.2
- All user-facing documentation in English
- Improved PyPI package description

## [0.1.1] - 2025-11-03

### Changed
- **Package renamed**: `repomanager` → `debrepomanager`
  - New package name on PyPI: `debrepomanager`
  - Command name: `debrepomanager` (no alias to avoid PyPI conflicts)
  - All imports updated to `debrepomanager`
  - **Migration required**: Replace `repomanager` with `debrepomanager` in scripts
  
### Added
- **PyPI publication workflow**: Automatic publishing on releases
  - Triggered on GitHub release creation
  - Uses `PYPI_TOKEN` secret
  - Package: https://pypi.org/project/debrepomanager/
  
- **GPG Key Rotation plan**: Phase 9 added to roadmap (v1.1)
  - Zero downtime key rotation
  - Grace period support
  - Client migration tools
  - Rollback mechanism
  
- **Deployment Guide**: Complete step-by-step instructions
  - docs/DEPLOYMENT_GUIDE.md
  - Covers /opt/repo + /beta scenario
  - Automated scripts included
  - Client setup examples

### Fixed
- All workflows use self-hosted runners
- Artifacts minimized (0 uploads)
- Integration tests run on all push/PR events

### Documentation
- Git workflow rule added (NEVER push to main!)
- All cursorrules updated for v0.1.1
- 9 comprehensive reports in docs/reports/

## [0.1.0] - 2025-11-03

### Added

#### Core Functionality
- **Configuration management** (`config.py`)
  - YAML-based configuration with merging support
  - Server and repository level configs
  - Comprehensive validation
  - Support for multiple codenames, components, and architectures

- **Aptly wrapper** (`aptly.py`)
  - Multi-root architecture (isolated aptly instances per codename)
  - Repository operations: create, delete, list, verify
  - Atomic package updates via snapshots
  - Automatic snapshot cleanup (configurable retention)
  - Support for multiple architectures (amd64, arm64, riscv64)

- **GPG integration** (`gpg.py`)
  - Automatic GPG signing of all publications
  - Support for gpg-agent with passphrase caching
  - Key availability checking
  - Signing verification

- **Utilities** (`utils.py`)
  - Debian package metadata parsing (python-debian)
  - Version comparison with Debian rules (apt_pkg)
  - Recursive .deb file discovery
  - Package age calculation
  - Structured logging setup

- **CLI interface** (`cli.py`)
  - `add` - Add packages to repository with atomic updates
  - `create-repo` - Create new repository
  - `delete-repo` - Safely delete repository (with confirmation)
  - `list` - List repositories and packages
  - Global options: --config, --verbose, --dry-run
  - Progress indicators and user-friendly error messages

#### Dual Format Support
- **Backward compatibility** for old and new URL formats
  - Old format: `deb http://repo.site.com bookworm component`
  - New format: `deb http://repo.site.com/bookworm component main`
- Automatic symlink creation for old format access
- Configurable via `dual_format.enabled` and `dual_format.auto_symlink`
- Portable relative symlinks for easy repository migration

#### Documentation
- Comprehensive README with examples
- Architecture documentation (ARCHITECTURE.md)
- Implementation plan and progress tracking
- Development guide (DEVELOPMENT.md)
- Configuration reference (CONFIG.md)
- Quick start guide (QUICKSTART.md)
- APT configuration examples (APT_CONFIGURATION.md)
- Dual format technical documentation (DUAL_FORMAT.md)

#### Testing & Quality
- 181 unit tests with 93% code coverage
- Integration test infrastructure (Docker-based)
- pytest configuration with coverage enforcement
- Code quality tools: black, flake8, mypy
- Type hints throughout codebase
- Continuous integration via GitHub Actions

#### CI/CD for Development
- Automatic code review workflow
- Test execution on multiple Python versions (3.11, 3.12)
- Auto-fix workflow for code style issues
- Documentation validation
- Coverage reporting

### Features

- **Multi-distribution support**: bookworm, noble, trixie, jammy
- **Multi-architecture**: amd64, arm64, riscv64
- **Multi-component**: flexible component naming (jethome-tools, jethome-armbian, etc.)
- **Atomic updates**: zero downtime package updates via snapshots
- **Auto-create repositories**: optional automatic repository creation
- **Configurable snapshot retention**: keep last N snapshots per repository
- **Force operations**: recreate existing repositories with --force flag
- **Dry-run mode**: preview operations without making changes

### Technical Details

- Python 3.11+ required
- Dependencies: click, pyyaml, python-debian, apt_pkg (optional)
- Uses aptly for repository management
- Supports GPG signing with configurable key
- Modular architecture with clear separation of concerns

### Configuration

- YAML-based configuration file
- Default locations: `./config.yaml`, `/etc/debrepomanager/config.yaml`
- Configurable paths for aptly root and publish directories
- Per-component retention policy overrides
- GPG configuration with agent support

[Unreleased]: https://github.com/jethome/repomanager/compare/v0.3.7...HEAD
[0.3.7]: https://github.com/jethome/repomanager/compare/v0.3.6...v0.3.7
[0.3.6]: https://github.com/jethome/repomanager/compare/v0.3.5...v0.3.6
[0.3.5]: https://github.com/jethome/repomanager/compare/v0.3.4...v0.3.5
[0.3.4]: https://github.com/jethome/repomanager/compare/v0.3.3...v0.3.4
[0.3.3]: https://github.com/jethome/repomanager/compare/v0.3.2...v0.3.3
[0.3.2]: https://github.com/jethome/repomanager/compare/v0.3.1...v0.3.2
[0.3.1]: https://github.com/jethome/repomanager/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/jethome/repomanager/compare/v0.2.1...v0.3.0
[0.2.1]: https://github.com/jethome/repomanager/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/jethome/repomanager/compare/v0.1.3...v0.2.0
[0.1.3]: https://github.com/jethome/repomanager/compare/v0.1.2...v0.1.3
[0.1.2]: https://github.com/jethome/repomanager/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/jethome/repomanager/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/jethome/repomanager/releases/tag/v0.1.0

