Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: initial windows support #219

Merged
merged 3 commits into from
Sep 30, 2024
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
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

Check failure on line 68 in tasks/install_runner_win.yml

View workflow job for this annotation

GitHub Actions / Lint

schema[tasks]

'become_method' must be one of the currently available values: ansible.builtin.runas, ansible.builtin.su, ansible.builtin.sudo
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

Check failure on line 92 in tasks/install_runner_win.yml

View workflow job for this annotation

GitHub Actions / Lint

schema[tasks]

'become_method' must be one of the currently available values: ansible.builtin.runas, ansible.builtin.su, ansible.builtin.sudo
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

Check failure on line 31 in tasks/uninstall_runner_win.yml

View workflow job for this annotation

GitHub Actions / Lint

schema[tasks]

'become_method' must be one of the currently available values: ansible.builtin.runas, ansible.builtin.su, ansible.builtin.sudo
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] }}"
Loading