deploy: support multi-branches (git deploy <remote> <branche...>) + complétion
This commit is contained in:
+34
-20
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
# git-deploy <remote> <branche> -m "message"
|
||||
# git-deploy <remote> <branche...> -m "message"
|
||||
#
|
||||
# Depuis la branche de dev : commit (message obligatoire s'il y a des modifs)
|
||||
# → merge dans la branche d'env → push (dernière étape, atomique) → retour dev.
|
||||
# → merge dans une ou plusieurs branches d'env → push (dernière étape, atomique)
|
||||
# → retour dev.
|
||||
#
|
||||
# Sécurité : toutes les mutations locales sont faites AVANT tout push.
|
||||
# En cas d'échec local, l'arbre est restauré à l'identique et rien n'est poussé.
|
||||
@@ -16,7 +17,7 @@ DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
# shellcheck source=_deploy_lib.sh
|
||||
. "$DIR/_deploy_lib.sh"
|
||||
|
||||
usage() { echo 'Usage : git deploy <remote> <branche> -m "message"'; }
|
||||
usage() { echo 'Usage : git deploy <remote> <branche...> -m "message"'; }
|
||||
|
||||
SOURCE=$(deploy_source)
|
||||
PUSH=$(deploy_push)
|
||||
@@ -30,13 +31,19 @@ while [ $# -gt 0 ]; do
|
||||
*) POS+=("$1"); shift ;;
|
||||
esac
|
||||
done
|
||||
REMOTE="${POS[0]:-}"; BRANCH="${POS[1]:-}"
|
||||
{ [ -n "$REMOTE" ] && [ -n "$BRANCH" ]; } || { usage; exit 1; }
|
||||
REMOTE="${POS[0]:-}"
|
||||
BRANCHES=("${POS[@]:1}")
|
||||
{ [ -n "$REMOTE" ] && [ "${#BRANCHES[@]}" -ge 1 ]; } || { usage; exit 1; }
|
||||
|
||||
# ---- Validations pré-vol (aucune mutation) ---------------------------------
|
||||
git remote get-url "$REMOTE" >/dev/null 2>&1 || die "Remote inconnu : $REMOTE"
|
||||
git show-ref --verify --quiet "refs/heads/$BRANCH" || die "Branche locale inconnue : $BRANCH"
|
||||
[ "$BRANCH" != "$SOURCE" ] || die "'$SOURCE' est la branche de dev, pas une branche de déploiement."
|
||||
seen=""
|
||||
for b in "${BRANCHES[@]}"; do
|
||||
git show-ref --verify --quiet "refs/heads/$b" || die "Branche locale inconnue : $b"
|
||||
[ "$b" != "$SOURCE" ] || die "'$SOURCE' est la branche de dev, pas une branche de déploiement."
|
||||
case " $seen " in *" $b "*) die "Branche indiquée en double : $b" ;; esac
|
||||
seen="$seen $b"
|
||||
done
|
||||
current=$(git branch --show-current)
|
||||
[ "$current" = "$SOURCE" ] || die "Place-toi sur '$SOURCE' pour déployer (git switch $SOURCE)."
|
||||
assert_clean_git_state
|
||||
@@ -47,24 +54,28 @@ if [ "$dirty" = 1 ]; then
|
||||
fi
|
||||
|
||||
# ---- Confirmation ----------------------------------------------------------
|
||||
if [ "$PUSH" = true ]; then push_line="OUI vers '$REMOTE' ('$BRANCH' + '$SOURCE', atomique)"; else push_line="NON (désactivé)"; fi
|
||||
list="${BRANCHES[*]}"
|
||||
if [ "$PUSH" = true ]; then push_line="OUI vers '$REMOTE' ($list + '$SOURCE', atomique)"; else push_line="NON (désactivé)"; fi
|
||||
[ "$dirty" = 1 ] && commit_line="commit sur '$SOURCE' : \"$MSG\"" || commit_line="aucun commit (arbre propre)"
|
||||
confirm " • $commit_line
|
||||
• merge '$SOURCE' → '$BRANCH'
|
||||
• merge '$SOURCE' → $list
|
||||
• push : $push_line"
|
||||
|
||||
# ---- Sauvegarde de l'état pour rollback ------------------------------------
|
||||
SAVED_SOURCE=$(git rev-parse --verify "refs/heads/$SOURCE")
|
||||
SAVED_BRANCH=$(git rev-parse --verify "refs/heads/$BRANCH")
|
||||
SAVED_BRANCH=()
|
||||
for b in "${BRANCHES[@]}"; do SAVED_BRANCH+=("$(git rev-parse --verify "refs/heads/$b")"); done
|
||||
COMMITTED=0
|
||||
|
||||
rollback() {
|
||||
set +e
|
||||
echo "↩ Restauration de l'état initial…" >&2
|
||||
local gd; gd=$(git rev-parse --git-dir)
|
||||
local gd i; gd=$(git rev-parse --git-dir)
|
||||
[ -e "$gd/MERGE_HEAD" ] && git merge --abort
|
||||
git reset --hard -q
|
||||
git update-ref "refs/heads/$BRANCH" "$SAVED_BRANCH"
|
||||
for i in "${!BRANCHES[@]}"; do
|
||||
git update-ref "refs/heads/${BRANCHES[$i]}" "${SAVED_BRANCH[$i]}"
|
||||
done
|
||||
git switch -q "$SOURCE" 2>/dev/null || git switch -q --force "$SOURCE"
|
||||
if [ "$COMMITTED" = 1 ]; then
|
||||
# défait le commit mais garde les fichiers modifiés (état d'origine)
|
||||
@@ -84,22 +95,25 @@ if [ "$dirty" = 1 ]; then
|
||||
echo "✓ Commit sur '$SOURCE' : $MSG"
|
||||
fi
|
||||
|
||||
git switch -q "$BRANCH" || fail "Impossible de basculer sur '$BRANCH'."
|
||||
git merge --no-edit -q "$SOURCE" || fail "Conflit de merge sur '$BRANCH'."
|
||||
for b in "${BRANCHES[@]}"; do
|
||||
git switch -q "$b" || fail "Impossible de basculer sur '$b'."
|
||||
git merge --no-edit -q "$SOURCE" || fail "Conflit de merge sur '$b'."
|
||||
echo "✓ '$b' à jour depuis '$SOURCE'."
|
||||
done
|
||||
git switch -q "$SOURCE" || fail "Impossible de revenir sur '$SOURCE'."
|
||||
echo "✓ Local OK : '$BRANCH' à jour depuis '$SOURCE'."
|
||||
echo "✓ Local OK : $list."
|
||||
|
||||
# ---- Push : dernière étape, atomique, jamais forcé -------------------------
|
||||
if [ "$PUSH" = true ]; then
|
||||
echo "→ Vérification du push (dry-run)…"
|
||||
git push --atomic --dry-run "$REMOTE" "$BRANCH" "$SOURCE" \
|
||||
git push --atomic --dry-run "$REMOTE" "${BRANCHES[@]}" "$SOURCE" \
|
||||
|| { echo "✗ Push rejeté au dry-run (non fast-forward ?). RIEN poussé. Local conservé." >&2; exit 1; }
|
||||
echo "→ Push atomique '$BRANCH' + '$SOURCE' → '$REMOTE'…"
|
||||
git push --atomic "$REMOTE" "$BRANCH" "$SOURCE" \
|
||||
echo "→ Push atomique ($list + '$SOURCE') → '$REMOTE'…"
|
||||
git push --atomic "$REMOTE" "${BRANCHES[@]}" "$SOURCE" \
|
||||
|| { echo "✗ Échec du push. RIEN poussé (atomique). Local conservé." >&2; \
|
||||
echo " Relance : git push --atomic $REMOTE $BRANCH $SOURCE" >&2; exit 1; }
|
||||
echo " Relance : git push --atomic $REMOTE $list $SOURCE" >&2; exit 1; }
|
||||
echo "✓ Poussé sur '$REMOTE'."
|
||||
else
|
||||
echo "→ (push désactivé) aurait fait : git push --atomic $REMOTE $BRANCH $SOURCE"
|
||||
echo "→ (push désactivé) aurait fait : git push --atomic $REMOTE $list $SOURCE"
|
||||
fi
|
||||
echo "✓ Terminé. Tu es sur '$SOURCE'."
|
||||
|
||||
Reference in New Issue
Block a user