From 5ae2ef3b98a4b8bed85e0c4a03581f459284cfe9 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 19 Jul 2026 14:21:11 +0100 Subject: [PATCH] fix: contain Dependabot PR fan-out --- .github/dependabot.yml | 78 +++++++++--------------------- scripts/fix-dependabot-coverage.sh | 66 ++++++++++++++++--------- scripts/fix-dependabot.sh | 13 ++++- 3 files changed, 78 insertions(+), 79 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 185414ad..690b8821 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,58 +10,26 @@ updates: patterns: - "*" - # Rust dependencies - - package-ecosystem: "cargo" - directory: "/robot-repo-automaton" - schedule: - interval: "weekly" - - - package-ecosystem: "cargo" - directory: "/shared-context" - schedule: - interval: "weekly" - - - package-ecosystem: "cargo" - directory: "/bots/echidnabot" - schedule: - interval: "weekly" - - - package-ecosystem: "cargo" - directory: "/bots/glambot" - schedule: - interval: "weekly" - - - package-ecosystem: "cargo" - directory: "/bots/rhodibot" - schedule: - interval: "weekly" - - - package-ecosystem: "cargo" - directory: "/bots/seambot" - schedule: - interval: "weekly" - - - package-ecosystem: "cargo" - directory: "/bots/sustainabot" - schedule: - interval: "weekly" - - - package-ecosystem: "cargo" - directory: "/bots/finishingbot" - schedule: - interval: "weekly" - - - package-ecosystem: "cargo" - directory: "/bots/accessibilitybot" - schedule: - interval: "weekly" - - - package-ecosystem: "cargo" - directory: "/bots/cipherbot" - schedule: - interval: "weekly" - - - package-ecosystem: "cargo" - directory: "/bots/panicbot" - schedule: - interval: "weekly" + # Rust dependencies. Keep every Cargo project in one update entry so the + # open-PR limit applies to the fleet as a whole, rather than once per bot. + # Grouping by dependency name updates a shared crate across every affected + # project in one PR instead of opening one PR per Cargo.lock. + - package-ecosystem: "cargo" + directories: + - "/robot-repo-automaton" + - "/shared-context" + - "/bots/echidnabot" + - "/bots/glambot" + - "/bots/rhodibot" + - "/bots/seambot" + - "/bots/sustainabot" + - "/bots/finishingbot" + - "/bots/accessibilitybot" + - "/bots/cipherbot" + - "/bots/panicbot" + schedule: + interval: "weekly" + open-pull-requests-limit: 3 + groups: + fleet-dependencies: + group-by: dependency-name diff --git a/scripts/fix-dependabot-coverage.sh b/scripts/fix-dependabot-coverage.sh index 6eebd7eb..efb64060 100755 --- a/scripts/fix-dependabot-coverage.sh +++ b/scripts/fix-dependabot-coverage.sh @@ -51,48 +51,68 @@ if [[ ! -f "${DEPENDABOT_FILE}" ]]; then exit 1 fi +if ! command -v yq >/dev/null 2>&1; then + echo "ERROR: yq v4 is required to update Dependabot coverage safely." >&2 + exit 1 +fi + # --- Functions --- # Check whether a given ecosystem+directory pair already exists in dependabot.yml. -# Uses a simple text-based check: looks for the ecosystem line followed by -# the directory line within a few lines of each other. entry_exists() { local ecosystem="$1" local directory="$2" - # Normalise directory for matching: dependabot uses "/" for root, - # "/subdir" for subdirectories. - local dir_pattern - if [[ "${directory}" == "/" ]]; then - dir_pattern='directory: "/"' - else - dir_pattern="directory: \"${directory}\"" - fi - - # Search for the ecosystem+directory pair within the file. - # We look for both on adjacent lines (within 5 lines of each other). - if awk -v eco="\"${ecosystem}\"" -v dir="${dir_pattern}" ' - /package-ecosystem:/ && $0 ~ eco { found_eco=NR } - found_eco && NR <= found_eco+5 && $0 ~ dir { exit 0 } - END { exit 1 } - ' "${DEPENDABOT_FILE}"; then - return 0 - else - return 1 - fi + ECOSYSTEM="${ecosystem}" DIRECTORY="${directory}" yq -e ' + .updates[] + | select(."package-ecosystem" == strenv(ECOSYSTEM)) + | select( + .directory == strenv(DIRECTORY) or + (.directories[]? == strenv(DIRECTORY)) + ) + ' "${DEPENDABOT_FILE}" >/dev/null 2>&1 } # Append a new ecosystem+directory entry to dependabot.yml. append_entry() { local ecosystem="$1" local directory="$2" + local entry_count + + entry_count="$(ECOSYSTEM="${ecosystem}" yq ' + [.updates[] | select(."package-ecosystem" == strenv(ECOSYSTEM))] | length + ' "${DEPENDABOT_FILE}")" + + if [[ "${entry_count}" -gt 1 ]]; then + echo "ERROR: ${ecosystem} already has ${entry_count} update blocks." >&2 + echo "Consolidate them into one directories: block before adding coverage." >&2 + return 1 + fi + + if [[ "${entry_count}" -eq 1 ]]; then + ECOSYSTEM="${ecosystem}" DIRECTORY="${directory}" yq -i ' + (.updates[] | select(."package-ecosystem" == strenv(ECOSYSTEM))) |= ( + .directories = (((.directories // [.directory]) + [strenv(DIRECTORY)]) | unique) + | del(.directory) + | ."open-pull-requests-limit" = + ([(."open-pull-requests-limit" // 3), 3] | min) + | .groups."coverage-shared"."group-by" = "dependency-name" + ) + ' "${DEPENDABOT_FILE}" + echo " CONSOLIDATED: ${ecosystem} @ ${directory}" + return 0 + fi cat >> "${DEPENDABOT_FILE}" < "${REPO_PATH}/.github/dependabot.yml"