222 lines
5.4 KiB
Bash
Executable File
222 lines
5.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Read-only Gitea act-runner pool inventory.
|
|
# Run on 110, or from a workstation:
|
|
# ssh 192.168.0.110 'bash -s' < ops/runner/audit-runner-pool.sh
|
|
|
|
RUNNER_SERVICE_NAME="${RUNNER_SERVICE_NAME:-gitea-act-runner-host.service}"
|
|
RUNNER_CONFIG_PATH="${RUNNER_CONFIG_PATH:-/home/wooo/act-runner/config.yaml}"
|
|
DOCKER_RUNNER_NAME="${DOCKER_RUNNER_NAME:-gitea-runner}"
|
|
JOURNAL_SINCE="${JOURNAL_SINCE:-2 hours ago}"
|
|
TASK_LOG_LINES="${TASK_LOG_LINES:-80}"
|
|
|
|
section() {
|
|
printf '\n== %s ==\n' "$1"
|
|
}
|
|
|
|
command_exists() {
|
|
command -v "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
detect_systemd_scope() {
|
|
if systemctl --user show "$RUNNER_SERVICE_NAME" >/dev/null 2>&1; then
|
|
printf 'user'
|
|
return 0
|
|
fi
|
|
if systemctl show "$RUNNER_SERVICE_NAME" >/dev/null 2>&1; then
|
|
printf 'system'
|
|
return 0
|
|
fi
|
|
printf 'unknown'
|
|
}
|
|
|
|
print_service_status() {
|
|
local scope="$1"
|
|
|
|
section "runner service"
|
|
printf 'service=%s\n' "$RUNNER_SERVICE_NAME"
|
|
printf 'scope=%s\n' "$scope"
|
|
|
|
case "$scope" in
|
|
user)
|
|
systemctl --user show "$RUNNER_SERVICE_NAME" \
|
|
-p ActiveState -p SubState -p MainPID -p NRestarts \
|
|
-p ExecMainStartTimestamp --no-pager 2>/dev/null || true
|
|
;;
|
|
system)
|
|
systemctl show "$RUNNER_SERVICE_NAME" \
|
|
-p ActiveState -p SubState -p MainPID -p NRestarts \
|
|
-p ExecMainStartTimestamp --no-pager 2>/dev/null || true
|
|
;;
|
|
*)
|
|
printf 'status=unavailable\n'
|
|
;;
|
|
esac
|
|
}
|
|
|
|
extract_labels() {
|
|
local config_path="$1"
|
|
|
|
awk '
|
|
/^[[:space:]]*labels:[[:space:]]*$/ {
|
|
in_labels=1
|
|
next
|
|
}
|
|
in_labels && /^[[:space:]]*-[[:space:]]*/ {
|
|
line=$0
|
|
sub(/^[[:space:]]*-[[:space:]]*"/, "", line)
|
|
sub(/^[[:space:]]*-[[:space:]]*/, "", line)
|
|
sub(/"[[:space:]]*$/, "", line)
|
|
print line
|
|
next
|
|
}
|
|
in_labels && /^[^[:space:]]/ {
|
|
in_labels=0
|
|
}
|
|
' "$config_path"
|
|
}
|
|
|
|
print_config_inventory() {
|
|
section "runner config"
|
|
printf 'config_path=%s\n' "$RUNNER_CONFIG_PATH"
|
|
|
|
if [ ! -r "$RUNNER_CONFIG_PATH" ]; then
|
|
printf 'config_readable=false\n'
|
|
return 0
|
|
fi
|
|
|
|
awk '
|
|
/^runner:[[:space:]]*$/ {
|
|
in_runner=1
|
|
print
|
|
next
|
|
}
|
|
in_runner && /^[^[:space:]]/ && $0 !~ /^runner:[[:space:]]*$/ {
|
|
in_runner=0
|
|
}
|
|
in_runner && /^[[:space:]]*(capacity|timeout|shutdown_timeout):/ {
|
|
print
|
|
}
|
|
in_runner && /^[[:space:]]*labels:[[:space:]]*$/ {
|
|
print
|
|
}
|
|
in_runner && /^[[:space:]]*-[[:space:]]*/ {
|
|
print
|
|
}
|
|
' "$RUNNER_CONFIG_PATH"
|
|
|
|
section "runner label ownership"
|
|
local labels=()
|
|
while IFS= read -r label; do
|
|
[ -n "$label" ] && labels+=("$label")
|
|
done < <(extract_labels "$RUNNER_CONFIG_PATH")
|
|
|
|
if [ "${#labels[@]}" -eq 0 ]; then
|
|
printf 'labels_found=0\n'
|
|
return 0
|
|
fi
|
|
|
|
local foreign=()
|
|
local label_name owner
|
|
for label in "${labels[@]}"; do
|
|
label_name="${label%%:*}"
|
|
case "$label_name" in
|
|
ubuntu-latest|ubuntu-22.04|ubuntu-24.04|self-hosted|awoooi-*|awoooi)
|
|
owner="awoooi_or_shared_ci"
|
|
;;
|
|
*)
|
|
owner="foreign_or_cross_repo"
|
|
foreign+=("$label")
|
|
;;
|
|
esac
|
|
printf 'label=%s owner=%s\n' "$label" "$owner"
|
|
done
|
|
|
|
if [ "${#foreign[@]}" -gt 0 ]; then
|
|
printf 'foreign_labels=%s\n' "$(IFS=,; printf '%s' "${foreign[*]}")"
|
|
else
|
|
printf 'foreign_labels=none\n'
|
|
fi
|
|
}
|
|
|
|
print_docker_inventory() {
|
|
section "docker runner"
|
|
|
|
if ! command_exists docker; then
|
|
printf 'docker=unavailable\n'
|
|
return 0
|
|
fi
|
|
|
|
docker inspect "$DOCKER_RUNNER_NAME" \
|
|
--format 'name={{.Name}} Restart={{.HostConfig.RestartPolicy.Name}} Status={{.State.Status}} Running={{.State.Running}}' \
|
|
2>/dev/null || printf 'name=%s status=not_found\n' "$DOCKER_RUNNER_NAME"
|
|
|
|
section "active action containers"
|
|
local containers
|
|
containers="$(docker ps --format '{{.Names}}\t{{.Image}}\t{{.Status}}' 2>/dev/null | awk '$1 ~ /^GITEA-ACTIONS-TASK-/ { print }' || true)"
|
|
if [ -n "$containers" ]; then
|
|
printf '%s\n' "$containers"
|
|
else
|
|
printf 'active_action_containers=none\n'
|
|
fi
|
|
}
|
|
|
|
collect_journal() {
|
|
local scope="$1"
|
|
|
|
case "$scope" in
|
|
user)
|
|
journalctl --user -u "$RUNNER_SERVICE_NAME" --since "$JOURNAL_SINCE" --no-pager 2>/dev/null || true
|
|
;;
|
|
system)
|
|
journalctl -u "$RUNNER_SERVICE_NAME" --since "$JOURNAL_SINCE" --no-pager 2>/dev/null || true
|
|
;;
|
|
*)
|
|
true
|
|
;;
|
|
esac
|
|
}
|
|
|
|
print_recent_tasks() {
|
|
local scope="$1"
|
|
local journal_output
|
|
journal_output="$(collect_journal "$scope")"
|
|
|
|
section "recent runner task lines"
|
|
printf 'journal_since=%s\n' "$JOURNAL_SINCE"
|
|
if [ -z "$journal_output" ]; then
|
|
printf 'task_log=unavailable_or_empty\n'
|
|
return 0
|
|
fi
|
|
|
|
printf '%s\n' "$journal_output" | grep -E 'wooo/[A-Za-z0-9_.-]+' | tail -n "$TASK_LOG_LINES" || true
|
|
|
|
section "recent repo counts"
|
|
local counts
|
|
counts="$(printf '%s\n' "$journal_output" | grep -Eo 'wooo/[A-Za-z0-9_.-]+' | sort | uniq -c | sort -nr || true)"
|
|
if [ -n "$counts" ]; then
|
|
printf '%s\n' "$counts"
|
|
else
|
|
printf 'repo_counts=none\n'
|
|
fi
|
|
}
|
|
|
|
main() {
|
|
local scope
|
|
scope="$(detect_systemd_scope)"
|
|
|
|
section "audit metadata"
|
|
printf 'host=%s\n' "$(hostname 2>/dev/null || printf unknown)"
|
|
printf 'user=%s\n' "$(id -un 2>/dev/null || printf unknown)"
|
|
printf 'timestamp=%s\n' "$(date -Is 2>/dev/null || date)"
|
|
printf 'read_only=true\n'
|
|
|
|
print_service_status "$scope"
|
|
print_config_inventory
|
|
print_docker_inventory
|
|
print_recent_tasks "$scope"
|
|
}
|
|
|
|
main "$@"
|