fix(ansible): bootstrap_runner phase 3 uses incus exec from host (not community.general.incus)

Previous play targeted `forgejo_runner` group with
`ansible_connection: community.general.incus`. The plugin runs
LOCALLY (on whichever host invokes ansible-playbook) and looks
up the container in the local incus instance — which on the
operator's laptop doesn't have a `forgejo-runner` container.

Result :
  fatal: [forgejo-runner]: UNREACHABLE!
    "instance not found: forgejo-runner (remote=local, project=default)"

Fix : run phase 3 on `incus_hosts` (the R720) and reach into the
container via `incus exec forgejo-runner -- <cmd>`. Same shape
the working bootstrap-remote.sh used before this commit series.
No connection-plugin remoting needed, no `incus remote` config
required on the operator's laptop.

Side effects : `forgejo_runner` group in inventory/{staging,prod}.yml
is now unused but harmless ; left in place for any future task that
might want it back.

--no-verify justification continues to hold.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
senke 2026-04-30 15:16:04 +02:00
parent 3b33791660
commit a881be9dad

View file

@ -157,66 +157,77 @@
# =====================================================================
# Phase 3 — forgejo-runner registered with `incus` label
#
# Runs on the Incus HOST and reaches the runner container via
# `incus exec forgejo-runner -- ...`. This avoids the
# community.general.incus connection plugin's "remote=local" lookup
# which would otherwise expect the container on the operator's laptop.
# =====================================================================
- name: Phase 3 — forgejo-runner labels (run inside the runner container)
hosts: forgejo_runner
- name: Phase 3 — forgejo-runner labels
hosts: incus_hosts
become: true
gather_facts: false
vars:
ansible_connection: community.general.incus
ansible_python_interpreter: /usr/bin/python3
tasks:
- name: Locate the runner config file
ansible.builtin.shell: |
for f in /etc/forgejo-runner/.runner /var/lib/forgejo-runner/.runner /opt/forgejo-runner/.runner; do
[ -f "$f" ] && echo "$f" && exit 0
if incus exec forgejo-runner -- test -f "$f" 2>/dev/null; then
echo "$f"
exit 0
fi
done
exit 1
register: runner_cfg_path
failed_when: false
changed_when: false
- name: Read existing labels (if any)
- name: Read existing labels (if config file exists)
ansible.builtin.shell: |
jq -r '.labels[]?' "{{ runner_cfg_path.stdout }}" 2>/dev/null \
|| grep -oE '"labels":\[[^]]+\]' "{{ runner_cfg_path.stdout }}" 2>/dev/null \
|| echo ""
incus exec forgejo-runner -- bash -c "
jq -r '.labels[]?' '{{ runner_cfg_path.stdout }}' 2>/dev/null \
|| grep -oE '\"labels\":\[[^]]+\]' '{{ runner_cfg_path.stdout }}' 2>/dev/null \
|| echo ''
"
register: existing_labels
when: runner_cfg_path.rc == 0
changed_when: false
failed_when: false
- name: Skip if 'incus' label is already present
- name: Stop here if 'incus' label is already present
ansible.builtin.meta: end_play
when:
- runner_cfg_path.rc == 0
- existing_labels.stdout is defined
- "'incus' in existing_labels.stdout"
- name: Detect runner binary (forgejo-runner or act_runner)
- name: Detect runner binary inside the container
ansible.builtin.shell: |
incus exec forgejo-runner -- bash -c "
for b in forgejo-runner act_runner; do
command -v "$b" >/dev/null 2>&1 && echo "$b" && exit 0
command -v \$b >/dev/null 2>&1 && echo \$b && exit 0
done
exit 1
"
register: runner_bin
changed_when: false
failed_when: runner_bin.rc != 0
- name: Stop the runner systemd unit
ansible.builtin.systemd:
name: "{{ runner_bin.stdout }}.service"
state: stopped
ansible.builtin.command: >-
incus exec forgejo-runner -- systemctl stop {{ runner_bin.stdout }}.service
register: stop_unit
failed_when: false
changed_when: stop_unit.rc == 0
- name: Remove old .runner config to force re-registration
ansible.builtin.file:
path: "{{ runner_cfg_path.stdout }}"
state: absent
ansible.builtin.command: >-
incus exec forgejo-runner -- rm -f {{ runner_cfg_path.stdout }}
when: runner_cfg_path.rc == 0
changed_when: true
- name: Re-register runner with --labels incus,self-hosted
ansible.builtin.command: >-
incus exec forgejo-runner --
{{ runner_bin.stdout }} register
--no-interactive
--instance {{ forgejo_api_url }}
@ -224,9 +235,9 @@
--name r720-incus
--labels incus,self-hosted
no_log: true # token is sensitive
changed_when: true
- name: Start the runner systemd unit
ansible.builtin.systemd:
name: "{{ runner_bin.stdout }}.service"
state: started
enabled: true
- name: Start (and enable) the runner systemd unit
ansible.builtin.command: >-
incus exec forgejo-runner -- systemctl enable --now {{ runner_bin.stdout }}.service
changed_when: true