From 9b2893f4450a227d0abe6856a4649d3826b0ae3f Mon Sep 17 00:00:00 2001 From: nate Date: Tue, 6 Oct 2026 22:43:47 +0000 Subject: [PATCH] chore(hooks): drop Conventional Branches pre-push hook in favor of litellm_ prefix Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .githooks/pre-push | 90 -------------------------- CONTRIBUTING.md | 10 +-- Makefile | 2 +- scripts/install_git_hooks.sh | 2 +- tests/unit/test_git_hooks.py | 119 ++--------------------------------- 5 files changed, 13 insertions(+), 210 deletions(-) delete mode 100755 .githooks/pre-push diff --git a/.githooks/pre-push b/.githooks/pre-push deleted file mode 100755 index dc1a73a7ba2..00000000000 --- a/.githooks/pre-push +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env bash -# -# pre-push — enforce Conventional Branches -# https://conventional-branch.github.io/ -# -# Branch format: / -# must be one of: feature, bugfix, hotfix, release, chore -# -# Protected branches (always allowed): -# - main -# - dependabot/* -# - gh-readonly-queue/* -# -# Tag pushes and branch deletions are skipped. -# Bypass: git push --no-verify. - -set -eu - -ZERO_OID="0000000000000000000000000000000000000000" -ZERO_OID_SHA256="0000000000000000000000000000000000000000000000000000000000000000" -ALLOWED_TYPES="feature|bugfix|hotfix|release|chore" -BRANCH_PATTERN="^(${ALLOWED_TYPES})/.+" - -PROTECTED_NAMES="main" -PROTECTED_PREFIXES="dependabot/ gh-readonly-queue/" - -is_protected() { - branch="$1" - for name in $PROTECTED_NAMES; do - if [ "$branch" = "$name" ]; then - return 0 - fi - done - for prefix in $PROTECTED_PREFIXES; do - case "$branch" in "$prefix"*) return 0 ;; esac - done - return 1 -} - -invalid="" - -while read -r local_ref local_oid remote_ref remote_oid; do - # Branch deletion (no local commit being pushed). - if [ "$local_oid" = "$ZERO_OID" ] || [ "$local_oid" = "$ZERO_OID_SHA256" ]; then - continue - fi - - # Only validate branch pushes; ignore tags and other ref namespaces. - case "$remote_ref" in - refs/heads/*) ;; - *) continue ;; - esac - - branch="${remote_ref#refs/heads/}" - - if is_protected "$branch"; then - continue - fi - - if ! printf '%s' "$branch" | grep -Eq "$BRANCH_PATTERN"; then - invalid="$invalid $branch" - fi -done - -if [ -n "$invalid" ]; then - cat >&2 </ - - Allowed types: feature, bugfix, hotfix, release, chore - Examples: - feature/weighted-round-robin - bugfix/streaming-empty-chunks - chore/bump-deps - hotfix/auth-bypass - - Protected (always allowed): main, dependabot/*, gh-readonly-queue/*. - -See https://conventional-branch.github.io/ - -Rename with: git branch -m -To bypass (use sparingly): git push --no-verify -EOF - exit 1 -fi - -exit 0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0af12bd5318..9aacb7fe5dc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,12 +39,12 @@ git clone https://github.com/YOUR_USERNAME/litellm.git cd litellm # Create a new branch for your feature (see "Commit and Branch Conventions" below) -git checkout -b feature/your-feature +git checkout -b litellm_your_feature # Install development dependencies make install-dev -# Install git hooks that enforce commit + branch conventions (one-time, opt-in) +# Install git hooks that enforce commit conventions (one-time, opt-in) make install-hooks # Verify your setup works @@ -55,7 +55,7 @@ That's it! Your local development environment is ready. ## Commit and Branch Conventions -Commits follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) and branches follow [Conventional Branches](https://conventional-branch.github.io/). Run `make install-hooks` once per clone to enable the local git hooks that enforce these — see the [contributor docs](https://docs.litellm.ai/docs/extras/contributing_code#commit-and-branch-conventions) for the full type list, examples, the protected-branch bypass list, and how to opt out. +Commits follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). Branches use the `litellm_` prefix with no `/`. Run `make install-hooks` once per clone to enable the local hook that enforces the commit convention. See the [contributor docs](https://docs.litellm.ai/docs/extras/contributing_code#commit-and-branch-conventions) for details ### 2. Development Workflow @@ -78,8 +78,8 @@ uv run pytest tests/unit/.py -v git add . git commit -m "feat(scope): your descriptive commit message" -# Push and create a PR (branch must follow Conventional Branches — see above) -git push origin feature/your-feature +# Push and create a PR +git push origin litellm_your_feature ``` ## Adding Testing diff --git a/Makefile b/Makefile index 7c8511a44d7..4a25625136a 100644 --- a/Makefile +++ b/Makefile @@ -124,7 +124,7 @@ install-helm-unittest: helm plugin install https://github.com/helm-unittest/helm-unittest --version v0.8.2; \ } -# Install git hooks that enforce Conventional Commits and Conventional Branches. +# Install git hooks that enforce Conventional Commits. # Opt-in: not chained into install-dev. install-hooks: ./scripts/install_git_hooks.sh diff --git a/scripts/install_git_hooks.sh b/scripts/install_git_hooks.sh index 8f4e79e4ddd..cccc8d6afc4 100755 --- a/scripts/install_git_hooks.sh +++ b/scripts/install_git_hooks.sh @@ -31,7 +31,7 @@ cat < subprocess.CompletedProcess: @@ -54,21 +47,6 @@ def _run_commit_msg(subject: str, tmp_path: Path) -> subprocess.CompletedProcess ) -def _run_pre_push(stdin: str) -> subprocess.CompletedProcess: - return subprocess.run( - ["bash", str(_PRE_PUSH_HOOK)], - input=stdin, - capture_output=True, - text=True, - check=False, - ) - - -def _ref_line(branch: str, local_oid: str = _NONZERO_OID, remote_oid: str = _ZERO_OID) -> str: - ref = f"refs/heads/{branch}" - return f"{ref} {local_oid} {ref} {remote_oid}\n" - - # ----- commit-msg ----------------------------------------------------------- @@ -198,88 +176,3 @@ def test_commit_msg_uses_first_non_comment_line(tmp_path): check=False, ) assert result.returncode == 0, result.stderr - - -# ----- pre-push ------------------------------------------------------------- - - -@pytest.mark.parametrize( - "branch", - [ - "feature/weighted-round-robin", - "bugfix/streaming-empty-chunks", - "hotfix/auth-bypass", - "release/v1.45.0", - "chore/bump-deps", - "feature/nested/path/ok", # nested slashes after type are fine - ], -) -def test_pre_push_accepts_conventional_branches(branch): - result = _run_pre_push(_ref_line(branch)) - assert result.returncode == 0, ( - f"hook rejected a valid branch:\n branch: {branch!r}\n" - f" stderr: {result.stderr}" - ) - - -@pytest.mark.parametrize( - "branch", - [ - "random-branch-name", - "litellm_fix/optimize-streaming", # legacy pattern is now rejected - "ui/navbar-notifications", # not in the allow list - "feature/", # empty description - "Feature/foo", # type is case-sensitive - "feat/foo", # angular commit type, not branch type - ], -) -def test_pre_push_rejects_non_conventional_branches(branch): - result = _run_pre_push(_ref_line(branch)) - assert result.returncode == 1, ( - f"hook accepted an invalid branch:\n branch: {branch!r}\n" - f" stderr: {result.stderr}" - ) - assert "Conventional Branches" in result.stderr - - -@pytest.mark.parametrize( - "branch", - [ - "main", - "dependabot/github_actions/foo", - "gh-readonly-queue/main/abc123", - ], -) -def test_pre_push_bypasses_protected_branches(branch): - result = _run_pre_push(_ref_line(branch)) - assert result.returncode == 0, ( - f"protected branch was rejected:\n branch: {branch!r}\n" - f" stderr: {result.stderr}" - ) - - -def test_pre_push_skips_tag_pushes(): - line = f"refs/tags/v1 {_NONZERO_OID} refs/tags/v1 {_ZERO_OID}\n" - result = _run_pre_push(line) - assert result.returncode == 0, result.stderr - - -def test_pre_push_skips_branch_deletions(): - # local oid all zeros = deletion - line = f"refs/heads/whatever {_ZERO_OID} refs/heads/whatever {_NONZERO_OID}\n" - result = _run_pre_push(line) - assert result.returncode == 0, result.stderr - - -def test_pre_push_fails_if_any_ref_is_invalid(): - # Mixed batch: one valid, one invalid — entire push should fail. - stdin = _ref_line("feature/ok") + _ref_line("random-bad") - result = _run_pre_push(stdin) - assert result.returncode == 1 - assert "random-bad" in result.stderr - - -def test_pre_push_no_refs_passes(): - # Empty stdin (no refs being pushed) should pass. - result = _run_pre_push("") - assert result.returncode == 0, result.stderr