resq-cli 0.3.0

Developer CLI for the ResQ autonomous drone platform
Documentation
#!/usr/bin/env bash
# Copyright 2026 ResQ Software
# SPDX-License-Identifier: Apache-2.0
#
# Canonical ResQ pre-push shim — source: resq-software/dev.
# Force-push guard on main/master, branch naming convention, and an optional
# per-repo local-pre-push hook for language-specific checks
# (e.g. cargo check, ruff check, anchor build).

set -euo pipefail

[ -n "${GIT_HOOKS_SKIP:-}" ] && exit 0

echo "🚀 Running pre-push checks..."

BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "")

# Capture stdin (the ref info git passes to pre-push) so both the force-push
# guard and any local-pre-push hook can read it.
PUSH_REFS=""
if [ ! -t 0 ]; then
    PUSH_REFS=$(cat)
fi

# ── Force-push guard on main/master ─────────────────────────────────────────
case "$BRANCH" in
    main|master)
        # Only iterate when git actually gave us refs — an empty $PUSH_REFS
        # would otherwise feed one blank line through the heredoc and trip
        # the guard.
        if [ -n "$PUSH_REFS" ]; then
            while read -r _local_ref local_sha _remote_ref remote_sha; do
                [ -z "$local_sha" ] && continue
                if [ "$remote_sha" != "0000000000000000000000000000000000000000" ] && \
                   [ "$local_sha"  != "0000000000000000000000000000000000000000" ]; then
                    if ! git merge-base --is-ancestor "$remote_sha" "$local_sha" 2>/dev/null; then
                        echo "❌ Force push to $BRANCH is not allowed."
                        echo "   Override with:  git push --no-verify"
                        exit 1
                    fi
                fi
            done <<EOF
$PUSH_REFS
EOF
        fi
        ;;
esac

# ── Branch naming convention ────────────────────────────────────────────────
ALLOWED_PATTERN="^(feat|fix|docs|chore|refactor|test|ci|perf|release)/.*$"
SKIP_BRANCHES="^(main|master|dev|develop|staging|production|changeset-release/.*)$"

if [ -n "$BRANCH" ]; then
    if ! grep -qE "$SKIP_BRANCHES" <<<"$BRANCH"; then
        if ! grep -qE "$ALLOWED_PATTERN" <<<"$BRANCH"; then
            echo "❌ Branch '$BRANCH' does not follow naming convention."
            echo "   Expected: type/description  (e.g. feat/add-login)"
            echo "   Allowed prefixes: feat, fix, docs, chore, refactor, test, ci, perf, release"
            echo "   Override with:  git push --no-verify"
            exit 1
        fi
    fi
fi

# ── Local override (language-specific checks) ───────────────────────────────
LOCAL_HOOK="$(git rev-parse --show-toplevel)/.git-hooks/local-pre-push"
if [ -x "$LOCAL_HOOK" ]; then
    # Re-supply captured stdin so local hooks that inspect refs still work.
    "$LOCAL_HOOK" "$@" <<EOF
$PUSH_REFS
EOF
fi

echo "✅ Pre-push checks passed"