From 358620401df7997d725533743d8debf09c284645 Mon Sep 17 00:00:00 2001 From: emil Date: Wed, 1 Jul 2026 00:18:44 +0000 Subject: [PATCH] GRM-124: docs: fix outdated references and document health/restart/trigger-workflow commands --- AGENTS.md | 12 +++-- README.md | 1 + docs/tech/architecture.md | 8 +++- docs/tech/testing-strategy.md | 2 +- docs/user/cli-commands.md | 90 +++++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index f73c08b..037c3a9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -242,11 +242,11 @@ Not all changes require the full CI pipeline or a new release. The project classifies changes into two categories using `devx.ci.classify_changes`: **Classification strategy (safe-by-default):** Any file NOT in the explicit -workflow-only allowlist is treated as user-facing. This prevents new file +infrastructure allowlist is treated as user-facing. This prevents new file types from accidentally skipping releases. Classification is config-driven via `[tool.devx.classify]` in `pyproject.toml`. -**Workflow-only paths** (infrastructure → no release needed): +**Infrastructure paths** (no release needed): - `.gitea/**` — Gitea Actions workflows - `scripts/**` — Dev tools and CI/CD automation (not part of installed package) - `docs/**` — Documentation @@ -283,7 +283,7 @@ via `[tool.devx.classify]` in `pyproject.toml`. **AI agents must follow these rules:** - When working on workflow/CI/docs-only changes, use `ci:` or `docs:` commit prefixes -- Do NOT bump the version or create tags for workflow-only changes +- Do NOT bump the version or create tags for infrastructure-only changes - The `classify_changes` module enforces this automatically — no manual intervention needed ## Source Code Separation and devx Integration @@ -397,7 +397,7 @@ The devx package is configured via `DEVX_*` environment variables: - `DEVX_VIKUNJA_PROJECT_ID=6` — Vikunja project ID for task tracking - `DEVX_VERSION_FILE=src/gitea_runner_manager/__init__.py` — Path to the version source file -Change classification is config-driven via `[tool.devx.classify]` in `pyproject.toml`, which defines the workflow-only and user-facing path patterns. +Change classification is config-driven via `[tool.devx.classify]` in `pyproject.toml`, which defines the infrastructure and user-facing path patterns. ## Key Conventions @@ -422,10 +422,12 @@ main.yml → systemd_check → user_setup → rootless_docker → install_runner ## Molecule Scenarios -6 scenarios: `default`, `multi-instance`, `lifecycle`, `template-content`, `deregister`, `update` +7 scenarios: `default`, `multi-instance`, `lifecycle`, `template-content`, `deregister`, `update`, `remove` 4 platforms: `ubuntu-2204`, `ubuntu-2404`, `debian-12`, `archlinux` Platform list is defined in `devx.molecule.platforms` (single source of truth) +Note: `make molecule` and `make molecule-all` run 6 scenarios (excluding `remove`, which destroys the test container). CI discovers all 7 scenarios via `devx.molecule.distribute_molecule`. + ## Known Issues - `ansible-lint` may warn about `command-instead-of-module` for `systemctl --user` calls — this is expected (systemd module doesn't support user services) and skipped in `.ansible-lint` diff --git a/README.md b/README.md index 75a1317..bed1fe9 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,7 @@ GRM provides a single `grm` command with subcommands for the full runner lifecyc | `grm remove --force` | Remove only the local registry entry (skip remote cleanup) | | `grm list` | List all registered runners with live status | | `grm list --no-status` | List registered runners without SSH status checks | +| `grm health [name]` | Run health check (Docker, runner service, disk) on one or all runners | | `grm trigger-workflow ` | Trigger a Gitea Actions workflow via the API | | `grm trigger-workflow --list` | List available workflows in the repository | | `grm --version` | Show the installed version | diff --git a/docs/tech/architecture.md b/docs/tech/architecture.md index dfaf85f..b47125b 100644 --- a/docs/tech/architecture.md +++ b/docs/tech/architecture.md @@ -31,13 +31,14 @@ grm install ├── rootless_docker.yml (rootless Docker setup under runner user) ├── install_runner.yml (download binary, config, register, service) ├── prune.yml (Docker prune timer) + ├── healthcheck.yml (health check script + systemd timer) └── integration_test.yml (validate service is active) ``` The Ansible role task execution order (from `AGENTS.md`): ``` -main.yml → systemd_check → user_setup → rootless_docker → install_runner → prune → integration_test +main.yml → systemd_check → user_setup → rootless_docker → install_runner → prune → healthcheck → integration_test ``` - `install_runner.yml` handles: download, config, validate, register, service @@ -59,6 +60,7 @@ main.yml → systemd_check → user_setup → rootless_docker → install_runner | `register.yml` | Registers the runner with Gitea using the registration token | | `service.yml` | Creates the systemd user service file and starts/enables the service | | `prune.yml` | Creates a systemd user timer for daily Docker image and volume pruning | +| `healthcheck.yml` | Installs a health check script and systemd timer that monitors Docker daemon, runner service, and disk space; restarts unhealthy services automatically | | `integration_test.yml` | Verifies the `.runner` file exists and the systemd service is active; optionally queries the Gitea API | | `deregister.yml` | Deregisters the runner from Gitea and removes the `.runner` file | | `update_runner.yml` | Downloads a new version of the gitea_runner binary | @@ -71,6 +73,9 @@ main.yml → systemd_check → user_setup → rootless_docker → install_runner | `gitea-runner-config.yaml.j2` | Runner configuration file (labels, capacity, log level) | | `docker-prune.service.j2` | Systemd user service for Docker pruning (oneshot) | | `docker-prune.timer.j2` | Systemd user timer triggering daily Docker prune | +| `runner-healthcheck.sh.j2` | Health check script (checks Docker, runner service, disk space; restarts if down) | +| `runner-healthcheck.service.j2` | Systemd user service for the health check (oneshot) | +| `runner-healthcheck.timer.j2` | Systemd user timer triggering periodic health checks | ## Per-Runner Isolation @@ -139,6 +144,7 @@ flowchart TD - Registers the runner with Gitea - Creates and starts the systemd user service - Sets up the Docker prune timer + - Installs the health check script and systemd timer - Runs the integration test (verifies `.runner` file and service state) 7. Ansible output is streamed to a timestamped log file at `~/.local/state/grm/logs/ansible-.log` 8. On success, the runner is added to the local registry at `~/.local/share/grm/runners.json` diff --git a/docs/tech/testing-strategy.md b/docs/tech/testing-strategy.md index aa883f5..e0d090d 100644 --- a/docs/tech/testing-strategy.md +++ b/docs/tech/testing-strategy.md @@ -83,7 +83,7 @@ The platform list is defined in `devx.molecule.platforms` (single source of trut ### CI Test Distribution -CI runs all 6 scenarios x 4 platforms (24 test pairs) distributed across available Gitea Actions runners. +CI runs all 7 scenarios x 4 platforms (28 test pairs) distributed across available Gitea Actions runners. The `discover-runners` job runs `devx.molecule.discover_runners` which queries the Gitea API for registered runners at three levels (repo, org, instance) and generates a dynamic matrix. If the API query fails (e.g., no admin access for instance-level runners), it falls back to the `MOLECULE_RUNNERS` repo variable, then to a default of 3. diff --git a/docs/user/cli-commands.md b/docs/user/cli-commands.md index cf38f0a..d447062 100644 --- a/docs/user/cli-commands.md +++ b/docs/user/cli-commands.md @@ -10,11 +10,14 @@ GRM provides the following CLI commands for managing Gitea Actions runners. The | `grm update` | `` | Update the gitea_runner binary on a remote host | | `grm start` | `` | Start a registered runner | | `grm stop` | `` | Stop a registered runner | +| `grm restart` | `` | Restart a runner (stop, prune Docker images, start) | | `grm enable` | `` | Enable a runner to start on boot | | `grm disable` | `` | Disable and deregister a runner | | `grm status` | `` | Check the status of a registered runner | | `grm remove` | `` | Remove a runner completely | | `grm list` | — | List all registered runners with live status | +| `grm health` | `[runner_name]` | Run health check (Docker, runner service, disk) on one or all runners | +| `grm trigger-workflow` | `` | Trigger a Gitea Actions workflow via the API | | `grm --version` | — | Show the installed version | ### Common lifecycle options @@ -139,6 +142,29 @@ grm stop [options] | `--key` | `-k` | Override SSH key from registry | | `--ask-become-pass/--no-ask-become-pass` | — | Prompt for sudo password (default) or skip it | +## restart + +Restart a registered Gitea Runner (stop, prune Docker images, start). + +```bash +grm restart [options] +``` + +**Arguments:** + +| Argument | Description | +|----------|-------------| +| `runner_name` | Name of the registered runner | + +**Options (common lifecycle options):** + +| Option | Short | Description | +|--------|-------|-------------| +| `--host` | — | Override host from registry | +| `--user` | `-u` | Override user from registry | +| `--key` | `-k` | Override SSH key from registry | +| `--ask-become-pass/--no-ask-become-pass` | — | Prompt for sudo password (default) or skip it | + ## enable Enable a registered Gitea Runner to start on boot. @@ -276,6 +302,70 @@ If no runners are registered: No runners registered. Use 'grm install' to add one. ``` +## health + +Run a health check on one or all registered runners. Checks Docker daemon status, Gitea runner service status, and disk space usage. Unhealthy services are automatically restarted by the healthcheck script. + +```bash +grm health [runner_name] [options] +``` + +**Arguments:** + +| Argument | Description | +|----------|-------------| +| `runner_name` | (optional) Name of the runner to check. If omitted, checks all registered runners. | + +**Options (common lifecycle options):** + +| Option | Short | Description | +|--------|-------|-------------| +| `--host` | — | Override host from registry | +| `--user` | `-u` | Override user from registry | +| `--key` | `-k` | Override SSH key from registry | +| `--ask-become-pass/--no-ask-become-pass` | — | Prompt for sudo password (default) or skip it | + +**Example:** + +```bash +grm health +# Check a specific runner: +grm health prod-runner +``` + +Output shows NAME, HOST, HEALTHY (yes/no), and MESSAGE columns. The command exits with code 1 if any runner is unhealthy. + +The health check is also run automatically via a systemd timer installed by the Ansible role. See `ansible/roles/gitea-runner/templates/runner-healthcheck.sh.j2` for the script and `runner-healthcheck.timer.j2` for the timer. + +## trigger-workflow + +Trigger a Gitea Actions workflow via the API. + +```bash +grm trigger-workflow [options] +grm trigger-workflow --list +``` + +**Arguments:** + +| Argument | Description | +|----------|-------------| +| `workflow_id` | Workflow filename (e.g., `ci.yml`) or ID | + +**Options:** + +| Option | Description | +|--------|-------------| +| `--list` | List available workflows in the repository | +| `--ref` | Branch or tag to trigger on (default: repository default branch) | + +**Example:** + +```bash +grm trigger-workflow --list +grm trigger-workflow ci.yml --ref master +``` + ## --version Show the installed GRM version.