diff --git a/.github/workflows/generate-runners-status.yml b/.github/workflows/generate-runners-status.yml new file mode 100644 index 000000000..0c57255bd --- /dev/null +++ b/.github/workflows/generate-runners-status.yml @@ -0,0 +1,138 @@ +name: "Generate runners status" + +on: + push: + schedule: + - cron: '0 * * * *' # Run every hour + workflow_dispatch: # Manually triggered via GitHub Actions UI + +#concurrency: +# group: redirector +# cancel-in-progress: false + +jobs: + + Check: + + name: "Check permissions" + runs-on: "ubuntu-22.04" + steps: + + - name: "Check permissions" + uses: armbian/actions/team-check@main + with: + ORG_MEMBERS: ${{ secrets.ORG_MEMBERS }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TEAM: "Release manager" + + build: + name: "Get self hosted runners status" + runs-on: ubuntu-24.04 + needs: Check + steps: + + - name: "Install dependencies: jq" + uses: awalsh128/cache-apt-pkgs-action@latest + with: + packages: jq + version: 1.0 + + - name: "Get runners from ORG" + env: + GH_TOKEN: ${{ secrets.RUNNERS }} + run: | + + GH_TOKEN=${{ secrets.RUNNERS }} + NETBOX_TOKEN=${{ secrets.NETBOX_TOKEN }} + NETBOX_API=${{ secrets.NETBOX_API }} + + tmp="$(mktemp -d)" + trap 'rm -rf "$tmp"' EXIT + + runners_nd="$tmp/runners.ndjson" + out_html="$tmp/runners_summary.html" + : > "$runners_nd" + + # Fetch ALL GitHub org runners (prefer gh; fallback to curl) + if command -v gh >/dev/null 2>&1; then + gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + --paginate /orgs/armbian/actions/runners \ + -q '.runners[]' > "$runners_nd" + else + curl -fsSL \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${GH_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/orgs/armbian/actions/runners?per_page=100" \ + | jq -c '.runners[]' > "$runners_nd" + fi + + # Build lookup maps + declare -A RUNNER_STATUS RUNNER_BUSY + while IFS=$'\t' read -r name status busy; do + RUNNER_STATUS["$name"]="$status" + RUNNER_BUSY["$name"]="$busy" + done < <(jq -r '[.name, .status, (.busy|tostring)] | @tsv' "$runners_nd") + + # Fetch NetBox VMs + nb_json="$tmp/netbox.json" + + curl -s \ + -H "Authorization: Token ${NETBOX_TOKEN}" \ + -H "Accept: application/json; indent=4" \ + "${NETBOX_API}/virtualization/virtual-machines/?limit=500&name__empty=false&tag=github-runner&status=active" \ + > "$nb_json" + + # Render to stdout and to HTML file + echo "" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # init totals + total_cpu=0 + total_mem_gb=0 + total_storage_gb=0 + total_runners=0 + + while IFS=$'\t' read -r NAME CPU MEM_MB DISK_GB RUNNERS LABELS ID; do + CALC_MEM=$(( (MEM_MB + 512) / 1024 )) + printf "\n" \ + "$NAME" "$LABELS" "$CPU" "$CALC_MEM" "$DISK_GB" "$RUNNERS" >> $GITHUB_STEP_SUMMARY + + echo "" >> $GITHUB_STEP_SUMMARY + + # accumulate totals (note: no $ needed for CPU/RUNNERS inside arithmetic) + total_cpu=$(( total_cpu + CPU )) + total_mem_gb=$(( total_mem_gb + CALC_MEM )) + total_storage_gb=$(( total_storage_gb + DISK_GB )) + total_runners=$(( total_runners + RUNNERS )) + done < <(jq -r ' + .results[] | + [ + .name, + ((.vcpus // 0) | floor), + ((.memory // 0) | floor), + ((.disk // 0) | floor), + (.custom_fields["runners"] // 0), + (.custom_fields["labels"] // "null"), + .id + ] | @tsv + ' "$nb_json") + + # summary row + printf "\n" \ + "$total_cpu" "$total_mem_gb" "$total_storage_gb" "$total_runners" >> $GITHUB_STEP_SUMMARY + + echo "
ServerRunner labelCPU coresMemory GBStorage GBRunners
%s%s%d%d%d%d
" >> $GITHUB_STEP_SUMMARY + if [[ "$RUNNERS" -gt 0 ]]; then + for i in $(seq -f "%02g" 1 "$RUNNERS"); do + rn="${LABELS}-${i}" + if [[ -n "${RUNNER_STATUS[$rn]:-}" || "$LABELS" == "github" ]]; then + printf "🟢" >> $GITHUB_STEP_SUMMARY + else + printf "🔴 (%s) " "$i" >> $GITHUB_STEP_SUMMARY + fi + done + fi + echo "
Totals:%d%d%d%d
" >> $GITHUB_STEP_SUMMARY diff --git a/README.md b/README.md index 7e4780215..4fc3043f5 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,11 @@ It also produces [data exchange files](https://github.armbian.com/) used for aut GitHub Workflow Status Automatically invites external contributors to join the [Armbian GitHub organization](https://github.com/orgs/armbian/people). +- **Generate Self Hosted Runners Status page** + GitHub Workflow Status + Generates a table of Self Hosted runners with CPU, memory, storage, runner status, and totals. + + ### Documentation - **Generate Documentation**