Skip to content

[Infra] Guard main to only accept PRs from staging and hotfix branches - #25733

Merged
yuneng-berri merged 3 commits into
mainfrom
litellm_guardMainBranch
Apr 15, 2026
Merged

[Infra] Guard main to only accept PRs from staging and hotfix branches#25733
yuneng-berri merged 3 commits into
mainfrom
litellm_guardMainBranch

Conversation

@yuneng-berri

Copy link
Copy Markdown
Contributor

Relevant issues

Summary

As part of a new SDLC flow where litellm_internal_staging is the promotion source for main, this PR adds a GitHub Actions workflow that enforces which branches may open PRs against main.

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 on pull_request to main and passes only when the head branch is litellm_internal_staging or matches litellm_hotfix_*. Any other source branch fails the check. merge_group events are explicitly rejected since merge queue is not in use.

Security posture:

  • No secrets or env vars required.
  • permissions: {} — no token scopes granted.
  • github.head_ref is consumed via an env: mapping, not inline interpolation, avoiding script injection.

To take effect, the job Verify PR source branch must be added as a required status check in main'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_staging or litellm_hotfix_test and confirm it passes.

Type

🚄 Infrastructure

Screenshots

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.
@yuneng-berri
yuneng-berri requested a review from a team April 15, 2026 01:19
@vercel

vercel Bot commented Apr 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Apr 15, 2026 1:43am

Request Review

@codspeed-hq

codspeed-hq Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 16 untouched benchmarks


Comparing litellm_guardMainBranch (38f8d7a) with main (5c1f7d9)

Open in CodSpeed

@greptile-apps

greptile-apps Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces .github/workflows/guard-main-branch.yml, a lightweight GitHub Actions gate that rejects PRs to main unless they originate from litellm_internal_staging or a litellm_hotfix_* branch within the canonical repository. The fork-origin bypass raised in a prior review thread has been addressed: HEAD_REPO is checked against BASE_REPO before the branch-name test, and all GitHub context values flow through env: mappings rather than inline interpolation, eliminating script-injection risk.

Confidence Score: 5/5

Safe 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.

Important Files Changed

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]
Loading

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Fork branch name bypass

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 1

Note: 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.

@yuneng-berri
yuneng-berri temporarily deployed to integration-postgres April 15, 2026 01:42 — with GitHub Actions Inactive
@yuneng-berri
yuneng-berri temporarily deployed to integration-postgres April 15, 2026 01:42 — with GitHub Actions Inactive
@yuneng-berri
yuneng-berri temporarily deployed to integration-postgres April 15, 2026 01:42 — with GitHub Actions Inactive
@yuneng-berri
yuneng-berri temporarily deployed to integration-postgres April 15, 2026 01:42 — with GitHub Actions Inactive
@yuneng-berri
yuneng-berri merged commit 72a461b into main Apr 15, 2026
103 of 110 checks passed
@yuneng-berri
yuneng-berri deleted the litellm_guardMainBranch branch April 15, 2026 03:54
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
[Infra] Guard main to only accept PRs from staging and hotfix branches
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants