Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/lint-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
- android-runner
- android-runner-host
- org-runner
- no-docker-socket
fail-fast: false
max-parallel: 1

Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## [0.1.6] - 2026-08-20
### Added
- `github_runner_mount_docker_socket` (default `true`): whether to mount the host's `/var/run/docker.sock` into the runner container. Set to `false` for runners whose CI jobs never use docker — it drops a root-equivalent privilege, and on a desktop host it guarantees the runner's jobs can't churn veth interfaces (each add/remove aborts in-flight Chrome requests on that host with `ERR_NETWORK_CHANGED`).
- `no-docker-socket` molecule scenario verifying the runner converges without the socket bind.

## [0.1.5] - 2026-08-12
### Fixed
- The deploy no longer replaces a runner container while its runner is mid-job (which destroyed the CI job: GitHub waits out the runner heartbeat ~10 min, then fails every remaining step). When a replace is imminent — new image digest or config change — and the existing runner is busy, the role now polls the GitHub runners API until the runner is idle before replacing, failing the deploy loudly on timeout instead of killing the job. The busy-check fails loudly on a paginated (>100 runners) listing, treats malformed/rate-limited API responses as still-waiting, and clamps the poll interval to >=1s.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ github_runner_env_file | whether to use an env file for pas
github_runner_env_filename | the filename of the env file for passing extra environment variables into the container (defaults to ".env")
github_runner_github_host | The GITHUB_HOST used for registering the runner (defaults to "github.com")
github_runner_persist_config | whether to persist runner configuration across container restarts using a named volume (defaults to true)
github_runner_mount_docker_socket | whether to mount the host's /var/run/docker.sock into the runner container; set to false for runners whose jobs never use docker to drop the root-equivalent privilege (defaults to true)
github_runner_stop_timeout | seconds docker waits after SIGTERM before SIGKILL when stopping the runner container, e.g. while replacing it on an image bump (defaults to 10)
github_runner_docker_timeout | Docker API client timeout in seconds for the deploy task; stopping and removing a crash-looping runner can exceed the SDK's 60s default (defaults to 180)
github_runner_drain_before_replace | when a deploy is about to replace the runner container while the runner is executing a CI job, wait for the job to finish instead of destroying it (defaults to true)
Expand Down
2 changes: 1 addition & 1 deletion galaxy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: "Installs github self hosted repo or org runners within a docker co
can be a vanilla runner, or one with java / android installed."
license_file: LICENSE
readme: README.md
version: 0.1.5
version: 0.1.6
repository: https://github.com/compscidr/ansible-github-runner
tags:
- github
Expand Down
7 changes: 7 additions & 0 deletions molecule/no-docker-socket/converge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
- name: Converge
hosts: all
become: true
gather_facts: true
roles:
- role: github_runner
36 changes: 36 additions & 0 deletions molecule/no-docker-socket/molecule.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
dependency:
name: galaxy
options:
requirements-file: requirements.yml
driver:
name: docker
platforms:
- name: ubuntu-22.04-no-docker-socket
image: geerlingguy/docker-ubuntu2204-ansible:latest
command: ""
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /sys/fs/cgroup:/sys/fs/cgroup:rw
cgroupns_mode: host
privileged: true
pre_build_image: true
provisioner:
name: ansible
env:
ANSIBLE_ROLES_PATH: ${MOLECULE_PROJECT_DIRECTORY}/roles
playbooks:
prepare: ../default/prepare.yml
converge: converge.yml
verify: verify.yml
inventory:
host_vars:
ubuntu-22.04-no-docker-socket:
github_runner_personal_access_token: "test-token-no-docker-socket"
github_runner_name: "test-runner-no-docker-socket"
github_runner_repo: "test/repo"
github_runner_labels: "self-hosted,jvm"
github_runner_java: true
github_runner_mount_docker_socket: false
verifier:
name: ansible
37 changes: 37 additions & 0 deletions molecule/no-docker-socket/verify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
- name: Verify runner without docker socket
hosts: all
gather_facts: false
become: true
tasks:
- name: Check if GitHub runner container is running
community.docker.docker_container_info:
name: "{{ github_runner_name }}"
register: runner_container

- name: Verify container exists
ansible.builtin.assert:
that:
- runner_container.exists
fail_msg: "GitHub runner container does not exist"
success_msg: "GitHub runner container exists"

- name: Verify container is running
ansible.builtin.assert:
that:
- runner_container.container.State.Running
fail_msg: "GitHub runner container is not running"
success_msg: "GitHub runner container is running"

- name: Debug HostConfig.Binds
ansible.builtin.debug:
var: runner_container.container.HostConfig.Binds

- name: Verify docker socket is NOT mounted
ansible.builtin.assert:
that:
# default([], true) also covers Binds being None (e.g. every volume
# landing in Mounts instead): no binds at all still means no socket.
- runner_container.container.HostConfig.Binds | default([], true) | select('search', '/var/run/docker.sock') | list | length == 0
fail_msg: "Docker socket should not be mounted with github_runner_mount_docker_socket: false"
success_msg: "Docker socket correctly not mounted"
8 changes: 8 additions & 0 deletions roles/github_runner/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ github_runner_adb_port: 5037
# adb client reach an adb server running on the host at 127.0.0.1:5037.
github_runner_network_mode: default

# Whether to mount the host's /var/run/docker.sock into the runner container.
# Only needed when CI jobs themselves use docker (builds, testcontainers,
# service containers). Set to false for runners whose jobs never touch docker:
# it drops a root-equivalent privilege, and on a desktop host it guarantees the
# runner's jobs can't churn veth interfaces (each add/remove aborts in-flight
# Chrome requests on that host with ERR_NETWORK_CHANGED).
github_runner_mount_docker_socket: true

github_runner_github_host: "github.com"

github_runner_persist_config: true
Expand Down
2 changes: 1 addition & 1 deletion roles/github_runner/vars/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ github_runner_ports: >-
}}
github_runner_volumes: >-
{{
['/var/run/docker.sock:/var/run/docker.sock'] +
(['/var/run/docker.sock:/var/run/docker.sock'] if github_runner_mount_docker_socket else []) +
(['/root/.android:/root/.android'] if github_runner_android else []) +
([github_runner_name ~ '-runner-data:/runner-data'] if github_runner_persist_config else [])
}}
Expand Down