Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/workflows/enforce-repo-settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,58 @@ jobs:
|| echo "::warning::Failed to seed triage-bot.yml on $repo (ruleset or PAT scope)"
done < targets.txt

# Ensure every fleet repo that carries a Renovate config is in the
# Renovate App's installation scope. Workflow files can be file-synced
# (above), but App installation scope cannot — it's an API grant, not
# a file. Without this step new repos carry a Renovate config yet
# remain invisible to Renovate (silent gap on
# ANcpLua.OpenTelemetry.SemanticConventions.Analyzers tracked
# 2026-05-25 — repo carried a valid renovate.json for weeks but
# produced no PRs and no Dependency Dashboard issue).
#
# Renovate accepts its config at four common paths; we check all
# before skipping a repo. The .renovaterc* dotfiles and
# package.json#renovate key are intentionally out of scope — both
# are rare in this fleet and the latter would need content parsing,
# not just path existence.
#
# Installation id 79212889 is @ANcpLua's personal Renovate install
# (https://github.com/settings/installations/79212889). The PUT
# endpoint is idempotent — 204 whether newly added or already
# present — so we don't pre-check membership. Listing installations
# requires an App user-to-server token the PAT path can't issue,
# hence the hardcoded id; revisit if Renovate is ever reinstalled.
- name: Ensure fleet repos with a Renovate config are in Renovate App scope
env:
GH_TOKEN: ${{ secrets.REPO_SETTINGS_PAT_USER }}
RENOVATE_INSTALLATION_ID: "79212889"
run: |
set -uo pipefail
while read -r repo; do
[ -z "$repo" ] && continue
has_renovate_config=false
for cfg in renovate.json renovate.json5 .github/renovate.json .github/renovate.json5; do
if gh api "repos/$repo/contents/$cfg" --silent 2>/dev/null; then
has_renovate_config=true
break
fi
done
if [ "$has_renovate_config" = false ]; then
continue
Comment on lines +220 to +227
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/enforce-repo-settings.yml"
echo "== exists =="
ls -l "$FILE" || true
echo
echo "== context around lines 200-260 =="
nl -ba "$FILE" | sed -n '180,260p'
echo
echo "== search for set -u/o pipefail and has_renovate_config usage =="
rg -n "set -[^\n]*pipefail|has_renovate_config|RENOVATE_INSTALLATION_ID|PUT /user/installations" "$FILE"

Repository: ANcpLua/github-settings-automation

Length of output: 282


🌐 Web query:

gh cli gh api -i include response headers output format first line

💡 Result:

When you run gh api -i / --include, the first line of output is the HTTP status line in the form HTTP/<major>.<minor> <status-code> <reason-phrase> (the code prints resp.Proto and resp.Status as the first line, followed by headers). [1] Example shape: - First line: HTTP/1.1 200 OK - Then response headers (and a blank line after headers before the body, if any). [1] Notes: - -i/--include is documented as “Include HTTP response status line and headers in the output.” [2]

Citations:


🌐 Web query:

``gh api exit code 404 nonzero behavior

💡 Result:

When you run gh api and the GitHub API returns HTTP 404, gh treats it as an error and exits with a non-zero status code (exit code 1 in the cited behavior). This means you should not expect gh api to “succeed” on not-found responses; you should handle 404 explicitly (e.g., by checking the exit status or by using flags/logic that tolerate errors). Evidence: - The gh issue discussion notes: “using gh api to read non-existing resources will cause the command to exit with a status code of 1” and attributes this to the HTTP 404 response status returned by the API [1]. - The gh api command is documented as making an authenticated HTTP request and printing the response; when the API responds with an error like 404, the command surfaces that as an error (“gh: Not Found (HTTP 404)”) in examples [2][3]. Related notes (why you might see 404s even when something “should” exist): - Missing OAuth token scopes can sometimes produce confusing 404s (e.g., missing workflow scope when creating releases) [4]. If you tell me the exact gh api command you’re running (including flags like --silent, --method, and whether you’re using pipelines), I can suggest a reliable way to detect/ignore 404 in your script.

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/enforce-repo-settings.yml"
echo "== exists =="
ls -l "$FILE" || true
echo
echo "== context around lines 200-260 =="
nl -ba "$FILE" | sed -n '180,260p'
echo
echo "== search for set -u/o pipefail and has_renovate_config usage =="
rg -n "set -[^\n]*pipefail|has_renovate_config|RENOVATE_INSTALLATION_ID|PUT /user/installations" "$FILE"

Repository: ANcpLua/github-settings-automation

Length of output: 282


🌐 Web query:

gh cli gh api -i include response headers output format first line

💡 Result:

When you run gh api -i / gh api --include, the output starts with the HTTP status line (the “response status line”), i.e. the first line is HTTP/<version> <status code> <reason phrase> (e.g., HTTP/2 200 OK). This happens because the --include flag prints resp.Proto (protocol) and resp.Status (status line contents) as the first header line before printing the rest of the response headers. [1] After that first line, gh api -i prints the individual response headers, then a blank line (\r\n). [1]

Citations:


🌐 Web query:

``gh api exit code 404 nonzero behavior

💡 Result:

When you run gh api and the GitHub REST API returns HTTP 404 (Not Found), gh api exits non-zero (typically exit code 1). This matches GitHub’s expectation that 404 indicates an error condition for the requested resource/permission, and GitHub CLI treats non-2xx responses as failures. Evidence: - GitHub’s REST API troubleshooting doc notes that a 404 may be returned when a resource is private or authentication is missing/incorrect, and instructs you to check authentication/URL when you see 404. [1] - gh CLI issue reports show gh api surfacing a 404 as an error (example: HTTP 404: Not Found ...). [2] - A gh CLI issue clarifies that “using gh api to read non-existing resources will cause the command to exit with a status code of 1” (even with -X HEAD). [3] Practical implications for scripting: - Don’t rely on output parsing from a 404; handle the exit code. - If you need different behavior on “not found,” capture the exit status and treat it as a special case. Example: - if ! gh api repos/OWNER/REPO/...; then ... # handle 404/not-found ... fi If you want, paste the exact gh api ... command you’re running and how you’re checking the exit code/output, and I can suggest the cleanest conditional for your shell.

Citations:


Differentiate 404 from other gh api failures in the Renovate config probe, and stop swallowing enrollment errors

The config probe currently treats any non-zero gh api repos/$repo/contents/$cfg result as “no config” (stderr is suppressed), so 401/403/429/5xx can silently skip enrollment. Enrollment is also effectively unobservable: the PUT /user/installations/$RENOVATE_INSTALLATION_ID/repositories/$repo_id call is fully swallowed (--silent ... >/dev/null 2>&1 || true), and the existing /repos/$repo/installation call is ignored as well—so a stale/unauthorized RENOVATE_INSTALLATION_ID can result in zero enrollments with no signal. Handle only 404 as “absent”, warn/fail on other statuses, and log/report PUT failures.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/enforce-repo-settings.yml around lines 220 - 227, The
probe currently suppresses all gh api failures and treats any non-OK result as
“no config”; change the probe so gh api "repos/$repo/contents/$cfg" is invoked
in a way that captures the HTTP status (e.g., include response headers or status
output) and only treat 404 as “absent” (set has_renovate_config=false); for any
other non-200/404 status log a warning/error with repository and status and
stop/raise so enrollment isn’t silently skipped. Likewise, stop swallowing the
PUT enrollment call to
/user/installations/$RENOVATE_INSTALLATION_ID/repositories/$repo_id (remove
>/dev/null 2>&1 || true and --silent) and surface its exit code and response
body; if the PUT fails log the repo, installation id, status and response and
fail or return a non-zero exit to surface bad RENOVATE_INSTALLATION_ID or auth
errors. Ensure the probe also checks and logs the result of
/repos/$repo/installation rather than ignoring it.

fi
repo_id="$(gh api "repos/$repo" --jq .id 2>/dev/null || true)"
if [ -z "$repo_id" ] || [ "$repo_id" = "null" ]; then
echo "::warning::Cannot resolve numeric id for $repo"
continue
fi
if gh api --method PUT --silent \
"/user/installations/$RENOVATE_INSTALLATION_ID/repositories/$repo_id" 2>/dev/null; then
echo "Ensured Renovate scope for $repo (id $repo_id)"
else
echo "::warning::Failed to add $repo (id $repo_id) to Renovate scope"
fi
done < targets.txt

enforce-org:
runs-on: ubuntu-latest
steps:
Expand Down
Loading