diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index c9289fa..2b793bd 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -174,7 +174,7 @@ jobs: - name: Install dependencies run: | . .env 2>/dev/null || true - python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@master" + python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@v0.4.1" - name: Run automated PR review env: REPO_TOKEN: ${{ secrets.REPO_TOKEN }} @@ -201,7 +201,7 @@ jobs: - name: Install dependencies run: | . .env 2>/dev/null || true - python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@master" + python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@v0.4.1" - name: Squash merge with task ID env: REPO_TOKEN: ${{ secrets.REPO_TOKEN }} diff --git a/.gitea/workflows/post-merge.yml b/.gitea/workflows/post-merge.yml index c58df9a..9dc94d6 100644 --- a/.gitea/workflows/post-merge.yml +++ b/.gitea/workflows/post-merge.yml @@ -43,7 +43,7 @@ jobs: - name: Install dependencies run: | . .env 2>/dev/null || true - python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@master" + python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@v0.4.1" - name: Check if this is a release commit id: check env: @@ -62,7 +62,7 @@ jobs: - name: Install dependencies run: | . .env 2>/dev/null || true - python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@master" + python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@v0.4.1" - name: Validate latest commit message env: PYTHONPATH: src @@ -204,7 +204,7 @@ jobs: - name: Install dependencies run: | . .env 2>/dev/null || true - python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@master" + python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@v0.4.1" - name: Update Vikunja task env: VIKUNJA_TOKEN: ${{ secrets.VIKUNJA_TOKEN }} @@ -238,7 +238,7 @@ jobs: - name: Install dependencies run: | . .env 2>/dev/null || true - python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@master" + python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@v0.4.1" - name: Ensure branch protection and labels env: REPO_TOKEN: ${{ secrets.REPO_TOKEN }} diff --git a/.gitea/workflows/publish.yml b/.gitea/workflows/publish.yml index 00b2df0..27339cc 100644 --- a/.gitea/workflows/publish.yml +++ b/.gitea/workflows/publish.yml @@ -16,7 +16,7 @@ jobs: - name: Install CI tools run: | . .env 2>/dev/null || true - python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@master" + python3 -m pip install --break-system-packages "git+https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@v0.4.1" python3 -m devx.tools.install_tools --tool git-cliff --tool tea - name: Install build tools run: python3 -m pip install --break-system-packages build twine diff --git a/.taskid b/.taskid index abcc39f..cc069fe 100644 --- a/.taskid +++ b/.taskid @@ -1 +1 @@ -GRM-64 +GRM-65 diff --git a/CHANGELOG.md b/CHANGELOG.md index ef06f4a..39b66c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,196 +2,145 @@ All notable changes to this project will be documented in this file. -## [0.6.1] - 2026-06-22 +## [0.7.0] - 2026-06-22 -## [0.6.1] - 2026-06-22 +### Bug Fixes -## [0.6.1] - 2026-06-22 +- Include lint extras in setup-ci and setup-release +- Use commit SHA URLs for badges to bypass Gitea cache +- Make sync-wiki and vikunja depend on release -## [0.6.1] - 2026-06-22 - -## [0.6.1] - 2026-06-22 - -## [0.6.1] - 2026-06-22 +### Refactor +- Fully automate PR merge — no manual label/review needed +- Require tea CLI everywhere, fail on missing Vikunja task +- Separate GRM and CI translations with validation +- Migrate from scripts/ to devx package ## [0.6.1] - 2026-06-22 ### Bug Fixes -- Strengthen review process with deeper checks and structured checklist -- Close CI gaps with workflow dry-run, automated configure_repo, aligned timeouts - +- Badges always update on release commits + fix configure-repo PYTHONPATH +- Enforce commit message convention on master with CI validation +- Post-merge workflow failures (4 jobs) ## [0.6.0] - 2026-06-22 -### Features - -- Add self-updating quality badges to README -- Enforce mandatory PR reviews with automated checks - ### Bug Fixes -- Bridge test suite gaps — lint scripts, include integration tests -- Badge regex patterns and doc_coverage double-percent -- Generate self-contained SVG badges instead of shields.io JSON -- Auto_merge handles single-token workflow (self-approval) -- Workflow timing, timeouts, status polling, and release classification -- API resilience with retry, idempotent releases, and graceful Vikunja errors -- Release pipeline determinism with lock, rebase, and consistent classification -- Enforce conventional commit check in automated PR review - Molecule-tests matrix runner-index renders as empty for 0 - Use 1-based runner indices for Gitea Actions compatibility - Molecule-tests static matrix and role_dir path fix - Auto-merge label condition uses pull_request.labels -- Badges job runs after release to reflect actual state - Revert review_pr.py to GiteaClient (tea v0.14.1 is interactive-only) (#70) -- Fix broken automation pipeline (auto-merge, Vikunja, CI enforcement) - -### Refactor - -- Consolidate CI workflows to eliminate redundant runs -- Convert shell scripts and inline workflow scripts to Python -- Enforce script separation and document import rules ### Revert - Remove v0.6.0 release (no user-facing changes) - -## [0.5.0] - 2026-06-21 - -### Packaging - -- `pyproject.toml` now uses `dynamic = ["version"]` with setuptools `attr` to source version from `__init__.py` (single source of truth) -- Added `console_scripts` entry point (`grm = "gitea_runner_manager.cli:cli"`) - -### Bug Fixes - -- Arch Linux: pacman cache update now runs separately before package installation (fixes idempotence) -- `rootless_docker.yml`: separated `update_cache` from package installation task - -### Internal - -- Added `GiteaClient.create_issue`, `GiteaClient.get_pr_files`, `GiteaClient.create_review` API methods -- Added `VikunjaClient.get_task` method -- Config URLs and repo settings now overridable via environment variables - ## [0.4.0] - 2026-06-21 -### Rootless Docker Support - -- Full rootless Docker installation and configuration via Ansible -- `docker_rootless_setup` variable controls whether rootless Docker tasks run -- User setup tasks (subuid/subgid, lingering, dockerd-rootless) -- Proper gating of all Docker-dependent and `systemctl --user` tasks - -### Runner Labels - -- `--labels` option on `grm install` — specify runner labels (e.g., `--labels "ubuntu-latest:docker://node:20"`) -- Labels passed through to runner config YAML - -### Security Fix (CWE-214) - -- **Critical**: Registration tokens and admin tokens are no longer passed via `--extra-vars` on the command line -- Extra-vars are now written to a temporary JSON file with `0600` permissions and passed via `--extra-vars @tempfile` -- This prevents secrets from being visible in the process list (`ps aux`) - -### Configuration via Environment Variables - -- 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` - -### Ansible Role Improvements - -- Dead code cleanup (removed `config.yml`, legacy system-level service, duplicate task includes) -- `remove-runner.yml` now disables lingering and removes subuid/subgid entries for complete cleanup -- Arch Linux: `gnupg` package name fix, pacman cache handling -- Docker APT repository: deb822 format, proper GPG handling, arch mapping -- Idempotence fixes for user_setup and download tasks - -## [0.3.0] - 2026-06-21 - -### New CLI Options - -- `--force` flag on `grm remove` — remove a runner even when the host is unreachable (skips Ansible playbook, only deregisters via API) -- `--url` option — override the Gitea URL for any command (useful for multiple Gitea instances) -- `--ask-become-pass` is now the default behavior (no need to pass it explicitly) - -### Status Detection Fixes - -- `grm list` now correctly retrieves runner status (was showing "unknown" for active runners) -- Docker mode status detection via `docker inspect` -- Host/user context added to status output - -### Output Improvements - -- Colorized output for better visual feedback (green/red/yellow) -- Translated operation reports for success and failure cases -- Dual logging: `click.echo()` for user-facing messages, `logging` for debug -- `GRM_LOG_LEVEL` environment variable for controlling verbosity -- Full i18n support (all user-facing strings translated) - -### Internal Refactoring - -- Validation moved from CLI layer to business layer -- Centralized API clients and HTTP status codes -- User-friendly Click errors with i18n - -## [0.2.0] - 2026-06-21 - -### New CLI Commands - -- `grm start ` — start a runner's systemd service -- `grm stop ` — stop a runner's systemd service -- `grm enable ` — enable a runner to start on boot -- `grm disable ` — disable a runner from starting on boot -- `grm status ` — check runner service status -- `grm remove ` — deregister and remove a runner -- `grm list-runners` — list all runners from the local registry - -### Runner Registry - -- Runners are tracked in `~/.config/grm/runners.toml` for simplified CLI usage -- No need to specify `--url`, `--user`, `--key` for every command — the registry remembers - -### Multi-Instance Support - -- systemd template units (`gitea-runner@.service`) for running multiple runners per host -- Per-instance config and data directories - -### Ansible Role Improvements - -- Parameterized all hardcoded configuration values as Ansible variables -- Idempotence fixes for repeated runs -- Runner config converted from TOML to YAML format -- Registration timeout to prevent indefinite hangs -- Docker container entrypoint override and working directory fix for `.runner` persistence - -## [0.1.0] - 2026-06-21 - -### Initial Release - -The first release of GRM, a lean CLI for managing Gitea Actions runners via SSH. - -### CLI Commands - -- `grm install ` — install and register a Gitea Runner on a remote host via SSH -- `grm token` — generate a registration token via the Gitea API -- `grm list` — list all registered runners -- `grm update ` — update a runner to the latest version - -### Ansible Role - -- Installs Gitea Runner binary in binary or Docker mode -- Registers runner with Gitea instance -- Configures systemd service -- Supports Arch Linux, Ubuntu, and Debian - ### Features -- SSH-based remote execution via Ansible -- Automatic registration token generation -- Docker and binary installation modes -- Integration test verification after installation +- Replace inline workflow scripts with tested Python modules +- User-friendly click errors with i18n in configure_repo +- Bandit integration (#1) +- Auto-delete branch after merge in configure_repo script +- Add runner labels support and refactor i18n to JSON +- Parallel molecule runner with kill-on-first-failure +- Cross-runner molecule cancellation via Gitea API polling + +### Bug Fixes + +- Set runner_mode to binary in multi-instance converge +- Skip systemd operations in lifecycle molecule when unavailable +- Improve make setup with version guard, pre-push hooks and commit-msg validator +- Enforce GRM-N: conventional on master commits and PR titles +- Remove molecule tests from pre-push hooks +- Resolve bandit security warnings in source code and tests +- CI pipeline for rootless Docker runners +- CI workflows for rootless runner compatibility +- Vikunja task resolution pagination in post_merge.py +- Use PUT instead of POST for Vikunja task comments +- Parse pytest output with warnings in check_test_speed +- Use systemd as container command for rootless molecule tests +- Add Docker APT repository before installing docker-ce +- Use deb822_repository for Docker APT repo (proper GPG handling) +- Dearmor Docker GPG key with gpg --dearmor for apt_repository +- Use bash for gpg dearmor (pipefail not available in sh) +- Install curl, gpg, ca-certificates in molecule prepare +- Separate apt update after adding Docker repo, use variable for repo string +- Add apt source debug tasks, fix arch mapping for Docker repo +- Fail-fast CI, write Docker apt source directly, fix arch mapping +- Skip rootless Docker daemon startup in molecule tests +- Gate all Docker-dependent tasks behind docker_rootless_setup +- Catch TimeoutExpired in parallel runner wait loop +- Stream molecule subprocess output to CI logs +- Run molecule pairs sequentially within each CI runner +- Guard all systemctl --user tasks with docker_rootless_setup +- Guard handler systemctl --user calls with docker_rootless_setup +- Make user_setup and download tasks idempotent +- Use gnupg instead of gpg package name on Arch Linux +- Add default(0) to gitea_runner_uid in environment blocks +- Set runner_name in deregister verify.yml +- Security, dead code, idempotence, and documentation cleanup + +### Refactor + +- Standardise pre-commit hooks on make targets +- Use http.HTTPStatus constants instead of magic numbers +- Rework all scripts to use click and i18n +- *(scripts)* Centralize constants, API clients, and HTTP status codes +- Rootless Docker, fix auto-merge, molecule platform matrix +## [0.3.0] - 2026-06-19 + +### Features + +- Add translated operation report for success and failure cases +- Replace print() with stdlib logging module +- Use click.echo() for user-facing messages with dual logging +- Add colorized output for better visual feedback +- Add --force flag to grm remove for unreachable runners +- Make --ask-become-pass the default behavior + +### Bug Fixes + +- Eliminate duplicate console output, restore GRM_LOG_LEVEL filtering +- Make grm list retrieve runner status correctly + +### Refactor + +- Deduplicate CLI, remove dead code, move validation to business layer +- Resolve_runner returns gitea_url, add --url CLI option, force remove improvements, code quality fixes +## [0.2.0] - 2026-06-18 + +### Features + +- Parameterize all hardcoded configuration values as Ansible variables +- Add GITEA_ADMIN_TOKEN support for integration test +- Add AnsibleExecutor and i18n modules +- Integrate AnsibleExecutor and i18n into CLI and RunnerManager +- Add systemd template units and multi-instance Ansible support +- Add lifecycle CLI commands and RunnerManager extensions +- Add runner registry for simplified CLI UX + +### Bug Fixes + +- Resolve idempotence issues and testing infrastructure +- Remove recursive variable definitions in install and update playbooks +- Add timeout to runner registration to prevent indefinite hangs +- Override Docker container entrypoint to bypass run.sh wrapper +- Set Docker working dir to /data for .runner persistence +- Make integration test conditional on admin API accessibility +- Remove recursive var definitions from install-runner.yml +- Convert runner config from TOML to YAML format +- Rewrite integration test to verify .runner file and container health instead of unreliable API checks + +### Refactor + +- Remove dead code and legacy artifacts +- Migrate source terminology from act_runner to gitea_runner +- Consolidate systemd checks and deduplicate role structure +## [0.1.0] - 2026-06-17 + +### Features + +- Initial implementation of Gitea Runner Manager diff --git a/Makefile b/Makefile index d80a24e..3161fd8 100644 --- a/Makefile +++ b/Makefile @@ -7,11 +7,15 @@ CHECKMAKE := $(shell command -v checkmake 2>/dev/null || echo $(HOME)/go/bin/che all: setup +# Pinned devx version — update this when upgrading devx. +# All workflow files (.gitea/workflows/*.yml) must be updated to match. +DEVX_VERSION := v0.4.1 + install-devx: $(VENV)/bin/activate @# REPO_TOKEN may come from .env (local) or environment (CI secrets) @if [ -z "$$REPO_TOKEN" ]; then . .env 2>/dev/null; fi; \ if [ -z "$$REPO_TOKEN" ]; then echo "REPO_TOKEN not set (check .env or environment)"; exit 1; fi; \ - $(BIN)/pip install "git+https://emil:$$REPO_TOKEN@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@master" + $(BIN)/pip install "git+https://emil:$$REPO_TOKEN@git.oblachno.oblachno.fyi/oblachno-oss/devx.git@$(DEVX_VERSION)" # Full setup for local development (all deps, tools, collections, hooks) # install-devx must run before install-tools (which uses devx modules) diff --git a/cliff.toml b/cliff.toml index 77766a1..e7bd150 100644 --- a/cliff.toml +++ b/cliff.toml @@ -39,8 +39,8 @@ sort_commits = "oldest" recurse_submodules = false commit_preprocessors = [ - # Strip GRM-N task ID prefix from merge commits so git-cliff sees conventional commits - { pattern = "^GRM-\\d+\\s+", replace = "" }, + # Strip GRM-N: task ID prefix from squash-merge commits so git-cliff sees conventional commits + { pattern = "^GRM-\\d+:\\s+", replace = "" }, ] commit_parsers = [ @@ -66,3 +66,6 @@ commit_parsers = [ features_always_bump_minor = true breaking_always_bump_major = false initial_tag = "0.1.0" +# Refactor commits bump patch — structural changes to src/ or pyproject.toml +# affect users even though no new feature was added. +refactor_always_bump_patch = true diff --git a/src/gitea_runner_manager/__init__.py b/src/gitea_runner_manager/__init__.py index 324cc7f..449310a 100644 --- a/src/gitea_runner_manager/__init__.py +++ b/src/gitea_runner_manager/__init__.py @@ -1,3 +1,3 @@ """Gitea Runner Manager — lean CLI for managing Gitea Actions runners.""" -__version__ = "0.6.1" +__version__ = "0.7.0"