Skip to content

feat(git): per-repo partial-clone snapshot filters#394

Open
luispadron wants to merge 2 commits into
block:mainfrom
luispadron:luis/git-snapshot-filters
Open

feat(git): per-repo partial-clone snapshot filters#394
luispadron wants to merge 2 commits into
block:mainfrom
luispadron:luis/git-snapshot-filters

Conversation

@luispadron

@luispadron luispadron commented Jul 21, 2026

Copy link
Copy Markdown

Adds a snapshot-filters option to the git strategy: a map of host/org/repo to a git partial-clone filter (e.g. blob:none) applied to the workstation snapshot clone. Filtered snapshots keep full commit/tree history but only the blobs needed for the HEAD checkout; clients lazily fetch historical blobs through cachew on demand (mirrors already set uploadpack.allowFilter and allowAnySHA1InWant).

Motivation: for repos whose history dwarfs their checkout, the snapshot artifact is almost entirely dead weight. One large monorepo we cache serves a snapshot in the tens of GB, dominated by superseded binary test fixtures in history, while its HEAD checkout needs about 1 GiB — a blob:none snapshot of the same repo is roughly 95% smaller, which proportionally cuts snapshot storage, transfer, and the download window in which client timeouts and stalls can occur.

Details:

  • The filtered clone uses --no-local (git silently ignores --filter on hardlink local clones), which also stops objects unreachable from cloned refs — e.g. refs/pull/* history in the mirror — from riding along into the artifact.
  • A post-clone check fails generation loudly if the filter was silently ignored, rather than caching a full-size artifact for a repo configured to be filtered.
  • The filter applies to all client-facing snapshot paths (periodic generation, spool writer, direct stream). Mirror snapshots (pod bootstrap) and LFS snapshots are unchanged; the LFS clone stays unfiltered so its lazy fetches never hit upstream without credential injection.
  • Delta bundles are unaffected: bundles carry full objects, and fetching into a partial clone works normally.

Default behavior is unchanged; repos opt in via configuration.

@luispadron
luispadron marked this pull request as ready for review July 21, 2026 20:01
@luispadron
luispadron requested a review from a team as a code owner July 21, 2026 20:01
@luispadron
luispadron requested review from worstell and removed request for a team July 21, 2026 20:01

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2be39bef90

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/strategy/git/snapshot.go Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 903a4c67fc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/strategy/git/snapshot_test.go
luispadron and others added 2 commits July 23, 2026 12:01
Some repos' snapshot artifacts are dominated by history no checkout ever
touches. A new snapshot-filters config maps host/org/repo to a git
partial-clone filter (e.g. blob:none) applied to the workstation snapshot
clone via --no-local --filter. Filtered snapshots keep full commit/tree
history but only HEAD blobs; clients lazily fetch older blobs through
cachew. Mirror and LFS snapshots are unchanged.

Co-authored-by: Claude Code <noreply@anthropic.com>
Ai-assisted: true
git writes remote.origin.promisor and partialclonefilter even when the
server does not support filtering and the clone silently falls back to a
full clone, so the promisor config is no proof the filter applied. Detect
the fallback from git's warning in the clone output instead, with LC_ALL=C
pinned so the message is not localized.

Co-authored-by: Claude Code <noreply@anthropic.com>
Ai-assisted: true
@luispadron
luispadron force-pushed the luis/git-snapshot-filters branch from 903a4c6 to 64dbbc0 Compare July 23, 2026 16:04

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 64dbbc05d9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

ZstdThreads int `hcl:"zstd-threads,optional" help:"Threads for zstd compression/decompression. 0 = all CPU cores; useful for short-lived CLI invocations but risky on a long-running server where multiple snapshot/restore operations can run concurrently." default:"4"`
BundleCacheTTL time.Duration `hcl:"bundle-cache-ttl,optional" help:"TTL of cached server-side git bundles." default:"2h"`

SnapshotFilters map[string]string `hcl:"snapshot-filters,optional" help:"Per-repository git partial-clone filter applied to workstation snapshots, keyed by host/org/repo (e.g. {\"github.com/org/repo\": \"blob:none\"}). Filtered snapshots contain full history metadata but only the blobs needed for the HEAD checkout; clients lazily fetch historical blobs through cachew on demand."`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include filter config in snapshot freshness

When snapshot-filters is changed for a repo whose HEAD has not moved, the existing https://...snapshot cache entry is still considered valid: cache hits are served without checking this new setting, and generateAndUploadSnapshot skips regeneration based only on the upstream/head/cache key. That means enabling blob:none can keep returning the old full snapshot, while rolling the filter back can keep returning partial-clone snapshots until max-age/cache expiry or manual deletion. Store and compare the filter in snapshot metadata/coordination, or make the cache key vary by filter, so config changes take effect deterministically.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants