Add a script to put the ingest Mac on the repo
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 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ff6785b800
commit
4429ae70b7
Executable
+136
@@ -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."
|
||||
Reference in New Issue
Block a user