-
Notifications
You must be signed in to change notification settings - Fork 3
kbld #626
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThis PR consolidates the Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant RenderCmd as RenderCmd Function
participant Globe
participant Render as Render Pipeline
participant Kbld as Kbld Stage
User->>RenderCmd: RenderCmd(g, sync=true, render=true)
RenderCmd->>Globe: ValidateRootDir()
activate Globe
Globe-->>RenderCmd: ✓
deactivate Globe
RenderCmd->>Globe: Init(asyncLevel, envAppMap)
activate Globe
Globe-->>RenderCmd: ✓
deactivate Globe
alt sync=true
RenderCmd->>Globe: Sync(asyncLevel)
activate Globe
Globe-->>RenderCmd: ✓
deactivate Globe
end
alt render=true
RenderCmd->>Render: SyncAndRender(asyncLevel)
activate Render
Note over Render: Per-app YAML tools
Render->>Kbld: Render(previousStepFile)
activate Kbld
Kbld-->>Render: rendered output
deactivate Kbld
Render-->>RenderCmd: ✓
deactivate Render
end
alt envAppMap == nil
RenderCmd->>Globe: CleanupRenderedManifests(false)
activate Globe
Globe-->>RenderCmd: ✓
deactivate Globe
end
RenderCmd-->>User: error or nil
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes The PR involves heterogeneous changes spanning command consolidation, core initialization refactoring, path resolution updates across multiple files, new kbld integration (both embedded and render pipeline), and configuration enhancements. While individual patterns are relatively straightforward, the scope and interconnectedness of changes across command layer, core logic, and configuration schema require careful cross-cutting review of initialization order, error handling, path correctness, and backward compatibility implications. Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
go.mod (1)
21-21: Migrate from unmaintainedgopkg.in/yaml.v3to actively maintainedgo.yaml.in/yaml/v3.The original
gopkg.in/yaml.v3package (github.com/go-yaml/yaml) was archived as unmaintained on Apr 1, 2025. The YAML organization createdgo.yaml.in/yaml/v3as the actively maintained drop-in replacement. Your go.mod currently has direct dependency on the unmaintained version while indirect dependencies have migrated to the new path, causing version duplication (v3.0.1 vs v3.0.4) in the dependency graph. Update togo.yaml.in/yaml/v3to receive ongoing fixes and security updates.Occurrences at lines 21 and 105 in go.mod.
internal/myks/globe.go (1)
162-186: Swap mismatched log messages (branch vs url)The warning texts are reversed for branch/URL errors.
- if gitRepoBranch, err := getGitRepoBranch(g.RootDir); err != nil { - log.Warn().Err(err).Msg("Unable to set git repo url") + if gitRepoBranch, err := getGitRepoBranch(g.RootDir); err != nil { + log.Warn().Err(err).Msg("Unable to set git repo branch") } else { g.GitRepoBranch = gitRepoBranch } - if gitRepoURL, err := getGitRepoURL(g.RootDir); err != nil { - log.Warn().Err(err).Msg("Unable to set git repo branch") + if gitRepoURL, err := getGitRepoURL(g.RootDir); err != nil { + log.Warn().Err(err).Msg("Unable to set git repo url") } else { g.GitRepoURL = gitRepoURL }
🧹 Nitpick comments (16)
docs/configuration.md (3)
30-37: Clarify precedence between config-in-root and root-dir.State what wins when both are set (explicit root-dir vs config-in-root). This avoids surprises when users migrate configs.
86-97: Add CLI flag info for root-dir (if it exists).If there’s a --root-dir flag, list it here for parity with other options; if not supported by design, a one-liner saying “CLI flag not available” helps users.
9-14: Consider documenting .myks.yml (if supported).If both .myks.yaml and .myks.yml are accepted, list both; if only .yaml is supported, explicitly say so.
docs/smart-mode.md (1)
55-59: Fix markdownlint MD014 for command-only blocks.Remove “$ ” prompts or include example output. Suggested change: use shell blocks without the prompt.
-```console -$ myks render --smart-mode.base-revision=main -$ myks render --smart-mode.base-revision=HEAD~1 -$ myks render --smart-mode.base-revision=v1.2.3 -``` +```shell +myks render --smart-mode.base-revision=main +myks render --smart-mode.base-revision=HEAD~1 +myks render --smart-mode.base-revision=v1.2.3 +```internal/myks/render_kbld.go (2)
54-63: Prefer boolean flag only when true (avoid explicit “=false”).If kbld accepts a bare --images-annotation boolean flag, append it only when true to reduce ambiguity. Please verify kbld’s CLI semantics first.
- cmdArgs := []string{ - "kbld", - "--file=" + previousStepFile, - "--imgpkg-lock-output=" + lockFilePath, - fmt.Sprintf("--images-annotation=%t", config.ImagesAnnotation), - } + cmdArgs := []string{ + "kbld", + "--file=" + previousStepFile, + "--imgpkg-lock-output=" + lockFilePath, + } + if config.ImagesAnnotation { + cmdArgs = append(cmdArgs, "--images-annotation") + }
92-95: Consider failing on empty stdout.Returning an empty string can mask kbld failures upstream. Prefer returning an error so the pipeline stops early.
- if res.Stdout == "" { - log.Warn().Msg(k.app.Msg(k.getStepName(), "Empty kbld output")) - return "", nil - } + if res.Stdout == "" { + return "", fmt.Errorf("%s: kbld produced no output", k.getStepName()) + }internal/myks/bootstrap.go (1)
137-152: Prefer returning errors from library code instead of log.FatalCurrent log.Fatal calls exit the process from a library function, complicating testing and error handling. Recommend returning errors and letting callers decide.
Proposed refactor (essence):
- func (g *Globe) createDataSchemaFile() string { + func (g *Globe) createDataSchemaFile() (string, error) { dataSchemaFilePath := filepath.Join(g.RootDir, g.ServiceDirName, g.TempDirName, g.DataSchemaFileName) log.Debug().Str("dataSchemaFilePath", dataSchemaFilePath).Msg("Ensuring data schema file exists") - if ok, err := isExist(dataSchemaFilePath); err != nil { - log.Fatal().Err(err).Msg("Unable to stat data schema file") + if ok, err := isExist(dataSchemaFilePath); err != nil { + return "", err } else if !ok { - if err := os.MkdirAll(filepath.Dir(dataSchemaFilePath), 0o750); err != nil { - log.Fatal().Err(err).Msg("Unable to create data schema file directory") - } + if err := os.MkdirAll(filepath.Dir(dataSchemaFilePath), 0o750); err != nil { + return "", err + } } else { log.Debug().Msg("Overwriting existing data schema file") } - if err := os.WriteFile(dataSchemaFilePath, dataSchema, 0o600); err != nil { - log.Fatal().Err(err).Msg("Unable to create data schema file") - } - return dataSchemaFilePath + if err := os.WriteFile(dataSchemaFilePath, dataSchema, 0o600); err != nil { + return "", err + } + return dataSchemaFilePath, nil }And update the call site in createBaseFileStructure:
- g.createDataSchemaFile() + if _, err := g.createDataSchemaFile(); err != nil { + return err + }internal/integration/render_test.go (1)
90-92: LGTM; consider skipping sync to speed testsCalls to RenderCmd are correct. To reduce CI time, consider render-only when sources are already synced.
- if err := cmd.RenderCmd(myks.New("."), true, true); err != nil { + if err := cmd.RenderCmd(myks.New("."), false, true); err != nil {Also applies to: 122-124
cmd/root.go (1)
31-32: Global globe lifecyclePair this with sync.Once in getGlobe() to avoid double init and subtle races during shell-completion vs command execution.
Run the getGlobe change suggested in cmd/util.go and confirm no tests rely on reinitializing globe mid-run.
cmd/render.go (1)
79-85: Exported RenderCmd depends on package global envAppMapTight coupling complicates reuse/testing. Consider passing envAppMap as a parameter or deriving it internally from cmd context.
docs/README.md (5)
17-39: Add kbld to the Features listYou’ve added kbld support in this PR; the Features section should reflect it.
Apply:
- **Plugin system**: [Plugins](/docs/plugins.md) support for extending myks with custom tools +- **Image resolution and lock files**: Resolve image refs to immutable digests and + produce lock files with [kbld]; optionally build/push and relocate imagesAnd add a link ref at the bottom section:
[vendir]: https://carvel.dev/vendir/ [ytt]: https://carvel.dev/ytt/ +[kbld]: https://carvel.dev/kbld/
157-167: Document flag behavior and mutual exclusivityMake it explicit that --sync and --render are mutually exclusive and that omitting both runs both stages.
-The `render` command handles both stages and accepts optional flags to control -behavior: +The `render` command handles both stages. Flags control behavior: -- By default, it runs both sync and render stages sequentially -- Use `--sync` to only sync external sources -- Use `--render` to only render manifests +- By default, both sync and render stages run sequentially. +- Use `--sync` to only sync external sources. +- Use `--render` to only render manifests. +- Flags `--sync` and `--render` are mutually exclusive.
168-171: Clarify CLI argument grammar with examplesAdd concrete examples for envs/apps lists and ALL.
-The `render` command accepts two optional arguments (comma-separated lists or -`ALL`): environments and applications to process. When no arguments are -provided, myks will use the [Smart Mode](/docs/smart-mode.md) to detect what to -process. +The `render` command accepts two optional arguments (comma-separated lists or `ALL`): +1) environments, 2) applications. When no arguments are provided, [Smart Mode](/docs/smart-mode.md) +selects what to process. + +Examples: +```shell +myks render env-dev,env-stg app-a,app-b +myks render ALL app-web +myks render env-prod ALL +```
176-205: Cross-reference kbld configuration (follow-up doc stub is fine)Add a short note/link to kbld usage/config, since support was added in this PR.
## Configuration @@ - `plugin-sources`: Additional directories to search for myks plugins + +> [!NOTE] +> For image resolution/build pipelines, see the kbld integration guide +> (lock files, image overrides, and relocation). [kbld docs][kbld]I can draft a minimal docs/kbld.md with examples if helpful.
269-269: Fix markdownlint MD014: drop shell prompts or show outputRemove leading “$ ” prompts in command blocks (or switch to a “shell” fence) to satisfy MD014.
-```console -$ # Switch to an empty directory -$ cd $(mktemp -d) -$ # Initialize a repository -$ git init -$ # Make an initial commit -$ git commit --allow-empty -m "Initial commit" -$ # Initialize a new myks project -$ myks init -$ # Optionally, check the generated files -$ find -$ # Sync and render everything -$ myks render envs --log-level debug -``` +```shell +# Switch to an empty directory +cd "$(mktemp -d)" +# Initialize a repository +git init +# Make an initial commit +git commit --allow-empty -m "Initial commit" +# Initialize a new myks project +myks init +# Optionally, check the generated files +find +# Sync and render everything +myks render envs --log-level debug +```internal/myks/globe.go (1)
141-160: Consider surfacing errors from createDataSchemaFileIf createDataSchemaFile fails, we silently proceed; make it return (string, error) to log or fail early like dumpConfigAsYaml does.
- g.extraYttPaths = append(g.extraYttPaths, g.createDataSchemaFile()) + if schemaPath, err := g.createDataSchemaFile(); err != nil { + log.Warn().Err(err).Msg("Unable to create data schema file") + } else { + g.extraYttPaths = append(g.extraYttPaths, schemaPath) + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
go.sumis excluded by!**/*.sum
📒 Files selected for processing (32)
cmd/all.go(0 hunks)cmd/cleanup.go(1 hunks)cmd/embedded/embedded.go(2 hunks)cmd/embedded/kbld.go(1 hunks)cmd/plugin.go(1 hunks)cmd/render.go(1 hunks)cmd/root.go(3 hunks)cmd/smart-mode.go(1 hunks)cmd/sync.go(0 hunks)cmd/util.go(1 hunks)docs/README.md(4 hunks)docs/configuration.md(1 hunks)docs/optimizations.md(3 hunks)docs/plugins.md(1 hunks)docs/smart-mode.md(3 hunks)examples/README.md(1 hunks)examples/default/.gitignore(0 hunks)examples/default/envs/.gitignore(0 hunks)examples/integration-tests/.gitignore(0 hunks)examples/simple/.gitignore(0 hunks)go.mod(3 hunks)internal/integration/render_test.go(2 hunks)internal/myks/application.go(2 hunks)internal/myks/assets/data-schema.ytt.yaml(1 hunks)internal/myks/assets/myks_config.tpl.yaml(1 hunks)internal/myks/bootstrap.go(1 hunks)internal/myks/environment.go(3 hunks)internal/myks/git.go(2 hunks)internal/myks/globe.go(3 hunks)internal/myks/render_kbld.go(1 hunks)main.go(1 hunks)nix/package.nix(1 hunks)
💤 Files with no reviewable changes (6)
- examples/simple/.gitignore
- examples/default/envs/.gitignore
- examples/integration-tests/.gitignore
- examples/default/.gitignore
- cmd/all.go
- cmd/sync.go
🧰 Additional context used
🧬 Code graph analysis (10)
docs/optimizations.md (1)
internal/myks/smart_mode.go (1)
g(13-41)
cmd/smart-mode.go (1)
internal/myks/smart_mode.go (2)
g(13-41)g(60-230)
internal/integration/render_test.go (2)
cmd/render.go (1)
RenderCmd(79-102)internal/myks/globe.go (1)
New(131-160)
cmd/render.go (2)
cmd/smart-mode.go (2)
AnnotationSmartMode(18-18)AnnotationTrue(19-19)internal/myks/globe.go (1)
Globe(23-108)
main.go (1)
cmd/root.go (1)
NewMyksCmd(34-50)
internal/myks/environment.go (1)
internal/myks/render_kbld.go (1)
Kbld(12-16)
cmd/util.go (1)
internal/myks/globe.go (2)
Globe(23-108)New(131-160)
cmd/root.go (2)
internal/myks/globe.go (1)
Globe(23-108)cmd/embedded/embedded.go (1)
EmbeddedCmd(35-44)
internal/myks/render_kbld.go (1)
internal/myks/application.go (1)
Application(23-33)
internal/myks/globe.go (1)
internal/myks/environment.go (1)
Environment(18-36)
🪛 GitHub Check: lint / lint
internal/myks/globe.go
[failure] 134-134:
Error return value of os.Chdir is not checked (errcheck)
🪛 markdownlint-cli2 (0.18.1)
docs/README.md
269-269: Dollar signs used before commands without showing output
(MD014, commands-show-output)
docs/smart-mode.md
56-56: Dollar signs used before commands without showing output
(MD014, commands-show-output)
57-57: Dollar signs used before commands without showing output
(MD014, commands-show-output)
58-58: Dollar signs used before commands without showing output
(MD014, commands-show-output)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test / test
🔇 Additional comments (31)
examples/README.md (1)
6-7: Clear relative path convention.The explicit
./prefix on relative links improves clarity and follows markdown best practices for referencing local files within the repository.nix/package.nix (1)
13-13: LGTM: Routine vendorHash update.The vendorHash update is expected given the addition of kbld support and other dependency changes in this PR.
cmd/plugin.go (1)
63-63: LGTM: Centralized globe initialization.The refactoring to use
getGlobe()aligns with the broader pattern of centralizing globe acquisition across command handlers, improving consistency throughout the codebase.internal/myks/git.go (2)
50-50: LGTM: Iterator-based parsing refactor.The refactoring from
strings.Splittostrings.SplitSeqmodernizes the code to use iterator patterns while maintaining identical parsing behavior. The logic for handling git diff output remains correct.
76-76: LGTM: Iterator-based parsing refactor.Consistent with the refactoring in
convertDiffToChangedFiles, this change adopts iterator patterns while preserving the correct git status parsing logic.internal/myks/assets/myks_config.tpl.yaml (1)
5-7: LGTM: Clear documentation for new config-in-root option.The new
config-in-rootoption is well-documented with clear inline comments explaining its purpose and effect. This aligns with the PR objective to add config-in-root support (ref #573).internal/myks/application.go (3)
45-45: LGTM: Consistent RootDir-prefixed path construction.The addition of
RootDirprefixing ensures consistent path resolution across the codebase, aligning with the broader refactoring to standardize how paths are constructed relative to the project root.
102-102: LGTM: RootDir prefixing for service paths.Consistent with the prototype path change, this ensures service paths are correctly resolved relative to
RootDir.
106-106: LGTM: RootDir prefixing for vendir cache.This completes the consistent RootDir prefixing pattern for all path construction in the Application type.
internal/myks/environment.go (3)
44-44: LGTM: RootDir-prefixed environment data path.Consistent with the path prefixing changes across other files, this ensures the rendered environment data file path is correctly resolved relative to
RootDir.
85-85: LGTM: kbld integration.The addition of
Kbldto the YAML templating tools pipeline successfully implements the kbld support mentioned in the PR objectives, completing the rendering workflow with image building capabilities.
342-344: LGTM: Iterator-based path collection refactor.The refactoring to use
strings.SplitSeqand iterator-based loops modernizes the code while maintaining the correct behavior for collecting files by subpath. The path construction logic remains intact.docs/plugins.md (3)
28-34: LGTM: Enhanced plugin sources documentation.The additional example directories and clarifying paragraph improve understanding of how plugin sources work, making it clear that multiple directories can be configured beyond the default
./plugins.
38-40: LGTM: Updated execution logic description.The change from "render and sync logic" to "render logic" correctly reflects the PR's command consolidation where the focus is on the unified render workflow.
43-43: LGTM: Terminology correction.The capitalization of "YAMLs" improves consistency with technical documentation standards.
cmd/cleanup.go (1)
49-49: LGTM: Centralized globe initialization.Consistent with the refactoring in
cmd/plugin.go, this change adopts the centralizedgetGlobe()pattern for improved consistency across command handlers.docs/optimizations.md (1)
25-33: Smart Mode options section reads well and aligns with render workflow.Good clarity and cross-link to Smart Mode page.
docs/configuration.md (1)
58-69: No changes needed — documentation example is correct.The myks parser uses go-version, which accepts versions with a leading "v" prefix. The codebase confirms this: myks imports
github.com/hashicorp/go-versionv1.7.0 and usesgv.NewVersion(minVersion)to parse the configuration value. The documentation examplemin-version: 'v4.0.0'is valid and will parse correctly.cmd/embedded/embedded.go (1)
20-21: kbld dispatch addition looks good; confirm entrypoint presenceWiring kbld via kbldMain matches ytt/vendir pattern. Please confirm kbldMain exists in package embedded and tolerates os.Args = os.Args[1:] semantics.
main.go (1)
24-24: Inline Execute() is fineChaining construction + Execute keeps behavior and simplifies flow. No issues.
internal/myks/assets/data-schema.ytt.yaml (1)
121-131: kbld config block added appropriatelyDefaults look sane. Ensure CLI/flags and render step honor kbld.enabled and imagesAnnotation/cache behaviors consistently.
cmd/smart-mode.go (2)
29-31: Good: centralizing globe retrievalSwitch to getGlobe() here is consistent with the refactor. No issues.
39-43: <!-- [scratchpad_start]
[task verify_strings_SplitSeq_and_fixes complete][observations]
strings.SplitSeqIS a real function in Go standard library, added in Go 1.22/1.23- According to Go docs: "SplitSeq returns an iterator over all substrings... The iterator yields the same strings that would be returned by Split(s, sep)"
- Official example from pkg.go.dev:
for part := range strings.SplitSeq(s, ",") { fmt.Printf("%q\n", part) }- uses single variable, NOT index- SplitSeq returns
iter.Seq[string], which yields values (strings), not indices- When iterating with
for rangeover an iterator, a single variable receives the value- Review comment's claim that
for env := range ...yields indexes is INCORRECT - it yields values for iterators- Review's suggestion to use
for _, env := range strings.Split(...)is also wrong syntax (would be for an actual slice, not iterator)[critical findings]
- The current code
for env := range strings.SplitSeq(args[0], ",")is CORRECT syntax
- SplitSeq returns iter.Seq[string]
- Iterating with
for rangeon an iterator yields the values directly- The variable
envreceives each string value, not an index- The review's proposed fix
for _, env := range strings.Split(args[0], ",")is INCORRECT
- strings.Split returns []string (slice)
- For slices,
for rangeyields index, value pairs- Using
for _, envwould work (discarding index, taking value)- But the review's syntax shows
for _, env :=which is unusual phrasing and inconsistent- The issue with strings.SplitSeq NOT being in stdlib is FALSE
- The other issues in other files (environment.go, render.go, git.go) using SplitSeq are actually CORRECT
[analysis]
- Review comment is fundamentally wrong about:
- strings.SplitSeq not existing
- How iterators work in Go 1.22+ (for range yields values, not indices)
- The proposed fix would break the code or introduce subtle differences
[done]
Initial verification complete - review comment contains significant factual errors about Go iterators.
[scratchpad_start] -->Your review comment contains fundamental factual errors about Go's standard library and how range iteration works with iterators:
strings.SplitSeq is a real Go standard library function (added in Go 1.22–1.23). It returns an iterator over all substrings of s separated by sep, yielding the same strings that would be returned by Split(s, sep), but without constructing the slice.
The current code syntax is correct. The official example from the Go documentation shows:
for part := range strings.SplitSeq(s, ",") { fmt.Printf("%q\n", part) }— a single variable receiving the value, not an index. When iterating withfor rangeover an iterator (iter.Seq[string]), the loop variable receives values directly, not indices.The proposed fix is incorrect. The suggestion to use
for _, env := range strings.Split(args[0], ",")changes the semantic—while technically this would work with a slice (wherefor rangeyields index, value pairs), it's a different code pattern and removes the iterator efficiency benefit.The code at lines 39–43 and 52–58 in cmd/smart-mode.go is not breaking. The same pattern is correctly used throughout the codebase (git.go, environment.go, render.go), and all use
strings.SplitSeqfrom the standard library.The second concern (using
myks.NewWithDefaults()instead ofgetGlobe()at line 56) remains valid and should be addressed to ensure consistent configuration handling.Likely an incorrect or invalid review comment.
cmd/root.go (2)
45-46: kbld command availability depends on embedded wiringEnsure the embedded kbld entrypoint is compiled for your release builds; otherwise this command always errors at runtime.
See the kbld wiring script in cmd/embedded/kbld.go comment.
145-157: Verify config-in-root behavior with parent directory configsThe concern is valid: a FIXME comment at globe.go:132 acknowledges os.Chdir() is problematic and suggests implementing relative paths instead. However, the
config-in-rootfeature has no test coverage, and its interaction with shell completion is untested.Specifically verify:
- Shell completion (
cmd/util.go:39callsgetGlobe()) works correctly when config file is in a parent directory- Relative file paths in CLI arguments resolve correctly after CWD changes
- Dry runs behave as expected in both scenarios: config in current directory vs. parent directory
Consider adding integration tests for this scenario to prevent regressions.
cmd/render.go (1)
22-31: Default behavior: both sync and render when no flags were setGood UX: mutually exclusive when user specifies, both when unspecified. No change requested.
Confirm help text states “defaults to sync+render” when neither flag is set.
cmd/embedded/kbld.go (1)
15-15: No action required — kbld entrypoint is properly wired and reachable.The code is working correctly. When
myks kbldis invoked,embedded.CheckAndRun()is called immediately inmain()(line 20) before Cobra initialization. It matches the switch case for "kbld" and directly invokeskbldMain(), then returns early. TheEmbeddedCmd("kbld", ...)stub incmd/root.gois never reached for directmyks kbldinvocations. The routing logic is sound and requires no build tags or additional wiring.docs/README.md (1)
68-69: LGTM on updated quickstartSwitching the example to “myks render” matches the new unified flow.
internal/myks/globe.go (3)
377-378: LGTM: cache dir now rooted at RootDirRooting vendir cache cleanup under RootDir is correct and safer.
471-471: LGTM: search path now RootDir-prefixedThis aligns env discovery with explicit RootDir semantics.
152-156: Remove sensitive content from trace log to prevent credential leakageThe security concern is confirmed. GitRepoURL is populated from
git remote get-url origin, which can include embedded credentials in URLs likehttps://user:[email protected]/repo.git. The log statement at line 433 ininternal/myks/globe.gocurrently logs the fullyttDatacontent containing this URL, exposing credentials to logs even at Trace level.The provided diff is accurate and mandatory. Remove the
"content", yttDataparameters from the log statement:- log.Trace().Str("config file", configFileName).Str("content", yttData).Msg("Dumped config as yaml") + log.Trace().Str("config file", configFileName).Msg("Dumped config as yaml")Likely an incorrect or invalid review comment.
| switch { | ||
| case sync && render: | ||
| return okOrErrLog(g.SyncAndRender(asyncLevel), "Unable to sync and render applications") | ||
| case sync: | ||
| return okOrErrLog(g.Sync(asyncLevel), "Unable to sync external sources") | ||
| case render: | ||
| return okOrErrLog(g.Render(asyncLevel), "Unable to render manifests") | ||
| } | ||
|
|
||
| // Cleaning up only if all environments and applications were processed | ||
| if envAppMap == nil { | ||
| return okOrErrLog(g.CleanupRenderedManifests(false), "Unable to cleanup rendered manifests") | ||
| } | ||
|
|
||
| return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Cleanup is unreachable on normal CLI runs; run cleanup after a full render
Early returns skip post‑render cleanup. With defaults (sync+render), cleanup never runs; stale manifests may persist. Run cleanup after successful render when processing all envs/apps.
- switch {
- case sync && render:
- return okOrErrLog(g.SyncAndRender(asyncLevel), "Unable to sync and render applications")
- case sync:
- return okOrErrLog(g.Sync(asyncLevel), "Unable to sync external sources")
- case render:
- return okOrErrLog(g.Render(asyncLevel), "Unable to render manifests")
- }
-
- // Cleaning up only if all environments and applications were processed
- if envAppMap == nil {
- return okOrErrLog(g.CleanupRenderedManifests(false), "Unable to cleanup rendered manifests")
- }
-
- return nil
+ // Run actions
+ cleanupAfter := envAppMap == nil && render
+ switch {
+ case sync && render:
+ if err := okOrErrLog(g.SyncAndRender(asyncLevel), "Unable to sync and render applications"); err != nil {
+ return err
+ }
+ case sync:
+ return okOrErrLog(g.Sync(asyncLevel), "Unable to sync external sources")
+ case render:
+ if err := okOrErrLog(g.Render(asyncLevel), "Unable to render manifests"); err != nil {
+ return err
+ }
+ }
+ // Cleaning up only if all environments and applications were processed and a render occurred
+ if cleanupAfter {
+ return okOrErrLog(g.CleanupRenderedManifests(false), "Unable to cleanup rendered manifests")
+ }
+ return nil🏁 Script executed:
#!/bin/bash
# Ensure no other code path relies on the old fallthrough to trigger cleanup
rg -nP '\bCleanupRenderedManifests\s*\(' -C3Length of output: 1201
| func getGlobe() *myks.Globe { | ||
| if globe == nil { | ||
| globe = myks.New(viper.GetString("root-dir")) | ||
| } | ||
| return globe | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initialize globe once; avoid races and honor future config changes predictably
Current lazy init isn’t concurrency-safe. Use sync.Once to prevent double-inits under concurrent paths.
import (
"path/filepath"
"strings"
+ "sync"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
+var globeOnce sync.Once
+
func getGlobe() *myks.Globe {
- if globe == nil {
- globe = myks.New(viper.GetString("root-dir"))
- }
- return globe
+ globeOnce.Do(func() {
+ globe = myks.New(viper.GetString("root-dir"))
+ })
+ return globe
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| func getGlobe() *myks.Globe { | |
| if globe == nil { | |
| globe = myks.New(viper.GetString("root-dir")) | |
| } | |
| return globe | |
| } | |
| import ( | |
| "path/filepath" | |
| "strings" | |
| "sync" | |
| "github.com/rs/zerolog/log" | |
| "github.com/spf13/cobra" | |
| "github.com/spf13/viper" | |
| ) | |
| var globeOnce sync.Once | |
| func getGlobe() *myks.Globe { | |
| globeOnce.Do(func() { | |
| globe = myks.New(viper.GetString("root-dir")) | |
| }) | |
| return globe | |
| } |
🤖 Prompt for AI Agents
In cmd/util.go around lines 14 to 19 the lazy initialization of globe is not
concurrency-safe; replace the ad-hoc nil check with sync.Once to guarantee a
single init: add a package-level var globeOnce sync.Once and invoke
globeOnce.Do(func(){ globe = myks.New(viper.GetString("root-dir")) }) inside
getGlobe, then return globe; if you need to allow predictable re-initialization
on config changes, add an explicit ResetGlobe function that sets globe = nil and
globeOnce = sync.Once{} (or use a mutex-based reinit), rather than relying on
concurrent callers to trigger config updates.
| g := getGlobe() | ||
| err := g.Init(asyncLevel, map[string][]string{}) | ||
| if err != nil { | ||
| return nil, cobra.ShellCompDirectiveError | ||
| } | ||
| // return envs | ||
| if len(args) == 0 { | ||
| return getEnvNames(tmp), cobra.ShellCompDirectiveNoFileComp | ||
| return getEnvNames(g), cobra.ShellCompDirectiveNoFileComp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pass nil envAppMap to Init for “all envs/apps” semantics
Empty map can be interpreted differently than nil. Prefer nil to clearly indicate “no filter”.
- err := g.Init(asyncLevel, map[string][]string{})
+ err := g.Init(asyncLevel, nil)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}🤖 Prompt for AI Agents
In cmd/util.go around lines 39 to 46, the call g.Init(asyncLevel,
map[string][]string{}) passes an empty map which can be interpreted differently
than a nil filter; change the second argument to nil so Init receives a nil
envAppMap to indicate “no filter / all envs/apps” (i.e. call g.Init(asyncLevel,
nil)); keep the error handling and subsequent logic unchanged.
| @@ -1,8 +1,9 @@ | |||
| module github.com/mykso/myks | |||
|
|
|||
| go 1.24.6 | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid go directive: use major.minor; pin patch via toolchain.
The go directive must be “1.24”, not “1.24.6”. Optionally add a toolchain line to pin the exact patch.
-go 1.24.6
+go 1.24
+
+toolchain go1.24.6📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| go 1.24.6 | |
| go 1.24 | |
| toolchain go1.24.6 |
🤖 Prompt for AI Agents
In go.mod around line 3, the go directive currently specifies a patch version
"1.24.6" which is invalid; change the go directive to the major.minor form
"1.24" and, if you need to pin the exact patch, add a separate toolchain
directive such as "toolchain 1.24.6" on its own line to lock the patch-level
toolchain.
| // FIXME: Do not change working directory here, implement relative paths throughout the codebase instead | ||
| if rootDir != "." { | ||
| os.Chdir(rootDir) | ||
| rootDir = "." | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Do not mutate process CWD; also fix unchecked os.Chdir error (lint fail)
Changing global CWD is a concurrency and operational hazard; it also triggers errcheck. Prefer keeping RootDir explicit.
Option A (quick fix: pass lint, keep current behavior):
-// FIXME: Do not change working directory here, implement relative paths throughout the codebase instead
-if rootDir != "." {
- os.Chdir(rootDir)
- rootDir = "."
-}
+// FIXME: Avoid changing process CWD; see Option B below.
+if rootDir != "." {
+ if err := os.Chdir(rootDir); err != nil {
+ log.Fatal().Err(err).Str("rootDir", rootDir).Msg("Unable to change working directory")
+ }
+ rootDir = "."
+}Option B (preferred: remove CWD mutation):
-func New(rootDir string) *Globe {
- // FIXME: Do not change working directory here, implement relative paths throughout the codebase instead
- if rootDir != "." {
- os.Chdir(rootDir)
- rootDir = "."
- }
+func New(rootDir string) *Globe {
+ cleanRoot := filepath.Clean(rootDir)
g := NewWithDefaults()
- g.RootDir = rootDir
+ g.RootDir = cleanRoot
g.environments = make(map[string]*Environment)
// ...🏁 Script executed:
#!/bin/bash
# Scan for other working-directory mutations and suspicious relative I/O.
rg -nP 'os\.Chdir\(|os\.Getwd\('
rg -nP '\bReadFile\("|\bWriteFile\("|\bOpen\("|\bStat\("' -g '!**/vendor/**' -C2
rg -nP 'filepath\.Join\(\s*g\.RootDir' -C1Length of output: 3757
I need to examine the context around the os.Chdir call and verify whether removing the CWD mutation would break any production code.
Now I need to examine the actual New() function and surrounding code in globe.go to determine if removing the os.Chdir call would break anything:
Now I need to examine the actual New() function to see what happens after the os.Chdir call and determine if removing it would break anything:
[/run_scripts]
🏁 Script executed:
#!/bin/bash
# Examine the New() function in globe.go around line 132-160
sed -n '128,165p' internal/myks/globe.goLength of output: 1025
I need to verify that the functions called after os.Chdir (like initGitData() and dumpConfigAsYaml()) will properly handle an explicit RootDir path instead of relying on the mutated CWD:
[/run_scripts]
🏁 Script executed:
#!/bin/bash
# Examine initGitData() and dumpConfigAsYaml() to verify they handle g.RootDir properly
echo "=== initGitData() ===" && \
sed -n '/^func (g \*Globe) initGitData/,/^func /p' internal/myks/globe.go | head -20 && \
echo -e "\n=== dumpConfigAsYaml() ===" && \
sed -n '/^func (g \*Globe) dumpConfigAsYaml/,/^func /p' internal/myks/globe.go | head -30Length of output: 1510
Fix unchecked os.Chdir error (lint violation) and remove process CWD mutation
The unchecked os.Chdir at line 134 violates errcheck linting and creates a concurrency hazard. The codebase is already designed to use explicit paths throughout (all file I/O uses filepath.Join(g.RootDir, ...)), so Option B (removing the CWD mutation) is safe and should be implemented:
func New(rootDir string) *Globe {
- // FIXME: Do not change working directory here, implement relative paths throughout the codebase instead
- if rootDir != "." {
- os.Chdir(rootDir)
- rootDir = "."
- }
g := NewWithDefaults()
- g.RootDir = rootDir
+ g.RootDir = filepath.Clean(rootDir)
g.environments = make(map[string]*Environment)Both initGitData() and dumpConfigAsYaml() already pass g.RootDir as explicit path parameters and construct paths via filepath.Join(g.RootDir, ...), so they will continue working correctly with the actual path value instead of relying on CWD mutation.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // FIXME: Do not change working directory here, implement relative paths throughout the codebase instead | |
| if rootDir != "." { | |
| os.Chdir(rootDir) | |
| rootDir = "." | |
| } | |
| func New(rootDir string) *Globe { | |
| g := NewWithDefaults() | |
| g.RootDir = filepath.Clean(rootDir) | |
| g.environments = make(map[string]*Environment) |
🧰 Tools
🪛 GitHub Check: lint / lint
[failure] 134-134:
Error return value of os.Chdir is not checked (errcheck)
🤖 Prompt for AI Agents
In internal/myks/globe.go around lines 132-136, the code mutates the process CWD
with an unchecked os.Chdir call (and reassigns rootDir to "."), which violates
errcheck and creates a concurrency hazard; remove the entire if rootDir != "." {
os.Chdir(rootDir); rootDir = "." } block and keep rootDir unchanged, relying on
existing callers (initGitData and dumpConfigAsYaml) that already accept explicit
g.RootDir and build paths with filepath.Join; ensure no other code in this file
depends on the process CWD and adjust any remaining references to use g.RootDir
explicitly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolute paths differ in different environments. Those paths are written to some output files that are committed to the repository and shared. Using absolute paths would lead to a constant flow of changes in the output files, depending on where they are generated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Zebradil, thank you for that important context about relative paths in committed output files—that's a valid constraint I hadn't fully considered.
However, the unchecked os.Chdir error must be fixed to pass lint (errcheck violation). The minimal fix that preserves your current behavior is Option A from the original comment:
// FIXME: Avoid changing process CWD; refactor to explicit relative paths when possible.
if rootDir != "." {
if err := os.Chdir(rootDir); err != nil {
log.Fatal().Err(err).Str("rootDir", rootDir).Msg("Unable to change working directory")
}
rootDir = "."
}This keeps the CWD mutation (so all subsequent relative path operations continue to work as they do now) while satisfying the linter.
Question for future refactoring: Which output files write paths that get committed? If I understand which code writes those paths (e.g., in dumpConfigAsYaml, vendir configs, or rendered manifests), we could potentially refactor to avoid CWD mutation while ensuring paths remain relative to a consistent base. But that would be a larger change outside this PR's scope.
For now, adding the error check is the pragmatic fix. Would you like me to provide that as a committable suggestion?
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
New major version with a number of improvements. feat(cmd)!: replace `all`, `sync`, and `render` commands with a single `render` command (#570) chore: fix typos in documentation and rename embedded.go refactor(cmd): ensure mutuall exclusivity of sync and render flags via Cobra feat: add config-in-root option that sets root-dir to the config file location feat: add kbld support (#626)
Summary by CodeRabbit
Release Notes
New Features
config-in-rootconfiguration option for flexible project setup.Changes
allandsynccommands replaced by streamlinedrendercommand.Documentation