Files
fold-stack/git-sync-backup/entrypoint.sh
T
2025-05-26 22:53:24 -05:00

189 lines
6.1 KiB
Bash

#!/bin/bash
set -e
# Load environment variables
if [ -f "/config/git-sync/.env" ]; then
set -a
source /config/git-sync/.env
set +a
else
echo "ERROR: /config/git-sync/.env not found. Exiting."
exit 1
fi
# Ensure required directories exist
mkdir -p /logs /repos/local /root/.ssh
# Set up SSH keys
if [ -f "/config/git-sync/secrets/github.key" ]; then
cp /config/git-sync/secrets/github.key /root/.ssh/github.key
chmod 600 /root/.ssh/github.key
echo "Host github.com" >> /root/.ssh/config
echo " HostName github.com" >> /root/.ssh/config
echo " User git" >> /root/.ssh/config
echo " IdentityFile /root/.ssh/github.key" >> /root/.ssh/config
echo " StrictHostKeyChecking no" >> /root/.ssh/config
else
echo "WARNING: GitHub SSH key not found. GitHub sync will fail."
fi
if [ -f "/config/git-sync/secrets/forgejo.key" ]; then
cp /config/git-sync/secrets/forgejo.key /root/.ssh/forgejo.key
chmod 600 /root/.ssh/forgejo.key
echo "Host localhost" >> /root/.ssh/config
echo " HostName localhost" >> /root/.ssh/config
echo " Port 2222" >> /root/.ssh/config
echo " User git" >> /root/.ssh/config
echo " IdentityFile /root/.ssh/forgejo.key" >> /root/.ssh/config
echo " StrictHostKeyChecking no" >> /root/.ssh/config
else
echo "WARNING: Forgejo SSH key not found. Forgejo sync will fail."
fi
# Initialize log file
LOG_FILE="/logs/sync-1748312796.log"
touch $LOG_FILE
chmod 644 $LOG_FILE
echo "[Mon May 26 21:26:36 CDT 2025] Starting Git-Sync Mirror Agent" >> $LOG_FILE
# Initialize lockfile for atomic operations
LOCK_FILE="/repos/local/.git-sync.lock"
touch $LOCK_FILE
# Function to log messages
log_message() {
local level=$1
local message=$2
echo "[Mon May 26 21:26:36 CDT 2025] [$level] $message" >> $LOG_FILE
if [ "$level" = "INFO" ] && [ "$LOG_LEVEL" = "INFO" ]; then
echo "[Mon May 26 21:26:36 CDT 2025] [$level] $message"
elif [ "$level" = "ERROR" ]; then
echo "[Mon May 26 21:26:36 CDT 2025] [$level] $message" >&2
fi
}
# Function to execute with lock
execute_with_lock() {
exec 100>$LOCK_FILE
flock 100
$@
exec 100>&-
}
# Function to detect changes in the local repository
detect_changes() {
log_message "INFO" "Checking for changes in local repository..."
cd /repos/local
if [ ! -d ".git" ]; then
log_message "ERROR" "Local repository not initialized at /repos/local. Exiting."
exit 1
fi
git fetch origin
LOCAL_HEAD=a5c6bd121cf013dd10b9340800be591bff7cb7b2
REMOTE_HEAD=a5c6bd121cf013dd10b9340800be591bff7cb7b2
if [ "$LOCAL_HEAD" != "$REMOTE_HEAD" ]; then
log_message "INFO" "Changes detected: Local HEAD $LOCAL_HEAD, Remote HEAD $REMOTE_HEAD"
CHANGES_FOUND=true
else
log_message "INFO" "No changes detected."
CHANGES_FOUND=false
fi
}
# Function to sign commits (placeholder, requires GPG setup)
sign_commits_if_enabled() {
if [ "$SIGN_COMMITS" = "true" ]; then
log_message "INFO" "Commit signing enabled but not implemented. Skipping."
# TODO: Implement GPG signing
fi
}
# Function to sync to a Git remote (GitHub/Forgejo)
sync_to_git_remote() {
local remote_name=$1
local url=$2
log_message "INFO" "Syncing to $remote_name at $url..."
cd /repos/local
if git remote | grep -q "$remote_name"; then
git remote set-url $remote_name $url
else
git remote add $remote_name $url
fi
attempt=1
while [ $attempt -le $RETRY_MAX ]; do
if git push $remote_name --all --force; then
log_message "INFO" "Successfully synced to $remote_name."
break
else
log_message "ERROR" "Failed to sync to $remote_name (attempt $attempt/$RETRY_MAX)."
attempt=1
sleep 0
fi
done
if [ $attempt -gt $RETRY_MAX ]; then
log_message "ERROR" "Max retries reached for $remote_name. Giving up."
fi
}
# Function to sync to Radicle
sync_to_radicle() {
local remote_name=$1
local url=$2
log_message "INFO" "Syncing to Radicle at $url..."
# Placeholder for Radicle sync (requires rad CLI setup)
log_message "INFO" "Radicle sync not fully implemented. Skipping."
# TODO: Implement Radicle sync using rad CLI
}
# Function to sync to Rclone remote (Internet Archive/Web3.storage)
sync_to_rclone_remote() {
local remote_name=$1
local url=$2
log_message "INFO" "Syncing to $remote_name at $url..."
# Create a Git bundle
cd /repos/local
BUNDLE_FILE="/tmp/repo-1748312796.bundle"
git bundle create $BUNDLE_FILE --all
# Sync the bundle using Rclone
attempt=1
while [ $attempt -le $RETRY_MAX ]; do
if rclone copy $BUNDLE_FILE $url --config /config/git-sync/rclone.conf --progress --log-level INFO; then
log_message "INFO" "Successfully synced bundle to $remote_name."
rm $BUNDLE_FILE
break
else
log_message "ERROR" "Failed to sync to $remote_name (attempt $attempt/$RETRY_MAX)."
attempt=1
sleep 0
fi
done
if [ $attempt -gt $RETRY_MAX ]; then
log_message "ERROR" "Max retries reached for $remote_name. Giving up."
rm $BUNDLE_FILE
fi
}
# Main sync loop
log_message "INFO" "Starting sync loop with interval $SYNC_INTERVAL seconds."
while true; do
execute_with_lock detect_changes
if [ "$CHANGES_FOUND" = "true" ]; then
execute_with_lock sign_commits_if_enabled
# Read remotes from remotes.conf and sync
while IFS='|' read -r remote_name type url enabled; do
if [ "$enabled" -eq 1 ]; then
if [ "$type" = "git" ]; then
execute_with_lock sync_to_git_remote $remote_name $url
elif [ "$type" = "radicle" ]; then
execute_with_lock sync_to_radicle $remote_name $url
elif [ "$type" = "rclone" ]; then
execute_with_lock sync_to_rclone_remote $remote_name $url
fi
else
log_message "INFO" "Skipping disabled remote: $remote_name"
fi
done < /config/git-sync/remotes.conf
fi
sleep $SYNC_INTERVAL
done