GRM-1: feat: initial implementation of Gitea Runner Manager
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
---
|
||||
# Default variables for all hosts
|
||||
ansible_python_interpreter: /usr/bin/python3
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: Install Gitea Actions runner
|
||||
hosts: all
|
||||
become: true
|
||||
vars:
|
||||
gitea_url: "{{ gitea_url | mandatory }}"
|
||||
registration_token: "{{ registration_token | mandatory }}"
|
||||
runner_name: "{{ runner_name | default(inventory_hostname) }}"
|
||||
roles:
|
||||
- role: gitea-runner
|
||||
@@ -0,0 +1,3 @@
|
||||
[runners]
|
||||
192.168.1.10 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_ed25519
|
||||
runner.example.com ansible_user=arch
|
||||
@@ -0,0 +1,5 @@
|
||||
collections:
|
||||
- name: community.general
|
||||
version: ">=13.0.1"
|
||||
- name: ansible.posix
|
||||
version: ">=1.5.4"
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
- name: Reload systemd
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: true
|
||||
|
||||
- name: Restart act-runner
|
||||
ansible.builtin.systemd:
|
||||
name: "act-runner-{{ runner_name }}"
|
||||
state: restarted
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: Converge
|
||||
hosts: all
|
||||
become: true
|
||||
vars:
|
||||
gitea_url: "http://localhost:3000"
|
||||
registration_token: "fake-token-for-testing"
|
||||
runner_name: "molecule-test-runner"
|
||||
roles:
|
||||
- role: gitea-runner
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
driver:
|
||||
name: docker
|
||||
|
||||
platforms:
|
||||
- name: instance
|
||||
image: geerlingguy/docker-ubuntu2204-ansible:latest
|
||||
command: ""
|
||||
volumes:
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||
cgroupns_mode: host
|
||||
privileged: true
|
||||
pre_build_image: true
|
||||
|
||||
provisioner:
|
||||
name: ansible
|
||||
playbooks:
|
||||
converge: converge.yml
|
||||
|
||||
verifier:
|
||||
name: ansible
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
- name: Prepare
|
||||
hosts: all
|
||||
become: true
|
||||
tasks:
|
||||
- name: Update apt cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
when: ansible_facts['os_family'] == 'Debian'
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
- name: Verify
|
||||
hosts: all
|
||||
become: true
|
||||
tasks:
|
||||
- name: Check act_runner binary exists
|
||||
ansible.builtin.stat:
|
||||
path: /usr/local/bin/act_runner
|
||||
register: act_runner_stat
|
||||
|
||||
- name: Assert act_runner binary exists
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- act_runner_stat.stat.exists
|
||||
fail_msg: "act_runner binary is missing"
|
||||
|
||||
- name: Check Docker is installed
|
||||
ansible.builtin.command: docker --version
|
||||
changed_when: false
|
||||
|
||||
- name: Check systemd service file exists
|
||||
ansible.builtin.stat:
|
||||
path: "/etc/systemd/system/act-runner-molecule-test-runner.service"
|
||||
register: service_stat
|
||||
|
||||
- name: Assert service file exists
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- service_stat.stat.exists
|
||||
fail_msg: "Systemd service file is missing"
|
||||
|
||||
- name: Check prune timer exists
|
||||
ansible.builtin.stat:
|
||||
path: /etc/systemd/system/docker-prune.timer
|
||||
register: timer_stat
|
||||
|
||||
- name: Assert prune timer exists
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- timer_stat.stat.exists
|
||||
fail_msg: "Docker prune timer is missing"
|
||||
|
||||
- name: Check config file exists
|
||||
ansible.builtin.stat:
|
||||
path: /etc/act-runner/config.toml
|
||||
register: config_stat
|
||||
|
||||
- name: Assert config file exists
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- config_stat.stat.exists
|
||||
fail_msg: "Config file is missing"
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: Ensure config directory exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/act-runner
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Create act_runner config file
|
||||
ansible.builtin.template:
|
||||
src: act-runner-config.toml.j2
|
||||
dest: /etc/act-runner/config.toml
|
||||
mode: "0644"
|
||||
notify: Restart act-runner
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
- name: Install Docker (Debian/Ubuntu)
|
||||
when: ansible_facts['os_family'] == 'Debian'
|
||||
block:
|
||||
- name: Install prerequisite packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- curl
|
||||
- gnupg
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Add Docker GPG key
|
||||
ansible.builtin.apt_key:
|
||||
url: https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg
|
||||
keyring: /etc/apt/keyrings/docker.gpg
|
||||
when: ansible_distribution != 'Ubuntu' or ansible_distribution_major_version | int >= 22
|
||||
|
||||
- name: Add Docker repository
|
||||
ansible.builtin.apt_repository:
|
||||
repo: >-
|
||||
deb [arch={{ ansible_architecture }}
|
||||
signed-by=/etc/apt/keyrings/docker.gpg]
|
||||
https://download.docker.com/linux/{{ ansible_distribution | lower }}
|
||||
{{ ansible_distribution_release }} stable
|
||||
filename: docker
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Install Docker packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
- docker-compose-plugin
|
||||
state: present
|
||||
|
||||
- name: Install Docker (Arch Linux)
|
||||
when: ansible_facts['os_family'] == 'Archlinux'
|
||||
block:
|
||||
- name: Install Docker packages
|
||||
community.general.pacman:
|
||||
name:
|
||||
- docker
|
||||
- docker-compose
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Ensure Docker service is running
|
||||
ansible.builtin.systemd:
|
||||
name: docker
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: Add user to docker group
|
||||
ansible.builtin.user:
|
||||
name: "{{ ansible_user | default(ansible_user_id) }}"
|
||||
groups: docker
|
||||
append: true
|
||||
when: ansible_user is defined or ansible_user_id is defined
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
- name: Get latest act_runner release info
|
||||
ansible.builtin.uri:
|
||||
url: https://gitea.com/gitea/act_runner/releases/latest
|
||||
return_content: true
|
||||
headers:
|
||||
Accept: application/json
|
||||
register: act_runner_release
|
||||
when: act_runner_version | default('latest') == 'latest'
|
||||
changed_when: false
|
||||
|
||||
- name: Set act_runner version from latest release
|
||||
ansible.builtin.set_fact:
|
||||
act_runner_version: "{{ act_runner_release.json.tag_name }}"
|
||||
when: act_runner_version | default('latest') == 'latest'
|
||||
|
||||
- name: Set act_runner download URL
|
||||
ansible.builtin.set_fact:
|
||||
act_runner_url: >-
|
||||
https://gitea.com/gitea/act_runner/releases/download/{{ act_runner_version }}/
|
||||
act_runner-{{ act_runner_version }}-linux-{{ ansible_architecture | regex_replace('x86_64', 'amd64') }}
|
||||
|
||||
- name: Ensure /usr/local/bin directory exists
|
||||
ansible.builtin.file:
|
||||
path: /usr/local/bin
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Download act_runner binary
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ act_runner_url }}"
|
||||
dest: /usr/local/bin/act_runner
|
||||
mode: "0755"
|
||||
force: true
|
||||
notify: Restart act-runner
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
- name: Wait for runner to appear in Gitea API
|
||||
ansible.builtin.uri:
|
||||
url: "{{ gitea_url }}/api/v1/admin/runners"
|
||||
headers:
|
||||
Authorization: "token {{ registration_token }}"
|
||||
method: GET
|
||||
status_code: 200
|
||||
return_content: true
|
||||
register: runners_response
|
||||
until: >
|
||||
runners_response.json.runners | default([]) |
|
||||
selectattr('name', 'equalto', runner_name) | list | length > 0
|
||||
retries: 12
|
||||
delay: 10
|
||||
when: gitea_url is defined and registration_token is defined
|
||||
|
||||
- name: Verify runner is online
|
||||
ansible.builtin.uri:
|
||||
url: "{{ gitea_url }}/api/v1/admin/runners"
|
||||
headers:
|
||||
Authorization: "token {{ registration_token }}"
|
||||
method: GET
|
||||
status_code: 200
|
||||
return_content: true
|
||||
register: runners_check
|
||||
when: gitea_url is defined and registration_token is defined
|
||||
|
||||
- name: Fail if runner is not online
|
||||
ansible.builtin.fail:
|
||||
msg: "Runner '{{ runner_name }}' is not online in Gitea"
|
||||
when:
|
||||
- gitea_url is defined
|
||||
- registration_token is defined
|
||||
- >
|
||||
runners_check.json.runners | default([]) |
|
||||
selectattr('name', 'equalto', runner_name) |
|
||||
selectattr('status', 'equalto', 'online') | list | length == 0
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
- name: Include OS-specific Docker installation
|
||||
ansible.builtin.include_tasks: docker.yml
|
||||
|
||||
- name: Include act_runner download
|
||||
ansible.builtin.include_tasks: download_act_runner.yml
|
||||
|
||||
- name: Include validation
|
||||
ansible.builtin.include_tasks: validate.yml
|
||||
|
||||
- name: Include config creation
|
||||
ansible.builtin.include_tasks: config.yml
|
||||
|
||||
- name: Include registration
|
||||
ansible.builtin.include_tasks: register.yml
|
||||
|
||||
- name: Include service setup
|
||||
ansible.builtin.include_tasks: service.yml
|
||||
|
||||
- name: Include prune setup
|
||||
ansible.builtin.include_tasks: prune.yml
|
||||
|
||||
- name: Include integration test
|
||||
ansible.builtin.include_tasks: integration_test.yml
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
- name: Create docker-prune service file
|
||||
ansible.builtin.template:
|
||||
src: docker-prune.service.j2
|
||||
dest: /etc/systemd/system/docker-prune.service
|
||||
mode: "0644"
|
||||
|
||||
- name: Create docker-prune timer file
|
||||
ansible.builtin.template:
|
||||
src: docker-prune.timer.j2
|
||||
dest: /etc/systemd/system/docker-prune.timer
|
||||
mode: "0644"
|
||||
|
||||
- name: Enable and start docker-prune timer
|
||||
ansible.builtin.systemd:
|
||||
name: docker-prune.timer
|
||||
state: started
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
- name: Ensure work directory exists
|
||||
ansible.builtin.file:
|
||||
path: /var/lib/gitea-runner
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Check if runner is already registered
|
||||
ansible.builtin.stat:
|
||||
path: /var/lib/gitea-runner/.runner
|
||||
register: runner_registered
|
||||
|
||||
- name: Register runner with Gitea
|
||||
ansible.builtin.command: >
|
||||
/usr/local/bin/act_runner register
|
||||
--token {{ registration_token }}
|
||||
--name {{ runner_name }}
|
||||
--instance {{ gitea_url }}
|
||||
--labels ubuntu-latest:docker://node:16-bullseye
|
||||
--no-interactive
|
||||
args:
|
||||
chdir: /var/lib/gitea-runner
|
||||
when: not runner_registered.stat.exists
|
||||
register: register_output
|
||||
changed_when: "'already exists' not in register_output.stdout | default('')"
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
- name: Create systemd service file
|
||||
ansible.builtin.template:
|
||||
src: act-runner.service.j2
|
||||
dest: "/etc/systemd/system/act-runner-{{ runner_name }}.service"
|
||||
mode: "0644"
|
||||
notify:
|
||||
- Reload systemd
|
||||
- Restart act-runner
|
||||
|
||||
- name: Enable and start act-runner service
|
||||
ansible.builtin.systemd:
|
||||
name: "act-runner-{{ runner_name }}"
|
||||
state: started
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
- name: Check act_runner binary exists
|
||||
ansible.builtin.stat:
|
||||
path: /usr/local/bin/act_runner
|
||||
register: act_runner_stat
|
||||
|
||||
- name: Fail if act_runner binary is missing
|
||||
ansible.builtin.fail:
|
||||
msg: "act_runner binary not found at /usr/local/bin/act_runner"
|
||||
when: not act_runner_stat.stat.exists
|
||||
|
||||
- name: Verify act_runner is executable
|
||||
ansible.builtin.command: /usr/local/bin/act_runner --version
|
||||
register: act_runner_version_output
|
||||
changed_when: false
|
||||
|
||||
- name: Verify Docker connectivity
|
||||
ansible.builtin.command: docker version
|
||||
register: docker_version_output
|
||||
changed_when: false
|
||||
|
||||
- name: Set runner_validated fact
|
||||
ansible.builtin.set_fact:
|
||||
runner_validated: true
|
||||
@@ -0,0 +1,3 @@
|
||||
log.level = "info"
|
||||
runner.file = ".runner"
|
||||
container.label = "gitea-runner=true"
|
||||
@@ -0,0 +1,16 @@
|
||||
[Unit]
|
||||
Description=Gitea Actions Runner ({{ runner_name }})
|
||||
After=network.target docker.service
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/act_runner daemon --config /etc/act-runner/config.toml
|
||||
WorkingDirectory=/var/lib/gitea-runner
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
User={{ ansible_user | default('root') }}
|
||||
Group=docker
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=Docker prune for Gitea runner resources
|
||||
After=docker.service
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/bin/docker system prune -f --filter "label=gitea-runner=true" --filter "until=24h"
|
||||
ExecStart=/usr/bin/docker volume prune -f --filter "label=gitea-runner=true" --filter "until=24h"
|
||||
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=Daily Docker prune for Gitea runner resources
|
||||
|
||||
[Timer]
|
||||
OnCalendar=daily
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
@@ -0,0 +1,2 @@
|
||||
---
|
||||
act_runner_version: "latest"
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
- name: Update Gitea Actions runner binary
|
||||
hosts: all
|
||||
become: true
|
||||
vars:
|
||||
act_runner_version: "{{ act_runner_version | default('latest') }}"
|
||||
tasks:
|
||||
- name: Include download and validate tasks
|
||||
ansible.builtin.include_role:
|
||||
name: gitea-runner
|
||||
tasks_from: download_act_runner.yml
|
||||
|
||||
- name: Restart act-runner service
|
||||
ansible.builtin.systemd:
|
||||
name: "act-runner-{{ runner_name | default(inventory_hostname) }}"
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
Reference in New Issue
Block a user