Update 'git-cb' script
							parent
							
								
									608a3bc725
								
							
						
					
					
						commit
						a737b50284
					
				
							
								
								
									
										243
									
								
								.bin/git-cb
								
								
								
								
							
							
						
						
									
										243
									
								
								.bin/git-cb
								
								
								
								
							| 
						 | 
					@ -1,25 +1,110 @@
 | 
				
			||||||
#!/usr/bin/env bash
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					set -euo pipefail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
types=(
 | 
					readonly ALLOWED_MAIN_BRANCHES=("main" "master" "develop")
 | 
				
			||||||
  "feature   For new features"
 | 
					readonly BRANCH_TYPES=(
 | 
				
			||||||
  "bugfix    For bug fixes"
 | 
					  "feat      For new features"
 | 
				
			||||||
  "hotfix    For urgent fixes"
 | 
					  "hotfix    For urgent fixes"
 | 
				
			||||||
 | 
					  "fix       For fixes"
 | 
				
			||||||
  "release   For preparing releases"
 | 
					  "release   For preparing releases"
 | 
				
			||||||
  "chore     For non-code tasks"
 | 
					  "chore     For non-code tasks"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
selected=$(printf '%s\n' "${types[@]}" | fzf --prompt="Select branch type: ") || exit 1
 | 
					error() {
 | 
				
			||||||
type=${selected%% *}
 | 
					  echo "Error: $1" >&2
 | 
				
			||||||
 | 
					  exit 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "Fetching Jira tickets..."
 | 
					warn() {
 | 
				
			||||||
jira_data=$(jira issue list --assignee=hektor.misplon@rightcrowd.com --order-by=priority --plain --no-headers 2>/dev/null)
 | 
					  echo "Warning: $1" >&2
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [[ $? -ne 0 || -z "$jira_data" ]]; then
 | 
					check_dependencies() {
 | 
				
			||||||
  echo "Warning: Could not fetch Jira tickets or no tickets found."
 | 
					  local missing=()
 | 
				
			||||||
  echo "Proceeding without ticket ID..."
 | 
					  for cmd in git fzf; do
 | 
				
			||||||
  ticket_id=""
 | 
					    if ! command -v "$cmd" &> /dev/null; then
 | 
				
			||||||
else
 | 
					      missing+=("$cmd")
 | 
				
			||||||
  # Create formatted list for fzf: "TICKET-123 - Issue description"
 | 
					    fi
 | 
				
			||||||
 | 
					  done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if [[ ${#missing[@]} -gt 0 ]]; then
 | 
				
			||||||
 | 
					    error "Missing required commands: ${missing[*]}"
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					check_git_repo() {
 | 
				
			||||||
 | 
					  if ! git rev-parse --git-dir &> /dev/null; then
 | 
				
			||||||
 | 
					    error "Not in a git repository"
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					check_current_branch() {
 | 
				
			||||||
 | 
					  local current_branch
 | 
				
			||||||
 | 
					  current_branch=$(git branch --show-current)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  local is_main_branch=false
 | 
				
			||||||
 | 
					  for branch in "${ALLOWED_MAIN_BRANCHES[@]}"; do
 | 
				
			||||||
 | 
					    if [[ "$current_branch" == "$branch" ]]; then
 | 
				
			||||||
 | 
					      is_main_branch=true
 | 
				
			||||||
 | 
					      break
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					  done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if [[ "$is_main_branch" == false ]]; then
 | 
				
			||||||
 | 
					    warn "Not branching from a main branch (current: $current_branch)"
 | 
				
			||||||
 | 
					    read -rp "Continue anyway? [y/N] " response
 | 
				
			||||||
 | 
					    if [[ ! "$response" =~ ^[Yy]$ ]]; then
 | 
				
			||||||
 | 
					      exit 0
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					get_user_email() {
 | 
				
			||||||
 | 
					  local email
 | 
				
			||||||
 | 
					  email=$(git config --get user.email 2>/dev/null)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if [[ -z "$email" ]]; then
 | 
				
			||||||
 | 
					    error "Git user email not configured. Run: git config user.email 'your@email.com'"
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  echo "$email"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					select_branch_type() {
 | 
				
			||||||
 | 
					  local selected
 | 
				
			||||||
 | 
					  selected=$(printf '%s\n' "${BRANCH_TYPES[@]}" | \
 | 
				
			||||||
 | 
					    fzf --prompt="Select branch type: " \
 | 
				
			||||||
 | 
					        --height=40% \
 | 
				
			||||||
 | 
					        --border \
 | 
				
			||||||
 | 
					        --info=inline) || error "Branch type selection cancelled"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  echo "${selected%% *}"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					select_jira_ticket() {
 | 
				
			||||||
 | 
					  local email=$1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ! command -v jira &> /dev/null; then
 | 
				
			||||||
 | 
					    warn "Jira CLI not found. Proceeding without ticket ID."
 | 
				
			||||||
 | 
					    return 0
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  echo "Fetching Jira tickets for $email..." >&2
 | 
				
			||||||
 | 
					  local jira_data
 | 
				
			||||||
 | 
					  jira_data=$(jira issue list --assignee="$email" --order-by=priority --plain --no-headers 2>/dev/null) || {
 | 
				
			||||||
 | 
					    warn "Could not fetch Jira tickets. Proceeding without ticket ID."
 | 
				
			||||||
 | 
					    return 0
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if [[ -z "$jira_data" ]]; then
 | 
				
			||||||
 | 
					    warn "No Jira tickets found. Proceeding without ticket ID."
 | 
				
			||||||
 | 
					    return 0
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  echo "$jira_data" >&2
 | 
				
			||||||
 | 
					  echo "" >&2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  local formatted_tickets
 | 
				
			||||||
  formatted_tickets=$(echo "$jira_data" | awk '{
 | 
					  formatted_tickets=$(echo "$jira_data" | awk '{
 | 
				
			||||||
    ticket_id = $2
 | 
					    ticket_id = $2
 | 
				
			||||||
    $1 = $2 = ""
 | 
					    $1 = $2 = ""
 | 
				
			||||||
| 
						 | 
					@ -32,59 +117,105 @@ else
 | 
				
			||||||
  }')
 | 
					  }')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if [[ -z "$formatted_tickets" ]]; then
 | 
					  if [[ -z "$formatted_tickets" ]]; then
 | 
				
			||||||
    echo "No tickets found. Proceeding without ticket ID..."
 | 
					    warn "No tickets to display. Proceeding without ticket ID."
 | 
				
			||||||
    ticket_id=""
 | 
					    return 0
 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    # Let user select a ticket or skip
 | 
					 | 
				
			||||||
    echo ""
 | 
					 | 
				
			||||||
    selected_ticket=$(echo -e "SKIP - Create branch without ticket ID\n$formatted_tickets" | \
 | 
					 | 
				
			||||||
      fzf --prompt="Select Jira ticket (or skip): " --height=40%) || exit 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if [[ "$selected_ticket" == "SKIP"* ]]; then
 | 
					 | 
				
			||||||
      ticket_id=""
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      ticket_id=${selected_ticket%% -*}
 | 
					 | 
				
			||||||
    fi
 | 
					 | 
				
			||||||
  fi
 | 
					  fi
 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
editor="${EDITOR:-vi}"
 | 
					  local selected_ticket
 | 
				
			||||||
tmpfile=$(mktemp)
 | 
					  selected_ticket=$(echo -e "SKIP - Create branch without ticket ID\n$formatted_tickets" | \
 | 
				
			||||||
 | 
					    fzf --prompt="Select Jira ticket (or skip): " \
 | 
				
			||||||
 | 
					        --height=40% \
 | 
				
			||||||
 | 
					        --border \
 | 
				
			||||||
 | 
					        --info=inline) || error "Ticket selection cancelled"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [[ -n "$ticket_id" ]]; then
 | 
					  if [[ "$selected_ticket" != "SKIP"* ]]; then
 | 
				
			||||||
  cat > "$tmpfile" << EOF
 | 
					    echo "${selected_ticket%% -*}"
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					get_branch_description() {
 | 
				
			||||||
 | 
					  local ticket_id=$1
 | 
				
			||||||
 | 
					  local editor="${EDITOR:-vi}"
 | 
				
			||||||
 | 
					  local tmpfile
 | 
				
			||||||
 | 
					  tmpfile=$(mktemp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  trap "rm -f '$tmpfile'" EXIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if [[ -n "$ticket_id" ]]; then
 | 
				
			||||||
 | 
					    cat > "$tmpfile" << EOF
 | 
				
			||||||
# Selected ticket: $ticket_id
 | 
					# Selected ticket: $ticket_id
 | 
				
			||||||
# Enter your branch description below in kebab case (e.g. \`my-description\`):
 | 
					# Enter your branch description below in kebab-case (e.g., my-description):
 | 
				
			||||||
# The ticket ID will be automatically included in the branch name.
 | 
					# The ticket ID will be automatically included in the branch name.
 | 
				
			||||||
 | 
					# Lines starting with # will be ignored.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EOF
 | 
					EOF
 | 
				
			||||||
else
 | 
					  else
 | 
				
			||||||
  cat > "$tmpfile" << 'EOF'
 | 
					    cat > "$tmpfile" << 'EOF'
 | 
				
			||||||
# Enter your branch description below in kebab case (e.g. `my-description`):
 | 
					# Enter your branch description below in kebab-case (e.g., my-description):
 | 
				
			||||||
 | 
					# Lines starting with # will be ignored.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EOF
 | 
					EOF
 | 
				
			||||||
fi
 | 
					  fi
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  "$editor" "$tmpfile" < /dev/tty > /dev/tty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"$editor" "$tmpfile"
 | 
					  local desc
 | 
				
			||||||
 | 
					  desc=$(grep -v '^#' "$tmpfile" | tr -d '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
desc=$(grep -v '^#' "$tmpfile" | tr -d '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
 | 
					  echo "$desc"
 | 
				
			||||||
rm "$tmpfile"
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [[ -z "$desc" ]]; then
 | 
					validate_description() {
 | 
				
			||||||
  echo "No description provided."
 | 
					  local desc=$1
 | 
				
			||||||
  exit 1
 | 
					 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [[ ! "$desc" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then
 | 
					  if [[ -z "$desc" ]]; then
 | 
				
			||||||
  echo "Invalid branch description format."
 | 
					    error "No description provided"
 | 
				
			||||||
  echo "Use lowercase letters, numbers, and hyphens only."
 | 
					  fi
 | 
				
			||||||
  echo "No trailing or consecutive hyphens allowed."
 | 
					 | 
				
			||||||
  exit 1
 | 
					 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [[ -n "$ticket_id" ]]; then
 | 
					  if [[ ! "$desc" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then
 | 
				
			||||||
  branch="$type/$ticket_id-$desc"
 | 
					    error "Invalid branch description format.\nUse lowercase letters, numbers, and hyphens only.\nNo trailing or consecutive hyphens allowed.\nExample: my-feature-description"
 | 
				
			||||||
else
 | 
					  fi
 | 
				
			||||||
  branch="$type/$desc"
 | 
					}
 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "Creating branch: $branch"
 | 
					create_branch() {
 | 
				
			||||||
git checkout -b "$branch"
 | 
					  local type=$1
 | 
				
			||||||
 | 
					  local ticket_id=$2
 | 
				
			||||||
 | 
					  local desc=$3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  local branch
 | 
				
			||||||
 | 
					  if [[ -n "$ticket_id" ]]; then
 | 
				
			||||||
 | 
					    branch="$type/$ticket_id-$desc"
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    branch="$type/$desc"
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if git show-ref --verify --quiet "refs/heads/$branch"; then
 | 
				
			||||||
 | 
					    error "Branch '$branch' already exists"
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  echo ""
 | 
				
			||||||
 | 
					  echo "Creating branch: $branch"
 | 
				
			||||||
 | 
					  git checkout -b "$branch"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main() {
 | 
				
			||||||
 | 
					  check_dependencies
 | 
				
			||||||
 | 
					  check_git_repo
 | 
				
			||||||
 | 
					  check_current_branch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  local email
 | 
				
			||||||
 | 
					  email=$(get_user_email)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  local type
 | 
				
			||||||
 | 
					  type=$(select_branch_type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  echo "About to call select_jira_ticket" >&2
 | 
				
			||||||
 | 
					  local ticket_id=""
 | 
				
			||||||
 | 
					  ticket_id=$(select_jira_ticket "$email")
 | 
				
			||||||
 | 
					  local desc
 | 
				
			||||||
 | 
					  desc=$(get_branch_description "$ticket_id")
 | 
				
			||||||
 | 
					  validate_description "$desc"
 | 
				
			||||||
 | 
					  create_branch "$type" "$ticket_id" "$desc"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main "$@"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue