netgescon-day0/scripts/ops/netgescon-day0-cutover.sh

236 lines
6.6 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Day-0 Git cutover for NetGescon.
# Creates a clean project copy, initializes a fresh Git history, and can
# optionally create/push to a Gitea repository via API.
SOURCE_DIR="$(pwd)"
TARGET_DIR=""
BRANCH="main"
COMMIT_MESSAGE="chore: NetGescon day-0 baseline"
PUSH=0
FORCE=0
REPO_URL=""
GITEA_URL=""
GITEA_TOKEN=""
GITEA_OWNER=""
GITEA_REPO=""
GITEA_OWNER_TYPE="user" # user|org
GITEA_PRIVATE="true"
usage() {
cat <<'EOF'
Usage:
bash scripts/ops/netgescon-day0-cutover.sh [options]
Options:
--source <path> Source project directory (default: current dir)
--target <path> Target clean directory (default: sibling day0 folder)
--branch <name> Git branch name (default: main)
--message <text> Initial commit message
--force Remove existing target directory if present
--push Push to remote after commit
--repo-url <url> Remote URL to set as origin
--gitea-url <url> Gitea base URL (e.g. https://git.netgescon.it)
--gitea-token <token> Gitea API token (admin or owner with repo rights)
--gitea-owner <name> Owner username or org name
--gitea-repo <name> Repository name to create
--gitea-owner-type <type> user|org (default: user)
--gitea-private <bool> true|false (default: true)
Examples:
bash scripts/ops/netgescon-day0-cutover.sh --target /home/michele/netgescon/netgescon-day0
bash scripts/ops/netgescon-day0-cutover.sh \
--target /home/michele/netgescon/netgescon-day0 \
--push \
--gitea-url https://git.netgescon.it \
--gitea-token '***' \
--gitea-owner NetGescon \
--gitea-owner-type org \
--gitea-repo netgescon-day0
EOF
}
log() {
printf "[day0] %s\n" "$*"
}
die() {
printf "[day0][ERROR] %s\n" "$*" >&2
exit 1
}
require_cmd() {
command -v "$1" >/dev/null 2>&1 || die "Missing command: $1"
}
while [[ $# -gt 0 ]]; do
case "$1" in
--source) SOURCE_DIR="$2"; shift 2 ;;
--target) TARGET_DIR="$2"; shift 2 ;;
--branch) BRANCH="$2"; shift 2 ;;
--message) COMMIT_MESSAGE="$2"; shift 2 ;;
--force) FORCE=1; shift ;;
--push) PUSH=1; shift ;;
--repo-url) REPO_URL="$2"; shift 2 ;;
--gitea-url) GITEA_URL="$2"; shift 2 ;;
--gitea-token) GITEA_TOKEN="$2"; shift 2 ;;
--gitea-owner) GITEA_OWNER="$2"; shift 2 ;;
--gitea-repo) GITEA_REPO="$2"; shift 2 ;;
--gitea-owner-type) GITEA_OWNER_TYPE="$2"; shift 2 ;;
--gitea-private) GITEA_PRIVATE="$2"; shift 2 ;;
-h|--help) usage; exit 0 ;;
*) die "Unknown option: $1" ;;
esac
done
require_cmd rsync
require_cmd git
SOURCE_DIR="$(cd "$SOURCE_DIR" && pwd)"
if [[ -z "$TARGET_DIR" ]]; then
ts="$(date +%Y%m%d-%H%M%S)"
TARGET_DIR="$(dirname "$SOURCE_DIR")/netgescon-day0-${ts}"
fi
if [[ ! -d "$SOURCE_DIR" ]]; then
die "Source directory not found: $SOURCE_DIR"
fi
if [[ -e "$TARGET_DIR" ]]; then
if [[ "$FORCE" -eq 1 ]]; then
log "Removing existing target: $TARGET_DIR"
rm -rf "$TARGET_DIR"
else
die "Target already exists: $TARGET_DIR (use --force)"
fi
fi
log "Creating clean project copy"
mkdir -p "$TARGET_DIR"
rsync -a \
--exclude='.git/' \
--exclude='vendor/' \
--exclude='node_modules/' \
--exclude='storage/logs/' \
--exclude='storage/framework/cache/' \
--exclude='storage/framework/sessions/' \
--exclude='storage/framework/views/' \
--exclude='storage/backups/cutover-snapshots/' \
--exclude='.env' \
--exclude='.env.local' \
--exclude='.env.production' \
--exclude='.env.staging' \
--exclude='.env.development' \
--exclude='.env.test' \
--exclude='.env.testing' \
--exclude='*.log' \
--exclude='*.tmp' \
"$SOURCE_DIR"/ "$TARGET_DIR"/
cd "$TARGET_DIR"
if [[ -f .env.example && ! -f .env ]]; then
log "Keeping only .env.example in day-0 copy"
fi
# Add strict ignore guards for day-0 repository safety.
cat >> .gitignore <<'EOF'
# Day-0 safety guards
.env
.env.local
.env.production
.env.staging
.env.development
.env.test
.env.testing
vendor/
node_modules/
storage/logs/
storage/framework/cache/
storage/framework/sessions/
storage/framework/views/
storage/backups/
EOF
log "Initializing fresh git repository"
git init -q
git checkout -b "$BRANCH" >/dev/null 2>&1 || git checkout "$BRANCH"
name="$(git config --global --get user.name || true)"
email="$(git config --global --get user.email || true)"
if [[ -n "$name" ]]; then git config user.name "$name"; fi
if [[ -n "$email" ]]; then git config user.email "$email"; fi
git add -A
if git diff --cached --quiet; then
die "No files staged for initial commit. Check excludes."
fi
git commit -m "$COMMIT_MESSAGE" >/dev/null
if [[ -n "$GITEA_URL" || -n "$GITEA_TOKEN" || -n "$GITEA_OWNER" || -n "$GITEA_REPO" ]]; then
require_cmd curl
require_cmd jq
[[ -n "$GITEA_URL" ]] || die "--gitea-url is required when using Gitea API options"
[[ -n "$GITEA_TOKEN" ]] || die "--gitea-token is required when using Gitea API options"
[[ -n "$GITEA_OWNER" ]] || die "--gitea-owner is required when using Gitea API options"
[[ -n "$GITEA_REPO" ]] || die "--gitea-repo is required when using Gitea API options"
api_base="${GITEA_URL%/}/api/v1"
payload="$(jq -n --arg name "$GITEA_REPO" --argjson private "$GITEA_PRIVATE" '{name:$name, private:$private, auto_init:false}')"
if [[ "$GITEA_OWNER_TYPE" == "org" ]]; then
create_url="$api_base/orgs/$GITEA_OWNER/repos"
else
create_url="$api_base/user/repos"
fi
log "Creating repository on Gitea via API"
set +e
create_resp="$(curl -sS -X POST "$create_url" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$payload")"
create_code=$?
set -e
if [[ $create_code -ne 0 ]]; then
die "Failed to call Gitea API"
fi
if echo "$create_resp" | jq -e '.id' >/dev/null 2>&1; then
log "Repository created: $GITEA_OWNER/$GITEA_REPO"
else
# Repository may already exist; continue if URL can be inferred.
message="$(echo "$create_resp" | jq -r '.message // empty')"
log "Gitea API response: ${message:-non-standard response}"
fi
if [[ -z "$REPO_URL" ]]; then
REPO_URL="ssh://git@${GITEA_URL#*://}:2222/${GITEA_OWNER}/${GITEA_REPO}.git"
fi
fi
if [[ -n "$REPO_URL" ]]; then
git remote add origin "$REPO_URL"
log "Remote origin configured: $REPO_URL"
fi
if [[ "$PUSH" -eq 1 ]]; then
[[ -n "$REPO_URL" ]] || die "Cannot push without remote. Use --repo-url or Gitea API options."
log "Pushing day-0 baseline to origin/$BRANCH"
git push -u origin "$BRANCH"
fi
log "Done"
log "Clean repository path: $TARGET_DIR"
log "Last commit: $(git rev-parse --short HEAD)"