Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions gitops_backup/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.1.1

- Fix: keep the addon's own runtime files (`.gitops_backup_status`,
`gitops_backup.log`) out of backups when migrating a repo that already has a
`.gitignore` — they were previously swept into backup PRs and risked a
status-file PR feedback loop. Now excluded via `.git/info/exclude` on every
run, and untracked if a prior run committed them.

## 0.1.0

- Initial release: PR-gated backup (stash → rebase → drift → branch → PR),
Expand Down
2 changes: 1 addition & 1 deletion gitops_backup/config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "HA GitOps",
"version": "0.1.0",
"version": "0.1.1",
"slug": "gitops_backup",
"description": "PR-gated GitHub backup for your Home Assistant config \u2014 nothing force-pushes, every change is reviewable, CI validates before merge",
"url": "https://github.com/askb/ha-gitops",
Expand Down
32 changes: 32 additions & 0 deletions gitops_backup/rootfs/app/gitops_backup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,37 @@ EOF
fi
}

ensure_own_excludes() {
# The addon's own runtime files must never be committed — not even when the
# repo already had a .gitignore (seed_gitignore only writes one when none
# exists, so migrating an existing repo would otherwise sweep these into a
# backup PR and risk a status-file PR feedback loop). .git/info/exclude is
# git's local, non-committed ignore — the right home for addon-managed
# metadata. Idempotent: replace our managed block each run.
[ -d .git ] || return 0
mkdir -p .git/info
local exclude=".git/info/exclude"
if [ -f "$exclude" ]; then
sed -i \
'/# >>> gitops-backup managed >>>/,/# <<< gitops-backup managed <<</d' \
"$exclude"
fi
cat >> "$exclude" <<'EOF'
# >>> gitops-backup managed >>>
.gitops_backup_status
gitops_backup.log
# <<< gitops-backup managed <<<
EOF
# If a prior buggy run already committed these, stop tracking them (the
# removal flows out through the next backup PR).
local f
for f in .gitops_backup_status gitops_backup.log; do
if git ls-files --error-unmatch "$f" >/dev/null 2>&1; then
git rm -q --cached "$f"
fi
done
}

bootstrap_if_needed() {
# Returns 0 if bootstrap ran (caller should stop), 1 if repo already exists
if [ -d .git ]; then return 1; fi
Expand Down Expand Up @@ -151,6 +182,7 @@ main() {
fi
git remote set-url origin "$REMOTE_URL"
seed_gitignore
ensure_own_excludes
trap cleanup_branch EXIT

# 1–2. Stash local drift, sync upstream (merged PRs flow back here)
Expand Down
21 changes: 21 additions & 0 deletions tests/self_check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,25 @@ git -c safe.bareRepository=all -C "$TMP/origin.git" branch | grep -q "auto-backu
status | grep -q "warning:branch_pushed" || { echo "FAIL: drift status = $(status)"; exit 1; }
git -C "$TMP/config" branch --show-current | grep -q "^main$" || { echo "FAIL: not back on main"; exit 1; }

# 4. Migration case: repo already had its own .gitignore lacking the addon's
# entries, and was never excluded. The addon's own status file + log must
# still be kept out of the backup (regression test for the seed_gitignore
# skip-when-.gitignore-exists bug).
sleep 1 # ensure a distinct auto-backup/<timestamp> branch name
rm -f "$TMP/config/.git/info/exclude" # never-excluded repo
printf 'secrets.yaml\n' > "$TMP/config/.gitignore" # user ignore, no addon entries
HOME="$TMP" git -C "$TMP/config" add .gitignore
HOME="$TMP" git -C "$TMP/config" commit -q -m "user gitignore"
echo "success:no_changes:" > "$TMP/config/.gitops_backup_status"
echo "log line" > "$TMP/config/gitops_backup.log"
echo "more drift" >> "$TMP/config/configuration.yaml"
run
newbranch=$(git -c safe.bareRepository=all -C "$TMP/origin.git" branch \
| grep -o 'auto-backup/[^ ]*' | tail -1)
tree=$(git -c safe.bareRepository=all -C "$TMP/origin.git" ls-tree -r --name-only "$newbranch")
if echo "$tree" | grep -qE '^\.gitops_backup_status$|^gitops_backup\.log$'; then
echo "FAIL: addon runtime files committed to backup branch"; exit 1
fi
echo "$tree" | grep -q "^configuration.yaml$" || { echo "FAIL: real drift not backed up"; exit 1; }

echo "OK: all self-checks passed"
Loading