[Infra] Guard main to only accept PRs from staging and hotfix branches - #25733
Conversation
Adds a GHA that fails PRs to main unless the head branch is 'litellm_internal_staging' or 'litellm_hotfix_*'. Also fails merge_group events since merge queue is not in use.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR introduces Confidence Score: 5/5Safe to merge — the workflow is minimal, carries no secrets, and correctly handles the fork-bypass and injection concerns. The only outstanding call-out (fork name bypass) from the previous review thread has been addressed. All remaining observations are P2 or below (e.g. ubuntu-latest not pinned to a specific version) and do not affect correctness or security. No files require special attention.
|
| Filename | Overview |
|---|---|
| .github/workflows/guard-main-branch.yml | New workflow guarding main branch; fork-origin check and injection-safe env-var pattern are both present and correct. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A([PR opened → main]) --> B{event_name == merge_group?}
B -- Yes --> C[❌ Fail: merge queue not supported]
B -- No --> D{HEAD_REPO == BASE_REPO?}
D -- No --> E[❌ Fail: PR from fork]
D -- Yes --> F{HEAD_REF == litellm_internal_staging?}
F -- Yes --> G[✅ Pass: Allowed source branch]
F -- No --> H{HEAD_REF matches litellm_hotfix_?*?}
H -- Yes --> G
H -- No --> I[❌ Fail: Branch not allowed]
Reviews (2): Last reviewed commit: "Point contributors toward litellm_oss_br..." | Re-trigger Greptile
| HEAD_REF: ${{ github.head_ref }} | ||
| run: | | ||
| echo "PR head branch: $HEAD_REF" | ||
| if [ "$HEAD_REF" = "litellm_internal_staging" ] || [[ "$HEAD_REF" == litellm_hotfix_?* ]]; then |
There was a problem hiding this comment.
A contributor from a forked repository can name their branch litellm_internal_staging or litellm_hotfix_anything and the check will pass, since github.head_ref only contains the branch name — not the repository origin. Adding a github.event.pull_request.head.repo.full_name check ensures the source is the canonical repository:
run: |
echo "PR head branch: $HEAD_REF"
REPO="${{ github.event.pull_request.head.repo.full_name }}"
EXPECTED_REPO="${{ github.repository }}"
if [ "$REPO" != "$EXPECTED_REPO" ]; then
echo "::error::PRs to main must originate from the canonical repository ($EXPECTED_REPO), not a fork ($REPO)."
exit 1
fi
if [ "$HEAD_REF" = "litellm_internal_staging" ] || [[ "$HEAD_REF" == litellm_hotfix_?* ]]; then
echo "Allowed source branch."
exit 0
fi
echo "::error::PRs to main must originate from 'litellm_internal_staging' or a 'litellm_hotfix_*' branch. Got: '$HEAD_REF'."
exit 1Note: github.event.pull_request.head.repo.full_name is a static context value (not user-controlled shell input), so it is safe to interpolate directly.
[Infra] Guard main to only accept PRs from staging and hotfix branches
Relevant issues
Summary
As part of a new SDLC flow where
litellm_internal_stagingis the promotion source formain, this PR adds a GitHub Actions workflow that enforces which branches may open PRs againstmain.Failure Path (Before Fix)
No automated check existed to prevent PRs from arbitrary dev branches landing on
main.Fix
Adds
.github/workflows/guard-main-branch.yml, which runs onpull_requesttomainand passes only when the head branch islitellm_internal_stagingor matcheslitellm_hotfix_*. Any other source branch fails the check.merge_groupevents are explicitly rejected since merge queue is not in use.Security posture:
permissions: {}— no token scopes granted.github.head_refis consumed via anenv:mapping, not inline interpolation, avoiding script injection.To take effect, the job
Verify PR source branchmust be added as a required status check inmain's branch protection rule.Testing
Manual review of trigger conditions and branch-name matching. To validate end-to-end, open a test PR from a non-allowlisted branch and confirm the check fails, then from
litellm_internal_stagingorlitellm_hotfix_testand confirm it passes.Type
🚄 Infrastructure
Screenshots