236 lines
6.6 KiB
Bash
Executable File
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)"
|