From 9f745178b380e484f426118b6ec43108aa3e3e8b Mon Sep 17 00:00:00 2001 From: "Oliver Surke (Gitea)" Date: Mon, 11 May 2026 15:38:11 +0200 Subject: [PATCH] Add `ssr update` subcommand for self-update - bin/ssr-update: fast-forward `git pull` on the clone with safety guards (dirty tree, detached HEAD, divergent history all abort). - Re-renders & reloads the launchd plist when launchd/ or bin/ssr* changed AND the schedule is currently active, so the cron picks up any plist template updates automatically. - Reports VERSION delta, commit log, and new config keys introduced in config/ssr.conf.example so users can opt-in via `ssr config edit`. - `--dry-run` shows would-be changes without pulling or touching launchd. - Wired into bin/ssr dispatcher + README updated (Updating section, layout entry, command help line). Co-authored-by: Cursor --- README.md | 26 +++++++++++ bin/ssr | 3 +- bin/ssr-update | 117 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100755 bin/ssr-update diff --git a/README.md b/README.md index 9f1aa3c..14d2edd 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ export PATH="$HOME/.local/bin:$PATH" ssr install First-time install: link binary, seed config, schedule sync ssr sync One-shot backup → cloud ssr restore [Brewfile] Restore the machine; Brewfile defaults to the cloud copy +ssr update [--dry-run] Pull latest ssr code, refresh launchd if needed ssr schedule on|off Enable/disable the daily launchd job ssr config show|edit Show or edit the active config ssr status Show config, cloud target, last sync, schedule state @@ -146,6 +147,30 @@ log show --predicate 'process == "ssr"' --last 1h --- +## Updating + +Updates happen on three independent layers: + +**Tool code (this repo).** Self-update via `ssr update`: + +```bash +ssr update # git pull --ff-only on the clone, then refresh side-effects +ssr update --dry-run # show what would change, don't pull +``` + +`ssr update` will: + +- Refuse if the working tree is dirty or HEAD is detached. +- Fast-forward only — never rewrites history. +- Re-render and reload the launchd plist if `launchd/` or `bin/ssr*` changed *and* the schedule is currently active. +- Print added config keys when `config/ssr.conf.example` gained new options. + +**Backup data (cloud drive).** Refreshed automatically by the scheduled `ssr sync`. The previous `Brewfile` is preserved as `Brewfile.bak`; deeper history is provided by the cloud provider's built-in version retention (iCloud Drive, Dropbox, …). Trigger an on-demand sync with `ssr sync`. + +**Dependencies (Homebrew, mackup).** `ssr sync` runs `brew upgrade` and `brew cleanup` when `SSR_BREW_UPGRADE=true` / `SSR_BREW_CLEANUP=true` (both default `true`). Set them to `false` in `ssr.conf` to keep snapshots without auto-upgrading installed packages. + +--- + ## Project layout ``` @@ -154,6 +179,7 @@ log show --predicate 'process == "ssr"' --last 1h ├── bin/ │ ├── ssr # CLI dispatcher │ ├── ssr-install # Local install + scheduling +│ ├── ssr-update # Self-update (git pull + launchd refresh) │ ├── ssr-sync # Backup to cloud │ ├── ssr-restore # Rebuild a Mac from the backup │ ├── ssr-schedule # launchd on/off/status diff --git a/bin/ssr b/bin/ssr index 93539db..ed70934 100755 --- a/bin/ssr +++ b/bin/ssr @@ -29,6 +29,7 @@ Commands: install First-time install: links binary, seeds config, schedules sync. sync Run a backup: brew bundle dump + mackup backup → cloud. restore [Brewfile] Restore a machine: brew bundle + mackup restore + macOS defaults. + update [--dry-run] Pull latest ssr code, refresh launchd if needed. schedule on|off Enable/disable the scheduled launchd sync job. config show|edit Print or edit the active config file. status Show last sync time, cloud target, and scheduled state. @@ -60,7 +61,7 @@ done cmd="$1"; shift case "$cmd" in - install|sync|restore|schedule|config|status) + install|sync|restore|update|schedule|config|status) target="$SSR_BIN_DIR/ssr-$cmd" [[ -x "$target" ]] || ssr::die "Subcommand not executable: $target" exec "$target" "$@" diff --git a/bin/ssr-update b/bin/ssr-update new file mode 100755 index 0000000..a8acc9f --- /dev/null +++ b/bin/ssr-update @@ -0,0 +1,117 @@ +#!/usr/bin/env bash +# ssr-update — pull the latest ssr code from origin and refresh side-effects. +# +# Behavior: +# 1. Verify the repo is a clean git checkout on a real branch. +# 2. git fetch + fast-forward pull. Bail if FF would be impossible. +# 3. Report VERSION delta. +# 4. If the launchd template or any bin/ file changed and the schedule is +# currently active, re-render and reload it. +# 5. If config/ssr.conf.example gained new keys, warn the user. + +set -euo pipefail +SSR_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +# shellcheck source=../lib/common.sh +source "$SSR_ROOT/lib/common.sh" + +DRY_RUN=false +while [[ $# -gt 0 ]]; do + case "$1" in + -n|--dry-run) DRY_RUN=true; shift ;; + -h|--help) + cat </dev/null | grep -q "$label"; then + ssr::log "launchd-relevant files changed → reloading schedule" + "$SSR_ROOT/bin/ssr-schedule" on +fi + +# --- 5. config drift hint ------------------------------------------------- +example="$SSR_ROOT/config/ssr.conf.example" +user_cfg="${SSR_CONFIG:-$HOME/.config/ssr/ssr.conf}" +if [[ -f "$user_cfg" && -f "$example" ]]; then + new_keys="$(comm -23 \ + <(grep -E '^[A-Z_][A-Z0-9_]*=' "$example" | cut -d= -f1 | sort -u) \ + <(grep -E '^[A-Z_][A-Z0-9_]*=' "$user_cfg" | cut -d= -f1 | sort -u))" + if [[ -n "$new_keys" ]]; then + ssr::warn "New config keys available in $example:" + echo "$new_keys" | sed 's/^/ /' + echo "Review with: ssr config edit" + fi +fi + +ssr::ok "Update complete."