fix(memory-save): self-healing git auth bridge + non-silent push hook #31
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Контекст
При миграции с GitHub на Forgejo (ADR-093) было удалено insteadOf-правило для GitHub (
url."https://x-access-token:${GITHUB_TOKEN}@github.com/".insteadOf https://github.com/), но аналогичное правило для Forgejo не создали. Результат:git pushнаhttps://git.slaid098.dev/...падает с 401 — нет моста между env-переменными (FORGEJO_TOKEN/FORGEJO_URL) и git-конфигом. git не читает env-переменные, ему нужен токен в~/.gitconfigили remote URL.Это касается всех репозиториев, не только opencode-memory. Но проявилось на opencode-memory, потому что
memory-save.tsобновляет remote черезOPENCODE_MEMORY_REMOTEenv var, а post-commit hook тихо глотал ошибки push (2>/dev/null || true). 29 коммитов накопилось локально за сутки, пока пользователь не заметил расхождение.Дополнительно:
~/.gitconfigне персистится при пересоздании контейнера (если/rootvolume будет стёрт — insteadOf-правило пропадёт, и проблема вернётся).Задача
Реализовать self-healing git auth bridge: автоматическое (пере)создание insteadOf-правила для Forgejo из env-переменных, чтобы авторизация git никогда не требовала ручной настройки. Покрывает ВСЕ репо глобально, переживает пересоздание контейнера / стирание
~/.gitconfig.Вторая часть: сделать post-commit hook памяти не-silent на ошибки push — чтобы при сломанном sync ошибка была видна сразу, а не через неделю.
Контракты
Self-healing auth bridge
FORGEJO_TOKEN(env) +FORGEJO_URL(env, e.g.https://git.slaid098.dev)git config --global url."https://slaid098:${FORGEJO_TOKEN}@<host>/".insteadOf <FORGEJO_URL>/— где<host>= хост изFORGEJO_URL(parse),FORGEJO_URLбез trailing slashautoSetup()функцииmemory-save.ts(строки 18-68) — добавить блок, обеспечивающий insteadOf-правило, рядом с блокомif (remote)(строки 45-61). Вызывается безусловно при каждомmemory-save(как уже делает remote-update).git config --global --get-regexp), не переписывать если уже корректно (аналогично логике remote-update на строках 56-59)FORGEJO_TOKENилиFORGEJO_URLне заданы — пропустить (не падать, не предупреждать — это валидный кейс для пользователей без Forgejo)steps.push(...)НЕ выводить токен (замаскировать как***)Non-silent push hook
#!/bin/bash\ngit push origin master 2>/dev/null || true2>/dev/null), но не падать (оставить|| true— commit не должен фейлиться из-за push)#!/bin/bash\ngit push origin master || echo "[memory] push failed (non-fatal)" >&2memory-savedetect старый hook (сравнение сHOOK_BODYна строке 49) и перезаписать новым (needHook=true → writeFileSync)Инварианты
memory-saveНЕ падает, еслиFORGEJO_TOKEN/FORGEJO_URLотсутствуют — мост пропускается (backward compatible)memory-saveостаётся идемпотентным: повторный вызов не переписывает корректное insteadOf-правилоmemory-save(steps array) — только замаскированныйmemory-saveremote обновляется (еслиOPENCODE_MEMORY_REMOTEуказывает на Forgejo) + мост создаётся → push работаетГраничные случаи
FORGEJO_URLс trailing slash (https://git.slaid098.dev/) → вместоOf должен использовать без trailing slash, но матчить с trailing slash (git требует точный match)FORGEJO_TOKENсодержит спецсимволы (например/,+) → git config URL handling может сломаться. Решение: URL-encode токен? Проверить.~/.gitconfigread-only (immutable) →git config --globalупадёт.memory-saveдолжен сообщить warning, не падать.FORGEJO_URL=https://git.slaid098.dev(без path) vshttps://git.slaid098.dev/subpath(Forgejo в subpath) → вместоOf должен покрывать хост целиком, не pathВлияние на связанные компоненты
git push/git fetch/git cloneкgit.slaid098.dev. Это желаемое поведение (пользователь явно подтвердил: "для всех репозиториев автоматически").create-pr,merge-pr, etc.): push feature-веток на Forgejo — сейчас работает через токен-in-URL илиcurl; после моста — будет работать через чистый URL + insteadOf. Не ломается.checkGit()(строки ~70-80) — отображать ✓/✗ для "Forgejo auth bridge (insteadOf)" рядом сOPENCODE_MEMORY_REMOTEcheck (строки 90-92).## Git Host— можно обновить, указав что insteadOf-мост создаётся автоматическиmemory-save(раньше было "для операций без tool'а — curl к Forgejo API" — теперь git-native push тоже работает).OPENCODE_MEMORY_REMOTEкомментарий "optional — auto-setup on first memory-save if unset" — можно дополнить: "auth bridge auto-created from FORGEJO_TOKEN/FORGEJO_URL".Вне scope
.envфайла на хосте (это ручная операция пользователя, вне контейнера)git credential.helper storeкак альтернатива insteadOf (insteadOf проще и уже работает)setup-memory.sh— удалён в PR#103/ADR-045, не воскрешатьКритерии приемки
memory-saveвызывается в окружении сFORGEJO_TOKEN+FORGEJO_URL→ создаёт insteadOf-правило в~/.gitconfig(если отсутствует или токен сменился)memory-saveвызывается БЕЗFORGEJO_TOKEN/FORGEJO_URL→ мост пропускается, не падает, не warnsmemory-savegit pushнаhttps://git.slaid098.dev/...(чистый URL) проходит без 401[memory] push failed (non-fatal)в stderr, commit остаётся успешным2>/dev/null || true) перезаписывается новым при следующемmemory-savememory-save(steps array) — только***memory-doctorотображает статус insteadOf-моста (✓/✗)