fix(install): fetch hosted git deps over https, not ssh#394
Conversation
Match npm pacote / pnpm gitHostedTarballFetcher: for github / gitlab / bitbucket deps, the lockfile-canonical `git+ssh://git@…` URL is identity-only — re-derive an HTTPS URL from `(host, owner, repo, sha)` each install. Public reads go through `codeload.github.com/<owner>/<repo>/tar.gz/<sha>` (no `git` binary, no SSH key); on any HTTP error, fall back to a shallow `git clone` over the rewritten HTTPS URL so a system git credential helper (gh CLI etc.) keeps private repos working. Branch / tag committishes are pinned via `git ls-remote` on the same rewritten HTTPS URL before reaching the codeload path, so users with no SSH key configured can install non-SHA-pinned hosted git deps too. Non-hosted hosts (self-hosted GitLab / Gitea / arbitrary) keep using the URL as written in the lockfile, preserving SSH-only setups. Closes the follow-up reported in discussion #335 after #338: a `package-lock.json` recording `git+ssh://git@github.com/…#<sha>` no longer requires an SSH key to install. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR re-derives HTTPS fetch URLs at install/resolve time for GitHub, GitLab, and Bitbucket deps instead of dialling the lockfile-canonical Confidence Score: 5/5Safe to merge; only P2 findings present, both in edge cases that fall back gracefully to git clone. All P1-level concerns (codeload extraction failure falling back to clone, SSH→HTTPS rewrite consistency, cache key agreement between resolver and installer, tar safety) are handled correctly. Two P2 items found: dead crates/aube-store/src/lib.rs — concurrent rename recovery path around line 1971 Important Files Changed
Reviews (4): Last reviewed commit: "fix(resolver): fall back to clone on cod..." | Re-trigger Greptile |
Two review-flagged issues:
1. The three new codeload tests sandboxed `cache_dir()` by mutating
`XDG_CACHE_HOME` from inside `unsafe { set_var }`. cargo test runs
in parallel by default, so tests racing on the env-var read each
other's tempdir — Linux happened to schedule us out of it but
Windows surfaced it as a PermissionDenied on a sibling test's
already-dropped tempdir, breaking CI on that runner.
Factor a private `extract_codeload_tarball_at(cache_root, …)` and
have tests pass their own `tempfile::tempdir()` directly. The
public wrapper still resolves the cache root via `dirs::cache_dir()`,
so production callers are unchanged.
2. The Windows symlink branch of `extract_codeload_tarball` was a
silent `let _ = …` — packages that ship symlinks would extract
into a half-populated tree and the linker would later fail on a
missing entry several layers down with no breadcrumb back to the
git dep. Surface it as `Error::Tar` with a hint to remove the
cached extract so the next install attempt falls through to
`git clone` (which materializes symlinks via git's own write path).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Addressed both findings + the windows CI failure (same root cause as the test
Verified locally: 75/75 store unit tests + 11/11 git_deps bats green. CI should be clean now. |
Both the resolver and the install path were calling `fetch_tarball_bytes` *before* `extract_codeload_tarball`'s top-of- function `target.is_dir()` check. On the resolver→installer reuse path that meant the installer paid a full HTTPS round-trip for the codeload tarball only for the extract to immediately short-circuit and discard the bytes. The `git_shallow_clone` fallback already has this fast path at its entry — codeload should match. Add `aube_store::codeload_cache_lookup(url, commit)` (a public, network-free `target.is_dir()` probe sharing the same cache key derivation as the extract path) and consult it before the fetch in both call sites. Cache miss → unchanged behavior. Cache hit → skip the download entirely. Found by Cursor Bugbot review on PR #394. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Cursor Bugbot's redundant-download finding addressed in b3a5dad: added |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b3a5dad. Configure here.
Mirror the installer: a corrupt or unexpectedly-shaped codeload tarball (CDN hiccup, unsafe-path rejection, Windows symlink) now falls through to the shallow `git clone` path instead of hard-failing the resolve. Previously the `??` on `spawn_blocking` propagated the inner extract error past the clone fallback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Addressed in 8bd9198: the resolver's codeload extract path now matches on Verified locally: Written with Claude. |

Summary
(host, owner, repo, sha)at fetch time instead of dialing whatever scheme the lockfile recorded. Matches npmpacoteand pnpmgitHostedTarballFetcher.https://codeload.github.com/<owner>/<repo>/tar.gz/<sha>(nogitbinary, no SSH key); on any HTTP error, fall back to a shallowgit cloneover the rewritten HTTPS URL so a system git credential helper (gh CLI etc.) keeps private repos working.git ls-remoteon the same rewritten HTTPS URL before reaching the codeload path. Non-hosted hosts (self-hosted GitLab / Gitea / arbitrary) still use the URL as written, preserving SSH-only setups.Why
Reported in discussion #335 as a follow-up to #338. After #338 made
package-lock.jsongit deps parse correctly, aube was dialing the lockfile-canonicalgit+ssh://git@github.com/…#<sha>directly, which fails for users with HTTPS-only git auth (e.g.ghCLI's git credential helper, no~/.ssh/). npm/pnpm never dial that SSH URL — it's an identity form, not a fetch URL.LocalSource::Git.urlin the lockfile is preserved verbatim so cross-tool round-trip with pnpm / npm / yarn is unaffected.Test plan
cargo test -p aube-lockfile -p aube-store -p aube-resolver --lib(459 unit tests, all green)cargo clippy --all-targets -- -D warningscargo fmt --checkmise run test:bats test/git_deps.bats test/install.bats test/package_lock_write.bats(87 / 87 pass — clone fallback path unchanged)parse_hosted_gitacross all clone-URL forms (https / ssh / git+ / scp /github:), per-provider codeload URL synthesis,extract_codeload_tarballwrapper-strip + caching, defense against../absolute symlink targets in tarball entries, short-commit rejection.🤖 Generated with Claude Code
Note
Medium Risk
Changes git dependency fetching/materialization and introduces new tarball extraction logic, which can affect install reliability and security if edge cases slip through. Mitigated by strict SHA gating, cache reuse, and explicit unsafe-path/symlink defenses with clone fallback.
Overview
Git dependencies on GitHub/GitLab/Bitbucket are now resolved/installed using npm/pnpm-like hosted routing: derive a canonical
(host, owner, repo)identity from the lockfile URL, pin refs viagit ls-remoteover derived HTTPS, then prefer fetching a provider-specific codeload-style tarball for full-SHA commits (with fallback to shallowgit clone).This adds a new codeload extraction cache and hardened tarball extraction path in
aube-store(wrapper-dir stripping, atomic cache population, entry/path/symlink validation, and Windows symlink handling), and wires the new flow through both the resolver (resolve_git_sourcenow takes an optionalRegistryClient) and installer while keeping the original lockfileurlbytes unchanged for cross-tool round-tripping.Reviewed by Cursor Bugbot for commit 8bd9198. Bugbot is set up for automated code reviews on this repo. Configure here.