Skip to content

Commit

Permalink
Merge pull request #219 from steinwurf/feat/win-support
Browse files Browse the repository at this point in the history
feat: initial windows support
  • Loading branch information
MonolithProjects authored Sep 30, 2024
2 parents 75ae9e5 + 5adc706 commit 5e08b29
Show file tree
Hide file tree
Showing 10 changed files with 249 additions and 16 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ all_runners_in_same_repo: true
# GitHub Enterprise name
# github_enterprise: "yourenterprise"

# Runner user Windows password - the logon password for the service user when running on windows.
# runner_user_win_password: "{{ lookup('env', 'PASS') }}"

# Configuring a custom .env file
# custom_env: |
# http_proxy=YOUR_URL_HERE
Expand Down
7 changes: 5 additions & 2 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
runner_user: "{{ lookup('env', 'USER') }}"

# Directory where the local runner will be installed
runner_dir: /opt/actions-runner
runner_dir: "{{ 'C:\\actions-runner' if ansible_facts.system == 'Win32NT' else '/opt/actions-runner' }}"

# Version of the GitHub Actions Runner
runner_version: "latest"
Expand Down Expand Up @@ -42,7 +42,7 @@ runner_group: ""
runner_download_repository: "actions/runner"

# Extra arguments to pass to `config.sh`.
# Several arguments muste be set as one string (i.e. "--ephemeral --my_special_fork")
# Several arguments must be set as one string (i.e. "--ephemeral --my_special_fork")
runner_extra_config_args: ""

# Name to assign to this runner in GitHub (System hostname as default)
Expand All @@ -63,6 +63,9 @@ all_runners_in_same_repo: true
# GitHub Enterprise name
# github_enterprise: "yourenterprise"

# Runner user Windows password - the logon password for the service user when running on windows.
# runner_user_win_password: "{{ lookup('env', 'PASS') }}"

# Configuring a custom .env file
# custom_env: |
# http_proxy=YOUR_URL_HERE
Expand Down
8 changes: 8 additions & 0 deletions tasks/assert.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,11 @@
fail_msg: "github_repo was not found or is using an invalid format."
run_once: true
when: not runner_org and github_enterprise is not defined

- name: Check runner_user_win_password (RUN ONCE)
ansible.builtin.assert:
that:
- runner_user_win_password is defined
fail_msg: "runner_user_win_password was not defined, but it is required on a windows system"
run_once: true
when: github_actions_system == "win"
12 changes: 7 additions & 5 deletions tasks/collect_info.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
status_code: 201
force_basic_auth: true
register: registration
delegate_to: localhost
become: false
run_once: true

- name: "Check currently registered runners for repo {{ '(RUN ONCE)' if all_runners_in_same_repo else '' }}"
Expand All @@ -42,21 +44,21 @@
status_code: 200
force_basic_auth: true
register: registered_runners
delegate_to: localhost
become: false
run_once: "{{ all_runners_in_same_repo }}"

- name: Get Runner User IDs
ansible.builtin.command: id -u "{{ runner_user }}"
changed_when: false
register: runner_user_id
when: github_actions_system != "win"

- name: Get Runner Group IDs
ansible.builtin.command: id -g "{{ runner_user }}"
changed_when: false
register: runner_user_group_id

- name: Set runner_system variable
ansible.builtin.set_fact:
runner_system: "{{ 'osx' if ansible_facts.system == 'Darwin' else 'linux' }}"
when: github_actions_system != "win"

- name: Find the latest runner version (RUN ONCE)
ansible.builtin.uri:
Expand All @@ -77,4 +79,4 @@
- name: Get systemd service facts
ansible.builtin.service_facts:
register: service_facts
when: ansible_facts.system == "Linux"
when: github_actions_system == "linux"
2 changes: 1 addition & 1 deletion tasks/install_runner.yml → tasks/install_runner_unix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
- name: Unarchive runner package
ansible.builtin.unarchive:
src: "https://github.com/{{ runner_download_repository }}/releases/download/v{{ runner_version }}/\
actions-runner-{{ runner_system }}-{{ github_actions_architecture }}-{{ runner_version }}.tar.gz"
actions-runner-{{ github_actions_system }}-{{ github_actions_architecture }}-{{ runner_version }}.tar.gz"
dest: "{{ runner_dir }}/"
owner: "{{ runner_user_id.stdout }}"
group: "{{ runner_user_group_id.stdout }}"
Expand Down
142 changes: 142 additions & 0 deletions tasks/install_runner_win.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
---
- name: Create directory
ansible.windows.win_file:
path: "{{ runner_dir }}"
state: directory

- name: Set owner of directory
ansible.windows.win_owner:
path: "{{ runner_dir }}"
user: "{{ runner_user }}"

- name: Set runner_version variable (If latest)
ansible.builtin.set_fact:
runner_version: "{{ api_response.json.tag_name | regex_replace('^v', '') }}"
when: runner_version == "latest"

- name: Check if desired version already installed
ansible.windows.win_command: "grep -i {{ runner_version }} {{ runner_dir }}\\bin\\Runner.Listener.deps.json"
register: runner_installed
check_mode: false
changed_when: false
ignore_errors: true

- name: Download runner package
ansible.windows.win_get_url:
url: "https://github.com/{{ runner_download_repository }}/releases/download/v{{ runner_version }}/\
actions-runner-{{ github_actions_system }}-{{ github_actions_architecture }}-{{ runner_version }}.zip"
dest: "%TEMP%\\actions-runner-{{ github_actions_system }}-{{ github_actions_architecture }}-{{ runner_version }}.zip"
when: runner_version not in runner_installed.stdout or reinstall_runner

- name: Unarchive runner package
community.windows.win_unzip:
src: "%TEMP%\\actions-runner-{{ github_actions_system }}-{{ github_actions_architecture }}-{{ runner_version }}.zip"
dest: "{{ runner_dir }}\\"
delete_archive: yes
when: runner_version not in runner_installed.stdout or reinstall_runner

- name: Configure custom env file if required
randrej.windows.win_blockinfile:
path: "{{ runner_dir }}\\.env"
block: "{{ custom_env }}"
create: true
marker: "# {mark} ANSIBLE MANAGED BLOCK"
marker_begin: BEGIN
marker_end: END
when: custom_env is defined

- name: Check if runner service name file exist
ansible.windows.win_stat:
path: "{{ runner_dir }}/.service"
register: runner_service_file_path

- name: Set complete GitHub url for repo runner
ansible.builtin.set_fact:
github_full_url: "{{ github_url }}/{{ github_owner | default(github_account) }}/{{ github_repo }}"
when: not runner_org and github_enterprise is not defined

- name: Set complete GitHub url for org runner
ansible.builtin.set_fact:
github_full_url: "{{ github_url }}/{{ github_owner | default(github_account) }}"
when: runner_org | bool and github_enterprise is not defined

- name: Set complete GitHub url for enterprise runner
ansible.builtin.set_fact:
github_full_url: "{{ github_url }}/enterprises/{{ github_enterprise }}"
when: github_enterprise is defined

- name: Register runner # noqa no-changed-when
environment:
RUNNER_ALLOW_RUNASROOT: "1"
ansible.windows.win_command:
"{{ runner_dir }}\\config.cmd \
--url {{ github_full_url }} \
--token {{ registration.json.token }} \
--name {{ runner_name }} \
--labels {{ runner_labels | join(',') }} \
--runnergroup {{ runner_group }} \
--runasservice \
--windowslogonaccount {{ runner_user }} \
--windowslogonpassword {{ runner_user_win_password }} \
--unattended \
{{ runner_extra_config_args }}"
args:
chdir: "{{ runner_dir }}"
changed_when: true
become_method: runas
become_user: "{{ runner_user }}"
become: true
no_log: "{{ hide_sensitive_logs | bool }}"
when: runner_name not in registered_runners.json.runners|map(attribute='name')|list

- name: Replace registered runner # noqa no-changed-when
environment:
RUNNER_ALLOW_RUNASROOT: "1"
ansible.windows.win_command:
"{{ runner_dir }}\\config.cmd \
--url {{ github_full_url }} \
--token {{ registration.json.token }} \
--name {{ runner_name }} \
--labels {{ runner_labels | join(',') }} \
--runasservice \
--windowslogonaccount {{ runner_user }} \
--windowslogonpassword {{ runner_user_win_password }} \
--unattended \
{{ runner_extra_config_args }} \
--replace"
args:
chdir: "{{ runner_dir }}"
changed_when: true
become_method: runas
become_user: "{{ runner_user }}"
become: true
no_log: "{{ hide_sensitive_logs | bool }}"
when: >
runner_name in registered_runners.json.runners|map(attribute='name')|list and
reinstall_runner
- name: Read service name from file
ansible.windows.win_command: "cat {{ runner_dir }}\\.service"
register: runner_service
changed_when: false

- name: START and enable Github Actions Runner service
ansible.windows.win_service:
name: "{{ runner_service.stdout }}"
start_mode: auto
state: started
when: runner_state|lower == "started"

- name: STOP and disable Github Actions Runner service
ansible.windows.win_service:
name: "{{ runner_service.stdout }}"
start_mode: manual
state: stopped
when: runner_state|lower == "stopped"

- name: Version changed - RESTART Github Actions Runner service
ansible.windows.win_service:
name: "{{ runner_service.stdout }}"
start_mode: auto
state: restarted
when: runner_version not in runner_installed.stdout and not runner_state|lower == "stopped"
38 changes: 30 additions & 8 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,48 @@
- install
- uninstall

- name: Include Information collection taks
- name: Include Information collection tasks
ansible.builtin.include_tasks: collect_info.yml
tags:
- install
- uninstall

- name: Include tasks to install dependencies
ansible.builtin.include_tasks: install_deps.yml
when: runner_state|lower == "started" or runner_state|lower == "stopped"
when:
- runner_state|lower == "started" or runner_state|lower == "stopped"
- github_actions_system == "linux"
tags:
- install

- name: Include tasks to uninstall runner
ansible.builtin.include_tasks: uninstall_runner.yml
when: reinstall_runner or runner_state|lower == "absent"
- name: Include tasks to uninstall runner (UNIX-like)
ansible.builtin.include_tasks: uninstall_runner_unix.yml
when:
- reinstall_runner or runner_state|lower == "absent"
- github_actions_system == "linux" or github_actions_system == "osx"
tags:
- uninstall

- name: Include tasks to install runner
ansible.builtin.include_tasks: install_runner.yml
when: runner_state|lower == "started" or runner_state|lower == "stopped"
- name: Include tasks to uninstall runner (Windows)
ansible.builtin.include_tasks: uninstall_runner_win.yml
when:
- reinstall_runner or runner_state|lower == "absent"
- github_actions_system == "win"
tags:
- uninstall

- name: Include tasks to install runner (UNIX-like)
ansible.builtin.include_tasks: install_runner_unix.yml
when:
- runner_state|lower == "started" or runner_state|lower == "stopped"
- github_actions_system == "linux" or github_actions_system == "osx"
tags:
- install

- name: Include tasks to install runner (Windows)
ansible.builtin.include_tasks: install_runner_win.yml
when:
- runner_state|lower == "started" or runner_state|lower == "stopped"
- github_actions_system == "win"
tags:
- install
File renamed without changes.
47 changes: 47 additions & 0 deletions tasks/uninstall_runner_win.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
- name: Check if runner service name file exist
ansible.windows.win_stat:
path: "{{ runner_dir }}/.service"
register: runner_service_file_path

- name: Read service name from file
ansible.windows.win_command: "cat {{ runner_dir }}\\.service"
register: runner_service
changed_when: false
when: runner_service_file_path.stat.exists

- name: Uninstall service runner
ansible.windows.win_shell: |
if(Get-Service {{ runner_service.stdout }} -ErrorAction SilentlyContinue) {
Write-Host "Stopping and removing service: {{ runner_service.stdout }}"
sc.exe stop "{{ runner_service.stdout }}"
sc.exe delete "{{ runner_service.stdout }}"
}
args:
chdir: "{{ runner_dir }}"
register: uninstall_service_runner
changed_when: "'Stopping and removing service:' in uninstall_service_runner.stdout"
when: runner_service_file_path.stat.exists

- name: Check GitHub Actions runner file
ansible.windows.win_stat:
path: "{{ runner_dir }}/.runner"
register: runner_file

- name: Unregister runner from the GitHub
environment:
RUNNER_ALLOW_RUNASROOT: "1"
ansible.windows.win_command: "config.cmd remove --token {{ registration.json.token }} --name {{ runner_name }} --unattended"
args:
chdir: "{{ runner_dir }}"
become: true
become_method: runas
become_user: "{{ runner_user }}"
no_log: "{{ hide_sensitive_logs | bool }}"
changed_when: true
when: runner_name in registered_runners.json.runners|map(attribute='name')|list and runner_file.stat.exists

- name: Delete runner directory
ansible.windows.win_file:
path: "{{ runner_dir }}"
state: absent
6 changes: 6 additions & 0 deletions vars/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
github_actions_architecture_map:
amd64: x64
x86_64: x64
64-bit: x64
armv7l: arm
aarch64: arm64
arm64: arm64
github_actions_architecture: "{{ github_actions_architecture_map[ansible_facts.architecture] }}"
github_actions_system_map:
Darwin: osx
Linux: linux
Win32NT: win
github_actions_system: "{{ github_actions_system_map[ansible_facts.system] }}"

0 comments on commit 5e08b29

Please sign in to comment.