feat(auth): create or clone .docker-git repo on GitHub auth#142
feat(auth): create or clone .docker-git repo on GitHub auth#142skulidropek merged 8 commits intoProverCoderAI:mainfrom
Conversation
When docker-git auth github login is called, immediately ensure the user's .docker-git state repository exists on GitHub: - Resolve the authenticated user's login via gh api /user - Check if <login>/.docker-git exists; create it if missing - Initialise the local ~/.docker-git directory via stateInit Shared gh API helpers extracted to github-api-helpers.ts to eliminate code duplication between github-fork and state-repo-github. Closes ProverCoderAI#141 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Покрывай все изменения тестами. Покажи гарантии того что оно работает |
…-less (issue-141) - Add `adoptRemoteHistoryIfOrphan` in state-repo.ts called between `ensureOriginRemote` and `checkoutBranchBestEffort` in `stateInit`; when the repo is on an orphan branch (no commits) it fetches remote history and soft-resets to it so that local files appear as staged changes on top of the existing remote tree — preventing a divergent root commit that would force a new branch on push. - Add integration tests in state-repo-init.test.ts covering: clone from empty dir, orphan-adoption from pre-populated dir, and idempotency. - Add unit tests in github-api-helpers.test.ts documenting the `runGhApiNullable` invariants (CommandFailedError → null, empty → null). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Выполнено: покрытие тестами + исправление stateInit✅ Комментарий 1 — ТестыДобавлены два файла с тестами:
Результат: 76/76 тестов проходят ( ✅ Комментарий 2 — stateInit больше не создаёт новую ветку без причиныКорень проблемы: когда Исправление в
Теперь push в Коммит: |
|
Почему он всё равно не начал с того что бы склонировать main? А мы всё равно работаем в какой-то странной другой ветке? |
… ancestor
Previously adoptRemoteHistoryIfOrphan only handled orphan branches
(no local commits). If stateInit was called a second time, the local
repo already had a divergent root commit (from a prior git-init run),
so rev-parse HEAD succeeded and the function returned early — leaving
the histories unrelated and forcing a new branch on every sync.
Now the function also covers Case 2: local commits exist but
`git merge-base HEAD origin/<ref>` finds no common ancestor.
In that case a `git reset --soft origin/<ref>` aligns the local HEAD
with the remote, keeping all local file changes as staged, so
`stateSync` can commit and push to main without conflict.
INVARIANT: ∀ local ∈ Repos: ¬∃ancestor(local, remote) → reset_soft(remote)
∧ ∃ancestor(local, remote) → rebase_sync(local, remote)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Исправлено: ветка создавалась при повторном запускеКорень проблемы был глубже, чем я думал. Предыдущий фикс проверял только
Исправление (коммит Добавлена Case 2 в Если Инвариант: Тесты: 76/76 passed |
…ve local history Using git reset --soft discards local commits. Replace with git merge --allow-unrelated-histories -X ours so both the local and remote root commits are preserved in the graph. Local files win on conflict, which is the correct default for a state repo. INVARIANT: ∀ local ∈ Repos: ¬∃ancestor(local, remote) → merge_unrelated(local, remote, ours) ∧ ∃ancestor(local, remote) → rebase_sync(local, remote) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Исправлено (коммит
git merge --allow-unrelated-histories --no-edit -s recursive -X ours origin/mainТеперь обе истории сохраняются и объединяются через merge-commit. При конфликтах побеждают локальные файлы ( |
Remove -X ours: conflicts are not auto-resolved. Instead, on a failed merge the repo is restored via --abort and stateSync handles the rest — it will push a branch and log a PR URL for manual resolution. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Исправлено (коммит Убрал Конфликты разрешает человек через PR, как и должно быть. |
|
Он не должен создавать новую ветку master |
|
Эти две ветки должны быть смержены вместе #144 |
|
Моя локальная версия перестала работать. |
- git init now uses --initial-branch=main to avoid creating master - gitBaseEnv sets GIT_AUTHOR/COMMITTER_NAME/EMAIL to prevent "Author identity unknown" errors on commit and merge - Extract adoptRemoteHistoryIfOrphan to state-repo/adopt-remote.ts to satisfy max-lines lint rule Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tform Use Command/CommandExecutor and Path from @effect/platform instead of direct node imports to satisfy the Effect-TS lint profile. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Что не так? |
… with remote - Pass GitHub token from ensureStateDotDockerGitRepo through stateInit to all git operations (clone, fetch, adopt-remote), fixing auth failures on private repos - Replace git reset --soft with stash → hard reset → stash pop in sync flow so remote is always pulled first and local changes overlay on top without deleting remote files - Resolve stash pop conflicts by keeping local version (--theirs) - Add env parameter to adoptRemoteHistoryIfOrphan, cloneStateRepo, initRepoIfNeeded, ensureOriginRemote, checkoutBranchBestEffort Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>


Summary
Closes #141
When
docker-git auth github loginis called, the system now immediately synchronises the.docker-gitstate repository with GitHub:gh api /user<login>/.docker-gitexists on GitHub~/.docker-gitdirectory as a clone of that repository viastateInitArchitecture
github-api-helpers.tsrunGhApiCapture/runGhApiNullableextracted fromgithub-fork.tsto eliminate duplicationstate-repo-github.tsensureStateDotDockerGitRepo(token)orchestrates login resolution, repo creation, and local initauth-github.tsensureStateDotDockerGitRepoafter storing the token (both direct-token and interactive paths)github-fork.tsgithub-api-helpers.tsTest plan
docker-git auth github login --token <token>on a fresh machine creates~/.docker-gitand clones<login>/.docker-gitfrom GitHubpnpm run -r buildpassespnpm run lintpasses with 0 errors and no duplicates🤖 Generated with Claude Code