Skip to content

Update loft utils for helm v4#3121

Merged
zerbitx merged 5 commits intomainfrom
DSP-156
Apr 28, 2026
Merged

Update loft utils for helm v4#3121
zerbitx merged 5 commits intomainfrom
DSP-156

Conversation

@zerbitx
Copy link
Copy Markdown
Collaborator

@zerbitx zerbitx commented Feb 5, 2026

What issue type does this pull request address? (keep at least one, remove the others)
/kind enhancement

What does this pull request do? Which issues does it resolve? (use resolves #<issue_number> if possible)
resolves #DSP-156

Please provide a short message that should be published in the DevSpace release notes
Updates the loft-sh/utils dependency to be able to use Helm v4 and updates some logging code so it will build.

What else do we need to know?

@netlify
Copy link
Copy Markdown

netlify Bot commented Feb 5, 2026

Deploy Preview for devspace-docs canceled.

Name Link
🔨 Latest commit fd19932
🔍 Latest deploy log https://app.netlify.com/projects/devspace-docs/deploys/69f145362004f70008c03187

zerbitx added 2 commits April 27, 2026 14:36
Signed-off-by: Ryan Swanson <ryan.swanson@loft.sh>

# Conflicts:
#	go.mod
#	go.sum
#	vendor/github.com/otiai10/copy/README.md
#	vendor/github.com/otiai10/copy/copy.go
#	vendor/github.com/otiai10/copy/copy_namedpipes.go
#	vendor/github.com/otiai10/copy/copy_namedpipes_x.go
#	vendor/github.com/otiai10/copy/fileinfo_go1.15.go
#	vendor/github.com/otiai10/copy/options.go
#	vendor/github.com/otiai10/copy/permission_control.go
#	vendor/github.com/otiai10/copy/preserve_ltimes.go
#	vendor/github.com/otiai10/copy/preserve_ltimes_x.go
#	vendor/github.com/otiai10/copy/preserve_owner.go
#	vendor/github.com/otiai10/copy/preserve_owner_x.go
#	vendor/github.com/otiai10/copy/stat_times.go
#	vendor/github.com/otiai10/copy/stat_times_darwin.go
#	vendor/github.com/otiai10/copy/stat_times_freebsd.go
#	vendor/github.com/otiai10/copy/stat_times_js.go
#	vendor/github.com/otiai10/copy/stat_times_windows.go
#	vendor/github.com/otiai10/copy/stat_times_x.go
#	vendor/github.com/otiai10/copy/test_setup.go
#	vendor/github.com/otiai10/copy/test_setup_x.go
#	vendor/modules.txt
Signed-off-by: Ryan Swanson <ryan.swanson@loft.sh>
Signed-off-by: Ryan Swanson <ryan.swanson@loft.sh>
@zerbitx
Copy link
Copy Markdown
Collaborator Author

zerbitx commented Apr 28, 2026

From claude:

Adversarial Review — PR #3121: Update loft utils for helm v4

TL;DR

The core dependency migration and interface refactor are structurally sound. There is one blocker (debug statement in tests), several meaningful correctness and quality gaps in the new logr adapter, and a large
amount of trailing-whitespace noise polluting the diff.


[BLOCKER] Debug emoji print left in test

pkg/devspace/pipeline/engine/engine_test.go:137:
fmt.Println("👉:", stdout1.String())
This is a debug statement that will print raw Helm version output to go test stdout on every test run. Must be removed before merge.


[HIGH] LogrSink.Info formats structured key-value pairs as a raw slice

pkg/util/log/logr_adapter.go:23-26:
l.logger.Debugf("%s %v", msg, keysAndValues)
keysAndValues is []any. %v on a slice prints [key1 val1 key2 val2], producing output like:
downloading helm [component helm attempt 3]
instead of the logr convention of key=value pairs. The downloader library will call logger.Info("msg", "key", val, ...) and the output will be unreadable. A proper implementation should iterate the slice in pairs.


[HIGH] StartWait/StopWait are silently dropped — download progress is invisible

pkg/util/log/stream_logger.go:470-475:
func (s *StreamLogger) StartWait(message string) {
// TODO: implement spinner/wait indicator
}
func (s *StreamLogger) StopWait() {
// TODO: implement spinner/wait indicator
}
If the loft-sh/utils downloader calls StartWait("Downloading helm...") during binary acquisition, users see nothing — no spinner, no message. This is a silent UX regression versus the old behavior. The TODO is also
undated and untracked. At minimum, StartWait should fall through to l.Info(message).


[MEDIUM] WithValues silently drops structured context with no warning

pkg/util/log/logr_adapter.go:39-42:
func (l *LogrSink) WithValues(keysAndValues ...any) logr.LogSink {
// Our logger doesn't support key-value pairs, just return the same sink
return l
}
The logr contract for WithValues is that returned logs always include those key-value pairs. By returning l unchanged, any caller doing logger.WithValues("component", "helm-downloader").Info(...) permanently loses
that context. This is accepted given the adapter's purpose, but the comment should be explicit that this is an intentional lossy implementation, not a placeholder for future work.


[MEDIUM] Trailing-whitespace noise across hundreds of lines

The diff replaces blank lines (\n) with lines containing only a tab (\t\n) in cmd/init.go, cmd/run.go, e2e/tests/render/render.go, pkg/devspace/helm/v4/client.go, pkg/devspace/deploy/deployer/kubectl/kubectl.go, and
others. This produces hundreds of noisy diff hunks like:

This is an editor artifact and not idiomatic Go. gofmt does not produce trailing whitespace. It makes the real changes much harder to spot in review and will trigger complaints from linters or pre-commit hooks.


[MEDIUM] Duplicate Helm removal in CI

.github/workflows/unit-tests.yaml now has two separate Helm-removal mechanisms for the same matrix OS:

  1. An inline step: sudo rm -rf $(which helm) || true
  2. Inside the Test step: source ./hack/remove-system-helm.sh

The remove-system-helm.sh script (which correctly iterates all helm binaries in PATH) supersedes the inline step. The inline step should be removed — it's redundant and rm -rf on $(which helm) is a blunt instrument
that only catches one instance.


[LOW] hack/build-all.bash still hardcodes darwin-amd64

curl -s https://get.helm.sh/helm-v4.0.4-darwin-amd64.tar.gz > helm4.tar.gz
The old Helm 3 line had the same hardcoded platform. The PR updates the version but not the platform detection. This script fails silently on Linux CI runners. Pre-existing issue, but since the PR touches this line,
fixing it (or adding a $(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m) substitution) would be free to do here.

This is an editor artifact and not idiomatic Go. gofmt does not produce trailing whitespace. It makes the real changes much harder to spot in review and will trigger complaints from linters or pre-commit hooks.


This is an editor artifact and not idiomatic Go. gofmt does not produce trailing whitespace. It makes the real changes much harder to spot in review and will trigger complaints from linters or pre-commit hooks.


[MEDIUM] Duplicate Helm removal in CI

.github/workflows/unit-tests.yaml now has two separate Helm-removal mechanisms for the same matrix OS:

  1. An inline step: sudo rm -rf $(which helm) || true
  2. Inside the Test step: source ./hack/remove-system-helm.sh

The remove-system-helm.sh script (which correctly iterates all helm binaries in PATH) supersedes the inline step. The inline step should be removed — it's redundant and rm -rf on $(which helm) is a blunt instrument
that only catches one instance.


[LOW] hack/build-all.bash still hardcodes darwin-amd64

curl -s https://get.helm.sh/helm-v4.0.4-darwin-amd64.tar.gz > helm4.tar.gz
The old Helm 3 line had the same hardcoded platform. The PR updates the version but not the platform detection. This script fails silently on Linux CI runners. Pre-existing issue, but since the PR touches this line,
fixing it (or adding a $(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m) substitution) would be free to do here.


[LOW] LogrSink.Enabled always returns true — bypasses level-gating

func (l *LogrSink) Enabled(level int) bool {
return true
}
The logr pattern is: callers check log.V(n).Enabled() before constructing expensive log messages (e.g., marshaling structs). Always returning true means callers never short-circuit, even if the underlying Logger
level would suppress the message. For a download utility, the overhead is low, but it's worth noting.


[LOW] loft-util module status needs verification

The PR deletes vendor/github.com/loft-sh/loft-util/LICENSE and vendor/github.com/loft-sh/loft-util/pkg/command/command.go but the current go.mod on main still lists github.com/loft-sh/loft-util v0.0.9-alpha as a
direct dependency and vendor/modules.txt still references github.com/loft-sh/loft-util/pkg/command. No Go source files outside vendor import it anymore. If the PR's go.mod still lists it as a require entry, go mod
tidy would flag it as unused. Confirm the PR runs go mod tidy or removes the require entry manually.

… interface

- add a local helm v4 downloader command outside vendor
- restore repo builds with the current vendored utils state
- improve logr adapter formatting and StartWait fallback
- clean up helm test/build wiring and stale loft-util references

Signed-off-by: Ryan Swanson <ryan.swanson@loft.sh>
- avoid double-closing copied Helm binaries
- return non-missing Helm validation errors
- document StopWait fallback behavior
- derive build Helm version from helm_v4.go
- remove whitespace-only diff noise

Signed-off-by: Ryan Swanson <ryan.swanson@loft.sh>
@zerbitx zerbitx merged commit 1c18372 into main Apr 28, 2026
20 of 21 checks passed
@zerbitx zerbitx deleted the DSP-156 branch April 28, 2026 23:57
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