From b515541f7998c31fc8350e990512d47281f07fc0 Mon Sep 17 00:00:00 2001 From: Jason Ernst Date: Wed, 12 Aug 2026 14:26:56 -0700 Subject: [PATCH 1/3] fix: drain the runner before replacing its container mid-job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replacing a runner container while its runner is executing a CI job destroys the job: GitHub waits out the runner heartbeat (~10 min), then fails every remaining step (observed on BumpApp/bump 2026-08-10, two instrumentation suites killed by one deploy — BumpApp/bump#5223). - Split the image pull into its own docker_image_pull task (safe while a job runs) and run the container task with pull: false — a new digest still triggers the replace via image-ID comparison. - Add a check-mode pass of the container task to detect config-driven recreation without touching anything. - When either signals a replace and the container exists, poll the runners API (org or repo scope, same PAT used for registration) until no runner matching ^name(-|$) is busy; bounded by github_runner_drain_timeout_minutes (45) at github_runner_drain_poll_seconds (30) intervals. Timeout fails the deploy with guidance instead of killing the job. - github_runner_drain_before_replace=false restores old behavior; github_runner_force_replace=true is the emergency override. - Shared container args move to vars/main.yml (role-prefixed for ansible-lint); community.docker floor raised to >=3.6.0 for docker_image_pull. --- CHANGELOG.md | 7 ++ README.md | 5 + galaxy.yml | 2 +- roles/github_runner/defaults/main.yml | 17 ++++ roles/github_runner/tasks/main.yml | 134 ++++++++++++++++++-------- roles/github_runner/vars/main.yml | 52 ++++++++++ 6 files changed, 176 insertions(+), 41 deletions(-) create mode 100644 roles/github_runner/vars/main.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 12aaabf..5a1e1cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,18 @@ ## [0.1.4] - 2026-08-10 ### Fixed - First playbook run no longer fails with `UnixHTTPConnectionPool ... Read timed out (read timeout=60)` when replacing an existing runner container. Stopping and removing a crash-looping or wedged runner can exceed the Docker SDK's 60s default client timeout; the daemon finished the removal in the background, which is why an immediate rerun succeeded. +- 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. ### Added +- `github_runner_drain_before_replace` (default `true`), `github_runner_drain_timeout_minutes` (default `45`), `github_runner_drain_poll_seconds` (default `30`): drain-before-replace guard configuration. +- `github_runner_force_replace` (default `false`): emergency override — replace immediately even if a job is mid-flight. +- `github_runner_api_base`: GitHub API base for the busy-check, derived for github.com and GHES. - `github_runner_docker_timeout` (default `180`): Docker API client timeout for the deploy task. - `github_runner_stop_timeout` (default `10`): seconds docker waits after SIGTERM before SIGKILL when stopping the runner container. +### Changed +- The image pull is now a separate `docker_image_pull` task and the container task runs with `pull: false`; behavior is unchanged (a new digest still triggers the replace via image-ID comparison), but the pull result now feeds the drain guard. Requires `community.docker` >= 3.6.0. + ## [0.1.3] - 2026-05-27 ### Added - Added `github_runner_network_mode` variable (defaults to `default`) to control the runner container's Docker network mode. Set to `host` so the in-container `adb` client can reach an adb server running on the host at `127.0.0.1:5037`. diff --git a/README.md b/README.md index 550b4b6..489c11a 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,11 @@ github_runner_github_host | The GITHUB_HOST used for registeri github_runner_persist_config | whether to persist runner configuration across container restarts using a named volume (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) +github_runner_drain_timeout_minutes | how long to wait for a busy runner to go idle before failing the deploy (defaults to 45) +github_runner_drain_poll_seconds | polling interval for the busy-check against the GitHub runners API (defaults to 30) +github_runner_force_replace | emergency override: replace the container immediately even if a job is mid-flight (defaults to false) +github_runner_api_base | GitHub API base URL used by the busy-check; derived automatically for github.com and GHES (/api/v3) Notes: the env file lets you do things like set site-specific credentials into the runner that can be built into the code at build time, for instance, Wi-Fi credentials that can be built into tests that are specific to the location of diff --git a/galaxy.yml b/galaxy.yml index 7ad9e66..a11741f 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -18,4 +18,4 @@ tags: - hosted - infrastructure dependencies: - community.docker: "*" + community.docker: ">=3.6.0" # docker_image_pull diff --git a/roles/github_runner/defaults/main.yml b/roles/github_runner/defaults/main.yml index c0c2a6d..08034af 100644 --- a/roles/github_runner/defaults/main.yml +++ b/roles/github_runner/defaults/main.yml @@ -35,3 +35,20 @@ github_runner_stop_timeout: 10 # crash-looping or wedged runner container can exceed the SDK's 60s default, # which fails the first playbook run and succeeds on the rerun. github_runner_docker_timeout: 180 + +# Drain-before-replace: when the deploy is about to replace the runner +# container (new image digest or config change) while the existing runner is +# executing a CI job, wait for the job to finish instead of destroying it +# (replacing mid-job makes GitHub wait out the runner heartbeat ~10 min and +# fail every remaining step). If the runner is still busy when the timeout +# expires the deploy fails loudly rather than killing the job. +github_runner_drain_before_replace: true +github_runner_drain_timeout_minutes: 45 +github_runner_drain_poll_seconds: 30 + +# Emergency override: replace immediately even if a job is mid-flight. +github_runner_force_replace: false + +# GitHub API base for the drain busy-check. Derived for github.com and GHES +# (/api/v3); override if your API lives elsewhere. +github_runner_api_base: "{{ 'https://api.github.com' if github_runner_github_host == 'github.com' else 'https://' ~ github_runner_github_host ~ '/api/v3' }}" diff --git a/roles/github_runner/tasks/main.yml b/roles/github_runner/tasks/main.yml index 85a0fec..a8866fa 100644 --- a/roles/github_runner/tasks/main.yml +++ b/roles/github_runner/tasks/main.yml @@ -1,14 +1,104 @@ --- +# The pull is separated from the container task for the drain guard below: +# pulling is always safe while the runner is mid-job (it never touches the +# container), and whether the pull actually fetched a new digest is half the +# signal for "the container is about to be replaced". The deploy task then +# runs with pull: false — a freshly pulled image still triggers the replace +# via the module's image-ID comparison. +- name: Pull runner image + tags: github_runner + become: true + community.docker.docker_image_pull: + name: "{{ github_runner_java_image if github_runner_java else github_runner_non_java_image }}" + register: github_runner_image_pull + +# Check-mode pass with identical arguments (minus the pull): detects +# config-driven recreation (env, volumes, network mode, ...) without touching +# anything. Together with the pull result this decides whether the drain +# guard needs to run at all — an idempotent deploy skips straight through. +- name: Check whether the runner container would change + tags: github_runner + become: true + check_mode: true + community.docker.docker_container: + name: "{{ github_runner_name }}" + image: "{{ github_runner_java_image if github_runner_java else github_runner_non_java_image }}" + pull: false + devices: "{{ ['/dev/bus/usb:/dev/bus/usb:rwm'] if (github_runner_java and github_runner_java_mount_usb) else omit }}" + device_cgroup_rules: "{{ ['c 189:* rmw'] if (github_runner_java and github_runner_java_mount_usb) else omit }}" + volumes: "{{ github_runner_volumes }}" + restart_policy: unless-stopped + stop_timeout: "{{ github_runner_stop_timeout }}" + timeout: "{{ github_runner_docker_timeout }}" + network_mode: "{{ github_runner_network_mode }}" + ports: "{{ github_runner_ports }}" + env: "{{ github_runner_env }}" + env_file: "{{ github_runner_env_filename if github_runner_env_file else omit }}" + register: github_runner_container_plan + +- name: Look up existing runner container + tags: github_runner + become: true + community.docker.docker_container_info: + name: "{{ github_runner_name }}" + register: github_runner_existing + +# Drain-before-replace: replacing the container while its runner is executing +# a CI job destroys the job (GitHub waits out the runner heartbeat ~10 min, +# then fails every remaining step). When a replace is imminent and the +# existing runner is busy, poll the runners API until it goes idle. A timeout +# fails the deploy loudly — rerun with github_runner_force_replace=true to +# replace anyway (killing the in-flight job) in an emergency. +- name: Wait for the runner to finish its current job before replacing + tags: github_runner + check_mode: false + when: + - github_runner_drain_before_replace + - not github_runner_force_replace + - github_runner_existing.exists + - github_runner_image_pull is changed or github_runner_container_plan is changed + block: + - name: Poll the runners API until this runner is idle + ansible.builtin.uri: + url: "{{ github_runner_api_runners_url }}" + headers: + Authorization: "Bearer {{ github_runner_personal_access_token }}" + Accept: "application/vnd.github+json" + return_content: true + register: github_runner_busy_check + # The Authorization header carries the PAT — keep it out of logs. + no_log: true + retries: "{{ ((github_runner_drain_timeout_minutes | int) * 60 / (github_runner_drain_poll_seconds | int)) | round(0, 'ceil') | int }}" + delay: "{{ github_runner_drain_poll_seconds }}" + until: >- + github_runner_busy_check.json.runners + | selectattr('name', 'match', github_runner_name_match) + | selectattr('busy') + | list | length == 0 + rescue: + - name: Fail with drain guidance + ansible.builtin.fail: + msg: >- + Runner {{ github_runner_name }} was still busy after + {{ github_runner_drain_timeout_minutes }} minutes (or the busy-check + API call failed) — not replacing its container mid-job. Rerun with + -e github_runner_force_replace=true to replace anyway (this kills + the in-flight CI job), or with + -e github_runner_drain_before_replace=false to restore the old + always-replace behavior. + - name: Deploy Github Runner tags: github_runner become: true community.docker.docker_container: name: "{{ github_runner_name }}" image: "{{ github_runner_java_image if github_runner_java else github_runner_non_java_image }}" - pull: true + # Pulled above; the image-ID comparison against the running container + # still triggers the replace when the pull fetched a new digest. + pull: false devices: "{{ ['/dev/bus/usb:/dev/bus/usb:rwm'] if (github_runner_java and github_runner_java_mount_usb) else omit }}" device_cgroup_rules: "{{ ['c 189:* rmw'] if (github_runner_java and github_runner_java_mount_usb) else omit }}" - volumes: "{{ runner_volumes }}" + volumes: "{{ github_runner_volumes }}" restart_policy: unless-stopped # Replacing an existing container (image bump) stops and removes it first. # A crash-looping or wedged runner can take well over the Docker SDK's @@ -19,42 +109,6 @@ stop_timeout: "{{ github_runner_stop_timeout }}" timeout: "{{ github_runner_docker_timeout }}" network_mode: "{{ github_runner_network_mode }}" - ports: "{{ runner_ports }}" - env: "{{ runner_env }}" + ports: "{{ github_runner_ports }}" + env: "{{ github_runner_env }}" env_file: "{{ github_runner_env_filename if github_runner_env_file else omit }}" - vars: - # ports: is invalid together with network_mode: host, so omit it in host mode. - runner_ports: >- - {{ - [github_runner_adb_port | string ~ ':5037'] - if (github_runner_android and github_runner_android_expose_adb_ports - and github_runner_network_mode != 'host') - else omit - }} - runner_volumes: >- - {{ - ['/var/run/docker.sock:/var/run/docker.sock'] + - (['/root/.android:/root/.android'] if github_runner_android else []) + - ([github_runner_name ~ '-runner-data:/runner-data'] if github_runner_persist_config else []) - }} - runner_env: >- - {{ - { - 'ACCESS_TOKEN': github_runner_personal_access_token, - 'DISABLE_AUTO_UPDATE': 'true', - 'DISABLE_AUTOMATIC_DEREGISTRATION': 'true', - 'RUNNER_NAME_PREFIX': github_runner_name, - 'LABELS': github_runner_labels, - 'HOST_NAME': inventory_hostname, - 'GITHUB_HOST': github_runner_github_host - } | combine( - {'REPO_URL': 'https://' ~ github_runner_github_host ~ '/' ~ github_runner_repo} - if not github_runner_org else {} - ) | combine( - {'RUNNER_SCOPE': 'org', 'ORG_NAME': github_runner_org_name} - if github_runner_org else {} - ) | combine( - {'CONFIGURED_ACTIONS_RUNNER_FILES_DIR': '/runner-data'} - if github_runner_persist_config else {} - ) - }} diff --git a/roles/github_runner/vars/main.yml b/roles/github_runner/vars/main.yml new file mode 100644 index 0000000..6feeaf1 --- /dev/null +++ b/roles/github_runner/vars/main.yml @@ -0,0 +1,52 @@ +--- +# Internal computed values shared by the plan (check-mode) and deploy passes in +# tasks/main.yml. Not intended for consumer override — tune the github_runner_* +# variables in defaults/main.yml instead. + +# ports: is invalid together with network_mode: host, so omit it in host mode. +github_runner_ports: >- + {{ + [github_runner_adb_port | string ~ ':5037'] + if (github_runner_android and github_runner_android_expose_adb_ports + and github_runner_network_mode != 'host') + else omit + }} +github_runner_volumes: >- + {{ + ['/var/run/docker.sock:/var/run/docker.sock'] + + (['/root/.android:/root/.android'] if github_runner_android else []) + + ([github_runner_name ~ '-runner-data:/runner-data'] if github_runner_persist_config else []) + }} +github_runner_env: >- + {{ + { + 'ACCESS_TOKEN': github_runner_personal_access_token, + 'DISABLE_AUTO_UPDATE': 'true', + 'DISABLE_AUTOMATIC_DEREGISTRATION': 'true', + 'RUNNER_NAME_PREFIX': github_runner_name, + 'LABELS': github_runner_labels, + 'HOST_NAME': inventory_hostname, + 'GITHUB_HOST': github_runner_github_host + } | combine( + {'REPO_URL': 'https://' ~ github_runner_github_host ~ '/' ~ github_runner_repo} + if not github_runner_org else {} + ) | combine( + {'RUNNER_SCOPE': 'org', 'ORG_NAME': github_runner_org_name} + if github_runner_org else {} + ) | combine( + {'CONFIGURED_ACTIONS_RUNNER_FILES_DIR': '/runner-data'} + if github_runner_persist_config else {} + ) + }} + +# Runners API endpoint for the drain busy-check: org runners or repo runners +# depending on scope. The runners register as "-" +# (RUNNER_NAME_PREFIX), so the busy-check matches that prefix — and a bare +# "" too, in case a future image drops the suffix. +github_runner_api_runners_url: >- + {{ + github_runner_api_base ~ '/' ~ + ('orgs/' ~ github_runner_org_name if github_runner_org else 'repos/' ~ github_runner_repo) ~ + '/actions/runners?per_page=100' + }} +github_runner_name_match: "^{{ github_runner_name | regex_escape }}(-|$)" From 47e914aed3cc0de265c835742981a635a4fa6b5c Mon Sep 17 00:00:00 2001 From: Jason Ernst Date: Wed, 12 Aug 2026 15:00:39 -0700 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20harden=20drain=20gate=20=E2=80=94=20?= =?UTF-8?q?pagination=20tripwire,=20retry-safe=20until,=20poll=20clamp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Probe the runners listing before polling and fail loudly if it is paginated beyond one page: a truncated listing could hide the target runner and let the drain conclude idle while a job is mid-flight. - Guard the until expression on response shape so a rate-limit or transient non-JSON body counts as still-waiting (retry) instead of aborting the drain with an undefined-key error. - Clamp the poll interval to >=1s so drain_poll_seconds: 0 cannot divide the retry computation by zero. - Rescue message now includes the underlying failure so a pagination trip is distinguishable from a busy-timeout. --- roles/github_runner/tasks/main.yml | 52 ++++++++++++++++++++++++------ roles/github_runner/vars/main.yml | 4 +++ 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/roles/github_runner/tasks/main.yml b/roles/github_runner/tasks/main.yml index a8866fa..730d78e 100644 --- a/roles/github_runner/tasks/main.yml +++ b/roles/github_runner/tasks/main.yml @@ -58,6 +58,34 @@ - github_runner_existing.exists - github_runner_image_pull is changed or github_runner_container_plan is changed block: + # The busy-check reads a single page. A truncated listing could hide the + # target runner on a later page and let the drain conclude "idle" while a + # job is mid-flight — the exact failure this gate exists to prevent — so a + # paginated listing fails loudly instead of proceeding. + - name: Probe the runners listing for the drain check + ansible.builtin.uri: + url: "{{ github_runner_api_runners_url }}" + headers: + Authorization: "Bearer {{ github_runner_personal_access_token }}" + Accept: "application/vnd.github+json" + return_content: true + register: github_runner_listing_probe + # The Authorization header carries the PAT — keep it out of logs. + no_log: true + + - name: Fail if the runners listing is paginated beyond one page + ansible.builtin.assert: + that: + - github_runner_listing_probe.json.total_count == (github_runner_listing_probe.json.runners | length) + fail_msg: >- + The runners listing has + {{ github_runner_listing_probe.json.total_count }} runners but only + {{ github_runner_listing_probe.json.runners | length }} were + returned — the drain busy-check could miss the target runner on a + later page and replace it mid-job. Implement pagination in the + drain gate before deploying to this account. + quiet: true + - name: Poll the runners API until this runner is idle ansible.builtin.uri: url: "{{ github_runner_api_runners_url }}" @@ -68,22 +96,28 @@ register: github_runner_busy_check # The Authorization header carries the PAT — keep it out of logs. no_log: true - retries: "{{ ((github_runner_drain_timeout_minutes | int) * 60 / (github_runner_drain_poll_seconds | int)) | round(0, 'ceil') | int }}" - delay: "{{ github_runner_drain_poll_seconds }}" + retries: "{{ ((github_runner_drain_timeout_minutes | int) * 60 / (github_runner_drain_poll_seconds_clamped | int)) | round(0, 'ceil') | int }}" + delay: "{{ github_runner_drain_poll_seconds_clamped }}" + # Guard the shape before reading it: a rate-limit or transient non-JSON + # response must count as "still waiting" (retry), not blow up the until + # expression and abort the drain a retry might have saved. until: >- - github_runner_busy_check.json.runners + github_runner_busy_check.json is defined + and github_runner_busy_check.json.runners is defined + and (github_runner_busy_check.json.runners | selectattr('name', 'match', github_runner_name_match) | selectattr('busy') - | list | length == 0 + | list | length == 0) rescue: - name: Fail with drain guidance ansible.builtin.fail: msg: >- - Runner {{ github_runner_name }} was still busy after - {{ github_runner_drain_timeout_minutes }} minutes (or the busy-check - API call failed) — not replacing its container mid-job. Rerun with - -e github_runner_force_replace=true to replace anyway (this kills - the in-flight CI job), or with + Not replacing {{ github_runner_name }}'s container: the drain gate + did not confirm the runner idle within + {{ github_runner_drain_timeout_minutes }} minutes. + Underlying failure: {{ ansible_failed_result.msg | default('(none recorded)') }}. + Rerun with -e github_runner_force_replace=true to replace anyway + (this kills any in-flight CI job), or with -e github_runner_drain_before_replace=false to restore the old always-replace behavior. diff --git a/roles/github_runner/vars/main.yml b/roles/github_runner/vars/main.yml index 6feeaf1..b5b55eb 100644 --- a/roles/github_runner/vars/main.yml +++ b/roles/github_runner/vars/main.yml @@ -50,3 +50,7 @@ github_runner_api_runners_url: >- '/actions/runners?per_page=100' }} github_runner_name_match: "^{{ github_runner_name | regex_escape }}(-|$)" + +# Poll interval clamped to >=1s so a consumer setting 0 (or a value that casts +# to 0) can't divide the retry computation by zero or spin the API. +github_runner_drain_poll_seconds_clamped: "{{ [github_runner_drain_poll_seconds | int, 1] | max }}" From ca77a6f4d8e7b20f06320f74253fabcf0effc84f Mon Sep 17 00:00:00 2001 From: Jason Ernst Date: Wed, 12 Aug 2026 15:05:24 -0700 Subject: [PATCH 3/3] chore: bump collection version to 0.1.5 0.1.4 is already released on Galaxy (tagged at the docker-timeouts head), so the drain-before-replace work ships as 0.1.5; changelog split accordingly. --- CHANGELOG.md | 15 ++++++++++----- galaxy.yml | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a1e1cd..74e79e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,25 @@ # Changelog -## [0.1.4] - 2026-08-10 +## [0.1.5] - 2026-08-12 ### Fixed -- First playbook run no longer fails with `UnixHTTPConnectionPool ... Read timed out (read timeout=60)` when replacing an existing runner container. Stopping and removing a crash-looping or wedged runner can exceed the Docker SDK's 60s default client timeout; the daemon finished the removal in the background, which is why an immediate rerun succeeded. -- 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 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. ### Added - `github_runner_drain_before_replace` (default `true`), `github_runner_drain_timeout_minutes` (default `45`), `github_runner_drain_poll_seconds` (default `30`): drain-before-replace guard configuration. - `github_runner_force_replace` (default `false`): emergency override — replace immediately even if a job is mid-flight. - `github_runner_api_base`: GitHub API base for the busy-check, derived for github.com and GHES. -- `github_runner_docker_timeout` (default `180`): Docker API client timeout for the deploy task. -- `github_runner_stop_timeout` (default `10`): seconds docker waits after SIGTERM before SIGKILL when stopping the runner container. ### Changed - The image pull is now a separate `docker_image_pull` task and the container task runs with `pull: false`; behavior is unchanged (a new digest still triggers the replace via image-ID comparison), but the pull result now feeds the drain guard. Requires `community.docker` >= 3.6.0. +## [0.1.4] - 2026-08-10 +### Fixed +- First playbook run no longer fails with `UnixHTTPConnectionPool ... Read timed out (read timeout=60)` when replacing an existing runner container. Stopping and removing a crash-looping or wedged runner can exceed the Docker SDK's 60s default client timeout; the daemon finished the removal in the background, which is why an immediate rerun succeeded. + +### Added +- `github_runner_docker_timeout` (default `180`): Docker API client timeout for the deploy task. +- `github_runner_stop_timeout` (default `10`): seconds docker waits after SIGTERM before SIGKILL when stopping the runner container. + ## [0.1.3] - 2026-05-27 ### Added - Added `github_runner_network_mode` variable (defaults to `default`) to control the runner container's Docker network mode. Set to `host` so the in-container `adb` client can reach an adb server running on the host at `127.0.0.1:5037`. diff --git a/galaxy.yml b/galaxy.yml index a11741f..bcda969 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -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.4 +version: 0.1.5 repository: https://github.com/compscidr/ansible-github-runner tags: - github