`docker images` has no label formatter — check leases via image inspect
per candidate. `label!=` is invalid on volume/network ls but valid on
prune; `until=` is unsupported for volumes — drop it. Expired-lease
volumes/networks are reclaimed by an explicit inspect pass; anonymous
volumes only at routine/pressure, all unused volumes at critical.
Extend stopped-container protection to an explicit lease contract
(org.oblachno.lease-until / org.oblachno.owner) honored by every cleanup
path. Consolidate the duplicated inline prune logic from docker-prune
and the healthcheck into a single tiered runner-cleanup.sh; remove the
unfiltered `system prune -af --volumes` / `volume prune` paths that could
wipe a job's volumes mid-run, and keep warm base images under pressure.
At critical disk usage the healthcheck now stops admitting new work
(stops gitea-runner.service once no CI job is in flight) and resumes it
automatically after recovery. The runner config declares capacity, and
the role refuses to install on production-marked hosts.
## Summary
Thoroughly cleans Docker artifacts on runner removal, updates devx to v0.9.11, fixes Makefile checkmake graceful skip, and comprehensive docs rewrite.
Molecule tests fail due to pre-existing Docker infrastructure issue (Docker socket not available in CI runners).
Closes GRM-75
The deregister scenario's verify.yml was missing the runner_name var,
which is required because gitea_runner_data_dir depends on it via
defaults/main.yml. Without it, the verify phase fails with
"'runner_name' is undefined".
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-21 00:45:47 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Ansible evaluates environment blocks even when when conditions are
false. The deregister scenario sets skip_runner_registration: true
but the environment block still references gitea_runner_uid, causing
"variable is undefined" errors. Add default(0) filter to prevent
this.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-21 00:34:07 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The Arch Linux pacman package for GPG is called 'gnupg', not 'gpg'.
The molecule prepare.yml was trying to install a non-existent 'gpg'
package, causing failures on the archlinux platform.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-21 00:22:20 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The "Enable lingering" task always reported changed=true, and the
"Download gitea_runner binary" task used force=true which always
re-downloads. Both caused molecule idempotence tests to fail.
- Check /var/lib/systemd/linger/<user> before enabling lingering
- Set force=false on get_url so binary is only downloaded if missing
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-21 00:13:19 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The "Restart gitea-runner" handler was not guarded by
docker_rootless_setup, causing failures in CI containers without a
systemd user bus. Also add failed_when: false to all lifecycle
side_effect.yml systemctl --user tasks.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-21 00:06:27 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The daemon-reload, service restart, and service check tasks in
service.yml, prune.yml, update_runner.yml, and integration_test.yml
were not guarded by docker_rootless_setup. In CI containers without
a systemd user bus, these tasks fail with "Failed to connect to bus".
Also fix the integration_test.yml validation task to not fail on
service status when docker_rootless_setup is false.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-21 00:00:07 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The validate.yml had an unconditional 'docker version' check, and
service.yml/prune.yml unconditionally enabled services that need
Docker running. Added when: docker_rootless_setup to:
- validate.yml: Verify rootless Docker connectivity
- service.yml: Enable and start gitea-runner service
- prune.yml: Enable and start docker-prune timer
Also made lifecycle side_effect tolerant of service start failure
since Docker daemon isn't available in molecule containers.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-20 22:50:25 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Rootless Docker requires newuidmap/newgidmap kernel support which
doesn't work in nested Docker containers (Operation not permitted).
Added docker_rootless_setup variable (default true) to skip the
daemon startup steps. Set to false in all molecule converge playbooks
so tests verify package installation, user creation, service file
rendering, and config without requiring a working rootless daemon.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-20 22:37:31 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Three changes:
1. CI: add set -e and fail-fast: true to stop on first molecule failure
instead of continuing (all pairs fail for same reason anyway)
2. Docker APT repo: use copy module to write sources.list directly
instead of apt_repository module which wasn't picking up the repo
3. Fix arch mapping: ansible_facts returns x86_64, Docker repo needs amd64
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-20 22:31:08 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
ansible_facts['architecture'] returns x86_64 but Docker APT repo
expects amd64. Added docker_apt_arch mapping. Also added debug tasks
to show apt sources and apt-cache search results for docker-ce.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-20 22:24:02 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The apt_repository update_cache option wasn't reliably picking up the
new Docker APT repo. Split into separate apt update step. Also moved
the long repo string to a default variable to satisfy yaml line-length
lint rule.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-20 22:15:28 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The geerlingguy Docker containers don't include curl or gpg, which
are needed by the rootless Docker role to download and dearmor the
Docker APT repository GPG key. Added these prerequisites to the
molecule common prepare playbook.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-20 22:07:55 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The deb822_repository module isn't available in the CI Ansible
collection. Reverted to apt_repository but now properly dearmors
the GPG key using gpg --dearmor before referencing it in signed-by.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-20 21:46:33 +02:00
Emil SimeonovandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The apt_repository module with signed-by wasn't working because the
downloaded GPG key wasn't properly dearmored. The deb822_repository
module handles GPG key download and dearmoring automatically.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>