#!/bin/bash # adopt-repo.sh — turn an existing, unversioned checklist folder into a clone of the repo, # keeping every secret and every local setting that git deliberately does not carry. # # Written for the ingest Mac (the one whose user account is "Studio"), which still runs the # nightly Drive backup from a copy of this project that predates the repo. Until it has this, # fixes made anywhere else never reach the machine that actually runs the backup at 04:15. # # Safe to re-run. It never deletes the old folder — it renames it and leaves it in place. # # bash adopt-repo.sh # do it # bash adopt-repo.sh --dry-run # print the plan and change nothing set -uo pipefail REPO="http://chronicles-ab.waterschurch.org:3000/christian/recurring-checklist.git" DEST="$HOME/Documents/recurring-checklist-app" STAMP="$(date +%Y%m%d-%H%M%S)" KEEP="$DEST.before-git-$STAMP" DRY=0 [ "${1:-}" = "--dry-run" ] && DRY=1 say() { printf '%s\n' "$*"; } step() { printf '\n== %s\n' "$*"; } run() { if [ $DRY -eq 1 ]; then printf ' would: %s\n' "$*"; else eval "$@"; fi; } die() { printf '\n✗ %s\n' "$*" >&2; exit 1; } # The gitignored files. These are the whole reason this is a careful script and not a # `rm -rf` followed by a clone: none of them are in the repo and some cannot be reissued. SECRETS=( "server/.env" "mobile/keystore.properties" "mobile/keystore/upload-keystore.jks" "mobile/ios-signing.config" "mobile/android/local.properties" ) step "Checking what is here" [ -d "$DEST" ] || die "No folder at $DEST — nothing to adopt. Just clone the repo instead." if [ -d "$DEST/.git" ]; then say " $DEST is already a git checkout — pulling instead of re-cloning." run "cd '$DEST' && git pull --ff-only" say " Done. Skipping the rest; secrets were never touched." exit 0 fi [ -f "$DEST/backup-to-drive.sh" ] || die "$DEST does not look like the checklist project." say " Found an unversioned project at $DEST" step "Checking the secrets that must survive" MISSING=0 for f in "${SECRETS[@]}"; do if [ -e "$DEST/$f" ]; then say " ✓ $f"; else say " · $f (absent — will skip)"; MISSING=$((MISSING+1)); fi done [ -f "$DEST/server/.env" ] || die "server/.env is missing. It is not in the repo and not in the signing DMG. Stopping rather than producing a half-working machine." step "Checking the forge is reachable" curl -fsS -o /dev/null --max-time 15 "http://chronicles-ab.waterschurch.org:3000/api/v1/version" \ || die "Cannot reach the Gitea. This machine must be on the church network." say " ✓ reachable" step "Renaming the old folder out of the way (kept, not deleted)" run "mv '$DEST' '$KEEP'" say " old folder -> $KEEP" step "Cloning" if [ $DRY -eq 0 ]; then if ! git clone "$REPO" "$DEST"; then say " clone failed — putting the old folder back" rm -rf "$DEST"; mv "$KEEP" "$DEST" die "Clone failed and nothing was changed. If it asked for credentials, run: git config --global credential.helper osxkeychain then retry; git will ask once for username 'christian' and a Gitea token (Settings > Applications in the web UI) and remember it." fi else say " would: git clone $REPO $DEST" fi step "Restoring the secrets and local settings" for f in "${SECRETS[@]}"; do if [ -e "$KEEP/$f" ]; then run "mkdir -p '$(dirname "$DEST/$f")'" run "cp -p '$KEEP/$f' '$DEST/$f'" say " ✓ $f" fi done step "Fixing the paths a move always breaks" run "sed -i '' 's|^storeFile=.*|storeFile=$DEST/mobile/keystore/upload-keystore.jks|' '$DEST/mobile/keystore.properties' 2>/dev/null || true" say " keystore.properties storeFile -> $DEST/..." step "Making sure failures can reach a person" if [ $DRY -eq 0 ] && ! grep -q '^ALERT_EMAIL=' "$DEST/server/.env" 2>/dev/null; then printf '\n# Where breakage is reported (comma separated). Falls back to REPORT_EMAIL.\nALERT_EMAIL=christian@waterschurch.org,media@waterschurch.org\n' >> "$DEST/server/.env" say " added ALERT_EMAIL to server/.env" else say " ALERT_EMAIL already set (or dry run)" fi step "Installing server dependencies (alert.js needs nodemailer)" if [ $DRY -eq 0 ]; then ( cd "$DEST/server" && npm install --no-audit --no-fund >/dev/null 2>&1 ) \ && say " ✓ installed" || say " ! npm install failed — alerts will not send until this works" else say " would: npm install in server/" fi step "Pointing the nightly backup at the new folder" PLIST="$HOME/Library/LaunchAgents/org.waterschurch.checklist-drive-backup.plist" if [ -f "$PLIST" ]; then run "launchctl unload '$PLIST' 2>/dev/null || true" run "sed -i '' 's|$KEEP|$DEST|g' '$PLIST'" run "launchctl load '$PLIST'" say " LaunchAgent reloaded against $DEST" say " (check it still points at the right script:)" [ $DRY -eq 0 ] && grep -o '/Users/[^<]*backup-to-drive.sh' "$PLIST" | sed 's/^/ /' else say " ! No LaunchAgent at $PLIST — the nightly backup is not scheduled on this Mac." fi step "Storing the NAS password in this Mac's keychain" if security find-generic-password -s checklist-nas -a Christian >/dev/null 2>&1; then say " ✓ already stored" else say " Not stored yet. Run this and paste the NAS password when prompted:" say " security add-generic-password -U -s checklist-nas -a Christian -w" say " (it is in the checklist-signing DMG, server/nas-ssh-password.txt)" fi step "Proving it works" say " Run the backup by hand once and watch it:" say " cd $DEST && ./backup-to-drive.sh" say "" say "Done. The old folder is still at:" say " $KEEP" say "Delete it once a backup run and a build have both worked."