Skip to content

k8s manifests: multi-document files read as their first document; generated-file truncation can hide detection #258

Description

@nikolay-e

Two findings from the 2026-08-30 QA review of the #226 rewrite, both real, neither fixed in that pass because they are behaviour changes rather than defects in the fix.

1. A multi-document manifest is read as its first document only

build_manifest_views produces one ManifestView per FILE, and extract_resource_info takes the first ^kind: and the first metadata:\n name: of the whole reconstructed text. So a bundle.yaml holding ConfigMap + Deployment + Service is indexed as a ConfigMap; the Deployment is never a workload for selector matching, and references to that Service by name resolve to nothing.

Worse in the label path: extract_labels merges every labels: block in the file into one map, last-wins. A file with two Deployments (app: web, app: api) keeps only app: api, so a Service selecting app: web gets no edge.

Not a regression — before the fix this builder emitted nothing at all for any split manifest — but it is a correctness ceiling that neither the code nor its tests mention. Close condition: a corpus case with a ----separated bundle whose second document is the selector target, passing.

2. The generated-file reduction can delete the two lines detection needs

fragmentation.rs truncates an unchanged file whose header says do not edit / generated by to max_generated_fragments = 5, sorted by line count — and apiVersion: / kind: are one-line fragments, so they go first. The reconstructed text then has no kind:, is_kubernetes_manifest is false, and the whole file drops out of views.

This matters precisely for rendered/committed manifests, which is where cross-file k8s edges live. The old per-fragment path was less sensitive because it only needed one qualifying fragment; whole-file reassembly needs the file to survive intact. Close condition: a case with a # Generated by kustomize header whose Deployment is still pulled by its Service.

Both are Q-class (they change edges), so they wait for the v3 cycle's freeze boundary — see #256.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions