Skip to content

feat(scan-repo): adopt external-base overlays instead of refusing them#243

Merged
sunib merged 2 commits into
mainfrom
feat/scan-repo-overlay-classification
Jul 15, 2026
Merged

feat(scan-repo): adopt external-base overlays instead of refusing them#243
sunib merged 2 commits into
mainfrom
feat/scan-repo-overlay-classification

Conversation

@sunib

@sunib sunib commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Problem

Render-root scoping shipped for the live writer (#233/#239), so the operator adopts an external-base overlay (the base/ + overlays/{env} shape reached via ../../base). But scan-repo — the read-only repo-discovery library/CLI — still blanket-refused every such overlay with the forward-looking overlay-fan-out-unsupported reason. The design flagged this as a classification follow-up: the scanner must catch up to the runtime without widening either boundary.

Change

classifyRenderRoot no longer refuses an overlay just for reaching an out-of-subtree base. It runs the operator's own adoption gate over the overlay's render scope:

  • The render scope is a scoped FolderScan — the overlay subtree plus the exact base files its resources/patches graph reaches, never a whole base directory (so overlay-parked-base's unreferenced YAML can't refuse it, mirroring the runtime's "read scope is the exact reachable file set").
  • Handed to the same buildStore + Accept the live writer uses. Repo-relative keys mean ../../base resolves exactly as kustomize resolves it.
  • No runtime code touched — ScanRepo has zero callers in internal/controller/internal/watch/internal/git; it's a CLI/library the operator never runs.

overlay-fan-out-unsupported is retired. The public pkg/manifestanalyzer constant is kept (deprecated) for source compatibility; the classifier no longer emits it. An overlay refused for a real fault (foreign content, an unbuildable base, an unsupported nested kustomization) now carries that fault's own gate-issue code.

Semantic decision to review

A pure-passthrough overlay (only resources: [../../base] + namespace, nothing overlay-local) now reports acceptedByOperator: true with editable: 0. This is faithful to the runtime — the operator would set GitPathAccepted=True — with editable: 0 signalling that every field is base-owned and nothing is writable there yet (new-object creation and base-owned edits stay write-time-planned). The alternative — "accepted only if editable > 0" — is a one-line change + golden regen if you'd prefer discovery only flag overlays that can already mirror something. I went runtime-faithful.

Evidence (regenerated goldens + baseline)

Every kustomize-overlay candidate flips refused → accepted:

  • Corpus: base-overlays (3 overlays), overlay-nested-base, overlay-parked-base — the 3 fixtures moved unsupported/supported/.
  • test/fixtures/gitops-layouts/support-today.md: flux-monorepo (2), kustomize-overlay-minimal (2) all flip, overlay-fan-out-unsupported gone entirely; each shows editable: 0 (pure passthrough).

Validation

  • task fmt / task vet clean
  • task lint — doccheck OK, golangci-lint 0 issues
  • task test — all unit + CLI + golden tests pass; coverage 76.3% → 76.4% (baseline bumped)
  • task test-e2e — 55/56 green; the one failure (tilt_playground, a runtime WatchRule-Ready 90s timeout) is a confirmed flake: it passed on re-run in 3.7s, and this change has no runtime reach (scan-repo has no runtime callers).

🤖 Generated with Claude Code

Render-root scoping shipped for the live writer, but scan-repo (repo
discovery) still blanket-refused any overlay reaching an out-of-subtree
base with the forward-looking overlay-fan-out-unsupported reason. Flip the
classifier to match the runtime: classifyRenderRoot now runs the operator's
own adoption gate over the overlay's render scope.

The render scope is assembled as a scoped FolderScan — the overlay subtree
plus the EXACT base files its resources/patches graph reaches, never a whole
base directory — then handed to the same buildStore + Accept the live writer
uses, so a `../../base` reference resolves and parked YAML a base does not
reference can never refuse the overlay. This mirrors internal/git/render_scope.go
without touching the runtime (scan-repo has no runtime callers).

A kustomize-overlay candidate now reports acceptedByOperator from that gate;
its editable count shows how much it owns — a pure passthrough overlay is
adopted yet editable: 0, since every field is base-owned. New overlay object
creation and base-owned field edits stay write-time-planned: the scan reports
folder adoption, not write capability.

overlay-fan-out-unsupported is retired. The public pkg/manifestanalyzer
constant is kept (deprecated) for consumers pinning the string, but the
classifier no longer emits it. The three overlay corpus fixtures move
unsupported/ -> supported/, and the gitops-layouts baseline flips every
kustomize-overlay candidate refused -> accepted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@sunib, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 3 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e48e393c-d9e4-409c-8876-02bdca7f05a9

📥 Commits

Reviewing files that changed from the base of the PR and between 49327fd and cdba8f2.

📒 Files selected for processing (27)
  • cmd/manifest-analyzer/main_test.go
  • docs/design/support-boundary/README.md
  • docs/design/support-boundary/render-root-scoping.md
  • docs/design/support-boundary/repo-discovery-and-onboarding-scan.md
  • internal/manifestanalyzer/scan_repo.go
  • internal/manifestanalyzer/scan_repo_test.go
  • internal/manifestanalyzer/testdata/scan-repo/supported/base-overlays.golden.json
  • internal/manifestanalyzer/testdata/scan-repo/supported/base-overlays/base/deployment.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/base-overlays/base/kustomization.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/base-overlays/base/service.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/base-overlays/overlays/acc/kustomization.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/base-overlays/overlays/prod/kustomization.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/base-overlays/overlays/test/kustomization.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/overlay-nested-base.golden.json
  • internal/manifestanalyzer/testdata/scan-repo/supported/overlay-nested-base/base/common/configmap.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/overlay-nested-base/base/common/kustomization.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/overlay-nested-base/base/deployment.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/overlay-nested-base/base/kustomization.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/overlay-nested-base/overlays/test/kustomization.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/overlay-parked-base.golden.json
  • internal/manifestanalyzer/testdata/scan-repo/supported/overlay-parked-base/base/deployment.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/overlay-parked-base/base/kustomization.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/overlay-parked-base/base/parked.yaml
  • internal/manifestanalyzer/testdata/scan-repo/supported/overlay-parked-base/overlays/test/kustomization.yaml
  • pkg/manifestanalyzer/repo.go
  • pkg/manifestanalyzer/repo_test.go
  • test/fixtures/gitops-layouts/support-today.md
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/scan-repo-overlay-classification

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

# Conflicts:
#	test/fixtures/gitops-layouts/support-today.md
@sunib
sunib merged commit c7650f9 into main Jul 15, 2026
8 checks passed
@sunib
sunib deleted the feat/scan-repo-overlay-classification branch July 15, 2026 19:37
@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.66667% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/manifestanalyzer/scan_repo.go 66.6% 7 Missing and 5 partials ⚠️

📢 Thoughts on this report? Let us know!

sunib added a commit that referenced this pull request Jul 15, 2026
…ress CodeRabbit

- Resolve README / render-root-scoping conflicts between #243 (scan-repo adopts
  external-base overlays) and this branch (overlay write-path): keep both facts —
  scan-repo reports kustomize-overlay accepted, and the overlay authors new objects,
  images/replicas entries, and $patch: delete.
- CodeRabbit #1: distinguish read-only field patches from the authored $patch: delete
  in README and kustomize-support-boundary.
- CodeRabbit #2: authorInheritedDelete never overwrites an unrelated file at the
  deterministic patch path — it skips the delete on a content collision (idempotent
  resync still proceeds). Covered by TestOverlayAuthors_DeletePatch_SkipsOnPathCollision.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant