ci(runner): restore isolated Molecule CI

- Scope VirtualBox cleanup to repository-owned Molecule resources\n- Route lint to hosted runners and harden self-hosted workflow execution\n- Add diagnostics, fixture coverage, and reproducible lint validation
This commit is contained in:
Timothy Stewart
2026-07-30 22:07:22 -05:00
committed by Techno Tim
parent 2fad0a8db6
commit 29b7aa1b72
11 changed files with 474 additions and 70 deletions
+1
View File
@@ -3,6 +3,7 @@ profile: production
exclude_paths: exclude_paths:
# default paths # default paths
- .cache/ - .cache/
- .ansible/
- .github/ - .github/
- test/fixtures/formatting-before/ - test/fixtures/formatting-before/
- test/fixtures/formatting-prettier/ - test/fixtures/formatting-prettier/
+6
View File
@@ -0,0 +1,6 @@
---
self-hosted-runner:
labels:
- k3s-ci
- virtualbox
- nested-virt
+229
View File
@@ -0,0 +1,229 @@
#!/usr/bin/env bash
set -Eeuo pipefail
usage() {
printf '%s\n' \
'Usage: cleanup-runner-resources.sh [--snapshot|--dry-run|--apply]' \
'' \
'Discover and, with --apply, remove only VirtualBox resources referenced by' \
'repository-owned Molecule Vagrant state. The default is --dry-run.'
}
mode="dry-run"
case "${1:-}" in
"") ;;
--snapshot) mode="snapshot" ;;
--dry-run) mode="dry-run" ;;
--apply) mode="apply" ;;
--help|-h) usage; exit 0 ;;
*) usage >&2; exit 2 ;;
esac
home_dir="${HOME:?HOME must be set}"
molecule_root="${K3S_CI_MOLECULE_ROOT:-${home_dir}/.cache/molecule}"
virtualbox_root="${K3S_CI_VIRTUALBOX_ROOT:-${home_dir}/VirtualBox VMs}"
hostonly_marker="${K3S_CI_HOSTONLY_MARKER:-${home_dir}/.cache/k3s-ci/hostonly-interfaces}"
record_hostonly() {
local marker_dir="${hostonly_marker%/*}"
local marker_tmp="${hostonly_marker}.tmp"
local hostonly_inventory
if ! hostonly_inventory="$(VBoxManage list hostonlyifs)"; then
fail_closed 'unable to inventory VirtualBox host-only interfaces'
fi
mkdir -p -- "$marker_dir"
awk -F': ' '
/^Name:/ { name=$2 }
/^IPAddress:/ { print name "|" $2 }
' <<< "$hostonly_inventory" > "$marker_tmp"
mv -- "$marker_tmp" "$hostonly_marker"
chmod 600 "$hostonly_marker"
printf 'Recorded host-only interface baseline: %s\n' "$hostonly_marker"
}
cleanup_hostonly() {
local hostonly_inventory
if [[ ! -f "$hostonly_marker" ]]; then
printf 'No host-only interface baseline found; leaving interfaces unchanged.\n'
return 0
fi
if ! hostonly_inventory="$(VBoxManage list hostonlyifs)"; then
fail_closed 'unable to inventory VirtualBox host-only interfaces'
fi
while IFS='|' read -r interface_name interface_ip; do
[[ "$interface_name" == vboxnet* ]] || continue
[[ "$interface_ip" == 192.168.30.* || "$interface_ip" == fdad:bad:ba55:* ]] || continue
if grep -Fqx "${interface_name}|${interface_ip}" "$hostonly_marker"; then
continue
fi
if [[ "$mode" == apply ]]; then
VBoxManage hostonlyif remove "$interface_name"
printf 'Removed host-only interface %s (%s)\n' "$interface_name" "$interface_ip"
else
printf 'Would remove host-only interface %s (%s)\n' "$interface_name" "$interface_ip"
fi
done < <(awk -F': ' '
/^Name:/ { name=$2 }
/^IPAddress:/ { print name "|" $2 }
' <<< "$hostonly_inventory")
}
if [[ "$mode" == snapshot ]]; then
record_hostonly
exit 0
fi
resolve_existing_dir() {
local candidate="$1"
if [[ ! -d "$candidate" ]]; then
return 1
fi
readlink -f -- "$candidate"
}
root_contains() {
local root="$1"
local path="$2"
[[ "$path" == "$root"/* ]]
}
is_supported_scenario() {
case "$1" in
default|single_node|calico|cilium|kube-vip|ipv6) return 0 ;;
*) return 1 ;;
esac
}
is_unregistered_vm_error() {
grep -Eq 'Could not find a registered machine|VBOX_E_OBJECT_NOT_FOUND'
}
fail_closed() {
printf 'cleanup refused: %s\n' "$1" >&2
exit 3
}
print_inventory() {
local phase="$1"
printf '%s VirtualBox inventory:\n' "$phase"
VBoxManage list vms || true
VBoxManage list hdds || true
VBoxManage list hostonlyifs || true
}
molecule_root_real="$(resolve_existing_dir "$molecule_root" || true)"
if [[ -z "$molecule_root_real" ]]; then
printf 'No Molecule root exists: %s\n' "$molecule_root"
cleanup_hostonly
exit 0
fi
print_inventory before
declare -a state_files=()
while IFS= read -r -d '' state_file; do
state_files+=("$state_file")
done < <(find "$molecule_root_real/repo" -mindepth 6 -maxdepth 6 -type f \
-path '*/.vagrant/machines/*/virtualbox/id' -print0 2>/dev/null)
if ((${#state_files[@]} == 0)); then
printf 'No repository-owned Molecule Vagrant state found under %s\n' "$molecule_root_real"
cleanup_hostonly
print_inventory after
exit 0
fi
virtualbox_root_real="$(resolve_existing_dir "$virtualbox_root" || true)"
declare -a vm_records=()
for state_file in "${state_files[@]}"; do
state_file_real="$(readlink -f -- "$state_file")"
state_dir="${state_file_real%/.vagrant/machines/*/virtualbox/id}"
machine_dir="${state_file_real%/virtualbox/id}"
machine_name="${machine_dir##*/}"
scenario_name="${state_dir##*/}"
if ! root_contains "$molecule_root_real/repo" "$state_dir"; then
fail_closed "state path is outside the repository Molecule root: $state_file_real"
fi
if ! is_supported_scenario "$scenario_name"; then
fail_closed "unexpected Molecule scenario: $scenario_name"
fi
if [[ "$machine_name" != control* && "$machine_name" != node* ]]; then
fail_closed "unexpected Molecule machine name: $machine_name"
fi
vm_uuid="$(tr -d '[:space:]' < "$state_file_real")"
if [[ ! "$vm_uuid" =~ ^[0-9a-fA-F-]{36}$ ]]; then
fail_closed "invalid VirtualBox UUID in $state_file_real"
fi
if ! vm_info="$(VBoxManage showvminfo "$vm_uuid" --machinereadable 2>&1)"; then
if is_unregistered_vm_error <<< "$vm_info"; then
printf 'Stale Vagrant state without a registered VM: %s (%s)\n' "$machine_name" "$vm_uuid"
if [[ "$mode" == apply ]]; then
rm -rf -- "${state_dir}/.vagrant"
printf 'Removed stale Vagrant state: %s\n' "${state_dir}/.vagrant"
fi
continue
fi
fail_closed "unable to inspect VirtualBox VM $vm_uuid: $vm_info"
fi
if [[ -z "$virtualbox_root_real" ]]; then
fail_closed "VirtualBox VM root does not exist: $virtualbox_root"
fi
cfg_file="$(awk -F= '$1 == "CfgFile" {gsub(/"/, "", $2); print $2; exit}' <<< "$vm_info")"
if [[ -z "$cfg_file" ]]; then
fail_closed "VirtualBox configuration path missing for $vm_uuid"
fi
cfg_file_real="$(readlink -f -- "$cfg_file")"
if ! root_contains "$virtualbox_root_real" "$cfg_file_real"; then
fail_closed "VM configuration is outside VirtualBox root: $cfg_file_real"
fi
while IFS= read -r disk_path; do
[[ -z "$disk_path" ]] && continue
disk_path_real="$(readlink -f -- "$disk_path" 2>/dev/null || true)"
if [[ -z "$disk_path_real" ]] || ! root_contains "$virtualbox_root_real" "$disk_path_real"; then
fail_closed "attached disk is outside VirtualBox root: $disk_path"
fi
done < <(awk -F= '$1 ~ /^(SATA|IDE|SCSI|SAS|VirtioSCSI|NVMe)-[0-9]+-[0-9]+$/ {gsub(/"/, "", $2); print $2}' <<< "$vm_info")
vm_records+=("$vm_uuid|$machine_name|$cfg_file_real")
done
if ((${#vm_records[@]} == 0)); then
printf 'No live repository-owned VirtualBox resources found\n'
cleanup_hostonly
print_inventory after
exit 0
fi
for record in "${vm_records[@]}"; do
IFS='|' read -r vm_uuid machine_name cfg_file_real <<< "$record"
if [[ "$mode" == dry-run ]]; then
printf 'Would remove VM %s (%s) config=%s\n' "$machine_name" "$vm_uuid" "$cfg_file_real"
continue
fi
vm_state="$(VBoxManage showvminfo "$vm_uuid" --machinereadable | awk -F= '$1 == "VMState" {gsub(/"/, "", $2); print $2; exit}')"
if [[ "$vm_state" != poweroff && "$vm_state" != saved ]]; then
VBoxManage controlvm "$vm_uuid" poweroff
fi
VBoxManage unregistervm "$vm_uuid" --delete
printf 'Removed VM %s (%s)\n' "$machine_name" "$vm_uuid"
done
cleanup_hostonly
print_inventory after
if [[ "$mode" == apply ]]; then
printf 'Repository-owned VM and host-only interface cleanup complete.\n'
else
printf 'Dry run complete. No resources were modified.\n'
fi
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -Eeuo pipefail
output_dir="${1:-${RUNNER_TEMP:-/tmp}/k3s-ci-diagnostics}"
mkdir -p -- "$output_dir"
umask 077
run_capture() {
local output_file="$1"
shift
{
printf '$'
printf ' %q' "$@"
printf '\n'
"$@"
} > "$output_dir/$output_file" 2>&1 || true
}
run_capture system.txt uname -a
run_capture runner-user.txt id
run_capture memory.txt free -h
run_capture disk.txt df -h
run_capture virtualbox-version VBoxManage --version
run_capture virtualbox-vms VBoxManage list vms
run_capture virtualbox-running-vms VBoxManage list runningvms
run_capture virtualbox-disks VBoxManage list hdds
run_capture virtualbox-hostonlyifs VBoxManage list hostonlyifs
run_capture vagrant-status vagrant global-status
run_capture molecule-state find "${HOME}/.cache/molecule" -maxdepth 6 -type f -path '*/.vagrant/machines/*/virtualbox/id' -print
if [[ -r /etc/vbox/networks.conf ]]; then
cp -- /etc/vbox/networks.conf "$output_dir/virtualbox-networks.conf"
fi
printf 'Diagnostics written to %s\n' "$output_dir"
+121
View File
@@ -0,0 +1,121 @@
#!/usr/bin/env bash
# shellcheck disable=SC2016
set -Eeuo pipefail
repo_root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)"
test_root="$(mktemp -d "${TMPDIR:-/tmp}/k3s-ci-cleanup-test.XXXXXX")"
trap 'rm -rf -- "$test_root"' EXIT
molecule_root="$test_root/molecule"
virtualbox_root="$test_root/VirtualBox VMs"
fake_bin="$test_root/bin"
mkdir -p -- "$molecule_root/repo/single_node/.vagrant/machines/control1/virtualbox" \
"$virtualbox_root/control1" "$virtualbox_root/unmarked" "$fake_bin"
printf '%s\n' '11111111-1111-1111-1111-111111111111' \
> "$molecule_root/repo/single_node/.vagrant/machines/control1/virtualbox/id"
touch "$virtualbox_root/control1/control1.vbox" "$virtualbox_root/control1/disk.vdi" \
"$virtualbox_root/unmarked/unmarked.vbox"
printf '%s\n' \
'#!/usr/bin/env bash' \
'set -Eeuo pipefail' \
'case "${1:-}" in' \
' list)' \
' if [[ "${2:-}" == hostonlyifs && "${FAKE_HOSTONLY_FAIL:-false}" == true ]]; then exit 1; fi' \
' exit 0' \
' ;;' \
' showvminfo)' \
' if [[ "${FAKE_VM_MODE:-normal}" == missing ]]; then' \
' printf '\''VBoxManage: error: Could not find a registered machine named "missing"\n'\'' >&2' \
' exit 1' \
' fi' \
' if [[ "${FAKE_VM_MODE:-normal}" == fault ]]; then' \
' printf '\''VBoxManage: error: VirtualBox service is unavailable\n'\'' >&2' \
' exit 1' \
' fi' \
' printf '\''CfgFile="%s"\n'\'' "${FAKE_VBOX_ROOT}/control1/control1.vbox"' \
' printf '\''SATA-0-0="%s"\n'\'' "${FAKE_VBOX_ROOT}/control1/disk.vdi"' \
' printf '\''VMState="running"\n'\''' \
' ;;' \
' controlvm) printf '\''controlvm %s\n'\'' "$*" >> "${FAKE_LOG}" ;;' \
' unregistervm)' \
' printf '\''unregistervm %s\n'\'' "$*" >> "${FAKE_LOG}"' \
' rm -f -- "${FAKE_VBOX_ROOT}/control1/control1.vbox" "${FAKE_VBOX_ROOT}/control1/disk.vdi"' \
' ;;' \
' *) : ;;' \
'esac' > "$fake_bin/VBoxManage"
chmod 700 "$fake_bin/VBoxManage"
output="$test_root/output.txt"
if PATH="$fake_bin:$PATH" \
HOME="$test_root/home" \
K3S_CI_MOLECULE_ROOT="$molecule_root" \
K3S_CI_VIRTUALBOX_ROOT="$virtualbox_root" \
K3S_CI_HOSTONLY_MARKER="$test_root/hostonly-baseline" \
FAKE_VM_MODE=fault \
FAKE_VBOX_ROOT="$virtualbox_root" \
FAKE_LOG="$test_root/vbox.log" \
bash "$repo_root/.github/scripts/cleanup-runner-resources.sh" --apply > "$output" 2>&1; then
printf '%s\n' 'cleanup unexpectedly accepted a VirtualBox inspection failure' >&2
exit 1
fi
grep -Fq 'cleanup refused: unable to inspect VirtualBox VM' "$output"
[[ -f "$molecule_root/repo/single_node/.vagrant/machines/control1/virtualbox/id" ]]
printf '%s\n' 'vboxnet0|192.168.30.1' > "$test_root/hostonly-baseline"
if PATH="$fake_bin:$PATH" \
HOME="$test_root/home" \
K3S_CI_MOLECULE_ROOT="$molecule_root" \
K3S_CI_VIRTUALBOX_ROOT="$virtualbox_root" \
K3S_CI_HOSTONLY_MARKER="$test_root/hostonly-baseline" \
FAKE_HOSTONLY_FAIL=true \
FAKE_VBOX_ROOT="$virtualbox_root" \
FAKE_LOG="$test_root/vbox.log" \
bash "$repo_root/.github/scripts/cleanup-runner-resources.sh" --dry-run > "$output" 2>&1; then
printf '%s\n' 'cleanup unexpectedly accepted a host-only inventory failure' >&2
exit 1
fi
grep -Fq 'cleanup refused: unable to inventory VirtualBox host-only interfaces' "$output"
PATH="$fake_bin:$PATH" \
HOME="$test_root/home" \
K3S_CI_MOLECULE_ROOT="$molecule_root" \
K3S_CI_VIRTUALBOX_ROOT="$virtualbox_root" \
K3S_CI_HOSTONLY_MARKER="$test_root/hostonly-baseline" \
FAKE_VBOX_ROOT="$virtualbox_root" \
FAKE_LOG="$test_root/vbox.log" \
bash "$repo_root/.github/scripts/cleanup-runner-resources.sh" --dry-run > "$output"
grep -Fq 'Would remove VM control1 (11111111-1111-1111-1111-111111111111)' "$output"
[[ ! -e "$test_root/vbox.log" ]]
PATH="$fake_bin:$PATH" \
HOME="$test_root/home" \
K3S_CI_MOLECULE_ROOT="$molecule_root" \
K3S_CI_VIRTUALBOX_ROOT="$virtualbox_root" \
K3S_CI_HOSTONLY_MARKER="$test_root/hostonly-baseline" \
FAKE_VBOX_ROOT="$virtualbox_root" \
FAKE_LOG="$test_root/vbox.log" \
bash "$repo_root/.github/scripts/cleanup-runner-resources.sh" --apply > "$output"
grep -Fq 'controlvm 11111111-1111-1111-1111-111111111111 poweroff' "$test_root/vbox.log"
grep -Fq 'unregistervm unregistervm 11111111-1111-1111-1111-111111111111 --delete' "$test_root/vbox.log"
[[ ! -e "$virtualbox_root/control1/control1.vbox" ]]
[[ -e "$virtualbox_root/unmarked/unmarked.vbox" ]]
PATH="$fake_bin:$PATH" \
HOME="$test_root/home" \
K3S_CI_MOLECULE_ROOT="$molecule_root" \
K3S_CI_VIRTUALBOX_ROOT="$virtualbox_root" \
K3S_CI_HOSTONLY_MARKER="$test_root/hostonly-baseline" \
FAKE_VM_MODE=missing \
FAKE_VBOX_ROOT="$virtualbox_root" \
FAKE_LOG="$test_root/vbox.log" \
bash "$repo_root/.github/scripts/cleanup-runner-resources.sh" --apply > "$output"
grep -Fq 'Stale Vagrant state without a registered VM' "$output"
[[ ! -d "$molecule_root/repo/single_node/.vagrant" ]]
printf 'cleanup-runner-resources fixture test passed\n'
+20 -5
View File
@@ -5,15 +5,30 @@ on:
jobs: jobs:
molecule: molecule:
name: cache name: cache
runs-on: self-hosted runs-on: [self-hosted, linux, x64, k3s-ci, virtualbox, nested-virt]
env: env:
PYTHON_VERSION: "3.11" PYTHON_VERSION: "3.11"
VAGRANT_DEFAULT_PROVIDER: virtualbox
VAGRANT_HOME: ${{ github.workspace }}/.vagrant-home
steps: steps:
- name: Check out the codebase - name: Check out the codebase
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Check nested VirtualBox platform
run: |
set -Eeuo pipefail
grep -Eq 'vmx|svm' /proc/cpuinfo
test -c /dev/kvm
test -c /dev/vboxdrv
VBoxManage --version
vagrant --version
test -r /etc/vbox/networks.conf
test "$(stat -c '%u' /etc/vbox/networks.conf)" -eq 0
free -h
df -Pk "${RUNNER_TEMP}"
- name: Set up Python ${{ env.PYTHON_VERSION }} - name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # 5.3.0 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # 5.3.0
@@ -27,10 +42,10 @@ jobs:
with: with:
lookup-only: true # if it exists, we don't need to restore and can skip the next step lookup-only: true # if it exists, we don't need to restore and can skip the next step
path: | path: |
~/.vagrant.d/boxes .vagrant-home/boxes
key: vagrant-boxes-${{ hashFiles('**/molecule.yml') }} key: vagrant-boxes-${{ runner.os }}-${{ runner.arch }}-virtualbox-7.2-vagrant-2.4-${{ hashFiles('**/molecule.yml') }} # yamllint disable-line rule:line-length
restore-keys: | restore-keys: |
vagrant-boxes vagrant-boxes-${{ runner.os }}-${{ runner.arch }}-virtualbox-7.2-vagrant-2.4-
- name: Download Vagrant boxes for all scenarios - name: Download Vagrant boxes for all scenarios
# To save some cache space, all scenarios share the same cache key. # To save some cache space, all scenarios share the same cache key.
+12 -1
View File
@@ -5,6 +5,8 @@ on:
types: types:
- opened - opened
- synchronize - synchronize
- reopened
- ready_for_review
paths-ignore: paths-ignore:
- '**/.gitignore' - '**/.gitignore'
- '**/FUNDING.yml' - '**/FUNDING.yml'
@@ -16,12 +18,21 @@ on:
- '**/LICENSE' - '**/LICENSE'
- '**/reboot.sh' - '**/reboot.sh'
- '**/reset.sh' - '**/reset.sh'
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ci-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs: jobs:
pre: pre:
uses: ./.github/workflows/cache.yml uses: ./.github/workflows/cache.yml
needs: [lint]
lint: lint:
uses: ./.github/workflows/lint.yml uses: ./.github/workflows/lint.yml
needs: [pre]
test: test:
uses: ./.github/workflows/test.yml uses: ./.github/workflows/test.yml
needs: [pre, lint] needs: [pre, lint]
+4 -4
View File
@@ -5,15 +5,15 @@ on:
jobs: jobs:
pre-commit-ci: pre-commit-ci:
name: Pre-Commit name: Pre-Commit
runs-on: self-hosted runs-on: ubuntu-latest
env: env:
PYTHON_VERSION: "3.11" PYTHON_VERSION: "3.12"
steps: steps:
- name: Check out the codebase - name: Check out the codebase
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Set up Python ${{ env.PYTHON_VERSION }} - name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # 5.3.0 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # 5.3.0
@@ -42,7 +42,7 @@ jobs:
ensure-pinned-actions: ensure-pinned-actions:
name: Ensure SHA Pinned Actions name: Ensure SHA Pinned Actions
runs-on: self-hosted runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2
+32 -59
View File
@@ -5,7 +5,7 @@ on:
jobs: jobs:
molecule: molecule:
name: Molecule name: Molecule
runs-on: self-hosted runs-on: [self-hosted, linux, x64, k3s-ci, virtualbox, nested-virt]
strategy: strategy:
matrix: matrix:
scenario: scenario:
@@ -16,47 +16,36 @@ jobs:
- cilium - cilium
- kube-vip - kube-vip
fail-fast: false fail-fast: false
max-parallel: 1
env: env:
PYTHON_VERSION: "3.11" PYTHON_VERSION: "3.11"
VAGRANT_DEFAULT_PROVIDER: virtualbox
VAGRANT_HOME: ${{ github.workspace }}/.vagrant-home
steps: steps:
- name: Check out the codebase - name: Check out the codebase
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha || github.sha }}
# these steps are necessary if not using ephemeral nodes - name: Clean repository-owned resources before testing
- name: Delete old Vagrant box versions run: ./.github/scripts/cleanup-runner-resources.sh --apply
if: always() # do this even if a step before has failed
run: vagrant box prune --force
- name: Remove all local Vagrant boxes - name: Record host-only network baseline
if: always() # do this even if a step before has failed run: ./.github/scripts/cleanup-runner-resources.sh --snapshot
run: if vagrant box list 2>/dev/null; then vagrant box list | cut -f 1 -d ' ' | xargs -L 1 vagrant box remove -f 2>/dev/null && echo "All Vagrant boxes removed." || echo "No Vagrant boxes found."; else echo "No Vagrant boxes found."; fi
- name: Remove all Virtualbox VMs - name: Check nested VirtualBox platform
if: always() # do this even if a step before has failed run: |
run: VBoxManage list vms | awk -F'"' '{print $2}' | xargs -I {} VBoxManage unregistervm --delete "{}" set -Eeuo pipefail
grep -Eq 'vmx|svm' /proc/cpuinfo
- name: Remove all Virtualbox HDs test -c /dev/kvm
if: always() # do this even if a step before has failed test -c /dev/vboxdrv
run: VBoxManage list hdds | awk -F':' '/^UUID:/ {print $2}' | xargs -I {} VBoxManage closemedium disk "{}" --delete VBoxManage --version
vagrant --version
- name: Remove all Virtualbox Networks test -r /etc/vbox/networks.conf
if: always() # do this even if a step before has failed test "$(stat -c '%u' /etc/vbox/networks.conf)" -eq 0
run: VBoxManage list hostonlyifs | grep '^Name:' | awk '{print $2}' | grep '^vboxnet' | xargs -I {} VBoxManage hostonlyif remove {} free -h
df -Pk "${RUNNER_TEMP}"
- name: Remove Virtualbox network config
if: always() # do this even if a step before has failed
run: sudo rm /etc/vbox/networks.conf || true
- name: Configure VirtualBox
run: |-
sudo mkdir -p /etc/vbox
cat <<EOF | sudo tee -a /etc/vbox/networks.conf > /dev/null
* 192.168.30.0/24
* fdad:bad:ba55::/64
EOF
- name: Set up Python ${{ env.PYTHON_VERSION }} - name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # 5.3.0 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # 5.3.0
@@ -67,8 +56,8 @@ jobs:
- name: Restore vagrant Boxes cache - name: Restore vagrant Boxes cache
uses: actions/cache/restore@6849a6489940f00c2f30c0fb92c6274307ccb58a # 4.1.2 uses: actions/cache/restore@6849a6489940f00c2f30c0fb92c6274307ccb58a # 4.1.2
with: with:
path: ~/.vagrant.d/boxes path: .vagrant-home/boxes
key: vagrant-boxes-${{ hashFiles('**/molecule.yml') }} key: vagrant-boxes-${{ runner.os }}-${{ runner.arch }}-virtualbox-7.2-vagrant-2.4-${{ hashFiles('**/molecule.yml') }} # yamllint disable-line rule:line-length
fail-on-cache-miss: true fail-on-cache-miss: true
- name: Install dependencies - name: Install dependencies
@@ -91,36 +80,20 @@ jobs:
PY_COLORS: 1 PY_COLORS: 1
ANSIBLE_FORCE_COLOR: 1 ANSIBLE_FORCE_COLOR: 1
# these steps are necessary if not using ephemeral nodes - name: Collect runner diagnostics
- name: Delete old Vagrant box versions if: always()
if: always() # do this even if a step before has failed run: ./.github/scripts/collect-runner-diagnostics.sh "${RUNNER_TEMP}/logs/runner"
run: vagrant box prune --force
- name: Remove all local Vagrant boxes - name: Clean repository-owned resources after testing
if: always() # do this even if a step before has failed if: always()
run: if vagrant box list 2>/dev/null; then vagrant box list | cut -f 1 -d ' ' | xargs -L 1 vagrant box remove -f 2>/dev/null && echo "All Vagrant boxes removed." || echo "No Vagrant boxes found."; else echo "No Vagrant boxes found."; fi run: ./.github/scripts/cleanup-runner-resources.sh --apply
- name: Remove all Virtualbox VMs
if: always() # do this even if a step before has failed
run: VBoxManage list vms | awk -F'"' '{print $2}' | xargs -I {} VBoxManage unregistervm --delete "{}"
- name: Remove all Virtualbox HDs
if: always() # do this even if a step before has failed
run: VBoxManage list hdds | awk -F':' '/^UUID:/ {print $2}' | xargs -I {} VBoxManage closemedium disk "{}" --delete
- name: Remove all Virtualbox Networks
if: always() # do this even if a step before has failed
run: VBoxManage list hostonlyifs | grep '^Name:' | awk '{print $2}' | grep '^vboxnet' | xargs -I {} VBoxManage hostonlyif remove {}
- name: Remove Virtualbox network config
if: always() # do this even if a step before has failed
run: sudo rm /etc/vbox/networks.conf || true
- name: Upload log files - name: Upload log files
if: always() # do this even if a step before has failed if: always() # do this even if a step before has failed
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # 4.4.3 uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # 4.4.3
with: with:
name: logs name: logs-${{ matrix.scenario }}-${{ github.run_id }}-${{ github.run_attempt }}
path: | path: |
${{ runner.temp }}/logs ${{ runner.temp }}/logs
overwrite: true if-no-files-found: warn
retention-days: 14
+2
View File
@@ -1,4 +1,6 @@
.env/ .env/
*.log *.log
ansible.cfg ansible.cfg
.ansible/
kubeconfig kubeconfig
zIgnore/
+10
View File
@@ -20,6 +20,8 @@ repos:
rev: v6.22.2 rev: v6.22.2
hooks: hooks:
- id: ansible-lint - id: ansible-lint
additional_dependencies: [ansible-core==2.18.0]
language_version: python3.12
- repo: https://github.com/shellcheck-py/shellcheck-py - repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.9.0.6 rev: v0.9.0.6
hooks: hooks:
@@ -33,3 +35,11 @@ repos:
rev: 0.6.4 rev: 0.6.4
hooks: hooks:
- id: fix-smartquotes - id: fix-smartquotes
- repo: local
hooks:
- id: cleanup-runner-resources-test
name: cleanup runner resources test
entry: .github/scripts/test-cleanup-runner-resources.sh
language: system
pass_filenames: false
files: ^\.github/scripts/(cleanup-runner-resources|test-cleanup-runner-resources)\.sh$