GRM-148: chore: bump devx to v0.41.1, update deps and runner version
This commit is contained in:
@@ -178,13 +178,13 @@ jobs:
|
|||||||
- name: Discover assigned test pairs
|
- name: Discover assigned test pairs
|
||||||
env:
|
env:
|
||||||
RUNNER_INDEX: ${{ matrix.runner-index }}
|
RUNNER_INDEX: ${{ matrix.runner-index }}
|
||||||
MAX_RUNNERS: ${{ needs.validate.outputs.runner-count }}
|
MAX_RUNNERS: 6
|
||||||
run: |
|
run: |
|
||||||
. .venv/bin/activate 2>/dev/null || true
|
. .venv/bin/activate 2>/dev/null || true
|
||||||
python3 -m devx.molecule.distribute_molecule \
|
python3 -m devx.molecule.distribute_molecule \
|
||||||
--runner-index "$RUNNER_INDEX" \
|
--runner-index "$RUNNER_INDEX" \
|
||||||
--max-runners "$MAX_RUNNERS" \
|
--max-runners "$MAX_RUNNERS" \
|
||||||
--github-env --skip-if-excess
|
--github-env
|
||||||
- name: Run molecule tests
|
- name: Run molecule tests
|
||||||
if: env.SKIP != 'true'
|
if: env.SKIP != 'true'
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ CI also runs a best-effort `make workflow-dryrun` step (skipped if act_runner is
|
|||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
- **Python CLI** (`src/grm/`) — Click-based CLI that delegates to Ansible
|
- **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
|
- **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
|
- **Versioning** (`cliff.toml`) — git-cliff configuration for automated semver versioning from conventional commits
|
||||||
|
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ test-integration:
|
|||||||
$(BIN)/pytest tests/integration/ -v --no-cov
|
$(BIN)/pytest tests/integration/ -v --no-cov
|
||||||
|
|
||||||
MOLECULE := $(realpath $(BIN))/molecule
|
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
|
# Quick local test: Ubuntu 22.04 only, all scenarios
|
||||||
molecule:
|
molecule:
|
||||||
|
|||||||
@@ -266,8 +266,8 @@ One of GRM's core features is the ability to run multiple isolated runners on th
|
|||||||
|
|
||||||
- **Dedicated system user**: `grm-<name>` with its own home directory at `/home/grm-<name>/`
|
- **Dedicated system user**: `grm-<name>` with its own home directory at `/home/grm-<name>/`
|
||||||
- **Rootless Docker daemon**: Isolated Docker socket at `/run/user/<UID>/docker.sock`
|
- **Rootless Docker daemon**: Isolated Docker socket at `/run/user/<UID>/docker.sock`
|
||||||
- **Data directory**: `/var/lib/gitea-runner/<name>/`
|
- **Data directory**: `/var/lib/gitea_runner/<name>/`
|
||||||
- **Config directory**: `/etc/gitea-runner/<name>/`
|
- **Config directory**: `/etc/gitea_runner/<name>/`
|
||||||
- **Systemd user service**: `gitea-runner.service` (independent start/stop/enable)
|
- **Systemd user service**: `gitea-runner.service` (independent start/stop/enable)
|
||||||
- **Docker prune timer**: Per-instance daily cleanup
|
- **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.
|
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
|
```text
|
||||||
grm install <host>
|
grm install <host>
|
||||||
└── RunnerManager.install()
|
└── RunnerManager.install()
|
||||||
└── ansible-playbook ansible/install-runner.yml
|
└── ansible-playbook ansible/install-runner.yml
|
||||||
└── role: gitea-runner
|
└── role: gitea_runner
|
||||||
├── user_setup.yml (create per-runner system user + lingering)
|
├── user_setup.yml (create per-runner system user + lingering)
|
||||||
├── rootless_docker.yml (rootless Docker setup under runner user)
|
├── rootless_docker.yml (rootless Docker setup under runner user)
|
||||||
├── install_runner.yml (download binary, config, register, service)
|
├── install_runner.yml (download binary, config, register, service)
|
||||||
|
|||||||
@@ -6,13 +6,13 @@
|
|||||||
tasks:
|
tasks:
|
||||||
- name: Include systemd availability check
|
- name: Include systemd availability check
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: systemd_check.yml
|
tasks_from: systemd_check.yml
|
||||||
|
|
||||||
- name: Stop gitea-runner user service
|
- name: Stop gitea-runner user service
|
||||||
ansible.builtin.command: systemctl --user stop gitea-runner
|
ansible.builtin.command: systemctl --user stop gitea-runner
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}"
|
||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||||
when: systemd_available.stat.exists
|
when: systemd_available.stat.exists
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
- name: Stop and disable healthcheck timer
|
- name: Stop and disable healthcheck timer
|
||||||
ansible.builtin.command: systemctl --user stop --disable runner-healthcheck.timer
|
ansible.builtin.command: systemctl --user stop --disable runner-healthcheck.timer
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}"
|
||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||||
when: systemd_available.stat.exists
|
when: systemd_available.stat.exists
|
||||||
@@ -30,14 +30,14 @@
|
|||||||
|
|
||||||
- name: Include deregistration
|
- name: Include deregistration
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: deregister.yml
|
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
|
- name: Disable gitea-runner user service
|
||||||
ansible.builtin.command: systemctl --user disable gitea-runner
|
ansible.builtin.command: systemctl --user disable gitea-runner
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}"
|
||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||||
when: systemd_available.stat.exists
|
when: systemd_available.stat.exists
|
||||||
|
|||||||
@@ -6,13 +6,13 @@
|
|||||||
tasks:
|
tasks:
|
||||||
- name: Include systemd availability check
|
- name: Include systemd availability check
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: systemd_check.yml
|
tasks_from: systemd_check.yml
|
||||||
|
|
||||||
- name: Enable gitea-runner user service
|
- name: Enable gitea-runner user service
|
||||||
ansible.builtin.command: systemctl --user enable gitea-runner
|
ansible.builtin.command: systemctl --user enable gitea-runner
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}"
|
||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||||
when: systemd_available.stat.exists
|
when: systemd_available.stat.exists
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
- name: Start gitea-runner user service
|
- name: Start gitea-runner user service
|
||||||
ansible.builtin.command: systemctl --user start gitea-runner
|
ansible.builtin.command: systemctl --user start gitea-runner
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}"
|
||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||||
when: systemd_available.stat.exists
|
when: systemd_available.stat.exists
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
roles:
|
roles:
|
||||||
- role: gitea-runner
|
- role: gitea_runner
|
||||||
|
|||||||
+34
-34
@@ -6,11 +6,11 @@
|
|||||||
tasks:
|
tasks:
|
||||||
- name: Include systemd availability check
|
- name: Include systemd availability check
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: systemd_check.yml
|
tasks_from: systemd_check.yml
|
||||||
|
|
||||||
- name: Get runner user UID
|
- 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
|
register: runner_uid_result
|
||||||
changed_when: false
|
changed_when: false
|
||||||
failed_when: false
|
failed_when: false
|
||||||
@@ -23,20 +23,20 @@
|
|||||||
- name: Stop gitea-runner user service
|
- name: Stop gitea-runner user service
|
||||||
ansible.builtin.command: systemctl --user stop gitea-runner
|
ansible.builtin.command: systemctl --user stop gitea-runner
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}"
|
||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||||
when: systemd_available.stat.exists
|
when: gitea_runner_systemd_available.stat.exists
|
||||||
changed_when: true
|
changed_when: true
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Disable gitea-runner user service
|
- name: Disable gitea-runner user service
|
||||||
ansible.builtin.command: systemctl --user disable gitea-runner
|
ansible.builtin.command: systemctl --user disable gitea-runner
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}"
|
||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||||
when: systemd_available.stat.exists
|
when: gitea_runner_systemd_available.stat.exists
|
||||||
changed_when: true
|
changed_when: true
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
args:
|
args:
|
||||||
executable: /bin/bash
|
executable: /bin/bash
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}"
|
||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||||
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default('') }}/docker.sock"
|
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)
|
- name: Prune all Docker images, volumes, and build cache (rootless)
|
||||||
ansible.builtin.command: docker system prune -af --volumes
|
ansible.builtin.command: docker system prune -af --volumes
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}"
|
||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||||
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default('') }}/docker.sock"
|
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default('') }}/docker.sock"
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
- name: Stop rootless Docker daemon
|
- name: Stop rootless Docker daemon
|
||||||
ansible.builtin.command: systemctl --user stop docker
|
ansible.builtin.command: systemctl --user stop docker
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}"
|
||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||||
changed_when: true
|
changed_when: true
|
||||||
@@ -75,120 +75,120 @@
|
|||||||
|
|
||||||
- name: Include deregistration
|
- name: Include deregistration
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: deregister.yml
|
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
|
- name: Stop and disable healthcheck timer
|
||||||
ansible.builtin.command: systemctl --user stop --disable runner-healthcheck.timer
|
ansible.builtin.command: systemctl --user stop --disable runner-healthcheck.timer
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
become_user: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}"
|
||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||||
when: systemd_available.stat.exists
|
when: gitea_runner_systemd_available.stat.exists
|
||||||
changed_when: true
|
changed_when: true
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Remove docker-prune user service file
|
- name: Remove docker-prune user service file
|
||||||
ansible.builtin.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
|
state: absent
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Remove docker-prune user timer file
|
- name: Remove docker-prune user timer file
|
||||||
ansible.builtin.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
|
state: absent
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Remove healthcheck user service file
|
- name: Remove healthcheck user service file
|
||||||
ansible.builtin.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
|
state: absent
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Remove healthcheck user timer file
|
- name: Remove healthcheck user timer file
|
||||||
ansible.builtin.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
|
state: absent
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Remove healthcheck script
|
- name: Remove healthcheck script
|
||||||
ansible.builtin.file:
|
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
|
state: absent
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Remove systemd user unit file
|
- name: Remove systemd user unit file
|
||||||
ansible.builtin.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
|
state: absent
|
||||||
when: remove_systemd_template | default(true)
|
when: remove_systemd_template | default(true)
|
||||||
|
|
||||||
- name: Kill remaining processes of runner user
|
- 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
|
failed_when: false
|
||||||
changed_when: true
|
changed_when: true
|
||||||
|
|
||||||
- name: Wait for processes to terminate
|
- 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
|
failed_when: false
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: Disable lingering for runner user
|
- 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
|
failed_when: false
|
||||||
changed_when: true
|
changed_when: true
|
||||||
|
|
||||||
- name: Remove runner user and home directory
|
- name: Remove runner user and home directory
|
||||||
ansible.builtin.user:
|
ansible.builtin.user:
|
||||||
name: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
name: "{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}"
|
||||||
state: absent
|
state: absent
|
||||||
remove: true
|
remove: true
|
||||||
when: remove_runner_user | default(true)
|
when: gitea_runner_remove_user | default(true)
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Remove Docker data root when user is kept
|
- name: Remove Docker data root when user is kept
|
||||||
ansible.builtin.file:
|
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
|
state: absent
|
||||||
when: not (remove_runner_user | default(true))
|
when: not (gitea_runner_remove_user | default(true))
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Remove act cache when user is kept
|
- name: Remove act cache when user is kept
|
||||||
ansible.builtin.file:
|
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
|
state: absent
|
||||||
when: not (remove_runner_user | default(true))
|
when: not (gitea_runner_remove_user | default(true))
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Remove systemd user config dir when user is kept
|
- name: Remove systemd user config dir when user is kept
|
||||||
ansible.builtin.file:
|
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
|
state: absent
|
||||||
when: not (remove_runner_user | default(true))
|
when: not (gitea_runner_remove_user | default(true))
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Remove subuid entry for runner user
|
- name: Remove subuid entry for runner user
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
path: /etc/subuid
|
path: /etc/subuid
|
||||||
regexp: "^{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}:"
|
regexp: "^{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}:"
|
||||||
state: absent
|
state: absent
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Remove subgid entry for runner user
|
- name: Remove subgid entry for runner user
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
path: /etc/subgid
|
path: /etc/subgid
|
||||||
regexp: "^{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}:"
|
regexp: "^{{ gitea_runner_service_user | default('grm-' ~ gitea_runner_name) }}:"
|
||||||
state: absent
|
state: absent
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Remove runner data directory
|
- name: Remove runner data directory
|
||||||
ansible.builtin.file:
|
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
|
state: absent
|
||||||
|
|
||||||
- name: Remove runner config directory
|
- name: Remove runner config directory
|
||||||
ansible.builtin.file:
|
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
|
state: absent
|
||||||
|
|||||||
@@ -2,6 +2,6 @@ collections:
|
|||||||
- name: community.general
|
- name: community.general
|
||||||
version: "==13.1.0"
|
version: "==13.1.0"
|
||||||
- name: ansible.posix
|
- name: ansible.posix
|
||||||
version: "==2.2.0"
|
version: "==2.2.1"
|
||||||
- name: community.docker
|
- name: community.docker
|
||||||
version: "==5.2.1"
|
version: "==5.2.1"
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
tasks:
|
tasks:
|
||||||
- name: Include systemd availability check
|
- name: Include systemd availability check
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: systemd_check.yml
|
tasks_from: systemd_check.yml
|
||||||
|
|
||||||
- name: Resolve runner UID
|
- name: Resolve runner UID
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: resolve_uid.yml
|
tasks_from: resolve_uid.yml
|
||||||
|
|
||||||
- name: Stop gitea-runner user service
|
- name: Stop gitea-runner user service
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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."
|
|
||||||
+17
-17
@@ -1,19 +1,19 @@
|
|||||||
---
|
---
|
||||||
gitea_runner_version: "1.0.8"
|
gitea_runner_version: "2.0.1"
|
||||||
runner_labels: "docker,ubuntu-latest:docker://runner-images:ubuntu-26.04"
|
gitea_runner_labels: "docker,ubuntu-latest:docker://runner-images:ubuntu-26.04"
|
||||||
skip_runner_registration: false
|
gitea_runner_skip_registration: false
|
||||||
|
|
||||||
# Per-runner user (rootless isolation)
|
# Per-runner user (rootless isolation)
|
||||||
gitea_runner_user_prefix: "grm-"
|
gitea_runner_user_prefix: "grm-"
|
||||||
gitea_runner_base_home: "/home"
|
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 }}"
|
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_data_dir: "/var/lib/gitea-runner"
|
||||||
gitea_runner_base_config_dir: "/etc/gitea-runner"
|
gitea_runner_base_config_dir: "/etc/gitea-runner"
|
||||||
gitea_runner_data_dir: "{{ gitea_runner_base_data_dir }}/{{ runner_name }}"
|
gitea_runner_data_dir: "{{ gitea_runner_base_data_dir }}/{{ gitea_runner_name }}"
|
||||||
gitea_runner_config_dir: "{{ gitea_runner_base_config_dir }}/{{ runner_name }}"
|
gitea_runner_config_dir: "{{ gitea_runner_base_config_dir }}/{{ gitea_runner_name }}"
|
||||||
gitea_runner_binary_path: "/usr/local/bin/gitea_runner"
|
gitea_runner_binary_path: "/usr/local/bin/gitea_runner"
|
||||||
|
|
||||||
# Prune configuration
|
# Prune configuration
|
||||||
@@ -33,11 +33,11 @@ gitea_runner_healthcheck_script_path: "{{ gitea_runner_config_dir }}/healthcheck
|
|||||||
# Admin token for runner deregistration via Gitea API.
|
# Admin token for runner deregistration via Gitea API.
|
||||||
# If not set, falls back to registration_token (which likely lacks admin scope).
|
# 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.
|
# Set this to a token with admin scope to enable automatic runner cleanup on removal.
|
||||||
gitea_admin_token: ""
|
gitea_runner_admin_token: ""
|
||||||
|
|
||||||
# Removal defaults
|
# Removal defaults
|
||||||
remove_systemd_template: true
|
gitea_runner_remove_systemd_template: true
|
||||||
remove_runner_user: true
|
gitea_runner_remove_user: true
|
||||||
|
|
||||||
# Runner configuration
|
# Runner configuration
|
||||||
gitea_runner_log_level: "info"
|
gitea_runner_log_level: "info"
|
||||||
@@ -45,18 +45,18 @@ gitea_runner_container_label: "gitea-runner=true"
|
|||||||
gitea_runner_file: ".runner"
|
gitea_runner_file: ".runner"
|
||||||
|
|
||||||
# Docker installation (for rootless dependencies)
|
# Docker installation (for rootless dependencies)
|
||||||
docker_gpg_key_path: "/etc/apt/keyrings/docker.gpg"
|
gitea_runner_docker_gpg_key_path: "/etc/apt/keyrings/docker.gpg"
|
||||||
docker_apt_arch: "{{ 'amd64' if ansible_facts['architecture'] == 'x86_64' else ansible_facts['architecture'] }}"
|
gitea_runner_docker_apt_arch: "{{ 'amd64' if ansible_facts['architecture'] == 'x86_64' else ansible_facts['architecture'] }}"
|
||||||
docker_apt_source_line: >-
|
gitea_runner_docker_apt_source_line: >-
|
||||||
deb [arch={{ docker_apt_arch }} signed-by={{ docker_gpg_key_path }}]
|
deb [arch={{ gitea_runner_docker_apt_arch }} signed-by={{ gitea_runner_docker_gpg_key_path }}]
|
||||||
https://download.docker.com/linux/{{ ansible_facts['distribution'] | lower }}
|
https://download.docker.com/linux/{{ ansible_facts['distribution'] | lower }}
|
||||||
{{ ansible_facts['distribution_release'] }} stable
|
{{ ansible_facts['distribution_release'] }} stable
|
||||||
# Set to false in CI/molecule to skip rootless daemon startup (needs kernel userns)
|
# 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)
|
# Rootless Docker network driver: "pasta" (IPv6 support) or "slirp4netns" (IPv4 only)
|
||||||
# pasta has proper outgoing IPv6 support; slirp4netns does not (known limitation).
|
# 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)
|
# 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"
|
||||||
+1
-1
@@ -9,4 +9,4 @@
|
|||||||
when:
|
when:
|
||||||
- ansible_facts is defined
|
- ansible_facts is defined
|
||||||
- ansible_facts['service_mgr'] | default('') == 'systemd'
|
- ansible_facts['service_mgr'] | default('') == 'systemd'
|
||||||
- docker_rootless_setup
|
- gitea_runner_docker_rootless_setup
|
||||||
@@ -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
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
runner_name: "molecule-test-runner"
|
gitea_runner_name: "molecule-test-runner"
|
||||||
pre_tasks:
|
pre_tasks:
|
||||||
- name: Load role defaults
|
- name: Load role defaults
|
||||||
ansible.builtin.include_vars:
|
ansible.builtin.include_vars:
|
||||||
@@ -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
|
||||||
+5
-5
@@ -3,7 +3,7 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
runner_name: "deregister-test-runner"
|
gitea_runner_name: "deregister-test-runner"
|
||||||
pre_tasks:
|
pre_tasks:
|
||||||
- name: Load role defaults
|
- name: Load role defaults
|
||||||
ansible.builtin.include_vars:
|
ansible.builtin.include_vars:
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: "{{ gitea_runner_data_dir }}/.runner"
|
dest: "{{ gitea_runner_data_dir }}/.runner"
|
||||||
content: |
|
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 }}"
|
owner: "{{ gitea_runner_service_user }}"
|
||||||
group: "{{ gitea_runner_service_user }}"
|
group: "{{ gitea_runner_service_user }}"
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
@@ -22,12 +22,12 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
runner_name: "deregister-test-runner"
|
gitea_runner_name: "deregister-test-runner"
|
||||||
registration_token: "fake-token-for-testing"
|
registration_token: "fake-token-for-testing"
|
||||||
gitea_url: "http://localhost:3000"
|
gitea_url: "http://localhost:3000"
|
||||||
skip_runner_registration: false
|
gitea_runner_skip_registration: false
|
||||||
tasks:
|
tasks:
|
||||||
- name: Include deregistration tasks
|
- name: Include deregistration tasks
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: deregister.yml
|
tasks_from: deregister.yml
|
||||||
+3
-3
@@ -3,7 +3,7 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
runner_name: "deregister-test-runner"
|
gitea_runner_name: "deregister-test-runner"
|
||||||
pre_tasks:
|
pre_tasks:
|
||||||
- name: Load role defaults
|
- name: Load role defaults
|
||||||
ansible.builtin.include_vars:
|
ansible.builtin.include_vars:
|
||||||
@@ -12,12 +12,12 @@
|
|||||||
- name: Check registration file was removed
|
- name: Check registration file was removed
|
||||||
ansible.builtin.stat:
|
ansible.builtin.stat:
|
||||||
path: "{{ gitea_runner_data_dir }}/.runner"
|
path: "{{ gitea_runner_data_dir }}/.runner"
|
||||||
register: runner_file_stat
|
register: gitea_runner_file_stat
|
||||||
|
|
||||||
- name: Assert registration file no longer exists
|
- name: Assert registration file no longer exists
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
that:
|
that:
|
||||||
- not runner_file_stat.stat.exists
|
- not gitea_runner_file_stat.stat.exists
|
||||||
fail_msg: "Registration file (.runner) was not removed by deregistration"
|
fail_msg: "Registration file (.runner) was not removed by deregistration"
|
||||||
|
|
||||||
- name: Check systemd user service still exists
|
- name: Check systemd user service still exists
|
||||||
@@ -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
|
||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
runner_name: "lifecycle-test-runner"
|
gitea_runner_name: "lifecycle-test-runner"
|
||||||
pre_tasks:
|
pre_tasks:
|
||||||
- name: Load role defaults
|
- name: Load role defaults
|
||||||
ansible.builtin.include_vars:
|
ansible.builtin.include_vars:
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
runner_name: "lifecycle-test-runner"
|
gitea_runner_name: "lifecycle-test-runner"
|
||||||
pre_tasks:
|
pre_tasks:
|
||||||
- name: Load role defaults
|
- name: Load role defaults
|
||||||
ansible.builtin.include_vars:
|
ansible.builtin.include_vars:
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
runner_name: "lifecycle-test-runner"
|
gitea_runner_name: "lifecycle-test-runner"
|
||||||
pre_tasks:
|
pre_tasks:
|
||||||
- name: Load role defaults
|
- name: Load role defaults
|
||||||
ansible.builtin.include_vars:
|
ansible.builtin.include_vars:
|
||||||
+8
-8
@@ -5,11 +5,11 @@
|
|||||||
vars:
|
vars:
|
||||||
gitea_url: "http://localhost:3000"
|
gitea_url: "http://localhost:3000"
|
||||||
registration_token: "fake-token-for-testing"
|
registration_token: "fake-token-for-testing"
|
||||||
runner_name: "molecule-runner-a"
|
gitea_runner_name: "molecule-runner-a"
|
||||||
skip_runner_registration: true
|
gitea_runner_skip_registration: true
|
||||||
docker_rootless_setup: false
|
gitea_runner_docker_rootless_setup: false
|
||||||
roles:
|
roles:
|
||||||
- role: gitea-runner
|
- role: gitea_runner
|
||||||
|
|
||||||
- name: Converge second runner instance
|
- name: Converge second runner instance
|
||||||
hosts: all
|
hosts: all
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
vars:
|
vars:
|
||||||
gitea_url: "http://localhost:3000"
|
gitea_url: "http://localhost:3000"
|
||||||
registration_token: "fake-token-for-testing"
|
registration_token: "fake-token-for-testing"
|
||||||
runner_name: "molecule-runner-b"
|
gitea_runner_name: "molecule-runner-b"
|
||||||
skip_runner_registration: true
|
gitea_runner_skip_registration: true
|
||||||
docker_rootless_setup: false
|
gitea_runner_docker_rootless_setup: false
|
||||||
roles:
|
roles:
|
||||||
- role: gitea-runner
|
- role: gitea_runner
|
||||||
@@ -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
|
||||||
+2
-2
@@ -2,7 +2,7 @@
|
|||||||
- name: Remove runner via remove-runner playbook
|
- name: Remove runner via remove-runner playbook
|
||||||
ansible.builtin.import_playbook: "../../../../remove-runner.yml"
|
ansible.builtin.import_playbook: "../../../../remove-runner.yml"
|
||||||
vars:
|
vars:
|
||||||
runner_name: "remove-test-runner"
|
gitea_runner_name: "remove-test-runner"
|
||||||
registration_token: "fake-token-for-testing"
|
registration_token: "fake-token-for-testing"
|
||||||
gitea_url: "http://localhost:3000"
|
gitea_url: "http://localhost:3000"
|
||||||
skip_runner_registration: true
|
gitea_runner_skip_registration: true
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
runner_name: "remove-test-runner"
|
gitea_runner_name: "remove-test-runner"
|
||||||
pre_tasks:
|
pre_tasks:
|
||||||
- name: Load role defaults
|
- name: Load role defaults
|
||||||
ansible.builtin.include_vars:
|
ansible.builtin.include_vars:
|
||||||
@@ -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
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
runner_name: "template-test-runner"
|
gitea_runner_name: "template-test-runner"
|
||||||
pre_tasks:
|
pre_tasks:
|
||||||
- name: Load role defaults
|
- name: Load role defaults
|
||||||
ansible.builtin.include_vars:
|
ansible.builtin.include_vars:
|
||||||
@@ -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
|
||||||
+2
-2
@@ -3,9 +3,9 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
runner_name: "update-test-runner"
|
gitea_runner_name: "update-test-runner"
|
||||||
tasks:
|
tasks:
|
||||||
- name: Include update tasks
|
- name: Include update tasks
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: update_runner.yml
|
tasks_from: update_runner.yml
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
runner_name: "update-test-runner"
|
gitea_runner_name: "update-test-runner"
|
||||||
pre_tasks:
|
pre_tasks:
|
||||||
- name: Load role defaults
|
- name: Load role defaults
|
||||||
ansible.builtin.include_vars:
|
ansible.builtin.include_vars:
|
||||||
@@ -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
|
||||||
+4
-4
@@ -31,8 +31,8 @@
|
|||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
changed_when: true
|
changed_when: true
|
||||||
when:
|
when:
|
||||||
- systemd_available.stat.exists
|
- gitea_runner_systemd_available.stat.exists
|
||||||
- docker_rootless_setup
|
- gitea_runner_docker_rootless_setup
|
||||||
|
|
||||||
- name: Enable and start healthcheck user timer
|
- name: Enable and start healthcheck user timer
|
||||||
ansible.builtin.command: systemctl --user enable --now runner-healthcheck.timer
|
ansible.builtin.command: systemctl --user enable --now runner-healthcheck.timer
|
||||||
@@ -42,5 +42,5 @@
|
|||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
changed_when: true
|
changed_when: true
|
||||||
when:
|
when:
|
||||||
- systemd_available.stat.exists
|
- gitea_runner_systemd_available.stat.exists
|
||||||
- docker_rootless_setup
|
- gitea_runner_docker_rootless_setup
|
||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
- name: Include registration
|
- name: Include registration
|
||||||
ansible.builtin.include_tasks: register.yml
|
ansible.builtin.include_tasks: register.yml
|
||||||
when: not skip_runner_registration
|
when: not gitea_runner_skip_registration
|
||||||
|
|
||||||
- name: Include service setup
|
- name: Include service setup
|
||||||
ansible.builtin.include_tasks: service.yml
|
ansible.builtin.include_tasks: service.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."
|
||||||
+1
-1
@@ -19,4 +19,4 @@
|
|||||||
|
|
||||||
- name: Include integration test
|
- name: Include integration test
|
||||||
ansible.builtin.include_tasks: integration_test.yml
|
ansible.builtin.include_tasks: integration_test.yml
|
||||||
when: not skip_runner_registration
|
when: not gitea_runner_skip_registration
|
||||||
+4
-4
@@ -23,8 +23,8 @@
|
|||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
changed_when: true
|
changed_when: true
|
||||||
when:
|
when:
|
||||||
- systemd_available.stat.exists
|
- gitea_runner_systemd_available.stat.exists
|
||||||
- docker_rootless_setup
|
- gitea_runner_docker_rootless_setup
|
||||||
|
|
||||||
- name: Enable and start docker-prune user timer
|
- name: Enable and start docker-prune user timer
|
||||||
ansible.builtin.command: systemctl --user enable --now docker-prune.timer
|
ansible.builtin.command: systemctl --user enable --now docker-prune.timer
|
||||||
@@ -34,5 +34,5 @@
|
|||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
changed_when: true
|
changed_when: true
|
||||||
when:
|
when:
|
||||||
- systemd_available.stat.exists
|
- gitea_runner_systemd_available.stat.exists
|
||||||
- docker_rootless_setup
|
- gitea_runner_docker_rootless_setup
|
||||||
+6
-6
@@ -10,15 +10,15 @@
|
|||||||
- name: Check if runner is already registered
|
- name: Check if runner is already registered
|
||||||
ansible.builtin.stat:
|
ansible.builtin.stat:
|
||||||
path: "{{ gitea_runner_data_dir }}/.runner"
|
path: "{{ gitea_runner_data_dir }}/.runner"
|
||||||
register: runner_registered
|
register: gitea_runner_registered
|
||||||
|
|
||||||
- name: Register runner with Gitea
|
- name: Register runner with Gitea
|
||||||
ansible.builtin.command: >
|
ansible.builtin.command: >
|
||||||
{{ gitea_runner_binary_path }} register
|
{{ gitea_runner_binary_path }} register
|
||||||
--token {{ registration_token }}
|
--token {{ registration_token }}
|
||||||
--name {{ runner_name }}
|
--name {{ gitea_runner_name }}
|
||||||
--instance {{ gitea_url }}
|
--instance {{ gitea_url }}
|
||||||
--labels {{ runner_labels }}
|
--labels {{ gitea_runner_labels }}
|
||||||
--no-interactive
|
--no-interactive
|
||||||
args:
|
args:
|
||||||
chdir: "{{ gitea_runner_data_dir }}"
|
chdir: "{{ gitea_runner_data_dir }}"
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default(0) }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default(0) }}"
|
||||||
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default(0) }}/docker.sock"
|
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default(0) }}/docker.sock"
|
||||||
when: not runner_registered.stat.exists
|
when: not gitea_runner_registered.stat.exists
|
||||||
register: register_output
|
register: gitea_runner_register_output
|
||||||
changed_when: "'already exists' not in register_output.stdout | default('')"
|
changed_when: "'already exists' not in gitea_runner_register_output.stdout | default('')"
|
||||||
timeout: 60
|
timeout: 60
|
||||||
+3
-3
@@ -6,14 +6,14 @@
|
|||||||
|
|
||||||
- name: Resolve runner service user
|
- name: Resolve runner service user
|
||||||
ansible.builtin.set_fact:
|
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_data_dir: "/var/lib/gitea-runner"
|
||||||
gitea_runner_base_config_dir: "/etc/gitea-runner"
|
gitea_runner_base_config_dir: "/etc/gitea-runner"
|
||||||
|
|
||||||
- name: Resolve runner data and config dirs
|
- name: Resolve runner data and config dirs
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
gitea_runner_data_dir: "{{ gitea_runner_base_data_dir }}/{{ runner_name }}"
|
gitea_runner_data_dir: "{{ gitea_runner_base_data_dir }}/{{ gitea_runner_name }}"
|
||||||
gitea_runner_config_dir: "{{ gitea_runner_base_config_dir }}/{{ runner_name }}"
|
gitea_runner_config_dir: "{{ gitea_runner_base_config_dir }}/{{ gitea_runner_name }}"
|
||||||
|
|
||||||
- name: Resolve runner service user UID
|
- name: Resolve runner service user UID
|
||||||
ansible.builtin.getent:
|
ansible.builtin.getent:
|
||||||
+26
-25
@@ -9,18 +9,19 @@
|
|||||||
- name: Download and dearmor Docker GPG key (Debian/Ubuntu)
|
- name: Download and dearmor Docker GPG key (Debian/Ubuntu)
|
||||||
ansible.builtin.shell: |
|
ansible.builtin.shell: |
|
||||||
set -o pipefail
|
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:
|
args:
|
||||||
creates: "{{ docker_gpg_key_path }}"
|
creates: "{{ gitea_runner_docker_gpg_key_path }}"
|
||||||
executable: /bin/bash
|
executable: /bin/bash
|
||||||
when: ansible_facts['os_family'] == 'Debian'
|
when: ansible_facts['os_family'] == 'Debian'
|
||||||
|
|
||||||
- name: Add Docker APT repository (Debian/Ubuntu)
|
- name: Add Docker APT repository (Debian/Ubuntu)
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: /etc/apt/sources.list.d/docker.list
|
dest: /etc/apt/sources.list.d/docker.list
|
||||||
content: "{{ docker_apt_source_line }}\n"
|
content: "{{ gitea_runner_docker_apt_source_line }}\n"
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
register: docker_apt_repo
|
register: gitea_runner_docker_apt_repo
|
||||||
when: ansible_facts['os_family'] == 'Debian'
|
when: ansible_facts['os_family'] == 'Debian'
|
||||||
|
|
||||||
- name: Update apt cache after adding Docker repo (Debian/Ubuntu)
|
- name: Update apt cache after adding Docker repo (Debian/Ubuntu)
|
||||||
@@ -28,7 +29,7 @@
|
|||||||
update_cache: true
|
update_cache: true
|
||||||
when:
|
when:
|
||||||
- ansible_facts['os_family'] == 'Debian'
|
- ansible_facts['os_family'] == 'Debian'
|
||||||
- docker_apt_repo is changed
|
- gitea_runner_docker_apt_repo is changed
|
||||||
|
|
||||||
- name: Install rootless Docker dependencies (Debian/Ubuntu)
|
- name: Install rootless Docker dependencies (Debian/Ubuntu)
|
||||||
ansible.builtin.apt:
|
ansible.builtin.apt:
|
||||||
@@ -67,7 +68,7 @@
|
|||||||
- name: Check if rootless Docker is already set up
|
- name: Check if rootless Docker is already set up
|
||||||
ansible.builtin.stat:
|
ansible.builtin.stat:
|
||||||
path: "{{ gitea_runner_home }}/.config/systemd/user/docker.service"
|
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
|
- name: Set up rootless Docker for runner user
|
||||||
ansible.builtin.command: dockerd-rootless-setuptool.sh install
|
ansible.builtin.command: dockerd-rootless-setuptool.sh install
|
||||||
@@ -78,8 +79,8 @@
|
|||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
when:
|
when:
|
||||||
- docker_rootless_setup
|
- gitea_runner_docker_rootless_setup
|
||||||
- not rootless_docker_check.stat.exists
|
- not gitea_runner_rootless_docker_check.stat.exists
|
||||||
|
|
||||||
- name: Start rootless Docker daemon (systemd user service)
|
- name: Start rootless Docker daemon (systemd user service)
|
||||||
ansible.builtin.command: systemctl --user start docker
|
ansible.builtin.command: systemctl --user start docker
|
||||||
@@ -88,7 +89,7 @@
|
|||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
changed_when: true
|
changed_when: true
|
||||||
when: docker_rootless_setup
|
when: gitea_runner_docker_rootless_setup
|
||||||
|
|
||||||
- name: Enable rootless Docker daemon (systemd user service)
|
- name: Enable rootless Docker daemon (systemd user service)
|
||||||
ansible.builtin.command: systemctl --user enable docker
|
ansible.builtin.command: systemctl --user enable docker
|
||||||
@@ -97,7 +98,7 @@
|
|||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
changed_when: true
|
changed_when: true
|
||||||
when: docker_rootless_setup
|
when: gitea_runner_docker_rootless_setup
|
||||||
|
|
||||||
- name: Ensure Docker config directory exists
|
- name: Ensure Docker config directory exists
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
@@ -106,7 +107,7 @@
|
|||||||
mode: "0755"
|
mode: "0755"
|
||||||
owner: "{{ gitea_runner_service_user }}"
|
owner: "{{ gitea_runner_service_user }}"
|
||||||
group: "{{ 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
|
- name: Ensure systemd user override directory exists
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
@@ -115,21 +116,21 @@
|
|||||||
mode: "0755"
|
mode: "0755"
|
||||||
owner: "{{ gitea_runner_service_user }}"
|
owner: "{{ gitea_runner_service_user }}"
|
||||||
group: "{{ 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
|
- name: Configure rootless Docker to use pasta with IPv6
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: "{{ gitea_runner_home }}/.config/systemd/user/docker.service.d/override.conf"
|
dest: "{{ gitea_runner_home }}/.config/systemd/user/docker.service.d/override.conf"
|
||||||
content: |
|
content: |
|
||||||
[Service]
|
[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_PORT_DRIVER=implicit"
|
||||||
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS=--ipv6"
|
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS=--ipv6"
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
owner: "{{ gitea_runner_service_user }}"
|
owner: "{{ gitea_runner_service_user }}"
|
||||||
group: "{{ gitea_runner_service_user }}"
|
group: "{{ gitea_runner_service_user }}"
|
||||||
register: docker_network_override
|
register: gitea_runner_docker_network_override
|
||||||
when: docker_rootless_setup
|
when: gitea_runner_docker_rootless_setup
|
||||||
|
|
||||||
- name: Reload systemd user daemon if network config changed
|
- name: Reload systemd user daemon if network config changed
|
||||||
ansible.builtin.command: systemctl --user daemon-reload
|
ansible.builtin.command: systemctl --user daemon-reload
|
||||||
@@ -139,8 +140,8 @@
|
|||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
changed_when: true
|
changed_when: true
|
||||||
when:
|
when:
|
||||||
- docker_rootless_setup
|
- gitea_runner_docker_rootless_setup
|
||||||
- docker_network_override is changed
|
- gitea_runner_docker_network_override is changed
|
||||||
|
|
||||||
- name: Configure rootless Docker daemon with IPv6 enabled
|
- name: Configure rootless Docker daemon with IPv6 enabled
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
@@ -149,13 +150,13 @@
|
|||||||
{
|
{
|
||||||
"ipv6": true,
|
"ipv6": true,
|
||||||
"ip6tables": true,
|
"ip6tables": true,
|
||||||
"fixed-cidr-v6": "{{ docker_ipv6_cidr }}"
|
"fixed-cidr-v6": "{{ gitea_runner_docker_ipv6_cidr }}"
|
||||||
}
|
}
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
owner: "{{ gitea_runner_service_user }}"
|
owner: "{{ gitea_runner_service_user }}"
|
||||||
group: "{{ gitea_runner_service_user }}"
|
group: "{{ gitea_runner_service_user }}"
|
||||||
register: docker_ipv6_config
|
register: gitea_runner_docker_ipv6_config
|
||||||
when: docker_rootless_setup
|
when: gitea_runner_docker_rootless_setup
|
||||||
|
|
||||||
- name: Restart rootless Docker if config changed
|
- name: Restart rootless Docker if config changed
|
||||||
ansible.builtin.command: systemctl --user restart docker
|
ansible.builtin.command: systemctl --user restart docker
|
||||||
@@ -165,8 +166,8 @@
|
|||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
changed_when: true
|
changed_when: true
|
||||||
when:
|
when:
|
||||||
- docker_rootless_setup
|
- gitea_runner_docker_rootless_setup
|
||||||
- docker_ipv6_config is changed or docker_network_override is changed
|
- gitea_runner_docker_ipv6_config is changed or gitea_runner_docker_network_override is changed
|
||||||
|
|
||||||
- name: Wait for rootless Docker daemon to be ready
|
- name: Wait for rootless Docker daemon to be ready
|
||||||
ansible.builtin.command: docker version
|
ansible.builtin.command: docker version
|
||||||
@@ -175,9 +176,9 @@
|
|||||||
environment:
|
environment:
|
||||||
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid }}/docker.sock"
|
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid }}/docker.sock"
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
register: docker_ready
|
register: gitea_runner_docker_ready
|
||||||
until: docker_ready.rc == 0
|
until: gitea_runner_docker_ready.rc == 0
|
||||||
retries: 10
|
retries: 10
|
||||||
delay: 2
|
delay: 2
|
||||||
changed_when: false
|
changed_when: false
|
||||||
when: docker_rootless_setup
|
when: gitea_runner_docker_rootless_setup
|
||||||
+4
-4
@@ -15,8 +15,8 @@
|
|||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
changed_when: true
|
changed_when: true
|
||||||
when:
|
when:
|
||||||
- systemd_available.stat.exists
|
- gitea_runner_systemd_available.stat.exists
|
||||||
- docker_rootless_setup
|
- gitea_runner_docker_rootless_setup
|
||||||
|
|
||||||
- name: Enable and start gitea-runner user service
|
- name: Enable and start gitea-runner user service
|
||||||
ansible.builtin.command: systemctl --user enable --now gitea-runner
|
ansible.builtin.command: systemctl --user enable --now gitea-runner
|
||||||
@@ -26,5 +26,5 @@
|
|||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
changed_when: true
|
changed_when: true
|
||||||
when:
|
when:
|
||||||
- systemd_available.stat.exists
|
- gitea_runner_systemd_available.stat.exists
|
||||||
- docker_rootless_setup
|
- gitea_runner_docker_rootless_setup
|
||||||
+1
-1
@@ -2,4 +2,4 @@
|
|||||||
- name: Check if systemd is available
|
- name: Check if systemd is available
|
||||||
ansible.builtin.stat:
|
ansible.builtin.stat:
|
||||||
path: /run/systemd/system
|
path: /run/systemd/system
|
||||||
register: systemd_available
|
register: gitea_runner_systemd_available
|
||||||
+2
-2
@@ -9,6 +9,6 @@
|
|||||||
environment:
|
environment:
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
when:
|
when:
|
||||||
- systemd_available.stat.exists | default(false) | bool
|
- gitea_runner_systemd_available.stat.exists | default(false) | bool
|
||||||
- docker_rootless_setup
|
- gitea_runner_docker_rootless_setup
|
||||||
changed_when: true
|
changed_when: true
|
||||||
+5
-5
@@ -6,21 +6,21 @@
|
|||||||
shell: /bin/bash
|
shell: /bin/bash
|
||||||
system: true
|
system: true
|
||||||
create_home: true
|
create_home: true
|
||||||
register: runner_user
|
register: gitea_runner_user
|
||||||
|
|
||||||
- name: Set runner UID fact
|
- name: Set runner UID fact
|
||||||
ansible.builtin.set_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
|
- name: Check if lingering is already enabled
|
||||||
ansible.builtin.stat:
|
ansible.builtin.stat:
|
||||||
path: "/var/lib/systemd/linger/{{ gitea_runner_service_user }}"
|
path: "/var/lib/systemd/linger/{{ gitea_runner_service_user }}"
|
||||||
register: linger_stat
|
register: gitea_runner_linger_stat
|
||||||
|
|
||||||
- name: Enable lingering for runner user
|
- name: Enable lingering for runner user
|
||||||
ansible.builtin.command: loginctl enable-linger {{ gitea_runner_service_user }}
|
ansible.builtin.command: loginctl enable-linger {{ gitea_runner_service_user }}
|
||||||
changed_when: not linger_stat.stat.exists
|
changed_when: not gitea_runner_linger_stat.stat.exists
|
||||||
when: systemd_available.stat.exists
|
when: gitea_runner_systemd_available.stat.exists
|
||||||
|
|
||||||
- name: Ensure subuid entry for runner user
|
- name: Ensure subuid entry for runner user
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
+2
-2
@@ -21,6 +21,6 @@
|
|||||||
environment:
|
environment:
|
||||||
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid }}/docker.sock"
|
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid }}/docker.sock"
|
||||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||||
register: docker_version_output
|
register: gitea_runner_docker_version_output
|
||||||
changed_when: false
|
changed_when: false
|
||||||
when: docker_rootless_setup
|
when: gitea_runner_docker_rootless_setup
|
||||||
@@ -6,12 +6,12 @@
|
|||||||
tasks:
|
tasks:
|
||||||
- name: Include systemd availability check
|
- name: Include systemd availability check
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: systemd_check.yml
|
tasks_from: systemd_check.yml
|
||||||
|
|
||||||
- name: Resolve runner UID
|
- name: Resolve runner UID
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: resolve_uid.yml
|
tasks_from: resolve_uid.yml
|
||||||
|
|
||||||
- name: Check if runner is already registered
|
- name: Check if runner is already registered
|
||||||
@@ -21,11 +21,11 @@
|
|||||||
|
|
||||||
- name: Include registration if not registered
|
- name: Include registration if not registered
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: register.yml
|
tasks_from: register.yml
|
||||||
when:
|
when:
|
||||||
- not runner_registered.stat.exists
|
- not runner_registered.stat.exists
|
||||||
- not skip_runner_registration | default(false)
|
- not gitea_runner_skip_registration | default(false)
|
||||||
|
|
||||||
- name: Start gitea-runner user service
|
- name: Start gitea-runner user service
|
||||||
ansible.builtin.command: systemctl --user start gitea-runner
|
ansible.builtin.command: systemctl --user start gitea-runner
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
tasks:
|
tasks:
|
||||||
- name: Include systemd availability check
|
- name: Include systemd availability check
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: systemd_check.yml
|
tasks_from: systemd_check.yml
|
||||||
|
|
||||||
- name: Resolve runner UID
|
- name: Resolve runner UID
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: resolve_uid.yml
|
tasks_from: resolve_uid.yml
|
||||||
|
|
||||||
- name: Check systemd user service status
|
- name: Check systemd user service status
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
tasks:
|
tasks:
|
||||||
- name: Include systemd availability check
|
- name: Include systemd availability check
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: systemd_check.yml
|
tasks_from: systemd_check.yml
|
||||||
|
|
||||||
- name: Resolve runner UID
|
- name: Resolve runner UID
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: resolve_uid.yml
|
tasks_from: resolve_uid.yml
|
||||||
|
|
||||||
- name: Stop gitea-runner user service
|
- name: Stop gitea-runner user service
|
||||||
|
|||||||
@@ -6,5 +6,5 @@
|
|||||||
tasks:
|
tasks:
|
||||||
- name: Update runner
|
- name: Update runner
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: gitea-runner
|
name: gitea_runner
|
||||||
tasks_from: update_runner.yml
|
tasks_from: update_runner.yml
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
GRM consists of two layers:
|
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.
|
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
|
## High-Level Design
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ The Ansible role handles all remote state: user creation, package installation,
|
|||||||
grm install <host>
|
grm install <host>
|
||||||
└── RunnerManager.install()
|
└── RunnerManager.install()
|
||||||
└── ansible-playbook ansible/install-runner.yml
|
└── ansible-playbook ansible/install-runner.yml
|
||||||
└── role: gitea-runner
|
└── role: gitea_runner
|
||||||
├── user_setup.yml (create per-runner system user + lingering)
|
├── user_setup.yml (create per-runner system user + lingering)
|
||||||
├── rootless_docker.yml (rootless Docker setup under runner user)
|
├── rootless_docker.yml (rootless Docker setup under runner user)
|
||||||
├── install_runner.yml (download binary, config, register, service)
|
├── 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-<name>` (dedicated system user with lingering enabled)
|
- **User**: `grm-<name>` (dedicated system user with lingering enabled)
|
||||||
- **Home**: `/home/grm-<name>/`
|
- **Home**: `/home/grm-<name>/`
|
||||||
- **Data**: `/var/lib/gitea-runner/<name>/`
|
- **Data**: `/var/lib/gitea_runner/<name>/`
|
||||||
- **Config**: `/etc/gitea-runner/<name>/`
|
- **Config**: `/etc/gitea_runner/<name>/`
|
||||||
- **Service**: `gitea-runner.service` (systemd user service)
|
- **Service**: `gitea-runner.service` (systemd user service)
|
||||||
- **Docker socket**: `/run/user/<UID>/docker.sock` (rootless, per-runner)
|
- **Docker socket**: `/run/user/<UID>/docker.sock` (rootless, per-runner)
|
||||||
- **subuid/subgid**: `grm-<name>:100000:65536` (user namespace mapping)
|
- **subuid/subgid**: `grm-<name>:100000:65536` (user namespace mapping)
|
||||||
@@ -100,7 +100,7 @@ flowchart TD
|
|||||||
EXEC["Executor<br/>executor.py"]
|
EXEC["Executor<br/>executor.py"]
|
||||||
REG["Registry<br/>registry.py<br/>~/.local/share/grm/runners.json"]
|
REG["Registry<br/>registry.py<br/>~/.local/share/grm/runners.json"]
|
||||||
ANS["ansible-playbook subprocess"]
|
ANS["ansible-playbook subprocess"]
|
||||||
ROLE["Ansible Role<br/>ansible/roles/gitea-runner/"]
|
ROLE["Ansible Role<br/>ansible/roles/gitea_runner/"]
|
||||||
USER["user_setup.yml<br/>create system user + lingering"]
|
USER["user_setup.yml<br/>create system user + lingering"]
|
||||||
DOCKER["rootless_docker.yml<br/>rootless Docker setup"]
|
DOCKER["rootless_docker.yml<br/>rootless Docker setup"]
|
||||||
INSTALL["install_runner.yml<br/>download, config, register, service"]
|
INSTALL["install_runner.yml<br/>download, config, register, service"]
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
│ ├── ui.py # Colorised console output
|
│ ├── ui.py # Colorised console output
|
||||||
│ └── translations.json # Translation strings
|
│ └── translations.json # Translation strings
|
||||||
├── ansible/
|
├── ansible/
|
||||||
│ ├── roles/gitea-runner/ # Main Ansible role
|
│ ├── roles/gitea_runner/ # Main Ansible role
|
||||||
│ │ ├── defaults/main.yml # Default variables
|
│ │ ├── defaults/main.yml # Default variables
|
||||||
│ │ ├── tasks/ # Task files (13 files)
|
│ │ ├── tasks/ # Task files (13 files)
|
||||||
│ │ ├── templates/ # Jinja2 templates (4 files)
|
│ │ ├── templates/ # Jinja2 templates (4 files)
|
||||||
|
|||||||
@@ -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
|
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
|
### 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 |
|
| Scenario | Description | What it verifies |
|
||||||
|----------|-------------|------------------|
|
|----------|-------------|------------------|
|
||||||
|
|||||||
@@ -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.
|
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
|
## trigger-workflow
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -32,19 +32,19 @@ version = {attr = "grm.__version__"}
|
|||||||
ci = [
|
ci = [
|
||||||
"pytest==9.1.1",
|
"pytest==9.1.1",
|
||||||
"pytest-cov==7.1.0",
|
"pytest-cov==7.1.0",
|
||||||
"build==1.5.0",
|
"build==1.5.1",
|
||||||
"twine==6.2.0",
|
"twine==6.2.0",
|
||||||
# Reusable CI/CD and dev tools (auto-merge, pr-review, pre-push checks, etc.)
|
# 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 and type-checking tools (validate job)
|
||||||
lint = [
|
lint = [
|
||||||
"ruff==0.15.20",
|
"ruff==0.15.21",
|
||||||
"pyright==1.1.411",
|
"pyright==1.1.411",
|
||||||
"bandit==1.9.4",
|
"bandit==1.9.4",
|
||||||
"pip-audit==2.10.1",
|
"pip-audit==2.10.1",
|
||||||
"pre-commit==4.6.0",
|
"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 testing (molecule-tests job — stays as a separate CI job)
|
||||||
molecule = [
|
molecule = [
|
||||||
@@ -55,7 +55,7 @@ molecule = [
|
|||||||
dev = [
|
dev = [
|
||||||
"grm[ci,lint,molecule]",
|
"grm[ci,lint,molecule]",
|
||||||
# Reusable CI/CD and dev tools (pre-push hooks, create-task, create-pr)
|
# 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)
|
# Non-Python dev dependency: checkmake (Makefile linter)
|
||||||
# Install via: go install github.com/checkmake/checkmake/cmd/checkmake@latest
|
# Install via: go install github.com/checkmake/checkmake/cmd/checkmake@latest
|
||||||
]
|
]
|
||||||
@@ -108,7 +108,7 @@ repo_name = "grm"
|
|||||||
ci_scripts_dir = ""
|
ci_scripts_dir = ""
|
||||||
|
|
||||||
# Molecule test weights for LPT scheduling.
|
# 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.
|
# Weights are estimates — recalibrate from CI logs after next run.
|
||||||
[tool.devx.molecule.weights]
|
[tool.devx.molecule.weights]
|
||||||
"multi-instance" = 8
|
"multi-instance" = 8
|
||||||
|
|||||||
+1
-1
@@ -157,7 +157,7 @@ class AnsibleExecutor:
|
|||||||
with open(log_file) as f:
|
with open(log_file) as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
match = re.search(
|
match = re.search(
|
||||||
r'TASK \[gitea-runner : Report runner status\].*?"msg":\s*"([^"]+)"',
|
r'TASK \[gitea_runner : Report runner status\].*?"msg":\s*"([^"]+)"',
|
||||||
content,
|
content,
|
||||||
re.DOTALL,
|
re.DOTALL,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -100,14 +100,14 @@ class RunnerManager:
|
|||||||
|
|
||||||
extra_vars: dict[str, str | int] = {
|
extra_vars: dict[str, str | int] = {
|
||||||
"registration_token": token,
|
"registration_token": token,
|
||||||
"runner_name": name,
|
"gitea_runner_name": name,
|
||||||
"gitea_url": gitea_url,
|
"gitea_url": gitea_url,
|
||||||
"gitea_runner_integration_retries": integration_retries,
|
"gitea_runner_integration_retries": integration_retries,
|
||||||
}
|
}
|
||||||
if admin_token:
|
if admin_token:
|
||||||
extra_vars["gitea_admin_token"] = admin_token
|
extra_vars["gitea_admin_token"] = admin_token
|
||||||
if labels is not None:
|
if labels is not None:
|
||||||
extra_vars["runner_labels"] = labels
|
extra_vars["gitea_runner_labels"] = labels
|
||||||
|
|
||||||
with track_steps() as tracker:
|
with track_steps() as tracker:
|
||||||
tracker.begin(_("Installing Gitea Runner on {host}", host=host))
|
tracker.begin(_("Installing Gitea Runner on {host}", host=host))
|
||||||
@@ -216,7 +216,7 @@ class RunnerManager:
|
|||||||
"start-runner.yml",
|
"start-runner.yml",
|
||||||
actual_host,
|
actual_host,
|
||||||
actual_user,
|
actual_user,
|
||||||
{"runner_name": name},
|
{"gitea_runner_name": name},
|
||||||
actual_key,
|
actual_key,
|
||||||
ask_become_pass,
|
ask_become_pass,
|
||||||
description=_("Starting Gitea Runner {name} on {host}", name=name, host=actual_host),
|
description=_("Starting Gitea Runner {name} on {host}", name=name, host=actual_host),
|
||||||
@@ -243,7 +243,7 @@ class RunnerManager:
|
|||||||
"stop-runner.yml",
|
"stop-runner.yml",
|
||||||
actual_host,
|
actual_host,
|
||||||
actual_user,
|
actual_user,
|
||||||
{"runner_name": name},
|
{"gitea_runner_name": name},
|
||||||
actual_key,
|
actual_key,
|
||||||
ask_become_pass,
|
ask_become_pass,
|
||||||
description=_("Stopping Gitea Runner {name} on {host}", name=name, host=actual_host),
|
description=_("Stopping Gitea Runner {name} on {host}", name=name, host=actual_host),
|
||||||
@@ -270,7 +270,7 @@ class RunnerManager:
|
|||||||
"restart-runner.yml",
|
"restart-runner.yml",
|
||||||
actual_host,
|
actual_host,
|
||||||
actual_user,
|
actual_user,
|
||||||
{"runner_name": name},
|
{"gitea_runner_name": name},
|
||||||
actual_key,
|
actual_key,
|
||||||
ask_become_pass,
|
ask_become_pass,
|
||||||
description=_("Restarting Gitea Runner {name} on {host}", name=name, host=actual_host),
|
description=_("Restarting Gitea Runner {name} on {host}", name=name, host=actual_host),
|
||||||
@@ -297,7 +297,7 @@ class RunnerManager:
|
|||||||
"enable-runner.yml",
|
"enable-runner.yml",
|
||||||
actual_host,
|
actual_host,
|
||||||
actual_user,
|
actual_user,
|
||||||
{"runner_name": name},
|
{"gitea_runner_name": name},
|
||||||
actual_key,
|
actual_key,
|
||||||
ask_become_pass,
|
ask_become_pass,
|
||||||
description=_("Enabling Gitea Runner {name} on {host}", name=name, host=actual_host),
|
description=_("Enabling Gitea Runner {name} on {host}", name=name, host=actual_host),
|
||||||
@@ -331,7 +331,7 @@ class RunnerManager:
|
|||||||
"disable-runner.yml",
|
"disable-runner.yml",
|
||||||
actual_host,
|
actual_host,
|
||||||
actual_user,
|
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,
|
actual_key,
|
||||||
ask_become_pass,
|
ask_become_pass,
|
||||||
description=_("Disabling Gitea Runner {name} on {host}", name=name, host=actual_host),
|
description=_("Disabling Gitea Runner {name} on {host}", name=name, host=actual_host),
|
||||||
@@ -358,7 +358,7 @@ class RunnerManager:
|
|||||||
"status-runner.yml",
|
"status-runner.yml",
|
||||||
actual_host,
|
actual_host,
|
||||||
actual_user,
|
actual_user,
|
||||||
{"runner_name": name},
|
{"gitea_runner_name": name},
|
||||||
actual_key,
|
actual_key,
|
||||||
ask_become_pass,
|
ask_become_pass,
|
||||||
description=_("Checking status of Gitea Runner {name} on {host}", name=name, host=actual_host),
|
description=_("Checking status of Gitea Runner {name} on {host}", name=name, host=actual_host),
|
||||||
@@ -401,7 +401,7 @@ class RunnerManager:
|
|||||||
"remove-runner.yml",
|
"remove-runner.yml",
|
||||||
actual_host,
|
actual_host,
|
||||||
actual_user,
|
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,
|
actual_key,
|
||||||
ask_become_pass,
|
ask_become_pass,
|
||||||
description=_("Removing Gitea Runner {name} from {host}", name=name, host=actual_host),
|
description=_("Removing Gitea Runner {name} from {host}", name=name, host=actual_host),
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class TestAnsibleExecutorRun:
|
|||||||
|
|
||||||
def test_run_extracts_status(self, tmp_path: Path) -> None:
|
def test_run_extracts_status(self, tmp_path: Path) -> None:
|
||||||
log_content = (
|
log_content = (
|
||||||
"TASK [gitea-runner : Report runner status]\n"
|
"TASK [gitea_runner : Report runner status]\n"
|
||||||
"ok: [127.0.0.1] => {\n"
|
"ok: [127.0.0.1] => {\n"
|
||||||
' "msg": "Runner \'127.0.0.1\' is installed and running."\n'
|
' "msg": "Runner \'127.0.0.1\' is installed and running."\n'
|
||||||
"}\n"
|
"}\n"
|
||||||
@@ -89,7 +89,7 @@ class TestAnsibleExecutorExtractStatus:
|
|||||||
def test_extract_status_found(self, tmp_path: Path) -> None:
|
def test_extract_status_found(self, tmp_path: Path) -> None:
|
||||||
executor = AnsibleExecutor()
|
executor = AnsibleExecutor()
|
||||||
log_content = (
|
log_content = (
|
||||||
"TASK [gitea-runner : Report runner status]\n"
|
"TASK [gitea_runner : Report runner status]\n"
|
||||||
"ok: [127.0.0.1] => {\n"
|
"ok: [127.0.0.1] => {\n"
|
||||||
' "msg": "Runner \'127.0.0.1\' is installed and running."\n'
|
' "msg": "Runner \'127.0.0.1\' is installed and running."\n'
|
||||||
"}\n"
|
"}\n"
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class TestRunnerManager:
|
|||||||
assert "--extra-vars" in cmd_str
|
assert "--extra-vars" in cmd_str
|
||||||
assert "@/tmp/fake-vars.json" in cmd_str
|
assert "@/tmp/fake-vars.json" in cmd_str
|
||||||
assert manager._captured_extra_vars["registration_token"] == "tok"
|
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 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"]
|
assert "Installing Gitea Runner on 192.168.1.10" in mock_executor.run.call_args.kwargs["description"]
|
||||||
mock_registry.add.assert_called_once_with(
|
mock_registry.add.assert_called_once_with(
|
||||||
@@ -75,7 +75,7 @@ class TestRunnerManager:
|
|||||||
assert "--private-key" in cmd_str
|
assert "--private-key" in cmd_str
|
||||||
assert "/key" in cmd_str
|
assert "/key" in cmd_str
|
||||||
assert manager._captured_extra_vars["registration_token"] == "preset"
|
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
|
assert "--ask-become-pass" not in cmd_str
|
||||||
mock_registry.add.assert_called_once_with(
|
mock_registry.add.assert_called_once_with(
|
||||||
name="my-runner",
|
name="my-runner",
|
||||||
@@ -126,7 +126,7 @@ class TestRunnerManager:
|
|||||||
gitea_url="https://git.example.com",
|
gitea_url="https://git.example.com",
|
||||||
labels="docker:docker://alpine:latest",
|
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:
|
def test_install_no_labels(self) -> None:
|
||||||
mock_registry = MagicMock()
|
mock_registry = MagicMock()
|
||||||
@@ -145,7 +145,7 @@ class TestRunnerManager:
|
|||||||
manager._executor = mock_executor
|
manager._executor = mock_executor
|
||||||
|
|
||||||
manager.install("host1", "root", token="tok", gitea_url="https://git.example.com", labels="")
|
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:
|
def test_install_with_admin_token(self) -> None:
|
||||||
mock_registry = MagicMock()
|
mock_registry = MagicMock()
|
||||||
@@ -265,7 +265,7 @@ class TestRunnerManager:
|
|||||||
cmd = mock_executor.run.call_args.args[0]
|
cmd = mock_executor.run.call_args.args[0]
|
||||||
cmd_str = " ".join(cmd)
|
cmd_str = " ".join(cmd)
|
||||||
assert "start-runner.yml" in cmd_str
|
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"]
|
assert "Starting Gitea Runner r1 on host" in mock_executor.run.call_args.kwargs["description"]
|
||||||
|
|
||||||
def test_start_with_override(self) -> None:
|
def test_start_with_override(self) -> None:
|
||||||
@@ -304,7 +304,7 @@ class TestRunnerManager:
|
|||||||
cmd = mock_executor.run.call_args.args[0]
|
cmd = mock_executor.run.call_args.args[0]
|
||||||
cmd_str = " ".join(cmd)
|
cmd_str = " ".join(cmd)
|
||||||
assert "stop-runner.yml" in cmd_str
|
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"]
|
assert "Stopping Gitea Runner r1 on host" in mock_executor.run.call_args.kwargs["description"]
|
||||||
|
|
||||||
def test_restart(self) -> None:
|
def test_restart(self) -> None:
|
||||||
@@ -318,7 +318,7 @@ class TestRunnerManager:
|
|||||||
cmd = mock_executor.run.call_args.args[0]
|
cmd = mock_executor.run.call_args.args[0]
|
||||||
cmd_str = " ".join(cmd)
|
cmd_str = " ".join(cmd)
|
||||||
assert "restart-runner.yml" in cmd_str
|
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"]
|
assert "Restarting Gitea Runner r1 on host" in mock_executor.run.call_args.kwargs["description"]
|
||||||
|
|
||||||
def test_enable(self) -> None:
|
def test_enable(self) -> None:
|
||||||
@@ -332,7 +332,7 @@ class TestRunnerManager:
|
|||||||
cmd = mock_executor.run.call_args.args[0]
|
cmd = mock_executor.run.call_args.args[0]
|
||||||
cmd_str = " ".join(cmd)
|
cmd_str = " ".join(cmd)
|
||||||
assert "enable-runner.yml" in cmd_str
|
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"]
|
assert "Enabling Gitea Runner r1 on host" in mock_executor.run.call_args.kwargs["description"]
|
||||||
|
|
||||||
def test_disable(self) -> None:
|
def test_disable(self) -> None:
|
||||||
@@ -351,7 +351,7 @@ class TestRunnerManager:
|
|||||||
cmd = mock_executor.run.call_args.args[0]
|
cmd = mock_executor.run.call_args.args[0]
|
||||||
cmd_str = " ".join(cmd)
|
cmd_str = " ".join(cmd)
|
||||||
assert "disable-runner.yml" in cmd_str
|
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["registration_token"] == "tok"
|
||||||
assert manager._captured_extra_vars["gitea_url"] == "https://git.example.com"
|
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"]
|
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 = mock_executor.run.call_args.args[0]
|
||||||
cmd_str = " ".join(cmd)
|
cmd_str = " ".join(cmd)
|
||||||
assert "status-runner.yml" in cmd_str
|
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"]
|
assert "Checking status of Gitea Runner r1 on host" in mock_executor.run.call_args.kwargs["description"]
|
||||||
|
|
||||||
def test_remove(self) -> None:
|
def test_remove(self) -> None:
|
||||||
@@ -415,7 +415,7 @@ class TestRunnerManager:
|
|||||||
cmd = mock_executor.run.call_args.args[0]
|
cmd = mock_executor.run.call_args.args[0]
|
||||||
cmd_str = " ".join(cmd)
|
cmd_str = " ".join(cmd)
|
||||||
assert "remove-runner.yml" in cmd_str
|
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["registration_token"] == "tok"
|
||||||
assert manager._captured_extra_vars["gitea_url"] == "https://git.example.com"
|
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"]
|
assert "Removing Gitea Runner r1 from host" in mock_executor.run.call_args.kwargs["description"]
|
||||||
|
|||||||
Reference in New Issue
Block a user