From f6a4f1fe43b1c2ec9e2466e0ba7a551ad5e40667 Mon Sep 17 00:00:00 2001 From: emil User Date: Mon, 13 Jul 2026 03:24:35 +0000 Subject: [PATCH] GRM-148: chore: bump devx to v0.41.1, update deps and runner version --- .gitea/workflows/ci.yml | 4 +- AGENTS.md | 2 +- Makefile | 2 +- README.md | 8 +- ansible/disable-runner.yml | 12 +-- ansible/enable-runner.yml | 6 +- ansible/install-runner.yml | 2 +- ansible/remove-runner.yml | 68 ++++++------ ansible/requirements.yml | 2 +- ansible/restart-runner.yml | 4 +- .../molecule/default/converge.yml | 12 --- .../molecule/deregister/converge.yml | 12 --- .../molecule/lifecycle/converge.yml | 12 --- .../gitea-runner/molecule/remove/converge.yml | 12 --- .../molecule/template-content/converge.yml | 12 --- .../gitea-runner/molecule/update/converge.yml | 12 --- .../roles/gitea-runner/tasks/deregister.yml | 58 ---------- .../gitea-runner/tasks/integration_test.yml | 102 ------------------ .../defaults/main.yml | 34 +++--- .../handlers/main.yml | 2 +- .../molecule/common/prepare.yml | 0 .../molecule/default/converge.yml | 12 +++ .../molecule/default/molecule.yml | 0 .../molecule/default/verify.yml | 2 +- .../molecule/deregister/converge.yml | 12 +++ .../molecule/deregister/molecule.yml | 0 .../molecule/deregister/side_effect.yml | 10 +- .../molecule/deregister/verify.yml | 6 +- .../molecule/lifecycle/converge.yml | 12 +++ .../molecule/lifecycle/molecule.yml | 0 .../molecule/lifecycle/side_effect.yml | 4 +- .../molecule/lifecycle/verify.yml | 2 +- .../molecule/multi-instance/converge.yml | 16 +-- .../molecule/multi-instance/molecule.yml | 0 .../molecule/multi-instance/verify.yml | 0 .../gitea_runner/molecule/remove/converge.yml | 12 +++ .../molecule/remove/molecule.yml | 0 .../molecule/remove/side_effect.yml | 4 +- .../molecule/remove/verify.yml | 2 +- .../molecule/template-content/converge.yml | 12 +++ .../molecule/template-content/molecule.yml | 0 .../molecule/template-content/verify.yml | 2 +- .../gitea_runner/molecule/update/converge.yml | 12 +++ .../molecule/update/molecule.yml | 0 .../molecule/update/side_effect.yml | 4 +- .../molecule/update/verify.yml | 2 +- .../roles/gitea_runner/tasks/deregister.yml | 58 ++++++++++ .../tasks/download_gitea_runner.yml | 0 .../tasks/healthcheck.yml | 8 +- .../tasks/install_runner.yml | 2 +- .../gitea_runner/tasks/integration_test.yml | 102 ++++++++++++++++++ .../tasks/main.yml | 2 +- .../tasks/prune.yml | 8 +- .../tasks/register.yml | 12 +-- .../tasks/resolve_uid.yml | 6 +- .../tasks/rootless_docker.yml | 51 ++++----- .../tasks/service.yml | 8 +- .../tasks/systemd_check.yml | 2 +- .../tasks/update_runner.yml | 4 +- .../tasks/user_setup.yml | 10 +- .../tasks/validate.yml | 4 +- .../templates/docker-prune.service.j2 | 0 .../templates/docker-prune.timer.j2 | 0 .../templates/gitea-runner-config.yaml.j2 | 0 .../templates/gitea-runner-user.service.j2 | 0 .../templates/runner-healthcheck.service.j2 | 0 .../templates/runner-healthcheck.sh.j2 | 0 .../templates/runner-healthcheck.timer.j2 | 0 ansible/start-runner.yml | 8 +- ansible/status-runner.yml | 4 +- ansible/stop-runner.yml | 4 +- ansible/update-runner.yml | 2 +- docs/tech/architecture.md | 10 +- docs/tech/development-setup.md | 2 +- docs/tech/testing-strategy.md | 4 +- docs/user/cli-commands.md | 2 +- pyproject.toml | 12 +-- src/grm/executor.py | 2 +- src/grm/runner_manager.py | 18 ++-- tests/unit/test_executor.py | 4 +- tests/unit/test_runner_manager.py | 22 ++-- 81 files changed, 438 insertions(+), 437 deletions(-) delete mode 100644 ansible/roles/gitea-runner/molecule/default/converge.yml delete mode 100644 ansible/roles/gitea-runner/molecule/deregister/converge.yml delete mode 100644 ansible/roles/gitea-runner/molecule/lifecycle/converge.yml delete mode 100644 ansible/roles/gitea-runner/molecule/remove/converge.yml delete mode 100644 ansible/roles/gitea-runner/molecule/template-content/converge.yml delete mode 100644 ansible/roles/gitea-runner/molecule/update/converge.yml delete mode 100644 ansible/roles/gitea-runner/tasks/deregister.yml delete mode 100644 ansible/roles/gitea-runner/tasks/integration_test.yml rename ansible/roles/{gitea-runner => gitea_runner}/defaults/main.yml (64%) rename ansible/roles/{gitea-runner => gitea_runner}/handlers/main.yml (89%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/common/prepare.yml (100%) create mode 100644 ansible/roles/gitea_runner/molecule/default/converge.yml rename ansible/roles/{gitea-runner => gitea_runner}/molecule/default/molecule.yml (100%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/default/verify.yml (98%) create mode 100644 ansible/roles/gitea_runner/molecule/deregister/converge.yml rename ansible/roles/{gitea-runner => gitea_runner}/molecule/deregister/molecule.yml (100%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/deregister/side_effect.yml (73%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/deregister/verify.yml (87%) create mode 100644 ansible/roles/gitea_runner/molecule/lifecycle/converge.yml rename ansible/roles/{gitea-runner => gitea_runner}/molecule/lifecycle/molecule.yml (100%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/lifecycle/side_effect.yml (93%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/lifecycle/verify.yml (95%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/multi-instance/converge.yml (53%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/multi-instance/molecule.yml (100%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/multi-instance/verify.yml (100%) create mode 100644 ansible/roles/gitea_runner/molecule/remove/converge.yml rename ansible/roles/{gitea-runner => gitea_runner}/molecule/remove/molecule.yml (100%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/remove/side_effect.yml (71%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/remove/verify.yml (99%) create mode 100644 ansible/roles/gitea_runner/molecule/template-content/converge.yml rename ansible/roles/{gitea-runner => gitea_runner}/molecule/template-content/molecule.yml (100%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/template-content/verify.yml (99%) create mode 100644 ansible/roles/gitea_runner/molecule/update/converge.yml rename ansible/roles/{gitea-runner => gitea_runner}/molecule/update/molecule.yml (100%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/update/side_effect.yml (71%) rename ansible/roles/{gitea-runner => gitea_runner}/molecule/update/verify.yml (96%) create mode 100644 ansible/roles/gitea_runner/tasks/deregister.yml rename ansible/roles/{gitea-runner => gitea_runner}/tasks/download_gitea_runner.yml (100%) rename ansible/roles/{gitea-runner => gitea_runner}/tasks/healthcheck.yml (88%) rename ansible/roles/{gitea-runner => gitea_runner}/tasks/install_runner.yml (93%) create mode 100644 ansible/roles/gitea_runner/tasks/integration_test.yml rename ansible/roles/{gitea-runner => gitea_runner}/tasks/main.yml (93%) rename ansible/roles/{gitea-runner => gitea_runner}/tasks/prune.yml (86%) rename ansible/roles/{gitea-runner => gitea_runner}/tasks/register.yml (74%) rename ansible/roles/{gitea-runner => gitea_runner}/tasks/resolve_uid.yml (91%) rename ansible/roles/{gitea-runner => gitea_runner}/tasks/rootless_docker.yml (78%) rename ansible/roles/{gitea-runner => gitea_runner}/tasks/service.yml (82%) rename ansible/roles/{gitea-runner => gitea_runner}/tasks/systemd_check.yml (69%) rename ansible/roles/{gitea-runner => gitea_runner}/tasks/update_runner.yml (76%) rename ansible/roles/{gitea-runner => gitea_runner}/tasks/user_setup.yml (89%) rename ansible/roles/{gitea-runner => gitea_runner}/tasks/validate.yml (90%) rename ansible/roles/{gitea-runner => gitea_runner}/templates/docker-prune.service.j2 (100%) rename ansible/roles/{gitea-runner => gitea_runner}/templates/docker-prune.timer.j2 (100%) rename ansible/roles/{gitea-runner => gitea_runner}/templates/gitea-runner-config.yaml.j2 (100%) rename ansible/roles/{gitea-runner => gitea_runner}/templates/gitea-runner-user.service.j2 (100%) rename ansible/roles/{gitea-runner => gitea_runner}/templates/runner-healthcheck.service.j2 (100%) rename ansible/roles/{gitea-runner => gitea_runner}/templates/runner-healthcheck.sh.j2 (100%) rename ansible/roles/{gitea-runner => gitea_runner}/templates/runner-healthcheck.timer.j2 (100%) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 865964b..91d2437 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -178,13 +178,13 @@ jobs: - name: Discover assigned test pairs env: RUNNER_INDEX: ${{ matrix.runner-index }} - MAX_RUNNERS: ${{ needs.validate.outputs.runner-count }} + MAX_RUNNERS: 6 run: | . .venv/bin/activate 2>/dev/null || true python3 -m devx.molecule.distribute_molecule \ --runner-index "$RUNNER_INDEX" \ --max-runners "$MAX_RUNNERS" \ - --github-env --skip-if-excess + --github-env - name: Run molecule tests if: env.SKIP != 'true' env: diff --git a/AGENTS.md b/AGENTS.md index 9be2b8f..ef59e94 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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 with pasta networking (IPv6 support) +- **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 diff --git a/Makefile b/Makefile index b5f9a38..79a8886 100644 --- a/Makefile +++ b/Makefile @@ -184,7 +184,7 @@ test-integration: $(BIN)/pytest tests/integration/ -v --no-cov MOLECULE := $(realpath $(BIN))/molecule -MOLECULE_BASE := cd $(CURDIR)/ansible/roles/gitea-runner && ANSIBLE_ALLOW_BROKEN_CONDITIONALS=true ANSIBLE_INJECT_INVOCATION=1 $(MOLECULE) +MOLECULE_BASE := cd $(CURDIR)/ansible/roles/gitea_runner && ANSIBLE_ALLOW_BROKEN_CONDITIONALS=true ANSIBLE_INJECT_INVOCATION=1 $(MOLECULE) # Quick local test: Ubuntu 22.04 only, all scenarios molecule: diff --git a/README.md b/README.md index 53617ee..cf8d4b3 100644 --- a/README.md +++ b/README.md @@ -266,8 +266,8 @@ One of GRM's core features is the ability to run multiple isolated runners on th - **Dedicated system user**: `grm-` with its own home directory at `/home/grm-/` - **Rootless Docker daemon**: Isolated Docker socket at `/run/user//docker.sock` -- **Data directory**: `/var/lib/gitea-runner//` -- **Config directory**: `/etc/gitea-runner//` +- **Data directory**: `/var/lib/gitea_runner//` +- **Config directory**: `/etc/gitea_runner//` - **Systemd user service**: `gitea-runner.service` (independent start/stop/enable) - **Docker prune timer**: Per-instance daily cleanup @@ -341,13 +341,13 @@ GRM consists of two layers: 1. **Python CLI** (`src/grm/`) — Built with Click, handles argument parsing, environment loading, i18n translations, and delegates to Ansible via the `ansible-playbook` subprocess. Secrets are passed via temporary JSON files to avoid exposure in the process list. -2. **Ansible Role** (`ansible/roles/gitea-runner/`) — Idempotent role that creates a dedicated system user, sets up rootless Docker, installs the runner binary, creates a systemd user service, registers the runner with Gitea, and sets up a Docker prune timer. +2. **Ansible Role** (`ansible/roles/gitea_runner/`) — Idempotent role that creates a dedicated system user, sets up rootless Docker, installs the runner binary, creates a systemd user service, registers the runner with Gitea, and sets up a Docker prune timer. ```text grm install └── RunnerManager.install() └── ansible-playbook ansible/install-runner.yml - └── role: gitea-runner + └── role: gitea_runner ├── user_setup.yml (create per-runner system user + lingering) ├── rootless_docker.yml (rootless Docker setup under runner user) ├── install_runner.yml (download binary, config, register, service) diff --git a/ansible/disable-runner.yml b/ansible/disable-runner.yml index b89deb3..7005c0b 100644 --- a/ansible/disable-runner.yml +++ b/ansible/disable-runner.yml @@ -6,13 +6,13 @@ tasks: - name: Include systemd availability check ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: systemd_check.yml - name: Stop gitea-runner user service ansible.builtin.command: systemctl --user stop gitea-runner become: true - become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}" when: systemd_available.stat.exists @@ -21,7 +21,7 @@ - name: Stop and disable healthcheck timer ansible.builtin.command: systemctl --user stop --disable runner-healthcheck.timer become: true - become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}" when: systemd_available.stat.exists @@ -30,14 +30,14 @@ - name: Include deregistration ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: deregister.yml - when: not skip_runner_registration | default(false) + when: not gitea_runner_skip_registration | default(false) - name: Disable gitea-runner user service ansible.builtin.command: systemctl --user disable gitea-runner become: true - become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}" when: systemd_available.stat.exists diff --git a/ansible/enable-runner.yml b/ansible/enable-runner.yml index b5913f4..e749318 100644 --- a/ansible/enable-runner.yml +++ b/ansible/enable-runner.yml @@ -6,13 +6,13 @@ tasks: - name: Include systemd availability check ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: systemd_check.yml - name: Enable gitea-runner user service ansible.builtin.command: systemctl --user enable gitea-runner become: true - become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}" when: systemd_available.stat.exists @@ -21,7 +21,7 @@ - name: Start gitea-runner user service ansible.builtin.command: systemctl --user start gitea-runner become: true - become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}" when: systemd_available.stat.exists diff --git a/ansible/install-runner.yml b/ansible/install-runner.yml index bc747ea..f7302e4 100644 --- a/ansible/install-runner.yml +++ b/ansible/install-runner.yml @@ -3,4 +3,4 @@ hosts: all become: true roles: - - role: gitea-runner + - role: gitea_runner diff --git a/ansible/remove-runner.yml b/ansible/remove-runner.yml index 555dcea..87032c5 100644 --- a/ansible/remove-runner.yml +++ b/ansible/remove-runner.yml @@ -6,11 +6,11 @@ tasks: - name: Include systemd availability check ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: systemd_check.yml - name: Get runner user UID - ansible.builtin.command: id -u "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + ansible.builtin.command: id -u "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" register: runner_uid_result changed_when: false failed_when: false @@ -23,20 +23,20 @@ - name: Stop gitea-runner user service ansible.builtin.command: systemctl --user stop gitea-runner become: true - become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}" - when: systemd_available.stat.exists + when: gitea_runner_systemd_available.stat.exists changed_when: true failed_when: false - name: Disable gitea-runner user service ansible.builtin.command: systemctl --user disable gitea-runner become: true - become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}" - when: systemd_available.stat.exists + when: gitea_runner_systemd_available.stat.exists changed_when: true failed_when: false @@ -47,7 +47,7 @@ args: executable: /bin/bash become: true - become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}" DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default('') }}/docker.sock" @@ -57,7 +57,7 @@ - name: Prune all Docker images, volumes, and build cache (rootless) ansible.builtin.command: docker system prune -af --volumes become: true - become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}" DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default('') }}/docker.sock" @@ -67,7 +67,7 @@ - name: Stop rootless Docker daemon ansible.builtin.command: systemctl --user stop docker become: true - become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}" changed_when: true @@ -75,120 +75,120 @@ - name: Include deregistration ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: deregister.yml - when: not skip_runner_registration | default(false) + when: not gitea_runner_skip_registration | default(false) - name: Stop and disable healthcheck timer ansible.builtin.command: systemctl --user stop --disable runner-healthcheck.timer become: true - become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}" - when: systemd_available.stat.exists + when: gitea_runner_systemd_available.stat.exists changed_when: true failed_when: false - name: Remove docker-prune user service file ansible.builtin.file: - path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.config/systemd/user/docker-prune.service" + path: "{{ gitea_runner_home | default('/home/grm-' ~ gitea_runner_name) }}/.config/systemd/user/docker-prune.service" state: absent failed_when: false - name: Remove docker-prune user timer file ansible.builtin.file: - path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.config/systemd/user/docker-prune.timer" + path: "{{ gitea_runner_home | default('/home/grm-' ~ gitea_runner_name) }}/.config/systemd/user/docker-prune.timer" state: absent failed_when: false - name: Remove healthcheck user service file ansible.builtin.file: - path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.config/systemd/user/runner-healthcheck.service" + path: "{{ gitea_runner_home | default('/home/grm-' ~ gitea_runner_name) }}/.config/systemd/user/runner-healthcheck.service" state: absent failed_when: false - name: Remove healthcheck user timer file ansible.builtin.file: - path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.config/systemd/user/runner-healthcheck.timer" + path: "{{ gitea_runner_home | default('/home/grm-' ~ gitea_runner_name) }}/.config/systemd/user/runner-healthcheck.timer" state: absent failed_when: false - name: Remove healthcheck script ansible.builtin.file: - path: "{{ gitea_runner_config_dir | default('/etc/gitea-runner/' ~ runner_name) }}/healthcheck.sh" + path: "{{ gitea_runner_config_dir | default('/etc/gitea-runner/' ~ gitea_runner_name) }}/healthcheck.sh" state: absent failed_when: false - name: Remove systemd user unit file ansible.builtin.file: - path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.config/systemd/user/gitea-runner.service" + path: "{{ gitea_runner_home | default('/home/grm-' ~ gitea_runner_name) }}/.config/systemd/user/gitea-runner.service" state: absent when: remove_systemd_template | default(true) - name: Kill remaining processes of runner user - ansible.builtin.command: loginctl terminate-user "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + ansible.builtin.command: loginctl terminate-user "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" failed_when: false changed_when: true - name: Wait for processes to terminate - ansible.builtin.command: "pkill -u {{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + ansible.builtin.command: "pkill -u {{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" failed_when: false changed_when: false - name: Disable lingering for runner user - ansible.builtin.command: loginctl disable-linger "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + ansible.builtin.command: loginctl disable-linger "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" failed_when: false changed_when: true - name: Remove runner user and home directory ansible.builtin.user: - name: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}" + name: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}" state: absent remove: true - when: remove_runner_user | default(true) + when: gitea_runner_remove_user | default(true) failed_when: false - name: Remove Docker data root when user is kept ansible.builtin.file: - path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.local/share/docker" + path: "{{ gitea_runner_home | default('/home/grm-' ~ gitea_runner_name) }}/.local/share/docker" state: absent - when: not (remove_runner_user | default(true)) + when: not (gitea_runner_remove_user | default(true)) failed_when: false - name: Remove act cache when user is kept ansible.builtin.file: - path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.cache/act" + path: "{{ gitea_runner_home | default('/home/grm-' ~ gitea_runner_name) }}/.cache/act" state: absent - when: not (remove_runner_user | default(true)) + when: not (gitea_runner_remove_user | default(true)) failed_when: false - name: Remove systemd user config dir when user is kept ansible.builtin.file: - path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.config/systemd/user" + path: "{{ gitea_runner_home | default('/home/grm-' ~ gitea_runner_name) }}/.config/systemd/user" state: absent - when: not (remove_runner_user | default(true)) + when: not (gitea_runner_remove_user | default(true)) failed_when: false - name: Remove subuid entry for runner user ansible.builtin.lineinfile: path: /etc/subuid - regexp: "^{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}:" + regexp: "^{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}:" state: absent failed_when: false - name: Remove subgid entry for runner user ansible.builtin.lineinfile: path: /etc/subgid - regexp: "^{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}:" + regexp: "^{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}:" state: absent failed_when: false - name: Remove runner data directory ansible.builtin.file: - path: "{{ gitea_runner_data_dir | default('/var/lib/gitea-runner/' ~ runner_name) }}" + path: "{{ gitea_runner_data_dir | default('/var/lib/gitea-runner/' ~ gitea_runner_name) }}" state: absent - name: Remove runner config directory ansible.builtin.file: - path: "{{ gitea_runner_config_dir | default('/etc/gitea-runner/' ~ runner_name) }}" + path: "{{ gitea_runner_config_dir | default('/etc/gitea-runner/' ~ gitea_runner_name) }}" state: absent diff --git a/ansible/requirements.yml b/ansible/requirements.yml index a0b7cf0..0c2292f 100644 --- a/ansible/requirements.yml +++ b/ansible/requirements.yml @@ -2,6 +2,6 @@ collections: - name: community.general version: "==13.1.0" - name: ansible.posix - version: "==2.2.0" + version: "==2.2.1" - name: community.docker version: "==5.2.1" diff --git a/ansible/restart-runner.yml b/ansible/restart-runner.yml index 3d75a73..16daa70 100644 --- a/ansible/restart-runner.yml +++ b/ansible/restart-runner.yml @@ -7,12 +7,12 @@ tasks: - name: Include systemd availability check ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: systemd_check.yml - name: Resolve runner UID ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: resolve_uid.yml - name: Stop gitea-runner user service diff --git a/ansible/roles/gitea-runner/molecule/default/converge.yml b/ansible/roles/gitea-runner/molecule/default/converge.yml deleted file mode 100644 index 9f0e1e2..0000000 --- a/ansible/roles/gitea-runner/molecule/default/converge.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Converge - hosts: all - become: true - vars: - gitea_url: "http://localhost:3000" - registration_token: "fake-token-for-testing" - runner_name: "molecule-test-runner" - skip_runner_registration: true - docker_rootless_setup: false - roles: - - role: gitea-runner diff --git a/ansible/roles/gitea-runner/molecule/deregister/converge.yml b/ansible/roles/gitea-runner/molecule/deregister/converge.yml deleted file mode 100644 index 02353f7..0000000 --- a/ansible/roles/gitea-runner/molecule/deregister/converge.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Converge - hosts: all - become: true - vars: - gitea_url: "http://localhost:3000" - registration_token: "fake-token-for-testing" - runner_name: "deregister-test-runner" - skip_runner_registration: true - docker_rootless_setup: false - roles: - - role: gitea-runner diff --git a/ansible/roles/gitea-runner/molecule/lifecycle/converge.yml b/ansible/roles/gitea-runner/molecule/lifecycle/converge.yml deleted file mode 100644 index 8567ef2..0000000 --- a/ansible/roles/gitea-runner/molecule/lifecycle/converge.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Converge - hosts: all - become: true - vars: - gitea_url: "http://localhost:3000" - registration_token: "fake-token-for-testing" - runner_name: "lifecycle-test-runner" - skip_runner_registration: true - docker_rootless_setup: false - roles: - - role: gitea-runner diff --git a/ansible/roles/gitea-runner/molecule/remove/converge.yml b/ansible/roles/gitea-runner/molecule/remove/converge.yml deleted file mode 100644 index b2e7f2c..0000000 --- a/ansible/roles/gitea-runner/molecule/remove/converge.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Converge - hosts: all - become: true - vars: - gitea_url: "http://localhost:3000" - registration_token: "fake-token-for-testing" - runner_name: "remove-test-runner" - skip_runner_registration: true - docker_rootless_setup: false - roles: - - role: gitea-runner diff --git a/ansible/roles/gitea-runner/molecule/template-content/converge.yml b/ansible/roles/gitea-runner/molecule/template-content/converge.yml deleted file mode 100644 index 81301ff..0000000 --- a/ansible/roles/gitea-runner/molecule/template-content/converge.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Converge - hosts: all - become: true - vars: - gitea_url: "http://localhost:3000" - registration_token: "fake-token-for-testing" - runner_name: "template-test-runner" - skip_runner_registration: true - docker_rootless_setup: false - roles: - - role: gitea-runner diff --git a/ansible/roles/gitea-runner/molecule/update/converge.yml b/ansible/roles/gitea-runner/molecule/update/converge.yml deleted file mode 100644 index 8ad9eee..0000000 --- a/ansible/roles/gitea-runner/molecule/update/converge.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Converge - hosts: all - become: true - vars: - gitea_url: "http://localhost:3000" - registration_token: "fake-token-for-testing" - runner_name: "update-test-runner" - skip_runner_registration: true - docker_rootless_setup: false - roles: - - role: gitea-runner diff --git a/ansible/roles/gitea-runner/tasks/deregister.yml b/ansible/roles/gitea-runner/tasks/deregister.yml deleted file mode 100644 index 35fc3ac..0000000 --- a/ansible/roles/gitea-runner/tasks/deregister.yml +++ /dev/null @@ -1,58 +0,0 @@ ---- -- name: Check if runner registration file exists - ansible.builtin.stat: - path: "{{ gitea_runner_data_dir }}/.runner" - register: runner_file_stat - -- name: Read runner registration file - ansible.builtin.slurp: - src: "{{ gitea_runner_data_dir }}/.runner" - register: runner_file_content - when: runner_file_stat.stat.exists | default(false) | bool - -- name: Parse runner registration data - ansible.builtin.set_fact: - runner_reg: > - {{ (runner_file_content.content | b64decode | from_json) - if (runner_file_content is defined and runner_file_content.content is defined) - else {} }} - when: runner_file_stat.stat.exists | default(false) | bool - -- name: Deregister runner from Gitea via API - ansible.builtin.command: > - curl -sf --connect-timeout 5 --max-time 10 -X DELETE - -H "Authorization: token {{ gitea_admin_token | default(registration_token) }}" - "{{ gitea_url }}/api/v1/admin/actions/runners/{{ runner_reg.id }}" - args: - chdir: "{{ gitea_runner_data_dir }}" - become: true - become_user: "{{ gitea_runner_service_user }}" - environment: - XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default(0) }}" - DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default(0) }}/docker.sock" - when: - - runner_file_stat.stat.exists | default(false) | bool - - not skip_runner_registration - - runner_reg.id is defined - register: deregister_output - changed_when: deregister_output.rc == 0 - failed_when: false - -- name: Warn if deregistration failed - ansible.builtin.debug: - msg: >- - WARNING: Runner deregistration from Gitea failed (rc={{ deregister_output.rc | default('N/A') }}). - The runner entry may remain in Gitea's admin UI as offline. - Use an admin token (gitea_admin_token var) to enable automatic cleanup, - or remove it manually from {{ gitea_url }}/-/admin/actions/runners - when: - - runner_file_stat.stat.exists | default(false) | bool - - not skip_runner_registration - - deregister_output is defined - - deregister_output.rc | default(1) != 0 - -- name: Remove runner registration file - ansible.builtin.file: - path: "{{ gitea_runner_data_dir }}/.runner" - state: absent - when: runner_file_stat.stat.exists | default(false) | bool diff --git a/ansible/roles/gitea-runner/tasks/integration_test.yml b/ansible/roles/gitea-runner/tasks/integration_test.yml deleted file mode 100644 index 11575ae..0000000 --- a/ansible/roles/gitea-runner/tasks/integration_test.yml +++ /dev/null @@ -1,102 +0,0 @@ ---- -- name: Check runner registration file exists - ansible.builtin.stat: - path: "{{ gitea_runner_data_dir }}/.runner" - register: runner_file_stat - -- name: Read runner registration file - ansible.builtin.slurp: - src: "{{ gitea_runner_data_dir }}/.runner" - register: runner_file_content - when: runner_file_stat.stat.exists | default(false) | bool - -- name: Parse runner registration data - ansible.builtin.set_fact: - runner_reg: > - {{ (runner_file_content.content | b64decode | from_json) - if (runner_file_content is defined and runner_file_content.content is defined) - else {} }} - when: runner_file_stat.stat.exists | default(false) | bool - -- name: Verify runner user service active - ansible.builtin.command: systemctl --user is-active gitea-runner - become: true - become_user: "{{ gitea_runner_service_user }}" - environment: - XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" - register: service_check - changed_when: false - when: - - systemd_available.stat.exists - - docker_rootless_setup - -- name: Validate runner installation - ansible.builtin.fail: - msg: > - Runner '{{ runner_name }}' is not properly installed: - {% if not (runner_file_stat.stat.exists | default(false)) %} - - Registration file (.runner) is missing. Registration may have failed. - {% endif %} - {% if docker_rootless_setup and not (service_check.stdout | default('') | trim) == 'active' %} - - Systemd user service is not active. - {% endif %} - when: > - not (runner_file_stat.stat.exists | default(false)) - or (docker_rootless_setup and not (service_check.stdout | default('') | trim) == 'active') - -- name: Report runner status - ansible.builtin.debug: - msg: > - Runner '{{ runner_name }}' is installed and running. - Registered: {{ runner_file_stat.stat.exists | default(false) }} - {% if runner_reg.id is defined %}Runner ID: {{ runner_reg.id }}{% endif %} - {% if runner_reg.uuid is defined %}UUID: {{ runner_reg.uuid }}{% endif %} - {% if runner_reg.address is defined %}Gitea: {{ runner_reg.address }}{% endif %} - Service: {{ service_check.stdout | default('unknown') | trim }} - -- name: Optional Gitea API verification - when: - - gitea_url is defined - - gitea_admin_token is defined - - gitea_admin_token | length > 0 - block: - - name: Check admin runners API - ansible.builtin.uri: - url: "{{ gitea_url }}/api/v1/admin/runners" - headers: - Authorization: "token {{ gitea_admin_token }}" - method: GET - status_code: [200, 401, 403, 404] - return_content: true - body_format: json - register: admin_api_response - ignore_errors: true - - - name: Check repo runners API - ansible.builtin.uri: - url: "{{ gitea_url }}/api/v1/repos/{{ gitea_runner_test_repo | default('oblachno-oss/grm') }}/actions/runners" - headers: - Authorization: "token {{ gitea_admin_token }}" - method: GET - status_code: [200, 401, 403, 404] - return_content: true - body_format: json - register: repo_api_response - ignore_errors: true - - - name: Report API status (informational only) - ansible.builtin.debug: - msg: > - API checks (informational only — not used for pass/fail): - Admin API: {{ admin_api_response.status | default('no response') }}. - Repo API: {{ repo_api_response.status | default('no response') }}. - {% if admin_api_response.json.runners | default([]) | selectattr('name', 'equalto', runner_name) | list | length > 0 %} - Runner found in admin API. - {% endif %} - {% if repo_api_response.json.runners | default([]) | selectattr('name', 'equalto', runner_name) | list | length > 0 %} - Runner found in repo API. - {% endif %} - rescue: - - name: API check failed - ansible.builtin.debug: - msg: "API verification skipped due to connection or permission error." diff --git a/ansible/roles/gitea-runner/defaults/main.yml b/ansible/roles/gitea_runner/defaults/main.yml similarity index 64% rename from ansible/roles/gitea-runner/defaults/main.yml rename to ansible/roles/gitea_runner/defaults/main.yml index 75a6ae0..5d7abea 100644 --- a/ansible/roles/gitea-runner/defaults/main.yml +++ b/ansible/roles/gitea_runner/defaults/main.yml @@ -1,19 +1,19 @@ --- -gitea_runner_version: "1.0.8" -runner_labels: "docker,ubuntu-latest:docker://runner-images:ubuntu-26.04" -skip_runner_registration: false +gitea_runner_version: "2.0.1" +gitea_runner_labels: "docker,ubuntu-latest:docker://runner-images:ubuntu-26.04" +gitea_runner_skip_registration: false # Per-runner user (rootless isolation) gitea_runner_user_prefix: "grm-" gitea_runner_base_home: "/home" -gitea_runner_service_user: "{{ gitea_runner_user_prefix }}{{ runner_name }}" +gitea_runner_service_user: "{{ gitea_runner_user_prefix }}{{ gitea_runner_name }}" gitea_runner_home: "{{ gitea_runner_base_home }}/{{ gitea_runner_service_user }}" -# Base paths (instance-scoped via runner_name) +# Base paths (instance-scoped via gitea_runner_name) gitea_runner_base_data_dir: "/var/lib/gitea-runner" gitea_runner_base_config_dir: "/etc/gitea-runner" -gitea_runner_data_dir: "{{ gitea_runner_base_data_dir }}/{{ runner_name }}" -gitea_runner_config_dir: "{{ gitea_runner_base_config_dir }}/{{ runner_name }}" +gitea_runner_data_dir: "{{ gitea_runner_base_data_dir }}/{{ gitea_runner_name }}" +gitea_runner_config_dir: "{{ gitea_runner_base_config_dir }}/{{ gitea_runner_name }}" gitea_runner_binary_path: "/usr/local/bin/gitea_runner" # Prune configuration @@ -33,11 +33,11 @@ gitea_runner_healthcheck_script_path: "{{ gitea_runner_config_dir }}/healthcheck # Admin token for runner deregistration via Gitea API. # If not set, falls back to registration_token (which likely lacks admin scope). # Set this to a token with admin scope to enable automatic runner cleanup on removal. -gitea_admin_token: "" +gitea_runner_admin_token: "" # Removal defaults -remove_systemd_template: true -remove_runner_user: true +gitea_runner_remove_systemd_template: true +gitea_runner_remove_user: true # Runner configuration gitea_runner_log_level: "info" @@ -45,18 +45,18 @@ gitea_runner_container_label: "gitea-runner=true" gitea_runner_file: ".runner" # Docker installation (for rootless dependencies) -docker_gpg_key_path: "/etc/apt/keyrings/docker.gpg" -docker_apt_arch: "{{ 'amd64' if ansible_facts['architecture'] == 'x86_64' else ansible_facts['architecture'] }}" -docker_apt_source_line: >- - deb [arch={{ docker_apt_arch }} signed-by={{ docker_gpg_key_path }}] +gitea_runner_docker_gpg_key_path: "/etc/apt/keyrings/docker.gpg" +gitea_runner_docker_apt_arch: "{{ 'amd64' if ansible_facts['architecture'] == 'x86_64' else ansible_facts['architecture'] }}" +gitea_runner_docker_apt_source_line: >- + deb [arch={{ gitea_runner_docker_apt_arch }} signed-by={{ gitea_runner_docker_gpg_key_path }}] https://download.docker.com/linux/{{ ansible_facts['distribution'] | lower }} {{ ansible_facts['distribution_release'] }} stable # Set to false in CI/molecule to skip rootless daemon startup (needs kernel userns) -docker_rootless_setup: true +gitea_runner_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" +gitea_runner_docker_rootless_net_driver: "pasta" # IPv6 subnet for rootless Docker containers (ULA range, not routable on internet) -docker_ipv6_cidr: "fd00:dead:beef::/48" +gitea_runner_docker_ipv6_cidr: "fd00:dead:beef::/48" diff --git a/ansible/roles/gitea-runner/handlers/main.yml b/ansible/roles/gitea_runner/handlers/main.yml similarity index 89% rename from ansible/roles/gitea-runner/handlers/main.yml rename to ansible/roles/gitea_runner/handlers/main.yml index 9336d5f..483f97f 100644 --- a/ansible/roles/gitea-runner/handlers/main.yml +++ b/ansible/roles/gitea_runner/handlers/main.yml @@ -9,4 +9,4 @@ when: - ansible_facts is defined - ansible_facts['service_mgr'] | default('') == 'systemd' - - docker_rootless_setup + - gitea_runner_docker_rootless_setup diff --git a/ansible/roles/gitea-runner/molecule/common/prepare.yml b/ansible/roles/gitea_runner/molecule/common/prepare.yml similarity index 100% rename from ansible/roles/gitea-runner/molecule/common/prepare.yml rename to ansible/roles/gitea_runner/molecule/common/prepare.yml diff --git a/ansible/roles/gitea_runner/molecule/default/converge.yml b/ansible/roles/gitea_runner/molecule/default/converge.yml new file mode 100644 index 0000000..5c06026 --- /dev/null +++ b/ansible/roles/gitea_runner/molecule/default/converge.yml @@ -0,0 +1,12 @@ +--- +- name: Converge + hosts: all + become: true + vars: + gitea_url: "http://localhost:3000" + registration_token: "fake-token-for-testing" + gitea_runner_name: "molecule-test-runner" + gitea_runner_skip_registration: true + gitea_runner_docker_rootless_setup: false + roles: + - role: gitea_runner diff --git a/ansible/roles/gitea-runner/molecule/default/molecule.yml b/ansible/roles/gitea_runner/molecule/default/molecule.yml similarity index 100% rename from ansible/roles/gitea-runner/molecule/default/molecule.yml rename to ansible/roles/gitea_runner/molecule/default/molecule.yml diff --git a/ansible/roles/gitea-runner/molecule/default/verify.yml b/ansible/roles/gitea_runner/molecule/default/verify.yml similarity index 98% rename from ansible/roles/gitea-runner/molecule/default/verify.yml rename to ansible/roles/gitea_runner/molecule/default/verify.yml index 037c154..fee8eb7 100644 --- a/ansible/roles/gitea-runner/molecule/default/verify.yml +++ b/ansible/roles/gitea_runner/molecule/default/verify.yml @@ -3,7 +3,7 @@ hosts: all become: true vars: - runner_name: "molecule-test-runner" + gitea_runner_name: "molecule-test-runner" pre_tasks: - name: Load role defaults ansible.builtin.include_vars: diff --git a/ansible/roles/gitea_runner/molecule/deregister/converge.yml b/ansible/roles/gitea_runner/molecule/deregister/converge.yml new file mode 100644 index 0000000..ce9f7ec --- /dev/null +++ b/ansible/roles/gitea_runner/molecule/deregister/converge.yml @@ -0,0 +1,12 @@ +--- +- name: Converge + hosts: all + become: true + vars: + gitea_url: "http://localhost:3000" + registration_token: "fake-token-for-testing" + gitea_runner_name: "deregister-test-runner" + gitea_runner_skip_registration: true + gitea_runner_docker_rootless_setup: false + roles: + - role: gitea_runner diff --git a/ansible/roles/gitea-runner/molecule/deregister/molecule.yml b/ansible/roles/gitea_runner/molecule/deregister/molecule.yml similarity index 100% rename from ansible/roles/gitea-runner/molecule/deregister/molecule.yml rename to ansible/roles/gitea_runner/molecule/deregister/molecule.yml diff --git a/ansible/roles/gitea-runner/molecule/deregister/side_effect.yml b/ansible/roles/gitea_runner/molecule/deregister/side_effect.yml similarity index 73% rename from ansible/roles/gitea-runner/molecule/deregister/side_effect.yml rename to ansible/roles/gitea_runner/molecule/deregister/side_effect.yml index 999181b..c58e6351 100644 --- a/ansible/roles/gitea-runner/molecule/deregister/side_effect.yml +++ b/ansible/roles/gitea_runner/molecule/deregister/side_effect.yml @@ -3,7 +3,7 @@ hosts: all become: true vars: - runner_name: "deregister-test-runner" + gitea_runner_name: "deregister-test-runner" pre_tasks: - name: Load role defaults ansible.builtin.include_vars: @@ -13,7 +13,7 @@ ansible.builtin.copy: dest: "{{ gitea_runner_data_dir }}/.runner" content: | - {"id": 1, "uuid": "test-uuid-1234", "name": "{{ runner_name }}", "address": "http://localhost:3000"} + {"id": 1, "uuid": "test-uuid-1234", "name": "{{ gitea_runner_name }}", "address": "http://localhost:3000"} owner: "{{ gitea_runner_service_user }}" group: "{{ gitea_runner_service_user }}" mode: "0644" @@ -22,12 +22,12 @@ hosts: all become: true vars: - runner_name: "deregister-test-runner" + gitea_runner_name: "deregister-test-runner" registration_token: "fake-token-for-testing" gitea_url: "http://localhost:3000" - skip_runner_registration: false + gitea_runner_skip_registration: false tasks: - name: Include deregistration tasks ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: deregister.yml diff --git a/ansible/roles/gitea-runner/molecule/deregister/verify.yml b/ansible/roles/gitea_runner/molecule/deregister/verify.yml similarity index 87% rename from ansible/roles/gitea-runner/molecule/deregister/verify.yml rename to ansible/roles/gitea_runner/molecule/deregister/verify.yml index bfdacdf..0ef3af7 100644 --- a/ansible/roles/gitea-runner/molecule/deregister/verify.yml +++ b/ansible/roles/gitea_runner/molecule/deregister/verify.yml @@ -3,7 +3,7 @@ hosts: all become: true vars: - runner_name: "deregister-test-runner" + gitea_runner_name: "deregister-test-runner" pre_tasks: - name: Load role defaults ansible.builtin.include_vars: @@ -12,12 +12,12 @@ - name: Check registration file was removed ansible.builtin.stat: path: "{{ gitea_runner_data_dir }}/.runner" - register: runner_file_stat + register: gitea_runner_file_stat - name: Assert registration file no longer exists ansible.builtin.assert: that: - - not runner_file_stat.stat.exists + - not gitea_runner_file_stat.stat.exists fail_msg: "Registration file (.runner) was not removed by deregistration" - name: Check systemd user service still exists diff --git a/ansible/roles/gitea_runner/molecule/lifecycle/converge.yml b/ansible/roles/gitea_runner/molecule/lifecycle/converge.yml new file mode 100644 index 0000000..88c7592 --- /dev/null +++ b/ansible/roles/gitea_runner/molecule/lifecycle/converge.yml @@ -0,0 +1,12 @@ +--- +- name: Converge + hosts: all + become: true + vars: + gitea_url: "http://localhost:3000" + registration_token: "fake-token-for-testing" + gitea_runner_name: "lifecycle-test-runner" + gitea_runner_skip_registration: true + gitea_runner_docker_rootless_setup: false + roles: + - role: gitea_runner diff --git a/ansible/roles/gitea-runner/molecule/lifecycle/molecule.yml b/ansible/roles/gitea_runner/molecule/lifecycle/molecule.yml similarity index 100% rename from ansible/roles/gitea-runner/molecule/lifecycle/molecule.yml rename to ansible/roles/gitea_runner/molecule/lifecycle/molecule.yml diff --git a/ansible/roles/gitea-runner/molecule/lifecycle/side_effect.yml b/ansible/roles/gitea_runner/molecule/lifecycle/side_effect.yml similarity index 93% rename from ansible/roles/gitea-runner/molecule/lifecycle/side_effect.yml rename to ansible/roles/gitea_runner/molecule/lifecycle/side_effect.yml index 710ffa1..1bf91aa 100644 --- a/ansible/roles/gitea-runner/molecule/lifecycle/side_effect.yml +++ b/ansible/roles/gitea_runner/molecule/lifecycle/side_effect.yml @@ -3,7 +3,7 @@ hosts: all become: true vars: - runner_name: "lifecycle-test-runner" + gitea_runner_name: "lifecycle-test-runner" pre_tasks: - name: Load role defaults ansible.builtin.include_vars: @@ -23,7 +23,7 @@ hosts: all become: true vars: - runner_name: "lifecycle-test-runner" + gitea_runner_name: "lifecycle-test-runner" pre_tasks: - name: Load role defaults ansible.builtin.include_vars: diff --git a/ansible/roles/gitea-runner/molecule/lifecycle/verify.yml b/ansible/roles/gitea_runner/molecule/lifecycle/verify.yml similarity index 95% rename from ansible/roles/gitea-runner/molecule/lifecycle/verify.yml rename to ansible/roles/gitea_runner/molecule/lifecycle/verify.yml index 4e902c7..78aaff9 100644 --- a/ansible/roles/gitea-runner/molecule/lifecycle/verify.yml +++ b/ansible/roles/gitea_runner/molecule/lifecycle/verify.yml @@ -3,7 +3,7 @@ hosts: all become: true vars: - runner_name: "lifecycle-test-runner" + gitea_runner_name: "lifecycle-test-runner" pre_tasks: - name: Load role defaults ansible.builtin.include_vars: diff --git a/ansible/roles/gitea-runner/molecule/multi-instance/converge.yml b/ansible/roles/gitea_runner/molecule/multi-instance/converge.yml similarity index 53% rename from ansible/roles/gitea-runner/molecule/multi-instance/converge.yml rename to ansible/roles/gitea_runner/molecule/multi-instance/converge.yml index 991877d..e65f616 100644 --- a/ansible/roles/gitea-runner/molecule/multi-instance/converge.yml +++ b/ansible/roles/gitea_runner/molecule/multi-instance/converge.yml @@ -5,11 +5,11 @@ vars: gitea_url: "http://localhost:3000" registration_token: "fake-token-for-testing" - runner_name: "molecule-runner-a" - skip_runner_registration: true - docker_rootless_setup: false + gitea_runner_name: "molecule-runner-a" + gitea_runner_skip_registration: true + gitea_runner_docker_rootless_setup: false roles: - - role: gitea-runner + - role: gitea_runner - name: Converge second runner instance hosts: all @@ -17,8 +17,8 @@ vars: gitea_url: "http://localhost:3000" registration_token: "fake-token-for-testing" - runner_name: "molecule-runner-b" - skip_runner_registration: true - docker_rootless_setup: false + gitea_runner_name: "molecule-runner-b" + gitea_runner_skip_registration: true + gitea_runner_docker_rootless_setup: false roles: - - role: gitea-runner + - role: gitea_runner diff --git a/ansible/roles/gitea-runner/molecule/multi-instance/molecule.yml b/ansible/roles/gitea_runner/molecule/multi-instance/molecule.yml similarity index 100% rename from ansible/roles/gitea-runner/molecule/multi-instance/molecule.yml rename to ansible/roles/gitea_runner/molecule/multi-instance/molecule.yml diff --git a/ansible/roles/gitea-runner/molecule/multi-instance/verify.yml b/ansible/roles/gitea_runner/molecule/multi-instance/verify.yml similarity index 100% rename from ansible/roles/gitea-runner/molecule/multi-instance/verify.yml rename to ansible/roles/gitea_runner/molecule/multi-instance/verify.yml diff --git a/ansible/roles/gitea_runner/molecule/remove/converge.yml b/ansible/roles/gitea_runner/molecule/remove/converge.yml new file mode 100644 index 0000000..26d50ec --- /dev/null +++ b/ansible/roles/gitea_runner/molecule/remove/converge.yml @@ -0,0 +1,12 @@ +--- +- name: Converge + hosts: all + become: true + vars: + gitea_url: "http://localhost:3000" + registration_token: "fake-token-for-testing" + gitea_runner_name: "remove-test-runner" + gitea_runner_skip_registration: true + gitea_runner_docker_rootless_setup: false + roles: + - role: gitea_runner diff --git a/ansible/roles/gitea-runner/molecule/remove/molecule.yml b/ansible/roles/gitea_runner/molecule/remove/molecule.yml similarity index 100% rename from ansible/roles/gitea-runner/molecule/remove/molecule.yml rename to ansible/roles/gitea_runner/molecule/remove/molecule.yml diff --git a/ansible/roles/gitea-runner/molecule/remove/side_effect.yml b/ansible/roles/gitea_runner/molecule/remove/side_effect.yml similarity index 71% rename from ansible/roles/gitea-runner/molecule/remove/side_effect.yml rename to ansible/roles/gitea_runner/molecule/remove/side_effect.yml index e96c23c..b11a623 100644 --- a/ansible/roles/gitea-runner/molecule/remove/side_effect.yml +++ b/ansible/roles/gitea_runner/molecule/remove/side_effect.yml @@ -2,7 +2,7 @@ - name: Remove runner via remove-runner playbook ansible.builtin.import_playbook: "../../../../remove-runner.yml" vars: - runner_name: "remove-test-runner" + gitea_runner_name: "remove-test-runner" registration_token: "fake-token-for-testing" gitea_url: "http://localhost:3000" - skip_runner_registration: true + gitea_runner_skip_registration: true diff --git a/ansible/roles/gitea-runner/molecule/remove/verify.yml b/ansible/roles/gitea_runner/molecule/remove/verify.yml similarity index 99% rename from ansible/roles/gitea-runner/molecule/remove/verify.yml rename to ansible/roles/gitea_runner/molecule/remove/verify.yml index 08a81cb..94713cd 100644 --- a/ansible/roles/gitea-runner/molecule/remove/verify.yml +++ b/ansible/roles/gitea_runner/molecule/remove/verify.yml @@ -3,7 +3,7 @@ hosts: all become: true vars: - runner_name: "remove-test-runner" + gitea_runner_name: "remove-test-runner" pre_tasks: - name: Load role defaults ansible.builtin.include_vars: diff --git a/ansible/roles/gitea_runner/molecule/template-content/converge.yml b/ansible/roles/gitea_runner/molecule/template-content/converge.yml new file mode 100644 index 0000000..97a9587 --- /dev/null +++ b/ansible/roles/gitea_runner/molecule/template-content/converge.yml @@ -0,0 +1,12 @@ +--- +- name: Converge + hosts: all + become: true + vars: + gitea_url: "http://localhost:3000" + registration_token: "fake-token-for-testing" + gitea_runner_name: "template-test-runner" + gitea_runner_skip_registration: true + gitea_runner_docker_rootless_setup: false + roles: + - role: gitea_runner diff --git a/ansible/roles/gitea-runner/molecule/template-content/molecule.yml b/ansible/roles/gitea_runner/molecule/template-content/molecule.yml similarity index 100% rename from ansible/roles/gitea-runner/molecule/template-content/molecule.yml rename to ansible/roles/gitea_runner/molecule/template-content/molecule.yml diff --git a/ansible/roles/gitea-runner/molecule/template-content/verify.yml b/ansible/roles/gitea_runner/molecule/template-content/verify.yml similarity index 99% rename from ansible/roles/gitea-runner/molecule/template-content/verify.yml rename to ansible/roles/gitea_runner/molecule/template-content/verify.yml index 7018150..6c91b73 100644 --- a/ansible/roles/gitea-runner/molecule/template-content/verify.yml +++ b/ansible/roles/gitea_runner/molecule/template-content/verify.yml @@ -3,7 +3,7 @@ hosts: all become: true vars: - runner_name: "template-test-runner" + gitea_runner_name: "template-test-runner" pre_tasks: - name: Load role defaults ansible.builtin.include_vars: diff --git a/ansible/roles/gitea_runner/molecule/update/converge.yml b/ansible/roles/gitea_runner/molecule/update/converge.yml new file mode 100644 index 0000000..c75dd3e --- /dev/null +++ b/ansible/roles/gitea_runner/molecule/update/converge.yml @@ -0,0 +1,12 @@ +--- +- name: Converge + hosts: all + become: true + vars: + gitea_url: "http://localhost:3000" + registration_token: "fake-token-for-testing" + gitea_runner_name: "update-test-runner" + gitea_runner_skip_registration: true + gitea_runner_docker_rootless_setup: false + roles: + - role: gitea_runner diff --git a/ansible/roles/gitea-runner/molecule/update/molecule.yml b/ansible/roles/gitea_runner/molecule/update/molecule.yml similarity index 100% rename from ansible/roles/gitea-runner/molecule/update/molecule.yml rename to ansible/roles/gitea_runner/molecule/update/molecule.yml diff --git a/ansible/roles/gitea-runner/molecule/update/side_effect.yml b/ansible/roles/gitea_runner/molecule/update/side_effect.yml similarity index 71% rename from ansible/roles/gitea-runner/molecule/update/side_effect.yml rename to ansible/roles/gitea_runner/molecule/update/side_effect.yml index 59fa8b7..fd82af2 100644 --- a/ansible/roles/gitea-runner/molecule/update/side_effect.yml +++ b/ansible/roles/gitea_runner/molecule/update/side_effect.yml @@ -3,9 +3,9 @@ hosts: all become: true vars: - runner_name: "update-test-runner" + gitea_runner_name: "update-test-runner" tasks: - name: Include update tasks ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: update_runner.yml diff --git a/ansible/roles/gitea-runner/molecule/update/verify.yml b/ansible/roles/gitea_runner/molecule/update/verify.yml similarity index 96% rename from ansible/roles/gitea-runner/molecule/update/verify.yml rename to ansible/roles/gitea_runner/molecule/update/verify.yml index 25e15ee..a74ab40 100644 --- a/ansible/roles/gitea-runner/molecule/update/verify.yml +++ b/ansible/roles/gitea_runner/molecule/update/verify.yml @@ -3,7 +3,7 @@ hosts: all become: true vars: - runner_name: "update-test-runner" + gitea_runner_name: "update-test-runner" pre_tasks: - name: Load role defaults ansible.builtin.include_vars: diff --git a/ansible/roles/gitea_runner/tasks/deregister.yml b/ansible/roles/gitea_runner/tasks/deregister.yml new file mode 100644 index 0000000..517eabe --- /dev/null +++ b/ansible/roles/gitea_runner/tasks/deregister.yml @@ -0,0 +1,58 @@ +--- +- name: Check if runner registration file exists + ansible.builtin.stat: + path: "{{ gitea_runner_data_dir }}/.runner" + register: gitea_runner_file_stat + +- name: Read runner registration file + ansible.builtin.slurp: + src: "{{ gitea_runner_data_dir }}/.runner" + register: gitea_runner_file_content + when: gitea_runner_file_stat.stat.exists | default(false) | bool + +- name: Parse runner registration data + ansible.builtin.set_fact: + gitea_runner_reg: > + {{ (gitea_runner_file_content.content | b64decode | from_json) + if (gitea_runner_file_content is defined and gitea_runner_file_content.content is defined) + else {} }} + when: gitea_runner_file_stat.stat.exists | default(false) | bool + +- name: Deregister runner from Gitea via API + ansible.builtin.command: > + curl -sf --connect-timeout 5 --max-time 10 -X DELETE + -H "Authorization: token {{ gitea_runner_admin_token | default(registration_token) }}" + "{{ gitea_url }}/api/v1/admin/actions/runners/{{ gitea_runner_reg.id }}" + args: + chdir: "{{ gitea_runner_data_dir }}" + become: true + become_user: "{{ gitea_runner_service_user }}" + environment: + XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default(0) }}" + DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default(0) }}/docker.sock" + when: + - gitea_runner_file_stat.stat.exists | default(false) | bool + - not gitea_runner_skip_registration + - gitea_runner_reg.id is defined + register: gitea_runner_deregister_output + changed_when: gitea_runner_deregister_output.rc == 0 + failed_when: false + +- name: Warn if deregistration failed + ansible.builtin.debug: + msg: >- + WARNING: Runner deregistration from Gitea failed (rc={{ gitea_runner_deregister_output.rc | default('N/A') }}). + The runner entry may remain in Gitea's admin UI as offline. + Use an admin token (gitea_runner_admin_token var) to enable automatic cleanup, + or remove it manually from {{ gitea_url }}/-/admin/actions/runners + when: + - gitea_runner_file_stat.stat.exists | default(false) | bool + - not gitea_runner_skip_registration + - gitea_runner_deregister_output is defined + - gitea_runner_deregister_output.rc | default(1) != 0 + +- name: Remove runner registration file + ansible.builtin.file: + path: "{{ gitea_runner_data_dir }}/.runner" + state: absent + when: gitea_runner_file_stat.stat.exists | default(false) | bool diff --git a/ansible/roles/gitea-runner/tasks/download_gitea_runner.yml b/ansible/roles/gitea_runner/tasks/download_gitea_runner.yml similarity index 100% rename from ansible/roles/gitea-runner/tasks/download_gitea_runner.yml rename to ansible/roles/gitea_runner/tasks/download_gitea_runner.yml diff --git a/ansible/roles/gitea-runner/tasks/healthcheck.yml b/ansible/roles/gitea_runner/tasks/healthcheck.yml similarity index 88% rename from ansible/roles/gitea-runner/tasks/healthcheck.yml rename to ansible/roles/gitea_runner/tasks/healthcheck.yml index de5e2de..1189437 100644 --- a/ansible/roles/gitea-runner/tasks/healthcheck.yml +++ b/ansible/roles/gitea_runner/tasks/healthcheck.yml @@ -31,8 +31,8 @@ XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" changed_when: true when: - - systemd_available.stat.exists - - docker_rootless_setup + - gitea_runner_systemd_available.stat.exists + - gitea_runner_docker_rootless_setup - name: Enable and start healthcheck user timer ansible.builtin.command: systemctl --user enable --now runner-healthcheck.timer @@ -42,5 +42,5 @@ XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" changed_when: true when: - - systemd_available.stat.exists - - docker_rootless_setup + - gitea_runner_systemd_available.stat.exists + - gitea_runner_docker_rootless_setup diff --git a/ansible/roles/gitea-runner/tasks/install_runner.yml b/ansible/roles/gitea_runner/tasks/install_runner.yml similarity index 93% rename from ansible/roles/gitea-runner/tasks/install_runner.yml rename to ansible/roles/gitea_runner/tasks/install_runner.yml index cfd7ee3..b977c45 100644 --- a/ansible/roles/gitea-runner/tasks/install_runner.yml +++ b/ansible/roles/gitea_runner/tasks/install_runner.yml @@ -15,7 +15,7 @@ - name: Include registration ansible.builtin.include_tasks: register.yml - when: not skip_runner_registration + when: not gitea_runner_skip_registration - name: Include service setup ansible.builtin.include_tasks: service.yml diff --git a/ansible/roles/gitea_runner/tasks/integration_test.yml b/ansible/roles/gitea_runner/tasks/integration_test.yml new file mode 100644 index 0000000..b0e65c3 --- /dev/null +++ b/ansible/roles/gitea_runner/tasks/integration_test.yml @@ -0,0 +1,102 @@ +--- +- name: Check runner registration file exists + ansible.builtin.stat: + path: "{{ gitea_runner_data_dir }}/.runner" + register: gitea_runner_file_stat + +- name: Read runner registration file + ansible.builtin.slurp: + src: "{{ gitea_runner_data_dir }}/.runner" + register: gitea_runner_file_content + when: gitea_runner_file_stat.stat.exists | default(false) | bool + +- name: Parse runner registration data + ansible.builtin.set_fact: + gitea_runner_reg: > + {{ (gitea_runner_file_content.content | b64decode | from_json) + if (gitea_runner_file_content is defined and gitea_runner_file_content.content is defined) + else {} }} + when: gitea_runner_file_stat.stat.exists | default(false) | bool + +- name: Verify runner user service active + ansible.builtin.command: systemctl --user is-active gitea-runner + become: true + become_user: "{{ gitea_runner_service_user }}" + environment: + XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" + register: gitea_runner_service_check + changed_when: false + when: + - gitea_runner_systemd_available.stat.exists + - gitea_runner_docker_rootless_setup + +- name: Validate runner installation + ansible.builtin.fail: + msg: > + Runner '{{ gitea_runner_name }}' is not properly installed: + {% if not (gitea_runner_file_stat.stat.exists | default(false)) %} + - Registration file (.runner) is missing. Registration may have failed. + {% endif %} + {% if gitea_runner_docker_rootless_setup and not (gitea_runner_service_check.stdout | default('') | trim) == 'active' %} + - Systemd user service is not active. + {% endif %} + when: > + not (gitea_runner_file_stat.stat.exists | default(false)) + or (gitea_runner_docker_rootless_setup and not (gitea_runner_service_check.stdout | default('') | trim) == 'active') + +- name: Report runner status + ansible.builtin.debug: + msg: > + Runner '{{ gitea_runner_name }}' is installed and running. + Registered: {{ gitea_runner_file_stat.stat.exists | default(false) }} + {% if gitea_runner_reg.id is defined %}Runner ID: {{ gitea_runner_reg.id }}{% endif %} + {% if gitea_runner_reg.uuid is defined %}UUID: {{ gitea_runner_reg.uuid }}{% endif %} + {% if gitea_runner_reg.address is defined %}Gitea: {{ gitea_runner_reg.address }}{% endif %} + Service: {{ gitea_runner_service_check.stdout | default('unknown') | trim }} + +- name: Optional Gitea API verification + when: + - gitea_url is defined + - gitea_runner_admin_token is defined + - gitea_runner_admin_token | length > 0 + block: + - name: Check admin runners API + ansible.builtin.uri: + url: "{{ gitea_url }}/api/v1/admin/runners" + headers: + Authorization: "token {{ gitea_runner_admin_token }}" + method: GET + status_code: [200, 401, 403, 404] + return_content: true + body_format: json + register: gitea_runner_admin_api_response + ignore_errors: true + + - name: Check repo runners API + ansible.builtin.uri: + url: "{{ gitea_url }}/api/v1/repos/{{ gitea_runner_test_repo | default('oblachno-oss/grm') }}/actions/runners" + headers: + Authorization: "token {{ gitea_runner_admin_token }}" + method: GET + status_code: [200, 401, 403, 404] + return_content: true + body_format: json + register: gitea_runner_repo_api_response + ignore_errors: true + + - name: Report API status (informational only) + ansible.builtin.debug: + msg: > + API checks (informational only — not used for pass/fail): + Admin API: {{ gitea_runner_admin_api_response.status | default('no response') }}. + Repo API: {{ gitea_runner_repo_api_response.status | default('no response') }}. + {% if gitea_runner_admin_api_response.json.runners | default([]) | selectattr('name', 'equalto', gitea_runner_name) | list | length > 0 %} + Runner found in admin API. + {% endif %} + {% if gitea_runner_repo_api_response.json.runners | default([]) | selectattr('name', 'equalto', gitea_runner_name) | list | length > 0 %} + Runner found in repo API. + {% endif %} + rescue: + - name: API check failed + ansible.builtin.debug: + msg: "API verification skipped due to connection or permission error." diff --git a/ansible/roles/gitea-runner/tasks/main.yml b/ansible/roles/gitea_runner/tasks/main.yml similarity index 93% rename from ansible/roles/gitea-runner/tasks/main.yml rename to ansible/roles/gitea_runner/tasks/main.yml index d984314..4973dd1 100644 --- a/ansible/roles/gitea-runner/tasks/main.yml +++ b/ansible/roles/gitea_runner/tasks/main.yml @@ -19,4 +19,4 @@ - name: Include integration test ansible.builtin.include_tasks: integration_test.yml - when: not skip_runner_registration + when: not gitea_runner_skip_registration diff --git a/ansible/roles/gitea-runner/tasks/prune.yml b/ansible/roles/gitea_runner/tasks/prune.yml similarity index 86% rename from ansible/roles/gitea-runner/tasks/prune.yml rename to ansible/roles/gitea_runner/tasks/prune.yml index 55e8d5d..3494632 100644 --- a/ansible/roles/gitea-runner/tasks/prune.yml +++ b/ansible/roles/gitea_runner/tasks/prune.yml @@ -23,8 +23,8 @@ XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" changed_when: true when: - - systemd_available.stat.exists - - docker_rootless_setup + - gitea_runner_systemd_available.stat.exists + - gitea_runner_docker_rootless_setup - name: Enable and start docker-prune user timer ansible.builtin.command: systemctl --user enable --now docker-prune.timer @@ -34,5 +34,5 @@ XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" changed_when: true when: - - systemd_available.stat.exists - - docker_rootless_setup + - gitea_runner_systemd_available.stat.exists + - gitea_runner_docker_rootless_setup diff --git a/ansible/roles/gitea-runner/tasks/register.yml b/ansible/roles/gitea_runner/tasks/register.yml similarity index 74% rename from ansible/roles/gitea-runner/tasks/register.yml rename to ansible/roles/gitea_runner/tasks/register.yml index 470e8c4..fd8c7d1 100644 --- a/ansible/roles/gitea-runner/tasks/register.yml +++ b/ansible/roles/gitea_runner/tasks/register.yml @@ -10,15 +10,15 @@ - name: Check if runner is already registered ansible.builtin.stat: path: "{{ gitea_runner_data_dir }}/.runner" - register: runner_registered + register: gitea_runner_registered - name: Register runner with Gitea ansible.builtin.command: > {{ gitea_runner_binary_path }} register --token {{ registration_token }} - --name {{ runner_name }} + --name {{ gitea_runner_name }} --instance {{ gitea_url }} - --labels {{ runner_labels }} + --labels {{ gitea_runner_labels }} --no-interactive args: chdir: "{{ gitea_runner_data_dir }}" @@ -27,7 +27,7 @@ environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default(0) }}" DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default(0) }}/docker.sock" - when: not runner_registered.stat.exists - register: register_output - changed_when: "'already exists' not in register_output.stdout | default('')" + when: not gitea_runner_registered.stat.exists + register: gitea_runner_register_output + changed_when: "'already exists' not in gitea_runner_register_output.stdout | default('')" timeout: 60 diff --git a/ansible/roles/gitea-runner/tasks/resolve_uid.yml b/ansible/roles/gitea_runner/tasks/resolve_uid.yml similarity index 91% rename from ansible/roles/gitea-runner/tasks/resolve_uid.yml rename to ansible/roles/gitea_runner/tasks/resolve_uid.yml index 31c5261..d583c12 100644 --- a/ansible/roles/gitea-runner/tasks/resolve_uid.yml +++ b/ansible/roles/gitea_runner/tasks/resolve_uid.yml @@ -6,14 +6,14 @@ - name: Resolve runner service user ansible.builtin.set_fact: - gitea_runner_service_user: "{{ gitea_runner_user_prefix | default('grm-') }}{{ runner_name }}" + gitea_runner_service_user: "{{ gitea_runner_user_prefix | default('grm-') }}{{ gitea_runner_name }}" gitea_runner_base_data_dir: "/var/lib/gitea-runner" gitea_runner_base_config_dir: "/etc/gitea-runner" - name: Resolve runner data and config dirs ansible.builtin.set_fact: - gitea_runner_data_dir: "{{ gitea_runner_base_data_dir }}/{{ runner_name }}" - gitea_runner_config_dir: "{{ gitea_runner_base_config_dir }}/{{ runner_name }}" + gitea_runner_data_dir: "{{ gitea_runner_base_data_dir }}/{{ gitea_runner_name }}" + gitea_runner_config_dir: "{{ gitea_runner_base_config_dir }}/{{ gitea_runner_name }}" - name: Resolve runner service user UID ansible.builtin.getent: diff --git a/ansible/roles/gitea-runner/tasks/rootless_docker.yml b/ansible/roles/gitea_runner/tasks/rootless_docker.yml similarity index 78% rename from ansible/roles/gitea-runner/tasks/rootless_docker.yml rename to ansible/roles/gitea_runner/tasks/rootless_docker.yml index bf2778c..7ef4067 100644 --- a/ansible/roles/gitea-runner/tasks/rootless_docker.yml +++ b/ansible/roles/gitea_runner/tasks/rootless_docker.yml @@ -9,18 +9,19 @@ - name: Download and dearmor Docker GPG key (Debian/Ubuntu) ansible.builtin.shell: | set -o pipefail - curl -fsSL "https://download.docker.com/linux/{{ ansible_facts['distribution'] | lower }}/gpg" | gpg --dearmor --yes -o {{ docker_gpg_key_path }} + curl -fsSL "https://download.docker.com/linux/{{ ansible_facts['distribution'] | lower }}/gpg" \ + | gpg --dearmor --yes -o {{ gitea_runner_docker_gpg_key_path }} args: - creates: "{{ docker_gpg_key_path }}" + creates: "{{ gitea_runner_docker_gpg_key_path }}" executable: /bin/bash when: ansible_facts['os_family'] == 'Debian' - name: Add Docker APT repository (Debian/Ubuntu) ansible.builtin.copy: dest: /etc/apt/sources.list.d/docker.list - content: "{{ docker_apt_source_line }}\n" + content: "{{ gitea_runner_docker_apt_source_line }}\n" mode: "0644" - register: docker_apt_repo + register: gitea_runner_docker_apt_repo when: ansible_facts['os_family'] == 'Debian' - name: Update apt cache after adding Docker repo (Debian/Ubuntu) @@ -28,7 +29,7 @@ update_cache: true when: - ansible_facts['os_family'] == 'Debian' - - docker_apt_repo is changed + - gitea_runner_docker_apt_repo is changed - name: Install rootless Docker dependencies (Debian/Ubuntu) ansible.builtin.apt: @@ -67,7 +68,7 @@ - name: Check if rootless Docker is already set up ansible.builtin.stat: path: "{{ gitea_runner_home }}/.config/systemd/user/docker.service" - register: rootless_docker_check + register: gitea_runner_rootless_docker_check - name: Set up rootless Docker for runner user ansible.builtin.command: dockerd-rootless-setuptool.sh install @@ -78,8 +79,8 @@ environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" when: - - docker_rootless_setup - - not rootless_docker_check.stat.exists + - gitea_runner_docker_rootless_setup + - not gitea_runner_rootless_docker_check.stat.exists - name: Start rootless Docker daemon (systemd user service) ansible.builtin.command: systemctl --user start docker @@ -88,7 +89,7 @@ environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" changed_when: true - when: docker_rootless_setup + when: gitea_runner_docker_rootless_setup - name: Enable rootless Docker daemon (systemd user service) ansible.builtin.command: systemctl --user enable docker @@ -97,7 +98,7 @@ environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" changed_when: true - when: docker_rootless_setup + when: gitea_runner_docker_rootless_setup - name: Ensure Docker config directory exists ansible.builtin.file: @@ -106,7 +107,7 @@ mode: "0755" owner: "{{ gitea_runner_service_user }}" group: "{{ gitea_runner_service_user }}" - when: docker_rootless_setup + when: gitea_runner_docker_rootless_setup - name: Ensure systemd user override directory exists ansible.builtin.file: @@ -115,21 +116,21 @@ mode: "0755" owner: "{{ gitea_runner_service_user }}" group: "{{ gitea_runner_service_user }}" - when: docker_rootless_setup + 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" content: | [Service] - Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_NET={{ docker_rootless_net_driver }}" + 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 }}" - register: docker_network_override - when: docker_rootless_setup + register: gitea_runner_docker_network_override + when: gitea_runner_docker_rootless_setup - name: Reload systemd user daemon if network config changed ansible.builtin.command: systemctl --user daemon-reload @@ -139,8 +140,8 @@ XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" changed_when: true when: - - docker_rootless_setup - - docker_network_override is changed + - gitea_runner_docker_rootless_setup + - gitea_runner_docker_network_override is changed - name: Configure rootless Docker daemon with IPv6 enabled ansible.builtin.copy: @@ -149,13 +150,13 @@ { "ipv6": true, "ip6tables": true, - "fixed-cidr-v6": "{{ docker_ipv6_cidr }}" + "fixed-cidr-v6": "{{ gitea_runner_docker_ipv6_cidr }}" } mode: "0644" owner: "{{ gitea_runner_service_user }}" group: "{{ gitea_runner_service_user }}" - register: docker_ipv6_config - when: docker_rootless_setup + register: gitea_runner_docker_ipv6_config + when: gitea_runner_docker_rootless_setup - name: Restart rootless Docker if config changed ansible.builtin.command: systemctl --user restart docker @@ -165,8 +166,8 @@ XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" changed_when: true when: - - docker_rootless_setup - - docker_ipv6_config is changed or docker_network_override is changed + - gitea_runner_docker_rootless_setup + - gitea_runner_docker_ipv6_config is changed or gitea_runner_docker_network_override is changed - name: Wait for rootless Docker daemon to be ready ansible.builtin.command: docker version @@ -175,9 +176,9 @@ environment: DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid }}/docker.sock" XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" - register: docker_ready - until: docker_ready.rc == 0 + register: gitea_runner_docker_ready + until: gitea_runner_docker_ready.rc == 0 retries: 10 delay: 2 changed_when: false - when: docker_rootless_setup + when: gitea_runner_docker_rootless_setup diff --git a/ansible/roles/gitea-runner/tasks/service.yml b/ansible/roles/gitea_runner/tasks/service.yml similarity index 82% rename from ansible/roles/gitea-runner/tasks/service.yml rename to ansible/roles/gitea_runner/tasks/service.yml index 63373c7..8b63486 100644 --- a/ansible/roles/gitea-runner/tasks/service.yml +++ b/ansible/roles/gitea_runner/tasks/service.yml @@ -15,8 +15,8 @@ XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" changed_when: true when: - - systemd_available.stat.exists - - docker_rootless_setup + - gitea_runner_systemd_available.stat.exists + - gitea_runner_docker_rootless_setup - name: Enable and start gitea-runner user service ansible.builtin.command: systemctl --user enable --now gitea-runner @@ -26,5 +26,5 @@ XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" changed_when: true when: - - systemd_available.stat.exists - - docker_rootless_setup + - gitea_runner_systemd_available.stat.exists + - gitea_runner_docker_rootless_setup diff --git a/ansible/roles/gitea-runner/tasks/systemd_check.yml b/ansible/roles/gitea_runner/tasks/systemd_check.yml similarity index 69% rename from ansible/roles/gitea-runner/tasks/systemd_check.yml rename to ansible/roles/gitea_runner/tasks/systemd_check.yml index 4f7044a..1fe94ee 100644 --- a/ansible/roles/gitea-runner/tasks/systemd_check.yml +++ b/ansible/roles/gitea_runner/tasks/systemd_check.yml @@ -2,4 +2,4 @@ - name: Check if systemd is available ansible.builtin.stat: path: /run/systemd/system - register: systemd_available + register: gitea_runner_systemd_available diff --git a/ansible/roles/gitea-runner/tasks/update_runner.yml b/ansible/roles/gitea_runner/tasks/update_runner.yml similarity index 76% rename from ansible/roles/gitea-runner/tasks/update_runner.yml rename to ansible/roles/gitea_runner/tasks/update_runner.yml index 9b5b7d8..5b306e7 100644 --- a/ansible/roles/gitea-runner/tasks/update_runner.yml +++ b/ansible/roles/gitea_runner/tasks/update_runner.yml @@ -9,6 +9,6 @@ environment: XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" when: - - systemd_available.stat.exists | default(false) | bool - - docker_rootless_setup + - gitea_runner_systemd_available.stat.exists | default(false) | bool + - gitea_runner_docker_rootless_setup changed_when: true diff --git a/ansible/roles/gitea-runner/tasks/user_setup.yml b/ansible/roles/gitea_runner/tasks/user_setup.yml similarity index 89% rename from ansible/roles/gitea-runner/tasks/user_setup.yml rename to ansible/roles/gitea_runner/tasks/user_setup.yml index 16deb97..4f99fe8 100644 --- a/ansible/roles/gitea-runner/tasks/user_setup.yml +++ b/ansible/roles/gitea_runner/tasks/user_setup.yml @@ -6,21 +6,21 @@ shell: /bin/bash system: true create_home: true - register: runner_user + register: gitea_runner_user - name: Set runner UID fact ansible.builtin.set_fact: - gitea_runner_uid: "{{ runner_user.uid }}" + gitea_runner_uid: "{{ gitea_runner_user.uid }}" - name: Check if lingering is already enabled ansible.builtin.stat: path: "/var/lib/systemd/linger/{{ gitea_runner_service_user }}" - register: linger_stat + register: gitea_runner_linger_stat - name: Enable lingering for runner user ansible.builtin.command: loginctl enable-linger {{ gitea_runner_service_user }} - changed_when: not linger_stat.stat.exists - when: systemd_available.stat.exists + changed_when: not gitea_runner_linger_stat.stat.exists + when: gitea_runner_systemd_available.stat.exists - name: Ensure subuid entry for runner user ansible.builtin.lineinfile: diff --git a/ansible/roles/gitea-runner/tasks/validate.yml b/ansible/roles/gitea_runner/tasks/validate.yml similarity index 90% rename from ansible/roles/gitea-runner/tasks/validate.yml rename to ansible/roles/gitea_runner/tasks/validate.yml index aca2708..7a3327b 100644 --- a/ansible/roles/gitea-runner/tasks/validate.yml +++ b/ansible/roles/gitea_runner/tasks/validate.yml @@ -21,6 +21,6 @@ environment: DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid }}/docker.sock" XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}" - register: docker_version_output + register: gitea_runner_docker_version_output changed_when: false - when: docker_rootless_setup + when: gitea_runner_docker_rootless_setup diff --git a/ansible/roles/gitea-runner/templates/docker-prune.service.j2 b/ansible/roles/gitea_runner/templates/docker-prune.service.j2 similarity index 100% rename from ansible/roles/gitea-runner/templates/docker-prune.service.j2 rename to ansible/roles/gitea_runner/templates/docker-prune.service.j2 diff --git a/ansible/roles/gitea-runner/templates/docker-prune.timer.j2 b/ansible/roles/gitea_runner/templates/docker-prune.timer.j2 similarity index 100% rename from ansible/roles/gitea-runner/templates/docker-prune.timer.j2 rename to ansible/roles/gitea_runner/templates/docker-prune.timer.j2 diff --git a/ansible/roles/gitea-runner/templates/gitea-runner-config.yaml.j2 b/ansible/roles/gitea_runner/templates/gitea-runner-config.yaml.j2 similarity index 100% rename from ansible/roles/gitea-runner/templates/gitea-runner-config.yaml.j2 rename to ansible/roles/gitea_runner/templates/gitea-runner-config.yaml.j2 diff --git a/ansible/roles/gitea-runner/templates/gitea-runner-user.service.j2 b/ansible/roles/gitea_runner/templates/gitea-runner-user.service.j2 similarity index 100% rename from ansible/roles/gitea-runner/templates/gitea-runner-user.service.j2 rename to ansible/roles/gitea_runner/templates/gitea-runner-user.service.j2 diff --git a/ansible/roles/gitea-runner/templates/runner-healthcheck.service.j2 b/ansible/roles/gitea_runner/templates/runner-healthcheck.service.j2 similarity index 100% rename from ansible/roles/gitea-runner/templates/runner-healthcheck.service.j2 rename to ansible/roles/gitea_runner/templates/runner-healthcheck.service.j2 diff --git a/ansible/roles/gitea-runner/templates/runner-healthcheck.sh.j2 b/ansible/roles/gitea_runner/templates/runner-healthcheck.sh.j2 similarity index 100% rename from ansible/roles/gitea-runner/templates/runner-healthcheck.sh.j2 rename to ansible/roles/gitea_runner/templates/runner-healthcheck.sh.j2 diff --git a/ansible/roles/gitea-runner/templates/runner-healthcheck.timer.j2 b/ansible/roles/gitea_runner/templates/runner-healthcheck.timer.j2 similarity index 100% rename from ansible/roles/gitea-runner/templates/runner-healthcheck.timer.j2 rename to ansible/roles/gitea_runner/templates/runner-healthcheck.timer.j2 diff --git a/ansible/start-runner.yml b/ansible/start-runner.yml index bf5cbee..9d4c00e 100644 --- a/ansible/start-runner.yml +++ b/ansible/start-runner.yml @@ -6,12 +6,12 @@ tasks: - name: Include systemd availability check ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: systemd_check.yml - name: Resolve runner UID ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: resolve_uid.yml - name: Check if runner is already registered @@ -21,11 +21,11 @@ - name: Include registration if not registered ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: register.yml when: - not runner_registered.stat.exists - - not skip_runner_registration | default(false) + - not gitea_runner_skip_registration | default(false) - name: Start gitea-runner user service ansible.builtin.command: systemctl --user start gitea-runner diff --git a/ansible/status-runner.yml b/ansible/status-runner.yml index a543b34..8551567 100644 --- a/ansible/status-runner.yml +++ b/ansible/status-runner.yml @@ -6,12 +6,12 @@ tasks: - name: Include systemd availability check ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: systemd_check.yml - name: Resolve runner UID ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: resolve_uid.yml - name: Check systemd user service status diff --git a/ansible/stop-runner.yml b/ansible/stop-runner.yml index 24db13f..5210d5d 100644 --- a/ansible/stop-runner.yml +++ b/ansible/stop-runner.yml @@ -6,12 +6,12 @@ tasks: - name: Include systemd availability check ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: systemd_check.yml - name: Resolve runner UID ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: resolve_uid.yml - name: Stop gitea-runner user service diff --git a/ansible/update-runner.yml b/ansible/update-runner.yml index 252be93..ba4bb11 100644 --- a/ansible/update-runner.yml +++ b/ansible/update-runner.yml @@ -6,5 +6,5 @@ tasks: - name: Update runner ansible.builtin.include_role: - name: gitea-runner + name: gitea_runner tasks_from: update_runner.yml diff --git a/docs/tech/architecture.md b/docs/tech/architecture.md index 8ff30e9..dd377d0 100644 --- a/docs/tech/architecture.md +++ b/docs/tech/architecture.md @@ -3,7 +3,7 @@ GRM consists of two layers: 1. **Python CLI** (`src/grm/`) — built with Click, handles argument parsing, environment loading, i18n translations, and delegates to Ansible via the `ansible-playbook` subprocess. -2. **Ansible Role** (`ansible/roles/gitea-runner/`) — idempotent role that creates a dedicated system user, sets up rootless Docker, installs the runner binary, creates a systemd user service, and registers the runner with Gitea. +2. **Ansible Role** (`ansible/roles/gitea_runner/`) — idempotent role that creates a dedicated system user, sets up rootless Docker, installs the runner binary, creates a systemd user service, and registers the runner with Gitea. ## High-Level Design @@ -26,7 +26,7 @@ The Ansible role handles all remote state: user creation, package installation, grm install └── RunnerManager.install() └── ansible-playbook ansible/install-runner.yml - └── role: gitea-runner + └── role: gitea_runner ├── user_setup.yml (create per-runner system user + lingering) ├── rootless_docker.yml (rootless Docker setup under runner user) ├── install_runner.yml (download binary, config, register, service) @@ -83,8 +83,8 @@ Each runner runs as a systemd user service under a dedicated system user (`grm-< - **User**: `grm-` (dedicated system user with lingering enabled) - **Home**: `/home/grm-/` -- **Data**: `/var/lib/gitea-runner//` -- **Config**: `/etc/gitea-runner//` +- **Data**: `/var/lib/gitea_runner//` +- **Config**: `/etc/gitea_runner//` - **Service**: `gitea-runner.service` (systemd user service) - **Docker socket**: `/run/user//docker.sock` (rootless, per-runner) - **subuid/subgid**: `grm-:100000:65536` (user namespace mapping) @@ -100,7 +100,7 @@ flowchart TD EXEC["Executor
executor.py"] REG["Registry
registry.py
~/.local/share/grm/runners.json"] ANS["ansible-playbook subprocess"] - ROLE["Ansible Role
ansible/roles/gitea-runner/"] + ROLE["Ansible Role
ansible/roles/gitea_runner/"] USER["user_setup.yml
create system user + lingering"] DOCKER["rootless_docker.yml
rootless Docker setup"] INSTALL["install_runner.yml
download, config, register, service"] diff --git a/docs/tech/development-setup.md b/docs/tech/development-setup.md index c799e94..56d6fa2 100644 --- a/docs/tech/development-setup.md +++ b/docs/tech/development-setup.md @@ -16,7 +16,7 @@ │ ├── ui.py # Colorised console output │ └── translations.json # Translation strings ├── ansible/ -│ ├── roles/gitea-runner/ # Main Ansible role +│ ├── roles/gitea_runner/ # Main Ansible role │ │ ├── defaults/main.yml # Default variables │ │ ├── tasks/ # Task files (13 files) │ │ ├── templates/ # Jinja2 templates (4 files) diff --git a/docs/tech/testing-strategy.md b/docs/tech/testing-strategy.md index dc7cabb..e0132a8 100644 --- a/docs/tech/testing-strategy.md +++ b/docs/tech/testing-strategy.md @@ -43,11 +43,11 @@ make molecule # Quick: all 6 scenarios on Ubuntu 22.04 make molecule-all # Full: all 6 scenarios on all 4 supported OSes ``` -Molecule tests validate the Ansible role (`ansible/roles/gitea-runner/`) by creating Docker containers as test hosts, applying the role, and verifying the results. Each scenario tests a specific aspect of the role. +Molecule tests validate the Ansible role (`ansible/roles/gitea_runner/`) by creating Docker containers as test hosts, applying the role, and verifying the results. Each scenario tests a specific aspect of the role. ### Scenarios -Seven Molecule scenarios are defined under `ansible/roles/gitea-runner/molecule/`: +Seven Molecule scenarios are defined under `ansible/roles/gitea_runner/molecule/`: | Scenario | Description | What it verifies | |----------|-------------|------------------| diff --git a/docs/user/cli-commands.md b/docs/user/cli-commands.md index ab484e6..1b7ce4e 100644 --- a/docs/user/cli-commands.md +++ b/docs/user/cli-commands.md @@ -335,7 +335,7 @@ 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. +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 diff --git a/pyproject.toml b/pyproject.toml index ed12225..db32929 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,19 +32,19 @@ version = {attr = "grm.__version__"} ci = [ "pytest==9.1.1", "pytest-cov==7.1.0", - "build==1.5.0", + "build==1.5.1", "twine==6.2.0", # Reusable CI/CD and dev tools (auto-merge, pr-review, pre-push checks, etc.) - "devx==0.40.0", + "devx==0.42.0", ] # Lint and type-checking tools (validate job) lint = [ - "ruff==0.15.20", + "ruff==0.15.21", "pyright==1.1.411", "bandit==1.9.4", "pip-audit==2.10.1", "pre-commit==4.6.0", - "ansible-lint==26.4.0", + "ansible-lint==26.6.0", ] # Molecule testing (molecule-tests job — stays as a separate CI job) molecule = [ @@ -55,7 +55,7 @@ molecule = [ dev = [ "grm[ci,lint,molecule]", # Reusable CI/CD and dev tools (pre-push hooks, create-task, create-pr) - "devx==0.40.0", + "devx==0.42.0", # Non-Python dev dependency: checkmake (Makefile linter) # Install via: go install github.com/checkmake/checkmake/cmd/checkmake@latest ] @@ -108,7 +108,7 @@ repo_name = "grm" ci_scripts_dir = "" # Molecule test weights for LPT scheduling. -# GRM has a single role (gitea-runner) with 7 scenarios. +# GRM has a single role (gitea_runner) with 7 scenarios. # Weights are estimates — recalibrate from CI logs after next run. [tool.devx.molecule.weights] "multi-instance" = 8 diff --git a/src/grm/executor.py b/src/grm/executor.py index 4f5634b..bfd4b7e 100644 --- a/src/grm/executor.py +++ b/src/grm/executor.py @@ -157,7 +157,7 @@ class AnsibleExecutor: with open(log_file) as f: content = f.read() match = re.search( - r'TASK \[gitea-runner : Report runner status\].*?"msg":\s*"([^"]+)"', + r'TASK \[gitea_runner : Report runner status\].*?"msg":\s*"([^"]+)"', content, re.DOTALL, ) diff --git a/src/grm/runner_manager.py b/src/grm/runner_manager.py index 59b8d49..6542c91 100644 --- a/src/grm/runner_manager.py +++ b/src/grm/runner_manager.py @@ -100,14 +100,14 @@ class RunnerManager: extra_vars: dict[str, str | int] = { "registration_token": token, - "runner_name": name, + "gitea_runner_name": name, "gitea_url": gitea_url, "gitea_runner_integration_retries": integration_retries, } if admin_token: extra_vars["gitea_admin_token"] = admin_token if labels is not None: - extra_vars["runner_labels"] = labels + extra_vars["gitea_runner_labels"] = labels with track_steps() as tracker: tracker.begin(_("Installing Gitea Runner on {host}", host=host)) @@ -216,7 +216,7 @@ class RunnerManager: "start-runner.yml", actual_host, actual_user, - {"runner_name": name}, + {"gitea_runner_name": name}, actual_key, ask_become_pass, description=_("Starting Gitea Runner {name} on {host}", name=name, host=actual_host), @@ -243,7 +243,7 @@ class RunnerManager: "stop-runner.yml", actual_host, actual_user, - {"runner_name": name}, + {"gitea_runner_name": name}, actual_key, ask_become_pass, description=_("Stopping Gitea Runner {name} on {host}", name=name, host=actual_host), @@ -270,7 +270,7 @@ class RunnerManager: "restart-runner.yml", actual_host, actual_user, - {"runner_name": name}, + {"gitea_runner_name": name}, actual_key, ask_become_pass, description=_("Restarting Gitea Runner {name} on {host}", name=name, host=actual_host), @@ -297,7 +297,7 @@ class RunnerManager: "enable-runner.yml", actual_host, actual_user, - {"runner_name": name}, + {"gitea_runner_name": name}, actual_key, ask_become_pass, description=_("Enabling Gitea Runner {name} on {host}", name=name, host=actual_host), @@ -331,7 +331,7 @@ class RunnerManager: "disable-runner.yml", actual_host, actual_user, - {"runner_name": name, "registration_token": token, "gitea_url": resolved_gitea_url}, + {"gitea_runner_name": name, "registration_token": token, "gitea_url": resolved_gitea_url}, actual_key, ask_become_pass, description=_("Disabling Gitea Runner {name} on {host}", name=name, host=actual_host), @@ -358,7 +358,7 @@ class RunnerManager: "status-runner.yml", actual_host, actual_user, - {"runner_name": name}, + {"gitea_runner_name": name}, actual_key, ask_become_pass, description=_("Checking status of Gitea Runner {name} on {host}", name=name, host=actual_host), @@ -401,7 +401,7 @@ class RunnerManager: "remove-runner.yml", actual_host, actual_user, - {"runner_name": name, "registration_token": resolved_token, "gitea_url": resolved_gitea_url}, + {"gitea_runner_name": name, "registration_token": resolved_token, "gitea_url": resolved_gitea_url}, actual_key, ask_become_pass, description=_("Removing Gitea Runner {name} from {host}", name=name, host=actual_host), diff --git a/tests/unit/test_executor.py b/tests/unit/test_executor.py index 214e07b..b728a92 100644 --- a/tests/unit/test_executor.py +++ b/tests/unit/test_executor.py @@ -70,7 +70,7 @@ class TestAnsibleExecutorRun: def test_run_extracts_status(self, tmp_path: Path) -> None: log_content = ( - "TASK [gitea-runner : Report runner status]\n" + "TASK [gitea_runner : Report runner status]\n" "ok: [127.0.0.1] => {\n" ' "msg": "Runner \'127.0.0.1\' is installed and running."\n' "}\n" @@ -89,7 +89,7 @@ class TestAnsibleExecutorExtractStatus: def test_extract_status_found(self, tmp_path: Path) -> None: executor = AnsibleExecutor() log_content = ( - "TASK [gitea-runner : Report runner status]\n" + "TASK [gitea_runner : Report runner status]\n" "ok: [127.0.0.1] => {\n" ' "msg": "Runner \'127.0.0.1\' is installed and running."\n' "}\n" diff --git a/tests/unit/test_runner_manager.py b/tests/unit/test_runner_manager.py index e979de7..9febca3 100644 --- a/tests/unit/test_runner_manager.py +++ b/tests/unit/test_runner_manager.py @@ -49,7 +49,7 @@ class TestRunnerManager: assert "--extra-vars" in cmd_str assert "@/tmp/fake-vars.json" in cmd_str assert manager._captured_extra_vars["registration_token"] == "tok" - assert manager._captured_extra_vars["runner_name"] == "192.168.1.10" + assert manager._captured_extra_vars["gitea_runner_name"] == "192.168.1.10" assert manager._captured_extra_vars["gitea_url"] == "https://git.example.com" assert "Installing Gitea Runner on 192.168.1.10" in mock_executor.run.call_args.kwargs["description"] mock_registry.add.assert_called_once_with( @@ -75,7 +75,7 @@ class TestRunnerManager: assert "--private-key" in cmd_str assert "/key" in cmd_str assert manager._captured_extra_vars["registration_token"] == "preset" - assert manager._captured_extra_vars["runner_name"] == "my-runner" + assert manager._captured_extra_vars["gitea_runner_name"] == "my-runner" assert "--ask-become-pass" not in cmd_str mock_registry.add.assert_called_once_with( name="my-runner", @@ -126,7 +126,7 @@ class TestRunnerManager: gitea_url="https://git.example.com", labels="docker:docker://alpine:latest", ) - assert manager._captured_extra_vars["runner_labels"] == "docker:docker://alpine:latest" + assert manager._captured_extra_vars["gitea_runner_labels"] == "docker:docker://alpine:latest" def test_install_no_labels(self) -> None: mock_registry = MagicMock() @@ -145,7 +145,7 @@ class TestRunnerManager: manager._executor = mock_executor manager.install("host1", "root", token="tok", gitea_url="https://git.example.com", labels="") - assert manager._captured_extra_vars["runner_labels"] == "" + assert manager._captured_extra_vars["gitea_runner_labels"] == "" def test_install_with_admin_token(self) -> None: mock_registry = MagicMock() @@ -265,7 +265,7 @@ class TestRunnerManager: cmd = mock_executor.run.call_args.args[0] cmd_str = " ".join(cmd) assert "start-runner.yml" in cmd_str - assert manager._captured_extra_vars["runner_name"] == "r1" + assert manager._captured_extra_vars["gitea_runner_name"] == "r1" assert "Starting Gitea Runner r1 on host" in mock_executor.run.call_args.kwargs["description"] def test_start_with_override(self) -> None: @@ -304,7 +304,7 @@ class TestRunnerManager: cmd = mock_executor.run.call_args.args[0] cmd_str = " ".join(cmd) assert "stop-runner.yml" in cmd_str - assert manager._captured_extra_vars["runner_name"] == "r1" + assert manager._captured_extra_vars["gitea_runner_name"] == "r1" assert "Stopping Gitea Runner r1 on host" in mock_executor.run.call_args.kwargs["description"] def test_restart(self) -> None: @@ -318,7 +318,7 @@ class TestRunnerManager: cmd = mock_executor.run.call_args.args[0] cmd_str = " ".join(cmd) assert "restart-runner.yml" in cmd_str - assert manager._captured_extra_vars["runner_name"] == "r1" + assert manager._captured_extra_vars["gitea_runner_name"] == "r1" assert "Restarting Gitea Runner r1 on host" in mock_executor.run.call_args.kwargs["description"] def test_enable(self) -> None: @@ -332,7 +332,7 @@ class TestRunnerManager: cmd = mock_executor.run.call_args.args[0] cmd_str = " ".join(cmd) assert "enable-runner.yml" in cmd_str - assert manager._captured_extra_vars["runner_name"] == "r1" + assert manager._captured_extra_vars["gitea_runner_name"] == "r1" assert "Enabling Gitea Runner r1 on host" in mock_executor.run.call_args.kwargs["description"] def test_disable(self) -> None: @@ -351,7 +351,7 @@ class TestRunnerManager: cmd = mock_executor.run.call_args.args[0] cmd_str = " ".join(cmd) assert "disable-runner.yml" in cmd_str - assert manager._captured_extra_vars["runner_name"] == "r1" + assert manager._captured_extra_vars["gitea_runner_name"] == "r1" assert manager._captured_extra_vars["registration_token"] == "tok" assert manager._captured_extra_vars["gitea_url"] == "https://git.example.com" assert "Disabling Gitea Runner r1 on host" in mock_executor.run.call_args.kwargs["description"] @@ -396,7 +396,7 @@ class TestRunnerManager: cmd = mock_executor.run.call_args.args[0] cmd_str = " ".join(cmd) assert "status-runner.yml" in cmd_str - assert manager._captured_extra_vars["runner_name"] == "r1" + assert manager._captured_extra_vars["gitea_runner_name"] == "r1" assert "Checking status of Gitea Runner r1 on host" in mock_executor.run.call_args.kwargs["description"] def test_remove(self) -> None: @@ -415,7 +415,7 @@ class TestRunnerManager: cmd = mock_executor.run.call_args.args[0] cmd_str = " ".join(cmd) assert "remove-runner.yml" in cmd_str - assert manager._captured_extra_vars["runner_name"] == "r1" + assert manager._captured_extra_vars["gitea_runner_name"] == "r1" assert manager._captured_extra_vars["registration_token"] == "tok" assert manager._captured_extra_vars["gitea_url"] == "https://git.example.com" assert "Removing Gitea Runner r1 from host" in mock_executor.run.call_args.kwargs["description"]