Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62b37d045e | ||
|
|
390fcb9d4b | ||
|
|
9f8adf14bc | ||
|
|
92e4d2fd2b | ||
|
|
f30764d60f | ||
|
|
a0e3fc09c9 |
+1
-1
@@ -51,7 +51,7 @@ GITEA_REGISTRATION_TOKEN=your-registration-token
|
||||
# Used by PIP_INSTALL to configure PIP_EXTRA_INDEX_URL
|
||||
CI_GITEA_USERNAME=your-gitea-username
|
||||
|
||||
# Role-based Gitea API tokens (devx 0.38.0+)
|
||||
# Role-based Gitea API tokens (devx 0.40.0+)
|
||||
# DEVELOPER_GITEA_API_TOKEN is used by local `grm trigger-workflow` and `make create-pr`.
|
||||
# CI_GITEA_API_TOKEN is used by CI workflows (and accepted as a fallback for local tools).
|
||||
# REVIEWER_GITEA_API_TOKEN is used by CI to post APPROVE reviews; it must belong to a
|
||||
|
||||
@@ -57,7 +57,7 @@ CI also runs a best-effort `make workflow-dryrun` step (skipped if act_runner is
|
||||
## Architecture
|
||||
|
||||
- **Python CLI** (`src/grm/`) — Click-based CLI that delegates to Ansible
|
||||
- **Ansible Role** (`ansible/roles/gitea-runner/`) — Idempotent role for rootless Docker runner setup
|
||||
- **Ansible Role** (`ansible/roles/gitea-runner/`) — Idempotent role for rootless Docker runner setup with pasta networking (IPv6 support)
|
||||
- **devx package** (installed from git) — Reusable CI/CD tools: auto-merge, post-merge, release, publishing, molecule distribution, PR reviews, failure notifications
|
||||
- **Versioning** (`cliff.toml`) — git-cliff configuration for automated semver versioning from conventional commits
|
||||
|
||||
@@ -84,6 +84,12 @@ as a defense-in-depth measure, but branch protection is the primary gate.
|
||||
### 1. Create Vikunja Task
|
||||
Create a task in Vikunja project 6 via `make create-task -- --title "Task title" --description "<h2>...</h2>"` (requires `VIKUNJA_TOKEN` in `.env`). This prints the `GRM-N` identifier and next-step instructions.
|
||||
|
||||
**IMPORTANT:** The task title must NOT include the `GRM-N:` prefix.
|
||||
The `make create-pr` and `check_auto_merge_ready` commands automatically
|
||||
prepend `GRM-N: ` to the Vikunja task title when forming the PR title.
|
||||
If the Vikunja task title already includes the prefix, the PR title will
|
||||
have a double prefix and auto-merge validation will fail.
|
||||
|
||||
### 2. Create Branch
|
||||
```bash
|
||||
git checkout master && git pull
|
||||
|
||||
@@ -2,6 +2,18 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.18.0] - 2026-07-12
|
||||
|
||||
### Features
|
||||
|
||||
- *(runner)* Enable IPv6 in rootless Docker via pasta network driver
|
||||
|
||||
## [0.17.2] - 2026-07-11
|
||||
|
||||
### Refactor
|
||||
|
||||
- Adopt devx v0.40.0
|
||||
|
||||
## [0.17.1] - 2026-07-09
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -8,12 +8,12 @@ Each runner runs in an isolated **rootless Docker** environment under a dedicate
|
||||
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/src/branch/master/LICENSE)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
|
||||
[](https://www.python.org/downloads/)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
|
||||
[](https://www.python.org/downloads/)
|
||||
|
||||
## Why GRM?
|
||||
|
||||
|
||||
@@ -53,3 +53,10 @@ docker_apt_source_line: >-
|
||||
{{ ansible_facts['distribution_release'] }} stable
|
||||
# Set to false in CI/molecule to skip rootless daemon startup (needs kernel userns)
|
||||
docker_rootless_setup: true
|
||||
|
||||
# Rootless Docker network driver: "pasta" (IPv6 support) or "slirp4netns" (IPv4 only)
|
||||
# pasta has proper outgoing IPv6 support; slirp4netns does not (known limitation).
|
||||
docker_rootless_net_driver: "pasta"
|
||||
|
||||
# IPv6 subnet for rootless Docker containers (ULA range, not routable on internet)
|
||||
docker_ipv6_cidr: "fd00:dead:beef::/48"
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
name:
|
||||
- uidmap
|
||||
- slirp4netns
|
||||
- passt
|
||||
- fuse-overlayfs
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
@@ -57,6 +58,7 @@
|
||||
- docker
|
||||
- docker-compose
|
||||
- slirp4netns
|
||||
- passt
|
||||
- fuse-overlayfs
|
||||
- rsync
|
||||
state: present
|
||||
@@ -106,12 +108,48 @@
|
||||
group: "{{ gitea_runner_service_user }}"
|
||||
when: docker_rootless_setup
|
||||
|
||||
- name: Configure rootless Docker to disable IPv6
|
||||
- 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: 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"
|
||||
content: |
|
||||
[Service]
|
||||
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_NET={{ 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 }}"
|
||||
register: docker_network_override
|
||||
when: docker_rootless_setup
|
||||
|
||||
- name: Reload systemd user daemon if network config changed
|
||||
ansible.builtin.command: systemctl --user daemon-reload
|
||||
become: true
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
changed_when: true
|
||||
when:
|
||||
- docker_rootless_setup
|
||||
- docker_network_override is changed
|
||||
|
||||
- name: Configure rootless Docker daemon with IPv6 enabled
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ gitea_runner_home }}/.config/docker/daemon.json"
|
||||
content: |
|
||||
{
|
||||
"ipv6": false
|
||||
"ipv6": true,
|
||||
"ip6tables": true,
|
||||
"fixed-cidr-v6": "{{ docker_ipv6_cidr }}"
|
||||
}
|
||||
mode: "0644"
|
||||
owner: "{{ gitea_runner_service_user }}"
|
||||
@@ -128,7 +166,7 @@
|
||||
changed_when: true
|
||||
when:
|
||||
- docker_rootless_setup
|
||||
- docker_ipv6_config is changed
|
||||
- docker_ipv6_config is changed or docker_network_override is changed
|
||||
|
||||
- name: Wait for rootless Docker daemon to be ready
|
||||
ansible.builtin.command: docker version
|
||||
|
||||
+6
-6
@@ -8,12 +8,12 @@ Each runner runs in an isolated **rootless Docker** environment under a dedicate
|
||||
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/src/branch/master/LICENSE)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
|
||||
[](https://www.python.org/downloads/)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
|
||||
[](https://www.python.org/downloads/)
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -173,9 +173,21 @@ Each runner operates under a dedicated unprivileged system user. The Docker daem
|
||||
|
||||
- User namespace mapping via `/etc/subuid` and `/etc/subgid` (range: 100000-165535)
|
||||
- Rootless Docker socket at `/run/user/<UID>/docker.sock`
|
||||
- `slirp4netns` for user-mode networking
|
||||
- `pasta` for user-mode networking with IPv6 support (replaces `slirp4netns`, which lacks outgoing IPv6)
|
||||
- `fuse-overlayfs` for rootless container storage
|
||||
|
||||
The rootless Docker daemon is configured via a systemd user override
|
||||
(`docker.service.d/override.conf`) that sets:
|
||||
|
||||
- `DOCKERD_ROOTLESS_ROOTLESSKIT_NET=pasta` — use pasta as the network driver
|
||||
- `DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=implicit` — pasta's native port forwarding
|
||||
- `DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS=--ipv6` — enable IPv6 routing
|
||||
|
||||
The daemon.json enables IPv6 with a ULA subnet (`fd00:dead:beef::/48`)
|
||||
for container addressing. This ensures runner containers can reach
|
||||
both IPv4 and IPv6 services (e.g., the Gitea registry) without
|
||||
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.
|
||||
|
||||
### Secret handling
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ ci = [
|
||||
"build==1.5.0",
|
||||
"twine==6.2.0",
|
||||
# Reusable CI/CD and dev tools (auto-merge, pr-review, pre-push checks, etc.)
|
||||
"devx==0.38.0",
|
||||
"devx==0.40.0",
|
||||
]
|
||||
# Lint and type-checking tools (quality job)
|
||||
lint = [
|
||||
@@ -54,7 +54,7 @@ molecule = [
|
||||
dev = [
|
||||
"grm[ci,lint,molecule]",
|
||||
# Reusable CI/CD and dev tools (pre-push hooks, create-task, create-pr)
|
||||
"devx==0.38.0",
|
||||
"devx==0.40.0",
|
||||
# Non-Python dev dependency: checkmake (Makefile linter)
|
||||
# Install via: go install github.com/checkmake/checkmake/cmd/checkmake@latest
|
||||
]
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
"""Gitea Runner Manager — lean CLI for managing Gitea Actions runners."""
|
||||
|
||||
__version__ = "0.17.1"
|
||||
__version__ = "0.18.0"
|
||||
|
||||
Reference in New Issue
Block a user