Preserve restored Terraform root identifiers - #4045
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review. 📝 WalkthroughWalkthrough
ChangesCommand facade restoration
Estimated code review effort: 4 (Complex) | ~45 minutes Merge Risk: ⚪ Minimal · up to The PR preserves restored Terraform identifiers and adds regression coverage; no actionable merge-blocking risk remains after normal checks and review. Sequence Diagram(s)sequenceDiagram
participant Preserver as GeneratedApiCompatibilityPreserver
participant Baseline as Baseline command
participant Current as Current command groups
participant Facades as Facade implementation types
participant Tree as CommandTreeNode
Preserver->>Baseline: Read restored command metadata
Preserver->>Current: Resolve a unique group identifier
Current-->>Preserver: Return live group or fallback identifier
Preserver->>Facades: Normalize types and parse facade suffixes
Facades-->>Preserver: Return command-part identifier overrides
Preserver->>Tree: Submit command definition
Tree-->>Tree: Apply overrides or reject conflicts
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThe PR preserves historical root and nested identifiers when restoring removed generated command facades.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Generators/GeneratedApiCompatibilityPreserver.cs | Restores historical root and nested identifiers from facade, current-command, and baseline naming information. |
| tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Models/CommandTreeNode.cs | Applies explicit nested identifiers while recursively grouping commands and rejects irreconcilable casing conflicts. |
| tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Models/CliCommandDefinition.cs | Adds immutable per-command metadata for historical nested identifier overrides. |
| tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator.Tests/Generators/GeneratorHardeningTests.cs | Adds comprehensive restoration regressions covering the previously reported root and mixed-facade failures. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Generated API baseline] --> B[Restore removed command]
C[Current command definitions] --> B
B --> D[Recover root identifier]
B --> E[Recover nested identifiers]
D --> F[Resolve sub-domain group]
E --> G[Build command tree]
F --> G
G --> H[Preserved generated facade]
Reviews (17): Last reviewed commit: "refactor(generator): unify fallback reco..." | Re-trigger Greptile
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a4ebdb2a9a
ℹ️ 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".
There was a problem hiding this comment.
Code Review — PR #4045
Summary: This PR fixes RestoreRemovedCommand to derive the restored command group identifier from the baseline definition rather than an arbitrary facade method (facadeMethods[0]), and adds a regression test for the multi-facade case. Good fix for the original bug — using the first facade method's declaring type as a proxy for the group identifier was fragile.
Issue found
GeneratedApiCompatibilityPreserver.cs:146-177 — the length-truncation fallback silently discards tool-specific identifier overrides that differ in length from the mechanical default.
When the restored command's whole group has vanished from the current scrape (currentIdentifiers.Length == 0, i.e. no live command shares CommandParts[0]), the code falls back to reconstructing the identifier from baseline.ClassName:
if (baseline.ClassName.StartsWith(tool.NamespacePrefix, StringComparison.Ordinal)
&& baseline.ClassName.AsSpan(tool.NamespacePrefix.Length)
.StartsWith(defaultIdentifier, StringComparison.OrdinalIgnoreCase))
{
return baseline.ClassName.Substring(tool.NamespacePrefix.Length, defaultIdentifier.Length);
}
return defaultIdentifier;This assumes the true identifier is always the same length as defaultIdentifier = ToPascalCase(rootCommand). That assumption breaks for any scraper that overrides NormalizeCommandIdentifier to a longer/shorter string than the mechanical Pascal-case conversion — which is exactly what ArgoCdCliScraper does:
// ArgoCdCliScraper.cs
protected override string NormalizeCommandIdentifier(string commandPart) =>
commandPart.Equals("appset", StringComparison.OrdinalIgnoreCase)
? "ApplicationSet"
: base.NormalizeCommandIdentifier(commandPart);Concrete failure scenario: if the entire appset ... command group disappears from a fresh CLI scrape (e.g. ArgoCD removes/renames it) while old generated facades for it still exist, RestoreRemovedCommand needs to regenerate appset create. currentIdentifiers is empty (no live appset commands), defaultIdentifier = "Appset", and baseline.ClassName = "ArgoCdApplicationSetCreateOptions". AsSpan(6) = "ApplicationSetCreateOptions", which does not start with "Appset" (mismatch at index 3: l vs s), so the StartsWith guard fails and the method falls through to return defaultIdentifier = "Appset" — instead of the correct "ApplicationSet". This reintroduces the exact class-name collision with the two-word app set command that the override exists to prevent (per the comment on NormalizeCommandIdentifier).
Even in the case where the StartsWith check does pass, truncating to defaultIdentifier.Length is still wrong in general — it can only ever reproduce defaultIdentifier itself (since a same-prefix, same-length substring starting with defaultIdentifier case-insensitively is defaultIdentifier when they're the same length), so the "success" branch is effectively dead code that never returns anything other than what the "fail" branch also returns. Either way, this fallback can never recover a genuinely different override string once no live command remains for the root — it can only recover the mechanical default.
Suggested fix: rather than reconstructing the identifier from a length-sliced substring of the baseline class name, prefer preserving the actual override text. Two options:
- Store
CommandGroupIdentifierOverride(or an equivalent "the identifier this baseline command actually used") directly onGeneratedApiBaselinewhen it's captured, so restoration never needs to reverse-engineer it from a mangled class name. - If baseline doesn't carry that field, search sibling baseline entries under the same root for their group identifier consistently, or fall back to stripping the known command-part suffixes (
CreateOptions, etc.) fromClassNamerather than assuming a fixed length match withdefaultIdentifier.
The added test (ApiCompatibilityPreserver_Uses_Root_Identifier_For_Restored_Nested_Facades) only covers the case where defaultIdentifier and the true override happen to be textually identical ("group" → "Group" either way), so it doesn't exercise this path — worth adding a case that mirrors the ArgoCD appset/ApplicationSet override to lock in the correct behavior.
Reviewed with the code-review skill against the current diff (tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Generators/GeneratedApiCompatibilityPreserver.cs), cross-checked against ArgoCdCliScraper.cs and CobraCliScraper.cs to confirm the override mechanism this fallback needs to preserve.
|
Fixed the Greptile custom-normalization finding at exact head ead0cb8. Baseline option types now recover the historical root identifier by stripping the tool prefix and non-root command suffix, preserving ArgoCdApplicationSetCreateOptions as ApplicationSet while nested facades still share one root. Added an appset regression. Validation: OptionsGenerator tests 988/988; Release build 0 warnings/errors; diff check clean. |
Code Review — PR #4045Summary: Good incremental fix. I verified the diff against the PR head ( 1.
|
|
Fixed the restored Validation: GeneratorHardeningTests 101/101; full OptionsGenerator suite 988/988; Release build 0 warnings/errors; diff check clean. Format verification remains blocked only by pre-existing @claude Please re-review exact head |
Code Review — PR #4045 (re-review at
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bdfe2f6708
ℹ️ 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".
feeeecc to
3f5db57
Compare
bdfe2f6 to
c77b027
Compare
|
Rebased the three-commit stacked diff onto the rewritten #4006 parent at exact head c77b027. Diff remains limited to GeneratedApiCompatibilityPreserver plus its hardening tests. Validation: full OptionsGenerator suite 1013/1013; Release build 0 warnings/errors; diff check clean. @claude Please re-review the exact current head. |
c77b027 to
b4c2578
Compare
|
Rebased the unchanged three-commit stacked diff onto #4006 exact parent Validation: full OptionsGenerator suite 1016/1016; Release build 0 warnings/errors; diff check clean. @claude Please re-review the exact current head. |
|
Fixed the historical facade-casing finding at exact head |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 34c14cea8a
ℹ️ 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".
Code Review — PR #4045 (re-review at
|
|
Fixed the live-sibling group-key finding at exact head ef2e258. Restored commands now reuse the unique current SubDomainGroup for their CLI root while keeping the recovered identifier as CommandGroupIdentifierOverride, preventing appset/ApplicationSet duplicate groups. Validation: full OptionsGenerator suite 1017/1017; Release build 0 warnings/errors; diff check clean. @claude Please re-review exact current head. |
|
Fixed the wholly-removed parent/child root split at exact head |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3da0fc22e8
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7d9a19888c
ℹ️ 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".
|
Resolved the CodeFactor complexity finding at exact head 5996dcf. Per-facade identifier recovery is now isolated from cross-facade conflict aggregation with behavior preserved. Validation: GeneratorHardeningTests 109/109; Release build 0 warnings/errors; scoped format and diff checks clean. The full coverage run hit the mandatory 2 GB agent guard at 2,150 MB, so CI owns that full check. @claude Please review exact head. @codex review |
|
Addressed exact-head Codex P2 in 78d3143: compatible facade prefix dictionaries now merge; only same-index identifier conflicts fail closed. Added regression for named facade + parent ExecuteAsync + child facade with historical intermediate casing. Validation: GeneratorHardeningTests 110/110, Release build 0 warnings/errors, scoped format and diff checks clean. @claude Please review exact head. @codex review |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Code Review — PR #4045 (re-review at
|
|
Addressed Claude's exact-head mixed live/restored finding in 45a2707. Command trees now resolve each shared raw prefix once: a single explicit historical identifier applies to live and restored siblings; genuinely conflicting explicit identifiers still fail fast. Added regressions for both paths. Validation: GeneratorHardeningTests 112/112, Release build 0 warnings/errors, scoped format and diff checks clean. @claude Please review exact head. @codex review |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 45a270727d
ℹ️ 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".
Code Review — PR #4045 (re-review at
|
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 45a270727d
ℹ️ 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".
|
Addressed both late exact-head Codex P2 findings in 86d1969: restored parent casing now flows into colliding live child nodes, and length-changing nested identifiers are recovered without fixed-length assumptions. Ambiguous recovery still fails closed. Validation: GeneratorHardeningTests 114/114, Release build 0 warnings/errors, scoped format and diff checks clean. @claude Please review exact head. @codex review |
|
Follow-up simplification at b9d6418: root and nested facade recovery now share the same ambiguity-safe identifier partitioner, removing the remaining fixed-suffix root assumption. GeneratorHardeningTests still pass 114/114; Release build 0 warnings/errors; format/diff clean. @claude Please review exact head. @codex review |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Code Review — PR #4045 (re-review at
|
|
Closed Claude's carried fallback inconsistency at 0162e92: baseline class-name fallback now uses the same ambiguity-safe identifier partitioner as facade root/nested recovery. Validation unchanged: GeneratorHardeningTests 114/114, Release build 0 warnings/errors, format/diff clean. @claude Please review exact head. @codex review |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Summary
stacksrestoration from producing conflictingStacks,StacksConfiguration,StacksDeploymentGroup, andStacksDeploymentRunidentifiersValidation
This is stacked on #4006 because Terraform reaches this path only after repeatable-option generation succeeds. Rebase onto
mainafter #4006 merges.Refs #3996
Summary by CodeRabbit
Bug Fixes
executecommands from parent command facades.Tests