Files
TX/scripts/publish-to-gitea.sh
riyadhafraa a85baa33f7 Improve script to prevent leaking sensitive tokens
Sanitize remote URLs to prevent token leaks and automatically inject GITEA_TOKEN into push URLs.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: db8b7fbd-83f8-4911-a71a-e6e5b6f8f1fd
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/eDmI6vt
Replit-Helium-Checkpoint-Created: true
2026-05-19 12:25:17 +00:00

163 lines
6.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# -----------------------------------------------------------------------------
# publish-to-gitea.sh
#
# Publishes a SANITIZED copy of this repository to a remote git server (Gitea
# by default). Runs entirely in a throw-away temp directory — your real
# working tree, Replit workspace, and local git history are never touched.
#
# What gets stripped from the published mirror:
# • Files: .replit, .replitignore, replit.nix, .local/, .agents/,
# attached_assets/, every .replit-artifact/ directory,
# every artifact.toml inside .replit-artifact/, .gitsafe-backup
# • Commit messages: every line starting with "Replit-" is removed.
# • Author/committer identity: rewritten to AUTHOR_NAME / AUTHOR_EMAIL
# (default: Riyadh <dev@tx.local>; override via env vars).
#
# Usage:
# ./scripts/publish-to-gitea.sh # dry run preview
# ./scripts/publish-to-gitea.sh --push # actually force-push
# AUTHOR_NAME="John" AUTHOR_EMAIL=a@b.c ./scripts/publish-to-gitea.sh --push
# GITEA_REMOTE_URL=https://... ./scripts/publish-to-gitea.sh --push
# GITEA_BRANCH=main ./scripts/publish-to-gitea.sh --push
# -----------------------------------------------------------------------------
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$REPO_ROOT"
AUTHOR_NAME="${AUTHOR_NAME:-Riyadh}"
AUTHOR_EMAIL="${AUTHOR_EMAIL:-dev@tx.local}"
GITEA_REMOTE_URL="${GITEA_REMOTE_URL:-$(git config --get remote.origin.url || echo "")}"
GITEA_BRANCH="${GITEA_BRANCH:-main}"
PUSH=0
[[ "${1:-}" == "--push" ]] && PUSH=1
if [[ -z "$GITEA_REMOTE_URL" ]]; then
echo "ERROR: no remote URL. Set GITEA_REMOTE_URL or add a git remote named 'origin'." >&2
exit 1
fi
# Strip any embedded "user:token@" so we never echo credentials. Used for
# all human-facing prints; the real $GITEA_REMOTE_URL (with token) is still
# what gets handed to git for the actual push.
sanitize_url() {
# shellcheck disable=SC2001
echo "$1" | sed -E 's#^(https?://)[^/@]+@#\1#'
}
SAFE_REMOTE_URL="$(sanitize_url "$GITEA_REMOTE_URL")"
echo "================================================================"
echo " Publish-to-Gitea — sanitized history mirror"
echo "----------------------------------------------------------------"
echo " Source repo: $REPO_ROOT"
echo " Target remote: $SAFE_REMOTE_URL"
echo " Target branch: $GITEA_BRANCH"
echo " New author: $AUTHOR_NAME <$AUTHOR_EMAIL>"
echo " Mode: $([[ $PUSH == 1 ]] && echo 'PUSH (will force-push)' || echo 'DRY RUN (no push)')"
echo "================================================================"
echo
WORK_DIR="$(mktemp -d -t tx-publish-XXXXXX)"
trap 'rm -rf "$WORK_DIR"' EXIT
# -- 1. Acquire git-filter-repo (single-file Python script) -------------------
FILTER_REPO="$WORK_DIR/git-filter-repo"
if command -v git-filter-repo >/dev/null 2>&1; then
FILTER_REPO="$(command -v git-filter-repo)"
echo "[1/5] Using system git-filter-repo: $FILTER_REPO"
else
echo "[1/5] Downloading git-filter-repo into temp dir ..."
if command -v curl >/dev/null 2>&1; then
curl -fsSL -o "$FILTER_REPO" \
"https://raw.githubusercontent.com/newren/git-filter-repo/v2.47.0/git-filter-repo"
elif command -v wget >/dev/null 2>&1; then
wget -q -O "$FILTER_REPO" \
"https://raw.githubusercontent.com/newren/git-filter-repo/v2.47.0/git-filter-repo"
else
echo "ERROR: neither curl nor wget is available." >&2
exit 1
fi
chmod +x "$FILTER_REPO"
fi
# -- 2. Mirror-clone the local repo into the temp dir -------------------------
MIRROR="$WORK_DIR/mirror"
echo "[2/5] Cloning a fresh mirror of the local repo ..."
git clone --no-local --bare "$REPO_ROOT" "$MIRROR" >/dev/null 2>&1 || \
git clone --bare "$REPO_ROOT" "$MIRROR" >/dev/null
# -- 3. Strip Replit-only paths from the entire history -----------------------
echo "[3/5] Removing Replit-specific files from every commit ..."
"$FILTER_REPO" --force --source "$MIRROR" --target "$MIRROR" \
--invert-paths \
--path .replit \
--path .replitignore \
--path replit.nix \
--path replit.md \
--path .local \
--path .agents \
--path attached_assets \
--path .gitsafe-backup \
--path PUBLISH.md \
--path MIGRATION_REPORT.md \
--path-glob '**/.replit-artifact' \
--path-glob '**/.replit-artifact/**'
# -- 4. Rewrite commit messages and author identity ---------------------------
echo "[4/5] Stripping 'Replit-*' trailers and rewriting author identity ..."
MSG_CALLBACK='
import re
text = message.decode("utf-8", errors="replace")
# Drop every line that begins with "Replit-"
cleaned = "\n".join(
line for line in text.splitlines()
if not re.match(r"^\s*Replit-", line)
)
# Collapse trailing whitespace
cleaned = re.sub(r"\n{3,}$", "\n\n", cleaned).rstrip() + "\n"
return cleaned.encode("utf-8")
'
NAME_BYTES="$(printf '%s' "$AUTHOR_NAME")"
EMAIL_BYTES="$(printf '%s' "$AUTHOR_EMAIL")"
NAME_CALLBACK="return b\"$NAME_BYTES\""
EMAIL_CALLBACK="return b\"$EMAIL_BYTES\""
"$FILTER_REPO" --force --source "$MIRROR" --target "$MIRROR" \
--message-callback "$MSG_CALLBACK" \
--name-callback "$NAME_CALLBACK" \
--email-callback "$EMAIL_CALLBACK"
# -- 5. Push (or preview) -----------------------------------------------------
echo "[5/5] Final state of the sanitized mirror:"
echo
git --git-dir="$MIRROR" log --pretty=format:'%h %an <%ae> %s' -n 5
echo
echo
echo "Tip: inspect the cleaned tree with:"
echo " git --git-dir=$MIRROR log --all --stat | less"
echo
if [[ $PUSH -eq 1 ]]; then
# Auto-inject GITEA_TOKEN into the push URL if the remote is https://
# and has no credentials already. Keeps the token out of any echoed
# output: $PUSH_URL is only ever passed to git, never printed.
PUSH_URL="$GITEA_REMOTE_URL"
if [[ -n "${GITEA_TOKEN:-}" && "$PUSH_URL" =~ ^https?:// && ! "$PUSH_URL" =~ @ ]]; then
PUSH_USER="${GITEA_USERNAME:-rafraa}"
PUSH_URL="$(echo "$PUSH_URL" | sed -E "s#^(https?://)#\1${PUSH_USER}:${GITEA_TOKEN}@#")"
fi
echo "Force-pushing branch '$GITEA_BRANCH' to $SAFE_REMOTE_URL ..."
git --git-dir="$MIRROR" remote add gitea "$PUSH_URL" 2>/dev/null || \
git --git-dir="$MIRROR" remote set-url gitea "$PUSH_URL"
git --git-dir="$MIRROR" push --force gitea "HEAD:refs/heads/$GITEA_BRANCH"
echo
echo "Done. Open $SAFE_REMOTE_URL to verify."
else
echo "DRY RUN complete — nothing was pushed."
echo "Re-run with --push to publish: ./scripts/publish-to-gitea.sh --push"
fi