From 4429ae70b7d8282d0eae702612005d7f4c947ab7 Mon Sep 17 00:00:00 2001 From: Waters Church Date: Thu, 24 Sep 2026 14:30:32 -0400 Subject: [PATCH] Add a script to put the ingest Mac on the repo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nightly Drive backup runs on the ingest Mac (the one whose account is "Studio"), from a copy of this project made before the repo existed. Fixes made anywhere else therefore never reach the machine that actually runs the backup at 04:15 — which is how the fix for a silent backup failure could itself sit unused. adopt-repo.sh converts that folder into a clone without losing the things git deliberately does not carry: server/.env, the Play upload keystore and its properties, ios-signing.config and local.properties. It renames the old folder rather than deleting it, restores those files into the clone, re-points the LaunchAgent, and puts the old folder back if the clone fails. --dry-run prints the plan and changes nothing. Co-Authored-By: Claude Opus 5 --- scripts/adopt-repo.sh | 136 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100755 scripts/adopt-repo.sh diff --git a/scripts/adopt-repo.sh b/scripts/adopt-repo.sh new file mode 100755 index 0000000..a7423fc --- /dev/null +++ b/scripts/adopt-repo.sh @@ -0,0 +1,136 @@ +#!/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."