Skip to content

fix(backup): keep the nightly job on copies with no origin remote - #27

Merged
Exploitacious merged 1 commit into
mainfrom
fix/no-origin-keeps-nightly-job
Nov 6, 2026
Merged

Exploitacious merged 1 commit into
mainfrom
fix/no-origin-keeps-nightly-job

Conversation

@Exploitacious

Copy link
Copy Markdown
Owner

What

A copy with no origin remote keeps its nightly job. daily-sync.sh commits the day's work as always, then logs one INFO line instead of an error and returns success; the project pull and branch-gc --apply run as on any copy. deploy.sh and deploy.ps1 schedule the job on every copy again (undoing the gating from #26), and the session briefing reads the INFO line as "local only".

Why

#26 stopped deploy from scheduling the job on a copy with no origin. That silenced the nightly 'origin' does not appear to be a git repository error, but such a copy also lost the job's nightly project pull and branch cleanup. #26's own "Worth a look" named this alternative; this PR takes it.

Behavior

  • No origin remote (git remote lists no origin): the day's work is committed, then the OPS stage logs exactly one line and returns 0:
    • OPS: INFO no origin remote: the day's commit is kept locally; nothing pulled or pushed
    • on a clean day: OPS: INFO no origin remote: no local changes to commit; nothing pulled or pushed
    • no git call talks to a remote; the project and branch-gc stages run (branch-gc skips the OPS repo itself, which has no GitHub origin, and cleans the project repos).
  • A remote under another name (upstream) is still "no origin": the script pulls and pushes only origin (the same rule fix(deploy): schedule the nightly backup only with an origin remote #26 used).
  • "No origin" is read from the local config only, so it can never be a network result. An origin that exists but cannot be reached (offline, a dead URL, no credentials) is still a failed pull and an ERROR, as is an origin with only a push URL. A git remote that itself fails is an ERROR (could not list the git remotes). The match is done in bash, not printf | grep -q, so pipefail cannot turn an early grep exit into "no origin".
  • Every other path is unchanged: commit failures, a rebase in progress, the push gate, the first-push case.
  • Briefing: when the last run logged the INFO line, Backup: local only (no origin remote): the nightly run at <time> kept the work in local commits, nothing pulled or pushed; to back it up off this machine, add a private origin (DEPLOYMENT.md step 8). It is not shown as a failure, and it is not left quiet either, since quiet means the work was backed up off the machine. An ERROR or WARN in the same run still wins.
  • Deploy: no remote check and no no-remote messages. An existing cron line is left alone (Cron job already installed.); on Windows the task is registered with -Force and verified, as before fix(deploy): schedule the nightly backup only with an origin remote #26.

Kept from #26

  • tests/deploy-cron-test.sh and the scheduled-task section of tests/deploy-windows-test.ps1: same harnesses and the same case set (origin, git init copy, a remote named upstream, no repository, an existing entry, unrelated entries, --no-system/-NoSystem). They now assert that the job is scheduled in every case, with no warning, and that the cron and task blocks run no git at all.
  • The deploy.sh --help fix (sed -n '2,42p'); the header stays the same length.

Worth a look

  • branch-gc-safety-test.py's daily-sync stage-order case ran daily-sync.sh on a fixture with no origin and expected a pull. It now gets an origin that is never contacted (its git interceptor fakes the pull), so it still checks the pull, then sync, then gc order.
  • daily-sync-test.sh now names branch-gc (a stub in its fixture), so sandbox-lint requires the guard, and the suite starts with it like the other deploy and branch-gc suites. Run it by hand through sandbox-run (the header says how). CI already runs it there.
  • A directory that is not a git repository is now scheduled too (deploy does not look). Its OPS stage logs the existing ERROR could not resolve current branch, which is loud, and the other stages still run.

Tests

Suite Before After
daily-sync-test.sh 15 21
deploy-cron-test.sh 7 7 (expectations flipped, plus the no-git check)
deploy-windows-test.ps1 18 18 (same)
session-briefing-backup-test.sh 8 14
branch-gc-safety-test.py 89 OK 89 OK (fixture fix)

New daily-sync cases: no origin on a dirty day and on a clean day, a remote named upstream, an unreachable origin, an origin with only a push URL, and a failing git remote. Every other suite under bin/tests and every self-test passes locally in sandbox-run; sandbox-lint reports no violation.

Mutation checks, each run on a copy outside the checkout:

  • pre-change daily-sync.sh: the no-origin case fails (ERROR pull --rebase failed ... 'origin' does not appear to be a git repository)
  • no-origin branch falls through to the pull: fails
  • INFO logged as ERROR: fails
  • "no origin" decided by git ls-remote origin (reachability) instead of the config: the unreachable-origin cases fail
  • a failing git remote not checked: the broken-config case fails
  • pre-change briefing, or the INFO match removed: the local-only cases fail; INFO put ahead of ERROR/WARN: the precedence case fails
  • pre-change deploy.sh / deploy.ps1, or a remote check added back: the no-git assertion fails, and with that assertion disabled the no-origin case still fails (not installed exactly once, not registered once (0))

CHANGELOG, README ("The daily backup"), DEPLOYMENT.md (step 8, the Windows summary, the verification commands) and CONTEXT/how-i-work.md are updated. The 2026-11-05 changelog entry gets a one-line pointer to the new one.

The 2026-11-05 change (#26) stopped deploy from scheduling the nightly job on
a copy with no origin remote. That silenced the nightly "'origin' does not
appear to be a git repository" error, but it also cost such a copy the job's
nightly project pull and branch-gc --apply.

daily-sync.sh is now the one place that decides what a copy with no origin
does. It commits the day's work as always, then logs one line,
"OPS: INFO no origin remote: the day's commit is kept locally; nothing pulled
or pushed" (or "no local changes to commit" on a clean day), returns success,
and the project and branch-gc stages run as on any copy. "No origin" is read
from the local config (`git remote` lists no origin, matched in bash so
pipefail cannot flip it), so an origin that exists but cannot be reached, or
has only a push URL, is still a failed pull and an ERROR; a `git remote` that
fails is an ERROR too.

deploy.sh and deploy.ps1 schedule the job on every copy again and no longer
look at the remotes. The session briefing reads the INFO line as
"Backup:  local only (no origin remote)", neither a failure nor quiet; an
ERROR or WARN in the same run still wins.

Kept from #26: its deploy test harnesses (now asserting the job is scheduled
with and without an origin, and that the cron and task blocks run no git) and
the deploy.sh --help fix. branch-gc-safety-test's daily-sync order case gets
an origin in its fixture so it still exercises the pull. daily-sync-test.sh
now names branch-gc (its fixture stub), so it starts with the sandbox guard.

Docs: CHANGELOG, README ("The daily backup"), DEPLOYMENT.md (step 8, the
Windows summary, the verification commands) and CONTEXT/how-i-work.md.
@Exploitacious
Exploitacious merged commit a37cdbc into main Nov 6, 2026
8 checks passed
@Exploitacious
Exploitacious deleted the fix/no-origin-keeps-nightly-job branch November 6, 2026 14:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant