Commit 51376380627 for nodejs

commit 51376380627ef1ec1db20fb53a0547e2a23995f0
Author: Filip Skokan <panva.ip@gmail.com>
Date:   Sun Sep 27 14:34:10 2026 +0200

    tools: check CI availability and workload

    Select mergeable PRs and check Jenkins availability and workload before
    removing request labels. Leave requests for a later run when Jenkins is
    unavailable or the workload has reached the configured limit.

    Make the batch size and workload limit repository variables, defaulting
    to 5 and 10 respectively.

    Refs: https://github.com/nodejs/node-core-utils/pull/1204
    Signed-off-by: Filip Skokan <panva.ip@gmail.com>
    Assisted-by: Codex
    PR-URL: https://github.com/nodejs/node/pull/66280
    Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
    Reviewed-By: Matteo Collina <matteo.collina@gmail.com>

diff --git a/.github/workflows/auto-start-ci.yml b/.github/workflows/auto-start-ci.yml
index c8b090fdc04..85f3e92f2ff 100644
--- a/.github/workflows/auto-start-ci.yml
+++ b/.github/workflows/auto-start-ci.yml
@@ -1,6 +1,9 @@
 # This action uses the following secrets:
 #   JENKINS_USER: GitHub user whose Jenkins token is defined below
 #   JENKINS_TOKEN: Jenkins token, to be used to start or resume CI
+# Optional repository variables:
+#   AUTO_START_CI_BATCH_SIZE: maximum PRs to process per run (default: 5)
+#   AUTO_START_CI_MAX_WORKLOAD: pause at this many running or queued PR jobs (default: 15)
 name: Auto Start CI

 on:
@@ -30,16 +33,25 @@ jobs:
     steps:
       - name: Get Pull Requests
         id: get_prs_for_ci
+        # Explicit bash enables pipefail so jq cannot hide a failed gh query.
+        shell: bash
         run: |
+          if ! [[ "$BATCH_SIZE" =~ ^[1-9][0-9]*$ ]]; then
+            echo '::error::AUTO_START_CI_BATCH_SIZE must be a strictly positive integer'
+            exit 1
+          fi
+          # Filter before selecting the batch; UNKNOWN mergeability is retried later.
           numbers=$(gh pr list \
                   --repo "$GITHUB_REPOSITORY" \
-                  --json 'number' \
+                  --json 'number,mergeable' \
                   --search 'review:approved label:request-ci,resume-ci' \
-                  -t '{{ range . }}{{ .number }} {{ end }}' \
-                  --limit 5)
+                  --limit 100 \
+                  | jq --argjson limit "$BATCH_SIZE" \
+                    '[.[] | select(.mergeable == "MERGEABLE") | .number] | .[:$limit] | map(tostring) | join(" ")' -r)
           echo "numbers=$numbers" >> "$GITHUB_OUTPUT"
         env:
           GH_TOKEN: ${{ github.token }}
+          BATCH_SIZE: ${{ vars.AUTO_START_CI_BATCH_SIZE || '5' }}
   start-ci:
     permissions:
       checks: read
@@ -78,3 +90,4 @@ jobs:
         env:
           GH_TOKEN: ${{ github.token }}
           PULL_REQUESTS: ${{ needs.get-prs-for-ci.outputs.numbers }}
+          MAX_WORKLOAD: ${{ vars.AUTO_START_CI_MAX_WORKLOAD || '15' }}
diff --git a/tools/actions/start-ci.sh b/tools/actions/start-ci.sh
index 4573b17761c..6482f366fa3 100755
--- a/tools/actions/start-ci.sh
+++ b/tools/actions/start-ci.sh
@@ -3,6 +3,14 @@
 set -xe

 cqurl="${GITHUB_SERVER_URL:?}/${GITHUB_REPOSITORY:?}/actions/runs/${GITHUB_RUN_ID:?}"
+max_workload=${MAX_WORKLOAD:-15}
+case $max_workload in
+  *[!0-9]*)
+    echo '::error::AUTO_START_CI_MAX_WORKLOAD must be a positive integer'
+    exit 1
+    ;;
+  *) ;;
+esac

 escape_code_block_or_line() {
   case $1 in
@@ -19,6 +27,30 @@ escape_code_block_or_line() {
 }

 for pr in "$@"; do
+  # Sleep in between.
+  [ "$pr" = "$1" ] || sleep 20
+
+  # Keep request labels until Jenkins is ready to accept more work.
+  if ! ncu-ci available; then
+    echo '::notice::CI is unavailable; leaving CI requests for a later run.'
+    break
+  fi
+  if ! workload=$(ncu-ci workload); then
+    echo '::notice::CI workload could not be checked; leaving CI requests for a later run.'
+    break
+  fi
+  case $workload in
+    ''|*[!0-9]*)
+      echo '::error::ncu-ci workload did not return a positive integer'
+      exit 1
+      ;;
+    *) ;;
+  esac
+  if ! [ "$workload" -lt "$max_workload" ]; then
+    echo "::notice::CI workload is $workload (limit: $max_workload); leaving CI requests for a later run."
+    break
+  fi
+
   request_labels=$(gh -R "$GITHUB_REPOSITORY" pr view "$pr" --json labels \
     --jq '[.labels[].name | select(. == "request-ci" or . == "resume-ci")] | sort | join(",")')
   case "$request_labels" in