runner icon indicating copy to clipboard operation
runner copied to clipboard

Vagrant KVM VM fail to register some of the runners.

Open DeltaFoxtrot01 opened this issue 9 months ago • 0 comments

Description

I am setting up a group of VMs to work as github action runners in a hetzner dedicated machine. Everything is installed as expected, but the ansible playbook for the role MonolithProjects.github_actions_runner is executed, in some of the machines it fails with a timeout in the registry of the runner:

FAILED! => {"changed": true, "cmd": ["/home/vagrant/actions-runner/./config.sh", "--url", "https://github.com/<NAME OF THE ORG>", "--token", "<CENSORED TOKEN>", "--name", "hetzner-mozart06-vm1", "--labels", "self-hosted,Linux,X64", "--runnergroup", "labgrid", "--unattended"], "delta": "0:01:44.447032", "end": "2025-03-18 10:31:22.856511", "msg": "non-zero return code", "rc": 1, "start": "2025-03-18 10:29:38.409479", "stderr": "The HTTP request timed out after 00:01:40.", "stderr_lines": ["The HTTP request timed out after 00:01:40."], "stdout": "\n--------------------------------------------------------------------------------\n|        ____ _ _   _   _       _          _        _   _                      |\n|       / ___(_) |_| | | |_   _| |__      / \\   ___| |_(_) ___  _ __  ___      |\n|      | |  _| | __| |_| | | | | '_ \\    / _ \\ / __| __| |/ _ \\| '_ \\/ __|     |\n|      | |_| | | |_|  _  | |_| | |_) |  / ___ \\ (__| |_| | (_) | | | \\__ \\     |\n|       \\____|_|\\__|_| |_|\\__,_|_.__/  /_/   \\_\\___|\\__|_|\\___/|_| |_|___/     |\n|                                                                              |\n|                       Self-hosted runner registration                        |\n|                                                                              |\n--------------------------------------------------------------------------------\n\n# Authentication\n\n\n√ Connected to GitHub\n\n# Runner Registration\n\n\n\n\n√ Runner successfully added", "stdout_lines": ["", "--------------------------------------------------------------------------------", "|        ____ _ _   _   _       _          _        _   _                      |", "|       / ___(_) |_| | | |_   _| |__      / \\   ___| |_(_) ___  _ __  ___      |", "|      | |  _| | __| |_| | | | | '_ \\    / _ \\ / __| __| |/ _ \\| '_ \\/ __|     |", "|      | |_| | | |_|  _  | |_| | |_) |  / ___ \\ (__| |_| | (_) | | | \\__ \\     |", "|       \\____|_|\\__|_| |_|\\__,_|_.__/  /_/   \\_\\___|\\__|_|\\___/|_| |_|___/     |", "|                                                                              |", "|                       Self-hosted runner registration                        |", "|                                                                              |", "--------------------------------------------------------------------------------", "", "# Authentication", "", "", "√ Connected to GitHub", "", "# Runner Registration", "", "", "", "", "√ Runner successfully added"]}

The definition of the Vagrant file can be seen here:

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

  config.vagrant.plugins = ["vagrant-libvirt"]
  config.vm.provider "libvirt"

  (1..3).each do |index| 
    config.vm.define "mozart-gh-actions#{index}" do |node|
      node.vm.hostname = "mozart-gh-actions"
      node.vm.box = "generic/ubuntu2204"
      node.vm.network "private_network", ip: "192.168.121.#{index + 1}"
      node.vm.synced_folder ".", "/home/vagrant/work", type: "nfs", nfs_version: 4, mount_options: ["tcp"]

      node.vm.provider "libvirt" do |lb|
        # do not change this to qemu. Dotnet does not work with qemu.
        lb.driver = "kvm"
        lb.memory = 4096
        lb.cpus = 4
      end

      node.vm.provision "init", type: "shell" do |shell|
        shell.path ="./bootstrap.sh"
        shell.args = ["hetzner-#{ENV["VM_NAME"]}-vm#{index}", "<NAME OF THE ORG>", "#{ENV["GITHUB_TOKEN"]}"]
      end

      node.vm.provision "ansible_local", after: "init" do |ansible|
        ansible.playbook = "gha-playbook.yml"
        ansible.galaxy_role_file = "requirements.yml"
        ansible.provisioning_path = "/home/vagrant/work"
        ansible.extra_vars = {
          "access_token" => "#{ENV["GITHUB_TOKEN"]}",
          "github_account" => "<NAME OF THE ORG>",
          "runner_user" => "vagrant",
          "runner_name" => "hetzner-#{ENV["VM_NAME"]}-vm#{index}",
          "runner_group" => "labgrid",
          "runner_dir" => "/home/vagrant/actions-runner",
          "runner_org" => true,
          "runner_labels" => ["self-hosted", "Linux", "X64"],
          "hide_sensitive_logs" => false
        }
      end
    end
  end
end

This is the bootstrap.sh script:

#!/bin/bash

# Commands for the startup of every VM

if [ "$#" -ne 3 ]; then
    echo "Name of the runner, of the organization and the gh token are expected"
    exit 1
fi

# Install basic dependencies
apt update -y
apt install net-tools curl -y
apt install -y software-properties-common libgnutls30 ca-certificates apt-transport-https
sudo update-ca-certificates

apt update -y
apt install -y jq

# Setup to install ansible
apt-add-repository ppa:ansible/ansible

apt update -y
apt install -y ansible

# Install nodejs
apt install -y nodejs

# Install docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh ./get-docker.sh
groupadd docker
gpasswd -a vagrant docker

# Check if runner exists, cleaning it in advance
python3 /home/vagrant/work/clean_gha_runner.py $1 $2 $3

# Disable IPv6 for GH Actions
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf
sudo sysctl -p

This is the clean_gha_runner.py:

"""
Search for all the github runners and deletes the one reffering to the machine, 
if it exists in the list.
"""
import requests
import sys

print("--- Clean Registered GH Actions Runner ---")

if len(sys.argv) != 4:
    print("Script requires 3 execution arguments: runner_name, org_name, token")
    print(f"Arguments passed: {sys.argv[1:]}")
    sys.exit(1)

runner_name: str = sys.argv[1]
get_request: str = f"https://api.github.com/orgs/{sys.argv[2]}/actions/runners"
del_request: str = f"https://api.github.com/orgs/{sys.argv[2]}/actions/runners"
headers: dict[str, str] = {
    "Authorization": f"Bearer {sys.argv[3]}",
    "X-GitHub-Api-Version": "2022-11-28",
    "Accept": "application/vnd.github+json"
}

response: requests.Response = requests.get(
    get_request,
    headers=headers)

print(f"Status code of runners request: {response.status_code}")

if "runners" in response.json():
  runner_list: list[dict[str,object]] = response.json()["runners"]

  print("Searching for the existing runner")
  for runner in runner_list:
      if runner["name"] == runner_name:
          print(f"Found runner {runner_name} with id {runner['id']}")
          requests.delete(f"{del_request}/{runner['id']}", headers=headers)
          print("Deletion of runner executed")
          sys.exit(0)

  print(f"No runner with name {runner_name} found")

print('No "runners" key found in request body. Skipped deletion of runners')

This is the requirements.yml:

---
roles:
  - name: MonolithProjects.github_actions_runner
    src: https://github.com/MonolithProjects/ansible-github_actions_runner
    version: 1.25.1

This is the gha-playbook.yml:

# role to install GH Actions runner in the VM
---
- name: Install GitHub Actions Runner on bang-olufsen VM runners
  hosts: all
  user: vagrant
  become: true
  roles:
    - role: MonolithProjects.github_actions_runner

Expected behavior

For all VMs to configure the runner successfully and show an output similar to this:

...
Mar 18 11:39:43 mozart06 vagrant[3104952]: TASK [MonolithProjects.github_actions_runner : Register runner] ****************
Mar 18 11:39:48 mozart06 vagrant[3104952]: changed: [mozart-gh-actions2]
Mar 18 11:39:48 mozart06 vagrant[3104952]: TASK [MonolithProjects.github_actions_runner : Update runner labels if changed] ***
Mar 18 11:39:48 mozart06 vagrant[3104952]: skipping: [mozart-gh-actions2]
Mar 18 11:39:48 mozart06 vagrant[3104952]: TASK [MonolithProjects.github_actions_runner : Replace registered runner] ******
Mar 18 11:39:48 mozart06 vagrant[3104952]: skipping: [mozart-gh-actions2]
Mar 18 11:39:48 mozart06 vagrant[3104952]: TASK [MonolithProjects.github_actions_runner : Install service] ****************
Mar 18 11:39:48 mozart06 vagrant[3104952]: changed: [mozart-gh-actions2]
Mar 18 11:39:48 mozart06 vagrant[3104952]: TASK [MonolithProjects.github_actions_runner : Read service name from file] ****
Mar 18 11:39:48 mozart06 vagrant[3104952]: ok: [mozart-gh-actions2]
Mar 18 11:39:48 mozart06 vagrant[3104952]: TASK [MonolithProjects.github_actions_runner : START and enable Github Actions Runner service (Linux)] ***
Mar 18 11:39:49 mozart06 vagrant[3104952]: changed: [mozart-gh-actions2]
Mar 18 11:39:49 mozart06 vagrant[3104952]: TASK [MonolithProjects.github_actions_runner : START and enable Github Actions Runner service (macOS)] ***
Mar 18 11:39:49 mozart06 vagrant[3104952]: skipping: [mozart-gh-actions2]
Mar 18 11:39:49 mozart06 vagrant[3104952]: TASK [MonolithProjects.github_actions_runner : STOP and disable Github Actions Runner service] ***
Mar 18 11:39:49 mozart06 vagrant[3104952]: skipping: [mozart-gh-actions2]
Mar 18 11:39:49 mozart06 vagrant[3104952]: TASK [MonolithProjects.github_actions_runner : Version changed - RESTART Github Actions Runner service] ***
Mar 18 11:39:54 mozart06 vagrant[3104952]: changed: [mozart-gh-actions2]
Mar 18 11:39:54 mozart06 vagrant[3104952]: TASK [MonolithProjects.github_actions_runner : Include tasks to install runner (Windows)] ***
Mar 18 11:39:54 mozart06 vagrant[3104952]: skipping: [mozart-gh-actions2]
Mar 18 11:39:54 mozart06 vagrant[3104952]: PLAY RECAP *********************************************************************
Mar 18 11:39:54 mozart06 vagrant[3104952]: mozart-gh-actions2         : ok=27   changed=7    unreachable=0    failed=0    skipped=23   rescued=0    ignored=1

Actual behavior

Some runners do not get registered with a timeout:

...
Mar 18 11:29:38 mozart06 vagrant[3096661]: TASK [MonolithProjects.github_actions_runner : Register runner] ****************
Mar 18 11:31:22 mozart06 vagrant[3096661]: fatal: [mozart-gh-actions1]: FAILED! => {"changed": true, "cmd": ["/home/vagrant/actions-runner/./config.sh", "--url", "https://github.com/<ORG>", "--token", "<CENSORED TOKEN>", "--name", "hetzner-mozart06-vm1", "--labels", "self-hosted,Linux,X64", "--runnergroup", "labgrid", "--unattended"], "delta": "0:01:44.447032", "end": "2025-03-18 10:31:22.856511", "msg": "non-zero return code", "rc": 1, "start": "2025-03-18 10:29:38.409479", "stderr": "The HTTP request timed out after 00:01:40.", "stderr_lines": ["The HTTP request timed out after 00:01:40."], "stdout": "\n--------------------------------------------------------------------------------\n|        ____ _ _   _   _       _          _        _   _                      |\n|       / ___(_) |_| | | |_   _| |__      / \\   ___| |_(_) ___  _ __  ___      |\n|      | |  _| | __| |_| | | | | '_ \\    / _ \\ / __| __| |/ _ \\| '_ \\/ __|     |\n|      | |_| | | |_|  _  | |_| | |_) |  / ___ \\ (__| |_| | (_) | | | \\__ \\     |\n|       \\____|_|\\__|_| |_|\\__,_|_.__/  /_/   \\_\\___|\\__|_|\\___/|_| |_|___/     |\n|                                                                              |\n|                       Self-hosted runner registration                        |\n|                                                                              |\n--------------------------------------------------------------------------------\n\n# Authentication\n\n\n√ Connected to GitHub\n\n# Runner Registration\n\n\n\n\n√ Runner successfully added", "stdout_lines": ["", "--------------------------------------------------------------------------------", "|        ____ _ _   _   _       _          _        _   _                      |", "|       / ___(_) |_| | | |_   _| |__      / \\   ___| |_(_) ___  _ __  ___      |", "|      | |  _| | __| |_| | | | | '_ \\    / _ \\ / __| __| |/ _ \\| '_ \\/ __|     |", "|      | |_| | | |_|  _  | |_| | |_) |  / ___ \\ (__| |_| | (_) | | | \\__ \\     |", "|       \\____|_|\\__|_| |_|\\__,_|_.__/  /_/   \\_\\___|\\__|_|\\___/|_| |_|___/     |", "|                                                                              |", "|                       Self-hosted runner registration                        |", "|                                                                              |", "--------------------------------------------------------------------------------", "", "# Authentication", "", "", "√ Connected to GitHub", "", "# Runner Registration", "", "", "", "", "√ Runner successfully added"]}
Mar 18 11:31:22 mozart06 vagrant[3096661]: PLAY RECAP *********************************************************************
Mar 18 11:31:22 mozart06 vagrant[3096661]: mozart-gh-actions1         : ok=22   changed=3    unreachable=0    failed=1    skipped=18   rescued=0    ignored=1
Mar 18 11:31:23 mozart06 vagrant[3096661]: Ansible failed to complete successfully. Any error output should be
Mar 18 11:31:23 mozart06 vagrant[3096661]: visible above. Please fix these errors and try again.
Mar 18 11:31:23 mozart06 systemd[1]: ghavm.service: Main process exited, code=exited, status=1/FAILURE
Mar 18 11:31:23 mozart06 systemd[1]: ghavm.service: Failed with result 'exit-code'.
Mar 18 11:31:23 mozart06 systemd[1]: Failed to start "Manage the launch of GHA Vagrant VMs".

These are the logs inside the _diag_folder:

[2025-03-18 10:29:41Z INFO RunnerServer] Establish connection with 60 seconds timeout.
[2025-03-18 10:29:41Z INFO GitHubActionsService] Starting operation Location.GetConnectionData
[2025-03-18 10:29:41Z INFO RunnerServer] EstablishVssConnection
[2025-03-18 10:29:41Z INFO RunnerServer] Establish connection with 60 seconds timeout.
[2025-03-18 10:29:41Z INFO GitHubActionsService] Starting operation Location.GetConnectionData
[2025-03-18 10:29:41Z INFO GitHubActionsService] Finished operation Location.GetConnectionData
[2025-03-18 10:29:41Z INFO GitHubActionsService] Finished operation Location.GetConnectionData
[2025-03-18 10:29:41Z INFO GitHubActionsService] Finished operation Location.GetConnectionData
[2025-03-18 10:29:42Z INFO RSAFileKeyManager] Loading RSA key parameters from file /home/vagrant/actions-runner/.credentials_rsaparams
[2025-03-18 10:29:42Z INFO RSAFileKeyManager] Loading RSA key parameters from file /home/vagrant/actions-runner/.credentials_rsaparams
[2025-03-18 10:30:07Z WARN GitHubActionsService] Attempt 1 of POST request to https://tokenghub.actions.githubusercontent.com/_apis/oauth2/token/6ab96a90-024f-4fc3-90fa-e9de285343ba failed (Socket Error: TryAgain). The operation will be retried in 11.042 seconds.
[2025-03-18 10:30:44Z WARN GitHubActionsService] Attempt 2 of POST request to https://tokenghub.actions.githubusercontent.com/_apis/oauth2/token/6ab96a90-024f-4fc3-90fa-e9de285343ba failed (Socket Error: TryAgain). The operation will be retried in 12.463 seconds.
[2025-03-18 10:31:16Z WARN GitHubActionsService] Attempt 3 of POST request to https://tokenghub.actions.githubusercontent.com/_apis/oauth2/token/6ab96a90-024f-4fc3-90fa-e9de285343ba failed (Socket Error: TryAgain). The operation will be retried in 18.295 seconds.
[2025-03-18 10:31:22Z WARN GitHubActionsService] Retrieving an AAD auth token took a long time (99.905605 seconds)
[2025-03-18 10:31:22Z WARN GitHubActionsService] GET request to https://pipelinesghubeus21.actions.githubusercontent.com/sI18qo0PwOakoMXABs6JqYkwneVB0dGAzRBBzMYmCQrvVROPZQ/_apis/distributedtask/pools?poolType=Automation timed out after 100 seconds.
[2025-03-18 10:31:22Z ERR  Runner] System.TimeoutException: The HTTP request timed out after 00:01:40.
 ---> System.Threading.Tasks.TaskCanceledException: A task was canceled.
 ---> System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at GitHub.Services.Common.VssHttpRetryMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.HttpClient.HandleFailure(Exception e, Boolean telemetryStarted, HttpResponseMessage response, CancellationTokenSource cts, CancellationToken cancellationToken, CancellationTokenSource pendingRequestsCts)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at GitHub.Services.OAuth.VssOAuthTokenHttpClient.GetTokenAsync(VssOAuthGrant grant, VssOAuthClientCredential credential, VssOAuthTokenParameters tokenParameters, CancellationToken cancellationToken)
   at GitHub.Services.OAuth.VssOAuthTokenProvider.OnGetTokenAsync(IssuedToken failedToken, CancellationToken cancellationToken)
   at GitHub.Services.Common.IssuedTokenProvider.GetTokenOperation.GetTokenAsync(VssTraceActivity traceActivity)
   at GitHub.Services.Common.IssuedTokenProvider.GetTokenAsync(IssuedToken failedToken, CancellationToken cancellationToken)
   at GitHub.Services.Common.VssHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at GitHub.Services.Common.VssHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at GitHub.Services.Common.VssHttpRetryMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at GitHub.Services.WebApi.VssHttpClientBase.SendAsync(HttpRequestMessage message, HttpCompletionOption completionOption, Object userState, CancellationToken cancellationToken)
   at GitHub.Services.WebApi.VssHttpClientBase.SendAsync[T](HttpRequestMessage message, Object userState, CancellationToken cancellationToken)
   at GitHub.Services.WebApi.VssHttpClientBase.SendAsync[T](HttpMethod method, IEnumerable`1 additionalHeaders, Guid locationId, Object routeValues, ApiResourceVersion version, HttpContent content, IEnumerable`1 queryParameters, Object userState, CancellationToken cancellationToken)
   at GitHub.Runner.Listener.Configuration.ConfigurationManager.ConfigureAsync(CommandSettings command)
   at GitHub.Runner.Listener.Runner.ExecuteCommand(CommandSettings command)
[2025-03-18 10:31:22Z ERR  Runner] #####################################################
[2025-03-18 10:31:22Z ERR  Runner] System.Threading.Tasks.TaskCanceledException: A task was canceled.
 ---> System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at GitHub.Services.Common.VssHttpRetryMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.HttpClient.HandleFailure(Exception e, Boolean telemetryStarted, HttpResponseMessage response, CancellationTokenSource cts, CancellationToken cancellationToken, CancellationTokenSource pendingRequestsCts)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at GitHub.Services.OAuth.VssOAuthTokenHttpClient.GetTokenAsync(VssOAuthGrant grant, VssOAuthClientCredential credential, VssOAuthTokenParameters tokenParameters, CancellationToken cancellationToken)
   at GitHub.Services.OAuth.VssOAuthTokenProvider.OnGetTokenAsync(IssuedToken failedToken, CancellationToken cancellationToken)
   at GitHub.Services.Common.IssuedTokenProvider.GetTokenOperation.GetTokenAsync(VssTraceActivity traceActivity)
   at GitHub.Services.Common.IssuedTokenProvider.GetTokenAsync(IssuedToken failedToken, CancellationToken cancellationToken)
   at GitHub.Services.Common.VssHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
[2025-03-18 10:31:22Z ERR  Runner] #####################################################
[2025-03-18 10:31:22Z ERR  Runner] System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at GitHub.Services.Common.VssHttpRetryMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
[2025-03-18 10:31:22Z ERR  Terminal] WRITE ERROR: The HTTP request timed out after 00:01:40.
[2025-03-18 10:31:22Z INFO Listener] Runner execution has finished with return code 1

Repro steps

This is a quick run down of the instructions that should be followed. In a ubuntu 22.04 system do the following:

  1. Disable IPv6 in the machine
  2. Set an environment variable named GITHUB_TOKEN with the github developer token with the proper permissions and VM_NAME
  3. Make sure kvm is properly configured in your system
  4. Install vagrant and the vagrant-libvirt plugin
  5. Run vagrant up --provider libvirt --no-parallel

This is the ansible playbook executed on the machine:

---
- name: Setup Vagrant GH actions Virtual Machines
  become: true
  hosts: github_runner_vms
  tasks:
    - name: Evaluate if required token is defined
      ansible.builtin.fail:
        msg: "Token is not defined in RUNNER_API_TOKEN"
      when: lookup('env', 'RUNNER_API_TOKEN') == ""

    - name: Install libvirt
      ansible.builtin.apt:
        pkg:
          - qemu
          - qemu-kvm
          - qemu-system
          - qemu-utils
          - libvirt-daemon-system
          - libvirt-clients
          - bridge-utils
          - ebtables
          - libguestfs-tools
          - libvirt-dev
          - ruby-fog-libvirt
          - nfs-kernel-server
          - pkg-config
          - cpu-checker
          - libvirt-daemon
          - libxml2-dev
          - libxslt-dev
        state: present

    - name: Ensure Vagrant Repository key exists
      ansible.builtin.apt_key:
        url: https://apt.releases.hashicorp.com/gpg
        state: present
    - name: Ensure APT repository file exists for vagrant
      ansible.builtin.apt_repository:
        repo: "deb https://apt.releases.hashicorp.com {{ ansible_distribution_release }} main"
        state: present
        filename: hashicorp

    - name: Update APT package list
      ansible.builtin.apt:
        update_cache: true

    - name: Enable nfs-server
      ansible.builtin.systemd_service:
        name: nfs-server
        enabled: true

    - name: Install vagrant-libvirt required packages
      ansible.builtin.apt:
        pkg: ruby-libvirt
        state: present
    - name: Install Vagrant
      ansible.builtin.apt:
        pkg: vagrant
        state: present
      register: vagrant_install

    # this is part of the vagrant installation
    - name: Install vagrant-libvirt plugin # noqa no-changed-when no-handler
      ansible.builtin.shell: >
        vagrant plugin install vagrant-libvirt
      args:
        executable: /bin/bash
      when: vagrant_install.changed


    # since it is a one shot service, we need to stop it first
    # it is also useful to make sure the vagrant lock is released
    - name: Check if GHA Vagrant service exists
      ansible.builtin.stat:
        path: "/etc/systemd/system/ghavm.service"
      register: gha_service_status

    - name: Stop service
      when: gha_service_status.stat.exists
      ansible.builtin.systemd_service:
        name: ghavm
        state: stopped

    - name: Ensure Vagrant is down
      ansible.builtin.shell: >
        if [ -d "$HOME/vagrant-gh-actions" ]; then
          cd ~/vagrant-gh-actions
          vagrant destroy -f
        fi
      args:
        executable: /bin/bash
      register: vagrant_down
      changed_when: false

    - name: Transfer Vagrant files
      ansible.builtin.copy:
        src: "vagrant-gh-actions"
        dest: "~"
        mode: "01777"

    # configure the systemd job
    - name: Create systemd job # noqa no-changed-when
      ansible.builtin.shell: >
        mv ~/vagrant-gh-actions/ghavm.service /etc/systemd/system/
    - name: Change permissions of systemd file
      ansible.builtin.file:
        path: /etc/systemd/system/ghavm.service
        mode: "01777"
    - name: Enable the service to start on reboot
      ansible.builtin.systemd_service:
        name: ghavm
        enabled: true

    - name: Reload service
      ansible.builtin.systemd_service:
        name: ghavm
        daemon_reload: true
    - name: Set environemnt variables in ghavm systemd service # noqa no-changed-when command-instead-of-module
      ansible.builtin.shell: >                                 # systemd_service module for ansible does not have a import-env command
        systemctl import-environment VM_NAME GITHUB_TOKEN
      environment:
        VM_NAME: "{{ inventory_hostname }}"
        GITHUB_TOKEN: "{{ lookup('env', 'RUNNER_API_TOKEN') }}"
    - name: Start service
      ansible.builtin.systemd_service:
        name: ghavm
        state: started
    - name: Unset environemnt variables in ghavm systemd service # noqa no-changed-when command-instead-of-module
      ansible.builtin.shell: >                                   # systemd_service module for ansible does not have a unset-env command
        systemctl unset-environment VM_NAME GITHUB_TOKEN

DeltaFoxtrot01 avatar Mar 18 '25 13:03 DeltaFoxtrot01