GRM-7: docs: overhaul README and add project documentation
This commit is contained in:
+11
-3
@@ -1,4 +1,12 @@
|
|||||||
|
# Gitea instance URL (used for runner registration and API validation)
|
||||||
GITEA_URL=https://git.example.com
|
GITEA_URL=https://git.example.com
|
||||||
GITEA_TOKEN=your-personal-access-token
|
|
||||||
# Optional: GITEA_RUNNER_USER=ubuntu
|
# Runner registration token from Gitea admin panel:
|
||||||
# Optional: GITEA_RUNNER_KEY=~/.ssh/id_ed25519
|
# Admin → Actions → Runners → Create Registration Token
|
||||||
|
GITEA_REGISTRATION_TOKEN=your-registration-token
|
||||||
|
|
||||||
|
# Default SSH user for remote hosts (optional, overrides --user)
|
||||||
|
# GITEA_RUNNER_USER=ubuntu
|
||||||
|
|
||||||
|
# Default SSH private key path (optional, overrides --key)
|
||||||
|
# GITEA_RUNNER_KEY=~/.ssh/id_ed25519
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Parameterized all hardcoded configuration values as Ansible variables in `defaults/main.yml`:
|
||||||
|
- `gitea_runner_docker_image` — Docker image name (default: `gitea/runner`)
|
||||||
|
- `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 both Molecule scenarios (`default` and `binary`).
|
||||||
|
- Comprehensive README overhaul with Architecture, Configuration, Development, Testing, and Troubleshooting sections.
|
||||||
|
|
||||||
|
### 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`.
|
||||||
|
- `docker_update.yml`: reordered `register` before `changed_when` for readability.
|
||||||
|
- `binary_update.yml`: removed redundant explicit service restart (handler handles this idempotently).
|
||||||
|
|
||||||
|
### 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 `docker_mode.yml` and `binary_mode.yml` (now included once from `main.yml`).
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Molecule idempotence failures caused by non-idempotent service restart in `binary_update.yml`.
|
||||||
|
- 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.
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
A lean command-line tool to automate the installation, configuration, and lifecycle management of Gitea Actions runners on Arch Linux, Ubuntu, and Debian hosts.
|
A lean command-line tool to automate the installation, configuration, and lifecycle management of Gitea Actions runners on Arch Linux, Ubuntu, and Debian hosts.
|
||||||
|
|
||||||
|
By default, runners are deployed as **Docker containers** using the official `gitea/runner` image. A traditional **binary** deployment mode is also available.
|
||||||
|
|
||||||
> **Pronunciation note:** GRM is short for *Gitea Runner Manager*, but say it like **ГРЪМ** (roughly "GRUM" in Latin letters) — the Bulgarian word for **thunder**. Wherever there are clouds, there may be thunders. This is an open-source project from **Oblachno** (облачно means *cloudy* in Bulgarian).
|
> **Pronunciation note:** GRM is short for *Gitea Runner Manager*, but say it like **ГРЪМ** (roughly "GRUM" in Latin letters) — the Bulgarian word for **thunder**. Wherever there are clouds, there may be thunders. This is an open-source project from **Oblachno** (облачно means *cloudy* in Bulgarian).
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
@@ -17,6 +19,11 @@ A lean command-line tool to automate the installation, configuration, and lifecy
|
|||||||
- Ubuntu 22.04 / 24.04 / 26.04
|
- Ubuntu 22.04 / 24.04 / 26.04
|
||||||
- Debian 12 / 13
|
- Debian 12 / 13
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- **SSH key authentication** — The remote host must be reachable via SSH using the user specified with `--user` and the private key specified with `--key`. GRM uses Ansible under the hood, which connects to the target host over SSH to execute all installation and configuration tasks. Without valid SSH credentials, Ansible cannot establish a connection and the deployment will fail.
|
||||||
|
- **Sudo privileges** — The specified user must have passwordless or password-prompted (`--ask-become-pass`) sudo access on the remote host. Runner installation requires root privileges for tasks such as installing packages, creating systemd services, and managing Docker.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Developer Setup
|
### Developer Setup
|
||||||
@@ -35,23 +42,40 @@ make setup
|
|||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
# Edit .env:
|
# Edit .env:
|
||||||
# GITEA_URL=https://git.example.com
|
# GITEA_URL=https://git.example.com
|
||||||
# GITEA_TOKEN=your-personal-access-token
|
# GITEA_REGISTRATION_TOKEN=your-registration-token
|
||||||
```
|
```
|
||||||
|
|
||||||
The token needs `admin:runner` scope.
|
`GITEA_REGISTRATION_TOKEN` is the runner registration token obtained from your Gitea instance (Admin → Actions → Runners → Create Registration Token).
|
||||||
|
|
||||||
### Install a Runner
|
### Install a Runner
|
||||||
|
|
||||||
Using the CLI:
|
Using the CLI:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./grm install 192.168.1.10 --user ubuntu --key ~/.ssh/id_ed25519 --name prod-runner
|
# Docker mode (default) — deploys gitea_runner as a container
|
||||||
|
grm install 192.168.1.10 --user ubuntu --key ~/.ssh/id_ed25519 --name prod-runner
|
||||||
|
|
||||||
|
# Binary mode — downloads and installs the gitea_runner binary with systemd
|
||||||
|
grm install 192.168.1.10 --user ubuntu --key ~/.ssh/id_ed25519 --name prod-runner --mode binary
|
||||||
|
```
|
||||||
|
|
||||||
|
If the remote user requires a sudo password:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grm install 192.168.1.10 --user ubuntu --ask-become-pass
|
||||||
```
|
```
|
||||||
|
|
||||||
Using Make:
|
Using Make:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Docker mode (default)
|
||||||
make install HOST=192.168.1.10 USER=ubuntu KEY=~/.ssh/id_ed25519 NAME=prod-runner
|
make install HOST=192.168.1.10 USER=ubuntu KEY=~/.ssh/id_ed25519 NAME=prod-runner
|
||||||
|
|
||||||
|
# Binary mode
|
||||||
|
make install HOST=192.168.1.10 USER=ubuntu KEY=~/.ssh/id_ed25519 NAME=prod-runner MODE=binary
|
||||||
|
|
||||||
|
# With sudo password prompt:
|
||||||
|
make install HOST=192.168.1.10 USER=ubuntu ASK_BECOME_PASS=1
|
||||||
```
|
```
|
||||||
|
|
||||||
### Verify Runner
|
### Verify Runner
|
||||||
@@ -61,15 +85,154 @@ Check Gitea admin UI under **Actions → Runners**. The runner should appear as
|
|||||||
### View Logs
|
### View Logs
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo journalctl -u act-runner-<name> -f
|
# Binary mode logs
|
||||||
|
sudo journalctl -u gitea-runner-<name> -f
|
||||||
|
|
||||||
|
# Docker mode logs
|
||||||
|
docker logs gitea-runner-<name> -f
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
GRM consists of two layers:
|
||||||
|
|
||||||
|
1. **Python CLI** (`src/gitea_runner_manager/`) — built with Click, handles argument parsing, environment loading, and delegates to Ansible via the `ansible-playbook` subprocess.
|
||||||
|
2. **Ansible Role** (`ansible/roles/gitea-runner/`) — idempotent role that installs Docker, configures the runner (binary or container), creates systemd services, and registers the runner with Gitea.
|
||||||
|
|
||||||
|
```
|
||||||
|
grm install <host>
|
||||||
|
└── RunnerManager.install()
|
||||||
|
└── ansible-playbook ansible/install-runner.yml
|
||||||
|
└── role: gitea-runner
|
||||||
|
├── docker.yml (Docker installation)
|
||||||
|
├── docker_mode.yml (container deployment)
|
||||||
|
├── binary_mode.yml (binary + systemd deployment)
|
||||||
|
├── prune.yml (Docker prune timer)
|
||||||
|
└── integration_test.yml (validate online status)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
All tunable values are exposed as Ansible variables in `ansible/roles/gitea-runner/defaults/main.yml`:
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `runner_mode` | `docker` | Deployment mode: `docker` or `binary` |
|
||||||
|
| `gitea_runner_version` | `1.0.8` | Docker image tag / binary version |
|
||||||
|
| `gitea_runner_docker_image` | `gitea/runner` | Docker image name |
|
||||||
|
| `runner_labels` | `ubuntu-latest:docker://runner-images:ubuntu-22.04` | Runner labels |
|
||||||
|
| `skip_runner_registration` | `false` | Skip API registration (useful for tests) |
|
||||||
|
| `gitea_runner_data_dir` | `/var/lib/gitea-runner` | Runtime data directory |
|
||||||
|
| `gitea_runner_config_dir` | `/etc/gitea-runner` | Config directory (binary mode) |
|
||||||
|
| `gitea_runner_binary_path` | `/usr/local/bin/gitea_runner` | Binary install path |
|
||||||
|
| `gitea_runner_prune_until` | `24h` | Prune resources older than this |
|
||||||
|
| `gitea_runner_prune_schedule` | `daily` | systemd timer schedule |
|
||||||
|
| `gitea_runner_prune_label` | `gitea-runner=true` | Docker label for pruning |
|
||||||
|
| `gitea_runner_service_restart_sec` | `5` | systemd RestartSec value |
|
||||||
|
| `gitea_runner_service_user` | `{{ ansible_user \| default('root') }}` | Service user |
|
||||||
|
| `gitea_runner_log_level` | `info` | Runner log level |
|
||||||
|
| `gitea_runner_container_label` | `gitea-runner=true` | Container label |
|
||||||
|
| `docker_gpg_key_path` | `/etc/apt/keyrings/docker.asc` | Docker GPG key path |
|
||||||
|
|
||||||
|
Override any variable by passing it to the CLI with `--extra-vars` or by setting it in your Ansible inventory.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── src/gitea_runner_manager/ # Python CLI source
|
||||||
|
│ ├── cli.py # Click commands
|
||||||
|
│ ├── runner_manager.py # Ansible orchestration
|
||||||
|
│ └── exceptions.py # Custom exceptions
|
||||||
|
├── ansible/
|
||||||
|
│ ├── roles/gitea-runner/ # Main Ansible role
|
||||||
|
│ │ ├── defaults/main.yml # Default variables
|
||||||
|
│ │ ├── tasks/ # Task files
|
||||||
|
│ │ ├── templates/ # Jinja2 templates
|
||||||
|
│ │ └── molecule/ # Test scenarios
|
||||||
|
│ ├── install-runner.yml # Install playbook
|
||||||
|
│ └── update-runner.yml # Update playbook
|
||||||
|
├── tests/ # Unit tests
|
||||||
|
├── Makefile # Build & test automation
|
||||||
|
└── pyproject.toml # Python project metadata
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setup Development Environment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make setup # Creates venv, installs deps, sets up hooks
|
||||||
|
source .venv/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running Linters
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make lint # Python (ruff + pyright)
|
||||||
|
make ansible-lint # Ansible
|
||||||
|
make makefile-lint # Makefile
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Unit Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test-unit
|
||||||
|
```
|
||||||
|
|
||||||
|
Runs pytest with 100% coverage requirement.
|
||||||
|
|
||||||
|
### Molecule Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make molecule
|
||||||
|
```
|
||||||
|
|
||||||
|
Runs two scenarios:
|
||||||
|
|
||||||
|
- **default** — Docker mode installation in an Ubuntu 22.04 container
|
||||||
|
- **binary** — Binary mode installation in an Ubuntu 22.04 container
|
||||||
|
|
||||||
|
Both scenarios test idempotence (second run produces zero changes).
|
||||||
|
|
||||||
|
### Full Test Suite
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test-all # Runs unit tests + linters + molecule
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Event loop is closed" warning
|
||||||
|
|
||||||
|
This is a harmless cleanup traceback from Molecule's Docker driver when the test process is interrupted. It does not indicate a test failure.
|
||||||
|
|
||||||
|
### Runner appears offline after installation
|
||||||
|
|
||||||
|
- Check that the `GITEA_URL` and `GITEA_REGISTRATION_TOKEN` environment variables are correct.
|
||||||
|
- Verify the runner container or service is running: `docker ps` or `systemctl status gitea-runner-<name>`.
|
||||||
|
- Check logs for registration errors.
|
||||||
|
|
||||||
|
### Docker mode: container won't start
|
||||||
|
|
||||||
|
- Ensure Docker is installed and running on the host.
|
||||||
|
- Verify the Docker socket is accessible: `docker version`.
|
||||||
|
|
||||||
|
### Binary mode: systemd service fails
|
||||||
|
|
||||||
|
- Check the service status: `systemctl status gitea-runner-<name>`.
|
||||||
|
- Verify the binary exists at `gitea_runner_binary_path`.
|
||||||
|
- Ensure the service user is in the `docker` group.
|
||||||
|
|
||||||
## Makefile Targets
|
## Makefile Targets
|
||||||
|
|
||||||
| Target | Description |
|
| Target | Description |
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| `setup` | Full environment setup |
|
| `setup` | Full environment setup |
|
||||||
| `install` | Installs a runner on a host |
|
| `install` | Installs a runner on a host (`MODE=docker` or `binary`) |
|
||||||
|
| `update` | Updates a runner on a host (`MODE=docker` or `binary`) |
|
||||||
| `lint` | Runs Python linters |
|
| `lint` | Runs Python linters |
|
||||||
| `ansible-lint` | Runs `ansible-lint` |
|
| `ansible-lint` | Runs `ansible-lint` |
|
||||||
| `test-unit` | Runs unit tests with coverage |
|
| `test-unit` | Runs unit tests with coverage |
|
||||||
|
|||||||
@@ -1,3 +1,14 @@
|
|||||||
|
# Gitea Runner Manager inventory example
|
||||||
|
# Each line represents a target host for runner installation.
|
||||||
|
#
|
||||||
|
# Required variables per host:
|
||||||
|
# ansible_user — SSH login user
|
||||||
|
# ansible_ssh_private_key_file — Path to SSH private key
|
||||||
|
#
|
||||||
|
# Optional variables per host:
|
||||||
|
# runner_mode=docker — Deployment mode: docker or binary
|
||||||
|
# gitea_runner_version=1.0.8 — Runner image/binary version
|
||||||
|
|
||||||
[runners]
|
[runners]
|
||||||
192.168.1.10 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_ed25519
|
192.168.1.10 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_ed25519
|
||||||
runner.example.com ansible_user=arch
|
runner.example.com ansible_user=arch ansible_ssh_private_key_file=~/.ssh/id_ed25519 runner_mode=binary
|
||||||
|
|||||||
Reference in New Issue
Block a user