Compare commits

...
Author SHA1 Message Date
Emil Simeonov 7c34c96b7f chore: trigger CI 2026-08-03 17:36:02 +02:00
Emil Simeonov 555fe7eb3b fix: compress setup-image to satisfy makefile-lint 2026-08-03 17:31:52 +02:00
Emil Simeonov 258b505d4a fix: update Vikunja project ID to 3 2026-08-03 17:21:50 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> cacbe72f92 fix: configure git auth in setup-image for git+https deps
Add git config url.insteadOf rewrite so pip can clone private
git+https dependencies (devx) using the CI token.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-03 17:17:04 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> e0e09aa70b chore: bump devx to v0.47.5
Includes wiki sync fix (push to main instead of master) and User-Agent
header fix for downloads.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-03 17:10:14 +02:00
gitea-actions-bot 8e9e58fedb chore: update badge URLs to commit 69e62973 [skip ci] 2026-07-17 02:03:11 +00:00
emil User 70d985ebaa GRM-155: chore: bump devx to v0.47.2 2026-07-17 02:00:23 +00:00
gitea-actions-bot 66f071b676 chore: update badge URLs to commit 7ee78d01 [skip ci] 2026-07-16 17:42:23 +00:00
grm-ci-bot 7e18d285ab release: v0.18.2 [skip ci] 2026-07-16 17:41:52 +00:00
emil User f6ba60bda6 GRM-154: fix: load tun module and pre-configure systemd override for Arch rootless Docker 2026-07-16 17:39:31 +00:00
gitea-actions-bot 0545388b34 chore: update badge URLs to commit bf77093c [skip ci] 2026-07-16 15:59:16 +00:00
grm-ci-bot eb0a56350b release: v0.18.1 [skip ci] 2026-07-16 15:58:51 +00:00
emil User f712a4493e GRM-152: fix: fetch rootless Docker scripts on Arch Linux 2026-07-16 15:56:59 +00:00
gitea-actions-bot 9289b19162 chore: update badge URLs to commit 1249a783 [skip ci] 2026-07-16 15:45:18 +00:00
emil User 185251090f GRM-153: chore: bump devx from v0.45.1 to v0.47.1 2026-07-16 15:43:09 +00:00
15 changed files with 150 additions and 30 deletions
+2 -2
View File
@@ -98,7 +98,7 @@ jobs:
env:
VIKUNJA_TOKEN: ${{ secrets.VIKUNJA_TOKEN }}
DEVX_TASK_PREFIX: GRM
DEVX_VIKUNJA_PROJECT_ID: 6
DEVX_VIKUNJA_PROJECT_ID: 3
HEAD_REF: ${{ github.head_ref }}
PR_TITLE: ${{ github.event.pull_request.title }}
REPOSITORY: ${{ github.repository }}
@@ -255,7 +255,7 @@ jobs:
CI_GITEA_API_TOKEN: ${{ secrets.CI_GITEA_API_TOKEN }}
VIKUNJA_TOKEN: ${{ secrets.VIKUNJA_TOKEN }}
DEVX_TASK_PREFIX: GRM
DEVX_VIKUNJA_PROJECT_ID: 6
DEVX_VIKUNJA_PROJECT_ID: 3
HEAD_REF: ${{ github.head_ref }}
PR_TITLE: ${{ github.event.pull_request.title }}
REPOSITORY: ${{ github.repository }}
+2 -2
View File
@@ -133,7 +133,7 @@ jobs:
env:
DEVX_VERSION_FILE: src/grm/__init__.py
DEVX_TASK_PREFIX: GRM
DEVX_VIKUNJA_PROJECT_ID: 6
DEVX_VIKUNJA_PROJECT_ID: 3
run: |
. .venv/bin/activate 2>/dev/null || true
export PATH="$HOME/.local/bin:$PATH"
@@ -161,7 +161,7 @@ jobs:
env:
VIKUNJA_TOKEN: ${{ secrets.VIKUNJA_TOKEN }}
DEVX_TASK_PREFIX: GRM
DEVX_VIKUNJA_PROJECT_ID: 6
DEVX_VIKUNJA_PROJECT_ID: 3
run: |
. .venv/bin/activate 2>/dev/null || true
python3 -m devx.ci.post_merge --git-sha "${{ github.sha }}"
+6
View File
@@ -475,6 +475,12 @@ main.yml → systemd_check → user_setup → rootless_docker → install_runner
- `main.yml` handles: prune, integration_test (NOT install_runner — avoids duplicates)
- `systemctl --user` tasks must be guarded by `docker_rootless_setup`
- Template creation tasks are NOT guarded by `docker_rootless_setup` (they only create files)
- On Arch Linux, `rootless_docker.yml` fetches the rootless setup scripts
(`dockerd-rootless-setuptool.sh`, `dockerd-rootless.sh`) from `moby/moby` `contrib/`
at a pinned ref (`gitea_runner_rootless_scripts_ref`) into `/usr/bin` and installs
`rootlesskit` — Arch's `docker` package ships neither. These fetch tasks run
regardless of `docker_rootless_setup` so CI exercises them on the archlinux platform.
See ADR-011 in the decision log.
## Molecule Scenarios
+12
View File
@@ -2,6 +2,18 @@
All notable changes to this project will be documented in this file.
## [0.18.2] - 2026-07-16
### Bug Fixes
- Load tun module and pre-configure systemd override for Arch rootless Docker
## [0.18.1] - 2026-07-16
### Bug Fixes
- Fetch rootless Docker scripts on Arch Linux
## [0.18.0] - 2026-07-12
### Features
+1 -1
View File
@@ -88,7 +88,7 @@ setup-release: $(VENV)/bin/activate .env configure-gitea-pypi
setup-image:
@if [ -d /opt/venv ]; then ln -sf /opt/venv .venv; . .venv/bin/activate; \
_TOKEN="$$CI_GITEA_API_TOKEN"; [ -z "$$_TOKEN" ] && _TOKEN="$$DEVELOPER_GITEA_API_TOKEN"; [ -z "$$_TOKEN" ] && _TOKEN="$$CI_GITEA_TOKEN"; \
if [ -n "$$_TOKEN" ]; then export PIP_EXTRA_INDEX_URL="https://$$CI_GITEA_USERNAME:$${_TOKEN}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"; fi; \
if [ -n "$$_TOKEN" ]; then export PIP_EXTRA_INDEX_URL="https://$$CI_GITEA_USERNAME:$${_TOKEN}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"; git config --global url."https://$$CI_GITEA_USERNAME:$${_TOKEN}@git.oblachno.oblachno.fyi/".insteadOf "https://git.oblachno.oblachno.fyi/"; fi; \
pip install -e .$(if $(EXTRAS),[$(EXTRAS)],); \
else echo "[setup-image] /opt/venv not found — falling back to setup-ci"; $(MAKE) setup-ci; fi
+6 -6
View File
@@ -8,12 +8,12 @@ Each runner runs in an isolated **rootless Docker** environment under a dedicate
[![CI](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions/workflows/ci.yml/badge.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![License: GPL-3.0](https://img.shields.io/badge/license-GPL--3.0-blue)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/src/branch/master/LICENSE)
[![Coverage](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/66400175dde113540d30b5d94fa458a96c092231/coverage.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Tests](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/66400175dde113540d30b5d94fa458a96c092231/tests.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Docs](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/66400175dde113540d30b5d94fa458a96c092231/docs.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
[![Code Quality](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/66400175dde113540d30b5d94fa458a96c092231/quality.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Version](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/66400175dde113540d30b5d94fa458a96c092231/version.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
[![Python](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/66400175dde113540d30b5d94fa458a96c092231/python.svg)](https://www.python.org/downloads/)
[![Coverage](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/69e62973f488eb61d5d32b9454037f75b9b2bcb7/coverage.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Tests](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/69e62973f488eb61d5d32b9454037f75b9b2bcb7/tests.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Docs](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/69e62973f488eb61d5d32b9454037f75b9b2bcb7/docs.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
[![Code Quality](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/69e62973f488eb61d5d32b9454037f75b9b2bcb7/quality.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Version](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/69e62973f488eb61d5d32b9454037f75b9b2bcb7/version.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
[![Python](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/69e62973f488eb61d5d32b9454037f75b9b2bcb7/python.svg)](https://www.python.org/downloads/)
## Why GRM?
@@ -54,6 +54,16 @@ gitea_runner_docker_apt_source_line: >-
# Set to false in CI/molecule to skip rootless daemon startup (needs kernel userns)
gitea_runner_docker_rootless_setup: true
# Rootless Docker helper scripts (dockerd-rootless-setuptool.sh / dockerd-rootless.sh).
# Arch Linux's "docker" package does not ship these (unlike Debian's docker-ce-rootless-extras),
# and no official Arch package provides them. They are fetched from the upstream moby/moby
# "contrib/" directory at the git ref below. The scripts are stable bash wrappers that are
# version-agnostic with respect to the dockerd binary, so a pinned ref is safe.
gitea_runner_rootless_scripts_ref: "v28.5.1"
# Install dir MUST match the location of the "docker" / "dockerd" / "rootlesskit" binaries so
# that dockerd-rootless-setuptool.sh (which derives BIN from its own dirname) finds them co-located.
gitea_runner_rootless_scripts_install_dir: "/usr/bin"
# Rootless Docker network driver: "pasta" (IPv6 support) or "slirp4netns" (IPv4 only)
# pasta has proper outgoing IPv6 support; slirp4netns does not (known limitation).
gitea_runner_docker_rootless_net_driver: "pasta"
@@ -62,14 +62,86 @@
- passt
- fuse-overlayfs
- rsync
# rootlesskit is the userspace networking/namespace driver for rootless Docker.
# It is NOT a dependency of the "docker" package on Arch and must be installed explicitly.
- rootlesskit
state: present
when: ansible_facts['os_family'] == 'Archlinux'
# The tun kernel module is required by rootlesskit (both slirp4netns and pasta
# drivers create a tap device inside a user namespace). On Arch Linux, CONFIG_TUN=m
# so the module must be loaded. If the running kernel doesn't match the installed
# kernel (e.g. after a pacman -Syu that upgraded linux but didn't reboot), modprobe
# will fail — in that case we warn but don't fail, as a reboot will fix it.
- name: Load tun kernel module for rootless networking
community.general.modprobe:
name: tun
state: present
ignore_errors: true
register: gitea_runner_tun_module
when: ansible_facts['os_family'] == 'Archlinux'
- name: Warn if tun module could not be loaded (kernel mismatch — reboot needed)
ansible.builtin.debug:
msg: >-
WARNING: Could not load the tun kernel module. This is likely because the
running kernel ({{ ansible_facts['kernel'] }}) does not match the installed
kernel modules. A reboot is required before rootless Docker can start.
when:
- ansible_facts['os_family'] == 'Archlinux'
- gitea_runner_tun_module is failed
# Arch Linux's "docker" package does not ship the rootless setup scripts (dockerd-rootless-setuptool.sh
# and dockerd-rootless.sh), unlike Debian/Ubuntu's docker-ce-rootless-extras. No official Arch package
# provides them, so fetch them from the upstream moby/moby contrib/ directory. They are installed
# alongside the docker binaries (/usr/bin) because dockerd-rootless-setuptool.sh derives its BIN
# directory from its own location and expects docker/dockerd/rootlesskit to be co-located there.
- name: Fetch rootless Docker setup scripts (Arch Linux)
ansible.builtin.get_url:
url: "https://raw.githubusercontent.com/moby/moby/{{ gitea_runner_rootless_scripts_ref }}/contrib/{{ item.name }}"
dest: "{{ gitea_runner_rootless_scripts_install_dir }}/{{ item.name }}"
mode: "0755"
owner: root
group: root
loop:
- name: dockerd-rootless-setuptool.sh
- name: dockerd-rootless.sh
when: ansible_facts['os_family'] == 'Archlinux'
- name: Check if rootless Docker is already set up
ansible.builtin.stat:
path: "{{ gitea_runner_home }}/.config/systemd/user/docker.service"
register: gitea_runner_rootless_docker_check
# Create the systemd override BEFORE running the setuptool so that when
# the setuptool starts docker.service, it picks up the pasta network driver
# instead of the default slirp4netns (which may fail on some kernels).
- name: Ensure systemd user override directory exists
ansible.builtin.file:
path: "{{ gitea_runner_home }}/.config/systemd/user/docker.service.d"
state: directory
mode: "0755"
owner: "{{ gitea_runner_service_user }}"
group: "{{ gitea_runner_service_user }}"
when:
- gitea_runner_docker_rootless_setup
- not gitea_runner_rootless_docker_check.stat.exists
- name: Pre-configure rootless Docker network driver override
ansible.builtin.copy:
dest: "{{ gitea_runner_home }}/.config/systemd/user/docker.service.d/override.conf"
content: |
[Service]
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_NET={{ gitea_runner_docker_rootless_net_driver }}"
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=implicit"
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS=--ipv6"
mode: "0644"
owner: "{{ gitea_runner_service_user }}"
group: "{{ gitea_runner_service_user }}"
when:
- gitea_runner_docker_rootless_setup
- not gitea_runner_rootless_docker_check.stat.exists
- name: Set up rootless Docker for runner user
ansible.builtin.command: dockerd-rootless-setuptool.sh install
args:
@@ -78,6 +150,7 @@
become_user: "{{ gitea_runner_service_user }}"
environment:
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
DOCKERD_ROOTLESS_ROOTLESSKIT_NET: "{{ gitea_runner_docker_rootless_net_driver }}"
when:
- gitea_runner_docker_rootless_setup
- not gitea_runner_rootless_docker_check.stat.exists
@@ -109,15 +182,6 @@
group: "{{ gitea_runner_service_user }}"
when: gitea_runner_docker_rootless_setup
- name: Ensure systemd user override directory exists
ansible.builtin.file:
path: "{{ gitea_runner_home }}/.config/systemd/user/docker.service.d"
state: directory
mode: "0755"
owner: "{{ gitea_runner_service_user }}"
group: "{{ gitea_runner_service_user }}"
when: gitea_runner_docker_rootless_setup
- name: Configure rootless Docker to use pasta with IPv6
ansible.builtin.copy:
dest: "{{ gitea_runner_home }}/.config/systemd/user/docker.service.d/override.conf"
+6 -6
View File
@@ -8,12 +8,12 @@ Each runner runs in an isolated **rootless Docker** environment under a dedicate
[![CI](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions/workflows/ci.yml/badge.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![License: GPL-3.0](https://img.shields.io/badge/license-GPL--3.0-blue)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/src/branch/master/LICENSE)
[![Coverage](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/66400175dde113540d30b5d94fa458a96c092231/coverage.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Tests](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/66400175dde113540d30b5d94fa458a96c092231/tests.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Docs](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/66400175dde113540d30b5d94fa458a96c092231/docs.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
[![Code Quality](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/66400175dde113540d30b5d94fa458a96c092231/quality.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Version](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/66400175dde113540d30b5d94fa458a96c092231/version.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
[![Python](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/66400175dde113540d30b5d94fa458a96c092231/python.svg)](https://www.python.org/downloads/)
[![Coverage](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/69e62973f488eb61d5d32b9454037f75b9b2bcb7/coverage.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Tests](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/69e62973f488eb61d5d32b9454037f75b9b2bcb7/tests.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Docs](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/69e62973f488eb61d5d32b9454037f75b9b2bcb7/docs.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
[![Code Quality](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/69e62973f488eb61d5d32b9454037f75b9b2bcb7/quality.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Version](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/69e62973f488eb61d5d32b9454037f75b9b2bcb7/version.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
[![Python](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/69e62973f488eb61d5d32b9454037f75b9b2bcb7/python.svg)](https://www.python.org/downloads/)
## Overview
+8 -1
View File
@@ -53,7 +53,7 @@ main.yml → systemd_check → user_setup → rootless_docker → install_runner
| `main.yml` | Entry point — includes all other task files in order |
| `systemd_check.yml` | Verifies systemd is available on the target host |
| `user_setup.yml` | Creates the per-runner system user, enables lingering, configures subuid/subgid, creates data and config directories |
| `rootless_docker.yml` | Installs Docker packages (apt for Debian/Ubuntu, pacman for Arch), runs `dockerd-rootless-setuptool.sh install`, starts and enables the rootless Docker daemon |
| `rootless_docker.yml` | Installs Docker packages (apt for Debian/Ubuntu, pacman for Arch), provisions the rootless setup scripts on Arch (not shipped by the `docker` package), runs `dockerd-rootless-setuptool.sh install`, starts and enables the rootless Docker daemon |
| `install_runner.yml` | Downloads the gitea_runner binary, creates the config file, validates the binary, registers the runner with Gitea, creates and starts the systemd user service |
| `download_gitea_runner.yml` | Downloads the gitea_runner binary from GitHub releases |
| `validate.yml` | Validates the downloaded binary |
@@ -190,6 +190,13 @@ per-workaround DNS hacks.
Containers launched by the runner never have root access to the host. The rootless Docker daemon is started as a systemd user service and persists via lingering.
#### Platform-specific rootless provisioning
The rootless setup scripts (`dockerd-rootless-setuptool.sh` and `dockerd-rootless.sh`) are provided differently per OS:
- **Debian/Ubuntu** — shipped by the `docker-ce-rootless-extras` package (installed via the Docker APT repo).
- **Arch Linux** — the `docker` package does **not** include these scripts, and no official Arch package provides them. The role fetches them from the upstream `moby/moby` `contrib/` directory at a pinned, overridable git ref (`gitea_runner_rootless_scripts_ref`, default `v28.5.1`) and installs them into `/usr/bin` — co-located with `docker`/`dockerd`/`rootlesskit`, which is required because `dockerd-rootless-setuptool.sh` derives its `BIN` directory from its own location and expects those binaries alongside it. The `rootlesskit` package (a required rootless runtime dependency that is not pulled in by Arch's `docker` package) is also installed explicitly.
### Secret handling
Registration tokens and admin API tokens are never exposed on the command line. The `RunnerManager._extra_vars_file()` context manager:
+10
View File
@@ -121,3 +121,13 @@ Key technical decisions for the GRM project, extracted from `CHANGELOG.md` and `
**Rationale:** Hardcoding the number of CI runners would require manual updates when runners are added or removed. Dynamic discovery auto-detects repo/org-level runners via the API. For instance-level runners (which may not be visible without admin scope), it falls back to the `MOLECULE_RUNNERS` repo variable, then to a default of 3. The workflow automatically scales the matrix to match available runners, distributing test pairs evenly.
**Source:** `AGENTS.md` (Dynamic Runner Discovery), `.gitea/workflows/ci.yml` (discover-runners step in the validate job)
---
## ADR-011: Fetch Rootless Docker Scripts from moby/moby on Arch Linux
**Date:** 2026-07-16 (v0.19.0)
**Decision:** On Arch Linux, fetch the rootless Docker setup scripts (`dockerd-rootless-setuptool.sh` and `dockerd-rootless.sh`) from the upstream `moby/moby` `contrib/` directory at a pinned git ref (`gitea_runner_rootless_scripts_ref`, default `v28.5.1`) and install them into `/usr/bin`. Install the `rootlesskit` package explicitly.
**Rationale:** Arch's `docker` package does not ship the rootless setup scripts (unlike Debian/Ubuntu's `docker-ce-rootless-extras`), and no official Arch package provides them (`pkgfile` confirms zero providers). `rootlesskit` — the required userspace networking/namespace driver — is also not a dependency of the `docker` package and must be installed explicitly. Without these, `grm install` fails with `No such file or directory: dockerd-rootless-setuptool.sh`. The scripts are installed into `/usr/bin` (not `/usr/local/bin`) because `dockerd-rootless-setuptool.sh` derives its `BIN` directory from its own location and expects `docker`, `dockerd`, and `rootlesskit` to be co-located. The scripts are stable, version-agnostic bash wrappers, so a pinned ref is safe across `dockerd` versions; the ref is overridable via `gitea_runner_rootless_scripts_ref`. This bug was not caught by CI because molecule scenarios run with `gitea_runner_docker_rootless_setup: false` (rootless daemon startup needs kernel userns unavailable in CI containers), so the Arch rootless path was never exercised — the script-fetch tasks now run regardless of that flag to provide URL-validation coverage.
+2
View File
@@ -105,6 +105,8 @@ grm remove prod-runner --force
GRM supports Arch Linux (rolling), Ubuntu 22.04/24.04, and Debian 12. All supported OSes are tested in CI via Molecule scenarios on every PR that changes Ansible files.
On Arch Linux, the rootless Docker setup scripts (`dockerd-rootless-setuptool.sh`, `dockerd-rootless.sh`) and the `rootlesskit` runtime are provisioned automatically — Arch's `docker` package does not ship them. No extra setup is required.
## How to change the UI language
Set the `GRM_LANG` environment variable to one of the supported languages: `en` (English, default), `bg` (Bulgarian), `de` (German), `ru` (Russian), `zh` (Chinese), `pl` (Polish).
+9
View File
@@ -2,6 +2,14 @@
## Installation Issues
### `No such file or directory: dockerd-rootless-setuptool.sh` (Arch Linux)
**Symptom:** `grm install` fails on an Arch Linux host during rootless Docker setup with `Error executing command: [Errno 2] No such file or directory: b'dockerd-rootless-setuptool.sh'`.
**Cause:** Arch's `docker` package does not ship the rootless setup scripts (unlike Debian/Ubuntu's `docker-ce-rootless-extras`), and `rootlesskit` is not a dependency of the `docker` package.
**Solution:** This is handled automatically by GRM ≥ v0.19.0. Ensure you are on the latest release (`git checkout $(git describe --tags --abbrev=0)`). The role fetches the scripts from upstream `moby/moby` and installs `rootlesskit` automatically. If it still fails, verify the host can reach `raw.githubusercontent.com` (the script source) and check the Ansible log under `~/.local/state/grm/logs/`.
### Ansible connection fails (UNREACHABLE)
**Symptom:** Ansible reports `UNREACHABLE` when trying to connect to the target host.
@@ -179,6 +187,7 @@ If Docker is not installed, install it via your package manager or [Docker's off
| Symptom | Likely Cause | Solution |
|---------|-------------|----------|
| Ansible UNREACHABLE | SSH connection failed | Verify `--user`, `--key`, and host reachability |
| `No such file ... dockerd-rootless-setuptool.sh` (Arch) | Arch `docker` pkg lacks rootless scripts + `rootlesskit` | Fixed in v0.19.0; update GRM to latest release |
| `GITEA_URL must be set` | Missing environment variable | Set `GITEA_URL` in `.env` or pass `--url` |
| `GITEA_REGISTRATION_TOKEN must be set` | Missing environment variable | Set `GITEA_REGISTRATION_TOKEN` in `.env` or pass `--token` |
| Runner appears offline | Registration failed or service not running | Check GITEA_URL, token validity, and service status |
+2 -2
View File
@@ -35,7 +35,7 @@ ci = [
"build==1.5.1",
"twine==6.2.0",
# Reusable CI/CD and dev tools (auto-merge, pr-review, pre-push checks, etc.)
"devx @ git+https://git.oblachno.oblachno.fyi/oblachno-oss/devx.git@v0.45.1",
"devx @ git+https://git.oblachno.oblachno.fyi/oblachno-oss/devx.git@v0.47.5",
]
# Lint and type-checking tools (validate job)
lint = [
@@ -55,7 +55,7 @@ molecule = [
dev = [
"grm[ci,lint,molecule]",
# Reusable CI/CD and dev tools (pre-push hooks, create-task, create-pr)
"devx @ git+https://git.oblachno.oblachno.fyi/oblachno-oss/devx.git@v0.45.1",
"devx @ git+https://git.oblachno.oblachno.fyi/oblachno-oss/devx.git@v0.47.5",
# Non-Python dev dependency: checkmake (Makefile linter)
# Install via: go install github.com/checkmake/checkmake/cmd/checkmake@latest
]
+1 -1
View File
@@ -1,3 +1,3 @@
"""Gitea Runner Manager — lean CLI for managing Gitea Actions runners."""
__version__ = "0.18.0"
__version__ = "0.18.2"