Created
October 6, 2025 12:13
-
-
Save rakeshtembhurne/7ca7383df22e9d43fda4fcc59da8d75d to your computer and use it in GitHub Desktop.
GitLab Protect Banches Script to avoid merging by developers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Script name: gitlab-protect-branches | |
| # Description: Protect main and develop branches in any GitLab project | |
| # Usage: gitlab-protect-branches [options] | |
| # sudo vim /usr/local/bin/gitlab-protect-branches | |
| # sudo chmod +x /usr/local/bin/gitlab-protect-branches | |
| # gitlab-protect-branches --help | |
| set -e | |
| # Color codes for output | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| NC='\033[0m' # No Color | |
| # Function to display usage | |
| usage() { | |
| echo "Usage: $(basename $0) [OPTIONS]" | |
| echo "" | |
| echo "Options:" | |
| echo " -b, --branches Comma-separated list of branches (default: main,develop)" | |
| echo " -l, --level Access level (default: 40 for Maintainer)" | |
| echo " -h, --help Show this help message" | |
| echo "" | |
| echo "Access Levels:" | |
| echo " 30 = Developer" | |
| echo " 40 = Maintainer" | |
| echo " 50 = Owner" | |
| echo "" | |
| echo "Examples:" | |
| echo " $(basename $0)" | |
| echo " $(basename $0) -b main,develop,staging" | |
| echo " $(basename $0) -b master -l 50" | |
| exit 1 | |
| } | |
| # Default values | |
| BRANCHES="main,develop" | |
| ACCESS_LEVEL=40 | |
| # Parse command line arguments | |
| while [[ $# -gt 0 ]]; do | |
| case $1 in | |
| -b|--branches) | |
| BRANCHES="$2" | |
| shift 2 | |
| ;; | |
| -l|--level) | |
| ACCESS_LEVEL="$2" | |
| shift 2 | |
| ;; | |
| -h|--help) | |
| usage | |
| ;; | |
| *) | |
| echo -e "${RED}Unknown option: $1${NC}" | |
| usage | |
| ;; | |
| esac | |
| done | |
| # Check if we're in a git repository | |
| if ! git rev-parse --git-dir > /dev/null 2>&1; then | |
| echo -e "${RED}❌ Error: Not in a git repository${NC}" | |
| exit 1 | |
| fi | |
| # Check if glab is installed | |
| if ! command -v glab &> /dev/null; then | |
| echo -e "${RED}❌ Error: glab CLI is not installed${NC}" | |
| echo "Install it from: https://gitlab.com/gitlab-org/cli" | |
| exit 1 | |
| fi | |
| # Extract GitLab project path from any GitLab instance | |
| get_project_path() { | |
| local origin_url=$(git remote get-url origin 2>/dev/null) | |
| if [ -z "$origin_url" ]; then | |
| echo -e "${RED}❌ Error: No git remote 'origin' found${NC}" | |
| exit 1 | |
| fi | |
| # Handle both SSH and HTTPS URLs | |
| local project_path | |
| if [[ $origin_url == git@* ]]; then | |
| # SSH URL: [email protected]:namespace/project.git | |
| project_path=$(echo "$origin_url" | sed 's/.*@[^:]*://' | sed 's/\.git$//') | |
| elif [[ $origin_url == https://* ]] || [[ $origin_url == http://* ]]; then | |
| # HTTPS URL: https://gitlab.example.com/namespace/project.git | |
| project_path=$(echo "$origin_url" | sed 's|.*://[^/]*/||' | sed 's/\.git$//') | |
| else | |
| echo -e "${RED}❌ Error: Unrecognized git remote URL format${NC}" | |
| exit 1 | |
| fi | |
| # URL encode the path (replace / with %2F) | |
| echo "$project_path" | sed 's/\//%2F/g' | |
| } | |
| # Main execution | |
| echo "🔐 GitLab Branch Protection Tool" | |
| echo "================================" | |
| REPO_PATH=$(get_project_path) | |
| echo -e "📦 Project: ${GREEN}$(echo $REPO_PATH | sed 's/%2F/\//g')${NC}" | |
| # Check current protected branches | |
| echo -e "\n🔍 Current protected branches:" | |
| CURRENT_PROTECTED=$(glab api "projects/$REPO_PATH/protected_branches" 2>/dev/null || echo "[]") | |
| if [ "$CURRENT_PROTECTED" = "[]" ]; then | |
| echo " No protected branches found" | |
| else | |
| echo "$CURRENT_PROTECTED" | jq -r '.[] | " - \(.name)"' 2>/dev/null || echo "$CURRENT_PROTECTED" | |
| fi | |
| # Protect specified branches | |
| echo -e "\n🛡️ Protecting branches with access level $ACCESS_LEVEL..." | |
| IFS=',' read -ra BRANCH_ARRAY <<< "$BRANCHES" | |
| for branch in "${BRANCH_ARRAY[@]}"; do | |
| branch=$(echo "$branch" | xargs) # Trim whitespace | |
| echo -n " Protecting '$branch'... " | |
| # Check if branch already protected | |
| if echo "$CURRENT_PROTECTED" | jq -e ".[] | select(.name == \"$branch\")" > /dev/null 2>&1; then | |
| echo -e "${YELLOW}already protected (skipping)${NC}" | |
| continue | |
| fi | |
| # Protect the branch | |
| if glab api "projects/$REPO_PATH/protected_branches" \ | |
| -X POST \ | |
| -f name="$branch" \ | |
| -f push_access_level=$ACCESS_LEVEL \ | |
| -f merge_access_level=$ACCESS_LEVEL \ | |
| -f unprotect_access_level=$ACCESS_LEVEL \ | |
| -f allow_force_push=false \ | |
| --silent > /dev/null 2>&1; then | |
| echo -e "${GREEN}✓ protected${NC}" | |
| else | |
| echo -e "${RED}✗ failed${NC}" | |
| fi | |
| done | |
| echo -e "\n✅ Branch protection complete!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment