# Changelog All notable changes to this project will be documented in this file. ## [0.3.0] - 2026-06-21 ### Features - Implement documentation-as-code with wiki sync and doc-coverage ## [0.2.2] - 2026-06-21 ### Bug Fixes - Enforce tests pass before tagging a release - Bypass commit-msg hook for release commits ## [0.2.1] - 2026-06-21 ### Bug Fixes - Strip git-cliff header from CHANGELOG.md updates ## [0.2.0] - 2026-06-21 ### Features - Fix 12 critical workflow gaps in release pipeline ### Bug Fixes - Release push permission and notify_failure label IDs ## [Unreleased] ### Added - **Automated semver versioning and releases**: `scripts/release.py` — CI script that uses git-cliff to calculate the next version from conventional commits, update version files, create a release commit, tag, and push. - `cliff.toml` — git-cliff configuration for conventional commit parsing, semver bumping, and changelog generation. - Release workflow (`.gitea/workflows/release.yml`) — triggers on push to master, runs `scripts/release.py` to automatically version and tag releases. - `publish.py` now uses git-cliff to generate release notes for Gitea releases (falls back to generic message if git-cliff is not available). - `pyproject.toml` now uses `dynamic = ["version"]` with setuptools `attr` to source version from `__init__.py` (single source of truth — release script only updates `__init__.py`). - **Mandatory PR review step**: `scripts/review_pr.py` — CLI to post Gitea PR reviews (COMMENT, APPROVE, REQUEST_CHANGES) with inline comments via `--comments-json` or `--comments-stdin`. - `GiteaClient.get_pr_files`, `GiteaClient.get_pr_commits`, `GiteaClient.create_review` — API methods for PR review workflow. - `VikunjaClient.get_task` — fetch a single task by numeric ID. - PR title format: `GRM-N: ` (colon-separated, human-friendly). - Merge commit format: `GRM-N ` (space-separated, conventional). - `auto_merge.py` now extracts the conventional commit message from PR commits and constructs the merge title as `GRM-N `. - `post_merge.py` `extract_conventional_msg` now handles both legacy (`GRM-N: `) and current (`GRM-N `) merge commit formats. - Full PR workflow documented in `AGENTS.md` and `README.md` (Vikunja task → branch → implement → commit → PR → review → address comments → approve → merge). ### Changed - Parameterized all hardcoded configuration values as Ansible variables in `defaults/main.yml`: - `gitea_runner_data_dir` — Runtime data directory - `gitea_runner_config_dir` — Config directory - `gitea_runner_binary_path` — Binary install path - `gitea_runner_prune_until` — Prune age filter - `gitea_runner_prune_schedule` — Prune timer schedule - `gitea_runner_prune_label` — Docker label for pruning - `gitea_runner_service_restart_sec` — systemd restart interval - `gitea_runner_service_user` — Service user - `gitea_runner_log_level` — Runner log level - `gitea_runner_container_label` — Container label - `gitea_runner_file` — Runner metadata file - `docker_gpg_key_path` — Docker GPG key path - Added `console_scripts` entry point in `pyproject.toml` (`grm = "gitea_runner_manager.cli:cli"`). - Added shared `molecule/common/prepare.yml` to eliminate duplicated prepare playbooks. - Extracted repeated systemd availability check into `tasks/systemd_check.yml`. - Added idempotence checks to all Molecule scenarios. - Comprehensive README overhaul with Architecture, Configuration, Development, Testing, and Troubleshooting sections. - API URLs and repo configuration in `config.py` are now overridable via environment variables (`GRM_GITEA_API_URL`, `GRM_VIKUNJA_API_URL`, `GRM_REPO_OWNER`, `GRM_REPO_NAME`, `GRM_VIKUNJA_PROJECT_ID`). - `remove-runner.yml` now disables lingering and removes subuid/subgid entries for complete cleanup. ### Security - **Critical fix**: Registration tokens and admin tokens are no longer passed via `--extra-vars` on the command line (CWE-214). Extra-vars are now written to a temporary JSON file with `0600` permissions and passed via `--extra-vars @tempfile`, which is deleted after execution. This prevents secrets from being visible in the process list (`ps aux`). ### Changed - Replaced legacy runner terminology with `gitea_runner` / `gitea-runner` / `Gitea Runner`. - Updated default Docker image from `gitea/gitea_runner` to `gitea/runner`. - `Makefile` now uses the installed `grm` console script instead of `python grm`. - `pyproject.toml` ruff and pyright target versions updated from `py311` to `py312` to match `requires-python = ">=3.12"`. - `BRANCH_PROTECTION_CONFIG` updated with correct Gitea Actions status check contexts (including `(pull_request)` suffix) and `required_approvals: 0` for auto-merge. - `CONVENTIONAL_RE` no longer matches `BREAKING CHANGE` as a commit type (it is a footer, not a type). - `rootless_docker.yml` apt cache update now only runs when the Docker repo file changes (idempotent, but always refreshes on first add). - `service.yml` and `prune.yml` template creation tasks are not guarded by `docker_rootless_setup` (templates just create files, they don't need Docker; molecule tests set `docker_rootless_setup: false` but still verify the service file exists). - `molecule_all.sh` now sources the platform list from `distribute_molecule.py` to avoid duplication. ### Removed - Deleted `setup.py` (redundant with `pyproject.toml`). - Deleted `grm` shell entrypoint script (replaced by `console_scripts`). - Deleted `initial-plan.md` and `tests/integration/test_provision.py` (dead code). - Removed empty `__init__.py` files from `tests/` directories. - Removed unused `runner_validated` fact from `validate.yml`. - Removed duplicate `prune.yml` and `integration_test.yml` includes from `install_runner.yml` (already included from `main.yml`). - Removed dead `tasks/config.yml` (never included by any playbook). - Removed dead `templates/gitea-runner.service.j2` (legacy system-level service, replaced by rootless `gitea-runner-user.service.j2`). - Removed dead "Reload systemd" handler (system-level reload, never notified, wrong scope for user services). - Removed dead `scripts/run_molecule_parallel.py` and its test (replaced by `molecule_ci_guard.py`). ### Fixed - Molecule idempotence failures caused by non-idempotent service restart. - Missing `/etc/docker` directory handling in Molecule tests. - `ansible-lint` formatting warnings (yaml empty lines). - Verify playbooks now explicitly load role defaults so parameterized variables are available during verification. - Duplicate execution of prune and integration test tasks during installation (were included from both `main.yml` and `install_runner.yml`). - apt cache update reporting `changed` on every run due to `cache_valid_time: 0`.