#!/usr/bin/env bash set -euo pipefail if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then echo "[pousse][ERROR] Not in a git repository" >&2 exit 1 fi PROJECT_ROOT="$(git rev-parse --show-toplevel)" DEPLOY_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" IA_DEV_ROOT="$(cd "$DEPLOY_DIR/.." && pwd)" if [[ "$(pwd)" != "$PROJECT_ROOT" ]]; then SCRIPT_ABS="${DEPLOY_DIR}/$(basename "${BASH_SOURCE[0]:-$0}")" cd "$PROJECT_ROOT" && exec "$SCRIPT_ABS" "$@" fi # Resolve project slug: .ia_project in repo root or IA_PROJECT env PROJECT_SLUG="" if [[ -f "$PROJECT_ROOT/.ia_project" ]]; then PROJECT_SLUG="$(cat "$PROJECT_ROOT/.ia_project" | sed 's/[[:space:]]//g')" fi if [[ -z "$PROJECT_SLUG" && -n "${IA_PROJECT:-}" ]]; then PROJECT_SLUG="$IA_PROJECT" fi remote="origin" bump_version=false usage() { cat <<'EOF' Usage: ./deploy/pousse.sh [--remote ] [--bump-version] --bump-version Increment patch (third component) in VERSION before staging. Reads a full multi-line commit message from STDIN, then: - if not in repo root: re-exec from repo root (standardized execution) - build check (npm run build in each directory listed in projects/.json build_dirs, if any; exit on failure) - git add -A - git commit -F - git push -u HEAD The current branch must already exist on the remote (e.g. origin/); otherwise the script refuses to push. Example: ./deploy/pousse.sh <<'MSG' Title **Motivations:** - ... **Root causes:** - ... **Correctifs:** - ... **Evolutions:** - ... **Pages affectées:** - ... MSG EOF } while [[ $# -gt 0 ]]; do case "$1" in --remote) remote="$2" shift 2 ;; --bump-version) bump_version=true shift ;; -h|--help) usage exit 0 ;; *) echo "[pousse][ERROR] Unknown arg: $1" >&2 usage >&2 exit 1 ;; esac done branch="$(git rev-parse --abbrev-ref HEAD)" if [[ -z "$branch" || "$branch" == "HEAD" ]]; then echo "[pousse][ERROR] Detached HEAD is not supported" >&2 exit 1 fi author_name="$(git config user.name || true)" if [[ "$author_name" != "4NK" && "$author_name" != "Nicolas Cantu" ]]; then echo "[pousse][ERROR] Refusing to commit: git user.name must be '4NK' or 'Nicolas Cantu' (got: '${author_name}')" >&2 exit 1 fi repo_root="$(git rev-parse --show-toplevel)" # Build dirs from project config (projects/.json); skip if no config or no build_dirs build_dirs=() if [[ -n "$PROJECT_SLUG" && -f "$IA_DEV_ROOT/projects/${PROJECT_SLUG}.json" ]] && command -v jq >/dev/null 2>&1; then while IFS= read -r d; do [[ -n "$d" ]] && build_dirs+=( "$d" ) done < <(jq -r '.build_dirs[]? // empty' "$IA_DEV_ROOT/projects/${PROJECT_SLUG}.json" 2>/dev/null) fi if [[ ${#build_dirs[@]} -gt 0 ]]; then echo "[pousse] Build check (${#build_dirs[@]} dirs from project config)..." for dir in "${build_dirs[@]}"; do if [[ ! -d "${repo_root}/${dir}" ]]; then echo "[pousse][WARN] Skipping build ${dir} (directory not found)" >&2 continue fi echo "[pousse] Building ${dir}..." (cd "${repo_root}/${dir}" && npm run build) || { echo "[pousse][ERROR] Build failed in ${dir}" >&2 exit 1 } done echo "[pousse] Build check OK" else echo "[pousse] No build_dirs in project config (or no projects/.json / jq); skipping build check" fi msg_file="$(mktemp -t pousse-commit-msg.XXXXXX)" cleanup() { rm -f "$msg_file" } trap cleanup EXIT cat >"$msg_file" || true if [[ ! -s "$msg_file" ]]; then echo "[pousse][ERROR] Empty commit message on STDIN" >&2 exit 1 fi if [[ "$bump_version" == "true" ]]; then version_file="${repo_root}/VERSION" if [[ ! -f "$version_file" ]]; then echo "[pousse][ERROR] VERSION not found at ${version_file}" >&2 exit 1 fi current="$(cat "$version_file" | sed 's/[[:space:]]//g')" if ! [[ "$current" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "[pousse][ERROR] VERSION format must be X.Y.Z (got: '${current}')" >&2 exit 1 fi maj="${current%%.*}" min="${current#*.}" min="${min%%.*}" patch="${current##*.}" patch=$((patch + 1)) new_version="${maj}.${min}.${patch}" echo "$new_version" > "$version_file" echo "[pousse] Bumped VERSION: ${current} -> ${new_version}" fi # Stage all changes git add -A git_status_short="$(git status -sb)" echo "$git_status_short" # Prevent committing potentially sensitive files staged_files="$(git diff --cached --name-only || true)" if [[ -n "$staged_files" ]]; then if echo "$staged_files" | grep -Eiq '^(\.secrets/|\.env($|\.)|\.env\.|.*\.(key|pem|p12)$|.*credentials.*)'; then echo "[pousse][ERROR] Refusing to commit: staged files look sensitive:" >&2 echo "$staged_files" | grep -Ei '^(\.secrets/|\.env($|\.)|\.env\.|.*\.(key|pem|p12)$|.*credentials.*)' >&2 exit 1 fi fi if git diff --cached --quiet; then echo "[pousse] No staged changes to commit" >&2 exit 0 fi echo "[pousse] Staged changes:" git diff --cached --stat git commit -F "$msg_file" if ! git rev-parse "${remote}/${branch}" >/dev/null 2>&1; then echo "[pousse][ERROR] Branch '${branch}' does not exist on remote '${remote}'. Refusing to push (would create a new remote branch). Create the branch on the remote first or push manually." >&2 exit 1 fi git push -u "$remote" HEAD