8000 feat(components): dedupe nested chart Components in component linter by VLukiantsev · Pull Request #1034 · google/xmc · GitHub
[go: up one dir, main page]

Skip to content

feat(components): dedupe nested chart Components in component linter - #1034

Merged
VLukiantsev merged 5 commits into
mainfrom
feat/components-linter-nested-chart-roots-b548435909
Oct 2, 2026
Merged

VLukiantsev merged 5 commits into
mainfrom
feat/components-linter-nested-chart-roots-b548435909

Conversation

@VLukiantsev
@VLukiantsev VLukiantsev commented Sep 29, 2026 •
Copy link
Copy Markdown
Collaborator

Stack 1/2 · base: main · next: #1016 (stable-2026a profile meta-chart)

Summary

component-linter now handles chart roots nested inside another chart root under --manifests-dir. Nested charts are still rendered, so their template errors surface. A nested Component is dropped only when the enclosing chart already renders a Component with the same canonical name. This lets a profile meta-chart that renders its co-located component charts through .Files and tpl be linted without reporting every Component twice as DUPLICATE_COMPONENT_NAME. The PR also fixes stale xmc-linter references.

Motivation & Context

The next PR in this stack (#1016) turns deploy/profiles/stable-2026a/ into a Helm chart whose templates render each components/<name>/templates/component.yaml. Without this change, walking the profile renders each Component twice: once from the profile chart and once from the component chart.

Helm loads only the enclosing chart's own templates/ as templates, and everything under components/ is plain .Files. Skipping nested charts entirely would therefore hide errors in nested templates that the meta-chart never reads, such as a component's templates/deployment.yaml, and in Components the meta-chart doesn't include. So nested charts keep being rendered on their own, and only the duplicated Components are dropped.

Which charts count as nested is decided relative to the walk root:

  • Pointing --manifests-dir at a single component chart, or at a directory of charts that has no chart of its own, lints each chart exactly as before.
  • Vendored subcharts directly under <chart>/charts/ are not treated as nested.

Note

Reachability: no chart root in the repository is nested inside another one until #1016 lands, so on main this behavior is inert. run_linter.py and the run-component-linter action are unchanged. The new path is exercised by unit tests on temporary chart trees.

Key Changes

  • Linter (pkg/components/linter):
    • collectManifests puts manifests from nested chart roots in a separate set. Nested charts are detected by isNestedChartRoot, which uses filepath.IsLocal and exempts <chart>/charts/<sub>. File reading and rendering moved into readManifestFile, and the YAML file filter into isManifestFile.
    • mergeNestedManifests appends nested manifests to the top-level ones. It drops a nested Component (comp and raw doc) only when a top-level chart renders the same canonical name.
    • findChartRoot's Chart.yaml probe is extracted into hasChartFile so both paths share it.
  • Tests:
    • TestValidateDirectory_NestedChartRoots: one shared tree with 8 cases, each comparing the full sorted list of <rule> <file> diagnostics. The tree contains:
      • a profile that renders its nested chart through tpl (.Files.Get ...): one MISSING_DEPENDENCY on the outer template, no DUPLICATE_COMPONENT_NAME;
      • a meta-chart that doesn't include its nested chart: the nested Component is still linted;
      • a nested template that fails to compile: YAML_SYNTAX;
      • a vendored charts/sub;
      • a chart-free catalog of two charts that both define dup.
    • New internal TestMergeNestedManifests, covering shadowed, kept, unnamed and non-Component documents.
    • New internal tests TestHasChartFile and TestIsNestedChartRoot. The linter_test BUILD target uses embed for the internal tests.
  • Docs:
    • cmd/component-linter/README.md documents the nested-chart rule. It also notes that diagnostics for a Component rendered by the enclosing chart point at the enclosing template, with line numbers from the rendered output, and recommends a per-document source comment in meta-charts.
    • Stale xmc-linter / //cmd/xmc-linter references are fixed in that README, the ingestion-gateway component README, the run_linter.py docstring, and the fake binary names in run_linter_test.py. The stale README references made the documented Bazel commands fail.

Assumptions

  • Nesting is decided relative to --manifests-dir, not the filesystem root. Why: callers that point the linter directly at a component chart must keep linting it unchanged. Impact if wrong: none functionally, because nested charts are still rendered; only the deduplication would differ.
  • Only direct children of <chart>/charts/ count as vendored subcharts. Why: that is Helm's layout for dependencies. Impact if wrong: Components in deeper vendored layouts that share a name with a top-level Component would be deduplicated. No such layout exists in the repository.
  • Deduplication is by canonical metadata.name only. Why: the enclosing chart's copy carries the values that are actually installed. Impact if wrong: a nested Component that the meta-chart renders under a different name is linted twice, with nested defaults and with profile values.
  • Diagnostics for deduplicated Components point at the enclosing chart's template. Mapping them back to the nested source file is a possible follow-up.
  • The filepath.Abs error branches in collectManifests and isNestedChartRoot are not covered by tests. They only fail if the working directory cannot be resolved.

Verification & Testing

  • Commands Executed:
    • bazel test //pkg/components/linter/... //tools/components/... //cmd/component-linter/... → 3/3 pass.
    • In a local merge of feat(components): package stable-2026a profile meta-chart #1016 with this branch (not pushed): those targets plus //test/helm/profiles/stable2026a/... pass. component-linter on deploy/profiles/stable-2026a with its rules.yaml passes. With a stray {{ end }} added to a copy of components/ingestion-gateway/templates/deployment.yaml, it reports YAML_SYNTAX.
    • Before the review follow-ups: python3 tools/components/run_linter.py --strict (default scan roots) and --scan-roots deploy/profiles --strict gave byte-identical output for binaries built from this branch and from main.
  • Coverage & Test Status: all new and changed linter lines are covered except the filepath.Abs and walk error branches. Pre-commit (buildifier, gofmt, golangci-lint, addlicense, ruff) is clean.

Related Issues / Bugs

Part of bug 548435909

TAG=agy
CONV=bd17ce9f-7baf-43c9-8f30-c169fd656954

@VLukiantsev
VLukiantsev added this pull request to stack #1035 September 29, 2026 11:26
@VLukiantsev VLukiantsev changed the title feat/components linter nested chart roots b548435909 feat(components): skip nested chart roots in component linter Sep 29, 2026
@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request renames the xmc-linter binary to component-linter across documentation, tests, and scripts. It also introduces logic to skip nested Helm chart roots during directory traversal in the linter to prevent duplicate manifest rendering, while still allowing vendored subcharts to be linted individually. Feedback on the changes suggests refactoring the isNestedChartRoot function to resolve absolute paths upfront, which simplifies error handling and avoids redundant path resolution.

Comment thread pkg/components/linter/chart_renderer.go Resolved
@VLukiantsev
VLukiantsev marked this pull request as ready for review September 29, 2026 11:36
@github-actions
github-actions Bot requested a review from pachopepe September 29, 2026 11:36
Comment thread pkg/components/linter/linter.go Resolved
Comment thread pkg/components/linter/linter_test.go Resolved
Comment thread cmd/component-linter/README.md Resolved
@VLukiantsev VLukiantsev changed the title feat(components): skip nested chart roots in component linter feat(components): dedupe nested chart Components in component linter Oct 2, 2026
@VLukiantsev
VLukiantsev force-pushed the feat/components-linter-nested-chart-roots-b548435909 branch from 0174cbd to fc94dc3 Compare October 2, 2026 08:16
@VLukiantsev
VLukiantsev requested a review from pachopepe October 2, 2026 08:23
A profile meta-chart renders its co-located component charts through
.Files, so walking into components/<name>/ and rendering those charts again
would lint every Component twice and report DUPLICATE_COMPONENT_NAME.

collectManifests now skips a directory whose Chart.yaml sits inside another
chart root at or below --manifests-dir. The check is relative to the walk
root, so pointing --manifests-dir at a single component chart, or at a
chart-free directory of component charts, still renders them individually.
Vendored subcharts directly under <chart>/charts/ are not treated as nested
and are still linted on their own.

findChartRoot's Chart.yaml probe is extracted into hasChartFile so the new
isNestedChartRoot helper can reuse it.

BUG=b/548435909
TAG=agy
CONV=bd17ce9f-7baf-43c9-8f30-c169fd656954
The linter binary and Bazel package are component-linter
(//cmd/component-linter), but the component-linter README still referred
to an xmc-linter binary and //cmd/xmc-linter targets that do not exist, so
the documented bazel run/test/coverage commands failed. The
ingestion-gateway component README, the run_linter.py docstring, and the
fake binary names in run_linter_test.py used the same stale name.

BUG=b/548435909
TAG=agy
CONV=bd17ce9f-7baf-43c9-8f30-c169fd656954
Resolve the absolute chart directory once, up front, with an early return
on error, and pass it to findChartRoot instead of resolving it twice. The
function now reads as a linear sequence of guard clauses: chart-file check,
path resolution, enclosing-chart lookup, vendored charts/ exemption, and the
walk-root containment check. findChartRoot starts at the parent directory,
so it still returns the enclosing chart; behavior is unchanged.

Add a table-driven TestIsNestedChartRoot covering each reachable branch.

Comment link: #1034 (comment)

BUG=b/548435909
TAG=agy
CONV=bd17ce9f-7baf-43c9-8f30-c169fd656954
Stop skipping chart roots nested under an enclosing chart root. Every
nested template is rendered again with the nested chart's own defaults,
so template errors surface as YAML_SYNTAX. A nested Component is dropped
only when the enclosing chart already renders a Component with the same
canonical name, which avoids DUPLICATE_COMPONENT_NAME. Nested Components
the enclosing chart does not render, and all other nested documents, are
linted as usual.

The nested-chart test fixture now renders its nested chart through
.Files and tpl. It asserts the exact set of diagnostics, and covers a
nested chart the outer chart does not include and a nested template that
fails to compile.

Comment link: #1034 (comment)
Comment link: #1034 (comment)

TAG=agy
CONV=bd17ce9f-7baf-43c9-8f30-c169fd656954
Describe the new nested-chart rule in the component-linter README. Note
that diagnostics for Components rendered by an enclosing meta-chart
point at the meta-chart's template, with line numbers from the rendered
output. Recommend a per-document source comment so these locations are
easy to trace. Drop the advice to lint nested charts on their own, which
CI never followed.

Comment link: #1034 (comment)

TAG=agy
CONV=bd17ce9f-7baf-43c9-8f30-c169fd656954
@VLukiantsev
VLukiantsev force-pushed the feat/components-linter-nested-chart-roots-b548435909 branch from fc94dc3 to d16b0b9 Compare October 2, 2026 12:11
@VLukiantsev
VLukiantsev added this pull request to the merge queue Oct 2, 2026
Merged via the queue into main with commit de491ee Oct 2, 2026
11 checks passed
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

0