ci: add playbook branch validation check#552
Conversation
Adds a CI workflow that checks local-antora-playbook.yml for non-standard branch references. Fails if any branch value doesn't match the allowed set (main, HEAD, v/*, shared, site-search, etc.). This prevents accidentally merging a playbook that still points to a PR branch instead of main, which would break the production build. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
✅ Deploy Preview for rp-cloud ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughA new GitHub Actions workflow ( Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/check-playbook.yml:
- Around line 25-41: The BRANCHES extraction currently only captures same-line
"branches:" values and ignores block-style lists (e.g., lines with "- main"),
which can leave BRANCHES empty and let the validation pass; update the
extraction logic that populates the BRANCHES variable to handle both inline and
block YAML list syntaxes (parse lines starting with "branches:" and also
subsequent indented "- ..." entries) so all branch entries are collected, and
add a check after populating BRANCHES to set FAILED=1 (fail closed) if BRANCHES
is empty or only whitespace; keep the existing validation loop that tests each
branch against ALLOWED and uses FAILED to gate the failure behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7c145ca3-e953-4db9-8e08-77d9f27a6368
📒 Files selected for processing (1)
.github/workflows/check-playbook.yml
| # Extract all branch values from the playbook | ||
| BRANCHES=$(grep 'branches:' local-antora-playbook.yml \ | ||
| | sed 's/.*branches:\s*//' \ | ||
| | tr -d "[]'" \ | ||
| | tr ',' '\n' \ | ||
| | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') | ||
|
|
||
| FAILED=0 | ||
| while IFS= read -r branch; do | ||
| [ -z "$branch" ] && continue | ||
| if ! echo "$branch" | grep -qE "^(${ALLOWED})$"; then | ||
| echo "::error::Non-standard branch reference found: '${branch}'" | ||
| FAILED=1 | ||
| fi | ||
| done <<< "$BRANCHES" | ||
|
|
||
| if [ "$FAILED" -eq 1 ]; then |
There was a problem hiding this comment.
Branch extraction is fail-open and misses common YAML branch-list syntax.
Line 26 only reads same-line branches: values. A block form like branches: followed by - main is skipped, and Line 41 can still pass with incomplete/empty extraction. This weakens the guardrail this workflow is meant to enforce.
Proposed fix (parse both inline and block lists + fail closed when nothing is extracted)
- # Extract all branch values from the playbook
- BRANCHES=$(grep 'branches:' local-antora-playbook.yml \
- | sed 's/.*branches:\s*//' \
- | tr -d "[]'" \
- | tr ',' '\n' \
- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
+ # Extract all branch values from the playbook (inline + block list forms)
+ BRANCHES=$(
+ awk '
+ /^[[:space:]]*#/ { next }
+ /^[[:space:]]*branches:[[:space:]]*\[/ {
+ line=$0
+ sub(/^[[:space:]]*branches:[[:space:]]*\[/, "", line)
+ sub(/\][[:space:]]*$/, "", line)
+ gsub(/["\047[:space:]]/, "", line)
+ n=split(line, a, ",")
+ for (i=1; i<=n; i++) if (a[i] != "") print a[i]
+ next
+ }
+ /^[[:space:]]*branches:[[:space:]]*$/ { in_block=1; next }
+ in_block && /^[[:space:]]*-[[:space:]]*/ {
+ line=$0
+ sub(/^[[:space:]]*-[[:space:]]*/, "", line)
+ sub(/[[:space:]]*#.*/, "", line)
+ gsub(/["\047]/, "", line)
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", line)
+ if (line != "") print line
+ next
+ }
+ in_block && !/^[[:space:]]*-[[:space:]]*/ { in_block=0 }
+ ' local-antora-playbook.yml
+ )
+
+ if [ -z "$BRANCHES" ]; then
+ echo "::error::Could not extract any branch references from local-antora-playbook.yml"
+ exit 1
+ fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Extract all branch values from the playbook | |
| BRANCHES=$(grep 'branches:' local-antora-playbook.yml \ | |
| | sed 's/.*branches:\s*//' \ | |
| | tr -d "[]'" \ | |
| | tr ',' '\n' \ | |
| | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') | |
| FAILED=0 | |
| while IFS= read -r branch; do | |
| [ -z "$branch" ] && continue | |
| if ! echo "$branch" | grep -qE "^(${ALLOWED})$"; then | |
| echo "::error::Non-standard branch reference found: '${branch}'" | |
| FAILED=1 | |
| fi | |
| done <<< "$BRANCHES" | |
| if [ "$FAILED" -eq 1 ]; then | |
| # Extract all branch values from the playbook (inline + block list forms) | |
| BRANCHES=$( | |
| awk ' | |
| /^[[:space:]]*#/ { next } | |
| /^[[:space:]]*branches:[[:space:]]*\[/ { | |
| line=$0 | |
| sub(/^[[:space:]]*branches:[[:space:]]*\[/, "", line) | |
| sub(/\][[:space:]]*$/, "", line) | |
| gsub(/["\047[:space:]]/, "", line) | |
| n=split(line, a, ",") | |
| for (i=1; i<=n; i++) if (a[i] != "") print a[i] | |
| next | |
| } | |
| /^[[:space:]]*branches:[[:space:]]*$/ { in_block=1; next } | |
| in_block && /^[[:space:]]*-[[:space:]]*/ { | |
| line=$0 | |
| sub(/^[[:space:]]*-[[:space:]]*/, "", line) | |
| sub(/[[:space:]]*#.*/, "", line) | |
| gsub(/["\047]/, "", line) | |
| gsub(/^[[:space:]]+|[[:space:]]+$/, "", line) | |
| if (line != "") print line | |
| next | |
| } | |
| in_block && !/^[[:space:]]*-[[:space:]]*/ { in_block=0 } | |
| ' local-antora-playbook.yml | |
| ) | |
| if [ -z "$BRANCHES" ]; then | |
| echo "::error::Could not extract any branch references from local-antora-playbook.yml" | |
| exit 1 | |
| fi | |
| FAILED=0 | |
| while IFS= read -r branch; do | |
| [ -z "$branch" ] && continue | |
| if ! echo "$branch" | grep -qE "^(${ALLOWED})$"; then | |
| echo "::error::Non-standard branch reference found: '${branch}'" | |
| FAILED=1 | |
| fi | |
| done <<< "$BRANCHES" | |
| if [ "$FAILED" -eq 1 ]; then |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/check-playbook.yml around lines 25 - 41, The BRANCHES
extraction currently only captures same-line "branches:" values and ignores
block-style lists (e.g., lines with "- main"), which can leave BRANCHES empty
and let the validation pass; update the extraction logic that populates the
BRANCHES variable to handle both inline and block YAML list syntaxes (parse
lines starting with "branches:" and also subsequent indented "- ..." entries) so
all branch entries are collected, and add a check after populating BRANCHES to
set FAILED=1 (fail closed) if BRANCHES is empty or only whitespace; keep the
existing validation loop that tests each branch against ALLOWED and uses FAILED
to gate the failure behavior.
There was a problem hiding this comment.
Could consider a YAML parser?
There was a problem hiding this comment.
@JakeSCahill Great suggestion! yq comes pre-installed on GitHub-hosted runners — no extra step or third-party action needed. It would handle both inline ([main, HEAD]) and block-list YAML forms natively, removing all the fragile grep/sed/awk chaining entirely.
Here's what the extraction block would look like with yq:
- # Extract all branch values from the playbook
- BRANCHES=$(grep 'branches:' local-antora-playbook.yml \
- | sed 's/.*branches:\s*//' \
- | tr -d "[]'" \
- | tr ',' '\n' \
- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
+ # Extract all branch values from the playbook using a proper YAML parser
+ BRANCHES=$(yq '.content.sources[].branches[]' local-antora-playbook.yml 2>/dev/null)
+
+ if [ -z "$BRANCHES" ]; then
+ echo "::error::Could not extract any branch references from local-antora-playbook.yml"
+ exit 1
+ fiThe yq path .content.sources[].branches[] directly targets the Antora playbook structure, handles any valid YAML spelling of the list, and the empty-output guard keeps the check fail-closed. The rest of the validation loop (while IFS= read -r branch) can remain unchanged.
🧠 Learnings used
Learnt from: micheleRP
Repo: redpanda-data/cloud-docs PR: 390
File: modules/manage/pages/schema-reg/schema-reg-authorization.adoc:4-4
Timestamp: 2025-08-15T04:45:28.695Z
Learning: In the Redpanda documentation system, content is single-sourced across multiple repositories (cloud-docs and docs repos). Include directives in the cloud-docs repo may reference files that exist in separate PRs in the docs repo. These PRs are linked via local-antora-playbook.yml for preview rendering, and the includes resolve correctly during the Antora build process when repositories are merged. The playbook is reverted to main before merging. This cross-repository single sourcing pattern is commonly used, so missing include targets should be verified against linked PRs in other repositories before flagging as errors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
local-antora-playbook.ymlfor non-standard branch referencesbranches:value doesn't match the allowed set (main,HEAD,v/*,shared,site-search,!v-end-of-life/*)Context
When single-sourcing pages across repos, we temporarily override playbook branch references to point to PR branches for Netlify previews. This CI check serves as a safety net to ensure those overrides are reverted before merge.
Test plan
🤖 Generated with Claude Code