opencode-config/docs/handoff/pr-53-git-insteadof.md
Sergey 02f0863a24
fix(memory): persist git insteadOf helper for GITHUB_TOKEN in setup-memory.sh (#53)
* fix(memory): add git insteadOf helper for GITHUB_TOKEN in setup-memory.sh

* test(memory): add tests for git insteadOf helper

* docs(handoff): add handoff + ADR-022 for git insteadOf helper

* docs(handoff): set PR number 53 in handoff + ADR-022

* style: ruff format test_setup_memory.py

---------

Co-authored-by: opencode-agent <agent@slaid098.dev>
2026-07-24 21:28:06 +03:00

4.7 KiB
Raw Blame History

pr title
53 persist git insteadOf helper for GITHUB_TOKEN in setup-memory.sh

PR 53: persist git insteadOf helper for GITHUB_TOKEN in setup-memory.sh

Что сделано

  • .opencode/scripts/setup-memory.sh:29-33 — перед git clone добавлен guarded блок git config --global url."https://x-access-token:${GITHUB_TOKEN}@github.com/".insteadOf https://github.com/. Срабатывает только если GITHUB_TOKEN непустой (if [ -n "${GITHUB_TOKEN:-}" ]), иначе пропускается без ошибки. Расположен ВНУТРИ ветки clone (if [ ! -d "$MEMORY_DIR/.git" ]), т.к. insteadOf нужен только при первом клонировании remote — pull на существующем репо уже авторизован через origin URL.
  • tests/test_setup_memory.py — 4 новых теста:
    • test_script_contains_git_insteadof — grep check: скрипт содержит git config --global url. + .insteadOf https://github.com/, и блок стоит ДО git clone --origin (позиционная проверка insteadof_pos < clone_pos).
    • test_script_contains_github_token_check — grep check: скрипт содержит GITHUB_TOKEN и это guarded check (-n "${GITHUB_TOKEN:-}"), а не hard-fail.
    • test_insteadof_idempotent — функциональный тест: запускает скрипт 2x с fake GITHUB_TOKEN против mock remote (isolated HOME), проверяет что ~/.gitconfig содержит ровно 1 insteadOf entry (не дублируется). git config --global перезаписывает значение, idempotent by git semantics.
    • test_no_github_token_skips_insteadof — когда GITHUB_TOKEN unset, ~/.gitconfig либо не создаётся, либо не содержит insteadOf (skip без ошибки).
  • ADR-022 + этот handoff.

Почему

При миграции opencode-config на linux-1 setup-memory.sh падал с could not read Username for 'https://github.com' при клонировании memory repo — git не подставляет GITHUB_TOKEN автоматически для HTTPS, и в non-interactive контексте (container, нет tty) prompts блокируют clone. Временный fix (git config --global url.insteadOf) применялся вручную, но ~/.gitconfig живёт в overlay container filesystem и теряется при docker compose restart — после рестарта memory-clone снова падал.

Решение: встроить insteadOf helper в сам setup-memory.sh (детерминированный flow, вызывается через memory-setup tool при старте opencode). Скрипт idempotent — git config --global перезаписывает значение, не дублирует. Guarded check на GITHUB_TOKEN — если token отсутствует (локальная dev-среда), скрипт не падает, клон идёт как обычно (для mock/file remotes).

Альтернатива (Dockerfile ENTRYPOINT / .bashrc hack) отклонена — setup-memory.sh вызывается детерминированно через tool, а .bashrc требует interactive shell (non-interactive container его не читает).

Pending

— (нет)

Watch out

  • insteadOf внутри clone-ветки — helper стоит внутри if [ ! -d "$MEMORY_DIR/.git" ], т.е. срабатывает только при первом клонировании. На последующих запусках (pull path) вместо него не выполняется — это намеренно: origin URL уже сохранён в .git/config клона, pull идёт через него. Если remote URL не содержит token (HTTPS без auth), pull упадёт — но это уже проблема конфигурации remote, а не скрипта. Для fresh clone вместоOf переписывает https://github.com/ на https://x-access-token:TOKEN@github.com/ в момент clone.
  • Isolated HOME в тестахtest_insteadof_idempotent и test_no_github_token_skips_insteadof используют HOME=$tmp_path/home, чтобы git config --global не писал в реальный ~/.gitconfig CI-раннера. Без этого тест загрязнил бы глобальный gitconfig.
  • ADR number = 022 (sequential, следующий после 021), НЕ PR number.
  • Существующие 358 тестов не сломаны — полный suite: 362 passed (358 + 4 новых).