Skip to content

feat(push): add --output json/yaml/table flag to helm push#32009

Open
Mentigen wants to merge 9 commits intohelm:mainfrom
Mentigen:add-helm-push-output-json
Open

feat(push): add --output json/yaml/table flag to helm push#32009
Mentigen wants to merge 9 commits intohelm:mainfrom
Mentigen:add-helm-push-output-json

Conversation

@Mentigen
Copy link
Copy Markdown
Contributor

@Mentigen Mentigen commented Apr 5, 2026

Summary

Add support for --output flag to 'helm push' command for machine-readable output formats (JSON and YAML). This enables programmatic consumption of push results and integration with tools like cosign for artifact signing.

Changes

  • Modified Pusher interface to return (*registry.PushResult, error)
  • Updated OCIPusher.Push() and push() to return PushResult
  • Updated action.Push.Run() to return (*registry.PushResult, error)
  • Added output formatting to push command (table/json/yaml)
  • Created pushResult struct with Ref and Digest fields
  • Implemented pushWriter with WriteTable/WriteJSON/WriteYAML methods
  • Updated test fixtures to handle new return signature

The default table format maintains backward compatibility with existing plain-text output style.

Test plan

  • Run go test ./pkg/cmd/... ./pkg/action/... ./pkg/pusher/... to ensure all tests pass
  • Manually test: helm push mychart oci://registry/repo --output json
  • Verify JSON output: {"ref":"...","digest":"..."}
  • Verify YAML output format
  • Verify default table format unchanged

Copilot AI review requested due to automatic review settings April 5, 2026 17:01
@pull-request-size pull-request-size bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Apr 5, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds machine-readable output support to helm push by plumbing a structured push result (*registry.PushResult) through the pusher/action layers and formatting it in the CLI as table/JSON/YAML.

Changes:

  • Update pusher/uploader/action push APIs to return (*registry.PushResult, error) instead of plain text / error-only.
  • Add --output support to helm push and implement table/JSON/YAML formatting for push results.
  • Adjust OCI pusher tests for the new return signature.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pkg/uploader/chart_uploader.go Propagates *registry.PushResult from the selected pusher.
pkg/pusher/pusher.go Changes Pusher interface to return *registry.PushResult.
pkg/pusher/ocipusher.go Returns the registry.Client.Push() result instead of only an error.
pkg/pusher/ocipusher_test.go Updates tests to ignore the new result value when asserting errors.
pkg/cmd/push.go Adds --output flag wiring and formats push result as table/JSON/YAML.
pkg/action/push.go Changes Push.Run() to return *registry.PushResult and adjusts output handling.
Comments suppressed due to low confidence (1)

pkg/action/push.go:100

  • WithPushOptWriter sets p.out, but Run() now hard-codes ChartUploader.Out to io.Discard and never uses p.out. This makes the option effectively dead and can change where push informational output/warnings are emitted (and can also contribute to duplicated output if the registry client still writes its own messages). Consider either wiring p.out through to whatever component is responsible for emitting push info, or removing WithPushOptWriter/Push.out entirely to avoid misleading API surface.
func (p *Push) Run(chartRef string, remote string) (*registry.PushResult, error) {
	c := uploader.ChartUploader{
		Out:     io.Discard,
		Pushers: pusher.All(p.Settings),
		Options: []pusher.Option{
			pusher.WithTLSClientConfig(p.certFile, p.keyFile, p.caFile),
			pusher.WithInsecureSkipTLSVerify(p.insecureSkipTLSVerify),
			pusher.WithPlainHTTP(p.plainHTTP),
		},

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +118 to 129
result, err := client.Run(chartRef, remote)
if err != nil {
return err
}
fmt.Fprint(out, output)
return nil
writer := &pushWriter{
result: pushResult{
Ref: result.Ref,
Digest: result.Manifest.Digest,
},
}
return o.outfmt.Write(out, writer)
},
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command now always prints a formatted result to out, but the registry client used by the pusher also prints "Pushed:" / "Digest:" to its own writer inside registry.Client.Push() (and newRegistryClient configures that writer as os.Stderr). In a terminal, this will typically result in duplicated output for the default table format. Consider suppressing registry-client push output when --output table is used (or conversely, for table output rely solely on the registry client’s messages), while keeping stderr clean for machine-readable --output json|yaml.

Copilot uses AI. Check for mistakes.
pkg/cmd/push.go Outdated
Comment on lines 115 to 116
action.WithPlainHTTP(o.plainHTTP),
action.WithPushOptWriter(out))
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

action.WithPushOptWriter(out) is still passed when constructing the push action, but Push.Run() no longer uses that writer. This is confusing for readers and suggests output routing is configurable when it currently isn't. Either remove this option usage here or restore using the writer in the action so the flag has an effect.

Suggested change
action.WithPlainHTTP(o.plainHTTP),
action.WithPushOptWriter(out))
action.WithPlainHTTP(o.plainHTTP))

Copilot uses AI. Check for mistakes.
@Mentigen Mentigen force-pushed the add-helm-push-output-json branch from 69abd22 to a5ebd5f Compare April 5, 2026 17:14
Copilot AI review requested due to automatic review settings April 5, 2026 17:28
@Mentigen Mentigen force-pushed the add-helm-push-output-json branch from a5ebd5f to 0b439c0 Compare April 5, 2026 17:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

pkg/action/push.go:105

  • WithPushOptWriter sets p.out, but Push.Run() only passes that writer to uploader.ChartUploader.Out. ChartUploader.UploadTo() currently never uses Out, so this option doesn’t actually control any push output and can’t be used to redirect/suppress registry client messages. Either wire out through to where output is emitted (e.g., registry client ClientOptWriter) or remove/rename this option to avoid a misleading API.
func (p *Push) Run(chartRef string, remote string) (*registry.PushResult, error) {
	out := p.out
	if out == nil {
		out = io.Discard
	}
	c := uploader.ChartUploader{
		Out:     out,
		Pushers: pusher.All(p.Settings),
		Options: []pusher.Option{
			pusher.WithTLSClientConfig(p.certFile, p.keyFile, p.caFile),
			pusher.WithInsecureSkipTLSVerify(p.insecureSkipTLSVerify),
			pusher.WithPlainHTTP(p.plainHTTP),
		},
	}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 118 to 143
@@ -104,5 +138,7 @@ func newPushCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f.StringVar(&o.username, "username", "", "chart repository username where to locate the requested chart")
f.StringVar(&o.password, "password", "", "chart repository password where to locate the requested chart")

bindOutputFlag(cmd, &o.outfmt)

return cmd
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New behavior adds JSON/YAML output for helm push, but there are no command-level tests asserting the emitted formats (unlike other commands in this package that use --output golden tests). Adding tests for table/json/yaml (and ensuring the default output remains unchanged) would help prevent regressions, especially around stderr/stdout interactions.

Copilot uses AI. Check for mistakes.
@Mentigen Mentigen force-pushed the add-helm-push-output-json branch from 0b439c0 to 0ee6823 Compare April 5, 2026 18:04
@pull-request-size pull-request-size bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Apr 5, 2026
Add support for --output flag to 'helm push' command for machine-readable
output formats (JSON and YAML). This enables programmatic consumption of push
results and integration with tools like cosign for artifact signing.

Changes:
- Modified Pusher interface to return (*registry.PushResult, error)
- Updated OCIPusher.Push() and push() to return PushResult
- Updated action.Push.Run() to return (*registry.PushResult, error)
- Added output formatting to push command (table/json/yaml)
- Created pushResult struct with Ref and Digest fields
- Implemented pushWriter with WriteTable/WriteJSON/WriteYAML methods
- Updated test fixtures to handle new return signature

The default table format maintains backward compatibility with existing
plain-text output style.

Fixes helm#11735

Signed-off-by: Ilya Kiselev <kis-ilya-a@yandex.ru>
Copilot AI review requested due to automatic review settings April 5, 2026 18:12
@Mentigen Mentigen force-pushed the add-helm-push-output-json branch from 0ee6823 to 0b9946a Compare April 5, 2026 18:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +92 to 96
func (p *Push) Run(chartRef string, remote string) (*registry.PushResult, error) {
c := uploader.ChartUploader{
Out: &out,
Out: io.Discard,
Pushers: pusher.All(p.Settings),
Options: []pusher.Option{
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Push.Run no longer uses p.out (set via WithPushOptWriter) and always builds the uploader with Out: io.Discard. That makes WithPushOptWriter effectively a no-op and can mislead API consumers/tests. Consider either wiring p.out through to the underlying registry client's writer (or uploader warnings) or removing/deprecating WithPushOptWriter and the unused out field/tests to avoid dead API surface.

Copilot uses AI. Check for mistakes.
pkg/cmd/push.go Outdated
Comment on lines +60 to +63
// WriteTable is a no-op for push: the registry client already prints
// "Pushed:" and "Digest:" to stderr, so we avoid duplicating that output.
func (w *pushWriter) WriteTable(_ io.Writer) error {
return nil
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pushWriter.WriteTable being a no-op means --output table produces no structured output on the command's out stream; the only visible result comes from registry client side-effects to stderr. Since --output advertises selectable formats, consider emitting a minimal human-readable table/lines (ref + digest) in WriteTable and, if needed, suppressing the registry client's own printing when --output is not table to prevent mixed/duplicated output.

Suggested change
// WriteTable is a no-op for push: the registry client already prints
// "Pushed:" and "Digest:" to stderr, so we avoid duplicating that output.
func (w *pushWriter) WriteTable(_ io.Writer) error {
return nil
// WriteTable writes a minimal human-readable push result to the provided output.
func (w *pushWriter) WriteTable(out io.Writer) error {
_, err := fmt.Fprintf(out, "REF\t%s\nDIGEST\t%s\n", w.result.Ref, w.result.Digest)
return err

Copilot uses AI. Check for mistakes.
cmd/push: implement WriteTable to emit ref and digest

The WithPushOptWriter option and the out field on Push were never
wired to any meaningful output path — ChartUploader.Out is not read
by UploadTo() and the registry client manages its own writer.
Remove them to avoid dead API surface.

WriteTable now writes a tab-aligned REF/DIGEST result to the
command's stdout stream. The registry client continues to write
its own progress output to stderr, so there is no duplication.

Signed-off-by: Mentigen <mentigen@mentigen.ru>
Signed-off-by: Ilya Kiselev <kis-ilya-a@yandex.ru>
@Mentigen Mentigen force-pushed the add-helm-push-output-json branch from 3602cda to 5a093e9 Compare April 5, 2026 18:23
Signed-off-by: Ilya Kiselev <kis-ilya-a@yandex.ru>
Copilot AI review requested due to automatic review settings April 5, 2026 18:31
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

pkg/cmd/push.go Outdated
Comment on lines +61 to +68
// WriteTable writes a minimal human-readable push result to the provided output.
// The registry client prints progress to stderr; this writes the structured
// result (ref + digest) to the command's stdout stream.
func (w *pushWriter) WriteTable(out io.Writer) error {
tw := tabwriter.NewWriter(out, 0, 0, 2, ' ', 0)
fmt.Fprintf(tw, "REF\t%s\n", w.result.Ref)
fmt.Fprintf(tw, "DIGEST\t%s\n", w.result.Digest)
return tw.Flush()
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default table output produced here ("REF"/"DIGEST") does not match the existing push summary strings emitted by the registry client ("Pushed: …" / "Digest: …" in pkg/registry/client.go:746-747). If the goal is backward-compatible human output, consider aligning WriteTable to the established wording/format, or explicitly documenting that the default output format changes.

Copilot uses AI. Check for mistakes.
Comment on lines +122 to 133
result, err := client.Run(chartRef, remote)
if err != nil {
return err
}
fmt.Fprint(out, output)
return nil
writer := &pushWriter{
result: pushResult{
Ref: result.Ref,
Digest: result.Manifest.Digest,
},
}
return o.outfmt.Write(out, writer)
},
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

helm.sh/helm/v4/pkg/registry.Client.Push already writes a push summary ("Pushed:" and "Digest:") to the registry client's configured writer (currently os.Stderr in pkg/cmd/root.go). With the additional structured output written here, a successful push will produce duplicated summary information across stderr/stdout. Consider suppressing the registry client's summary output for helm push (e.g., configure the registry client writer to io.Discard for this command, or add an option to registry.Push/client to disable the final summary lines) so that stdout is the single source of truth for --output consumers.

Copilot uses AI. Check for mistakes.
Comment on lines +126 to +132
writer := &pushWriter{
result: pushResult{
Ref: result.Ref,
Digest: result.Manifest.Digest,
},
}
return o.outfmt.Write(out, writer)
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new --output behavior is only unit-tested at the pushWriter level; there’s no command-level test asserting that helm push ... --output json|yaml|table wires through correctly and produces the expected stdout (similar to other commands’ golden tests like pkg/cmd/get_metadata_test.go). Adding an integration-style cmd test would help prevent regressions in flag binding and output shape.

Copilot uses AI. Check for mistakes.
Comment on lines 74 to 77
// Push file content by url string, returning the push result and any error
Push(chartRef, url string, options ...Option) (*registry.PushResult, error)
}

Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the exported pusher.Pusher interface method signature is a breaking API change for any external implementations of Pusher. If this package is intended as an extension point, consider preserving the old Push(...) error via a new interface (or an adapter layer) and introducing a new method/interface for returning *registry.PushResult, to avoid forcing downstream updates in a minor release.

Suggested change
// Push file content by url string, returning the push result and any error
Push(chartRef, url string, options ...Option) (*registry.PushResult, error)
}
// Push file content by url string, returning any error encountered.
Push(chartRef, url string, options ...Option) error
}
// ResultPusher is an optional extension interface for pushers that can also
// return a registry push result without breaking existing Pusher implementations.
type ResultPusher interface {
// PushWithResult pushes file content by url string, returning the push result
// and any error encountered.
PushWithResult(chartRef, url string, options ...Option) (*registry.PushResult, error)
}
// Push performs a push using the provided pusher. If the pusher also supports
// ResultPusher, the push result will be returned. Otherwise, this falls back to
// the legacy Push behavior and returns a nil result on success.
func Push(pusher Pusher, chartRef, url string, options ...Option) (*registry.PushResult, error) {
if resultPusher, ok := pusher.(ResultPusher); ok {
return resultPusher.PushWithResult(chartRef, url, options...)
}
if err := pusher.Push(chartRef, url, options...); err != nil {
return nil, err
}
return nil, nil
}

Copilot uses AI. Check for mistakes.
func (p *Push) Run(chartRef string, remote string) (string, error) {
var out strings.Builder

func (p *Push) Run(chartRef string, remote string) (*registry.PushResult, error) {
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

action.Push.Run changed from returning (string, error) to (*registry.PushResult, error), which is a breaking change for any callers using the action package as a library. If compatibility for existing consumers matters, consider adding a new method (e.g., RunWithResult) or keeping the old signature and returning the previous string form via the new result.

Suggested change
func (p *Push) Run(chartRef string, remote string) (*registry.PushResult, error) {
func (p *Push) Run(chartRef string, remote string) (string, error) {
result, err := p.RunWithResult(chartRef, remote)
if err != nil {
return "", err
}
return result.Ref, nil
}
// RunWithResult executes 'helm push' against the given chart archive and returns the full push result.
func (p *Push) RunWithResult(chartRef string, remote string) (*registry.PushResult, error) {

Copilot uses AI. Check for mistakes.
Mentigen added 2 commits April 5, 2026 21:40
Signed-off-by: Ilya Kiselev <kis-ilya-a@yandex.ru>
Address Copilot review feedback:
- WriteTable now uses "Pushed:"/"Digest:" labels consistent with the
  registry client's built-in output (pkg/registry/client.go:746-747),
  so the default --output table experience is familiar to existing users
- Add TestPushOutputFlagCompletion to verify the --output flag is
  properly registered and offers json/yaml/table completions
- Document that Pusher.Push and action.Push.Run signature changes are
  intentional breaking changes in the Helm v4 major release

Signed-off-by: Ilya Kiselev <kis-ilya-a@yandex.ru>
Copilot AI review requested due to automatic review settings April 5, 2026 18:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Ref: result.Ref,
Digest: result.Manifest.Digest,
},
}
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OCI registry client used here (created by newRegistryClient) writes its own push summary ("Pushed:"/"Digest:" and the underscore warning) to its configured writer (currently os.Stderr via registry.ClientOptWriter). Since this command also formats and writes the result, users will see duplicated table output and --output json|yaml will still produce extra human-readable lines on stderr. Consider constructing the registry client with an io.Discard writer for helm push (e.g., make newRegistryClient accept a writer override) and, if needed, emit only the underscore warning separately so structured output stays clean.

Suggested change
}
}
outputFlag := ""
if flag := cmd.Flag("output"); flag != nil {
outputFlag = flag.Value.String()
}
if outputFlag == "" || outputFlag == "table" {
return nil
}

Copilot uses AI. Check for mistakes.
Mentigen added 2 commits April 5, 2026 22:02
Add an optional io.Writer parameter to newRegistryClient (and the
internal newDefaultRegistryClient / newRegistryClientWithTLS helpers)
so callers can control where registry client output goes.

All existing callers are unaffected (default remains os.Stderr).

For helm push, pass io.Discard so that the registry client's built-in
"Pushed:"/"Digest:" lines are suppressed. The --output writer
(WriteTable / WriteJSON / WriteYAML) is the single source of truth for
push result output, preventing duplication on the terminal.

Signed-off-by: Ilya Kiselev <kis-ilya-a@yandex.ru>
Signed-off-by: Ilya Kiselev <kis-ilya-a@yandex.ru>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

pkg/cmd/push.go Outdated
Comment on lines 105 to 111
// Suppress the registry client's built-in "Pushed:"/"Digest:" lines;
// the --output writer (WriteTable/WriteJSON/WriteYAML) is the single
// source of structured push output for this command.
registryClient, err := newRegistryClient(
o.certFile, o.keyFile, o.caFile, o.insecureSkipTLSVerify, o.plainHTTP, o.username, o.password,
io.Discard,
)
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing io.Discard into newRegistryClient suppresses all registry client output, not just the built-in "Pushed:"/"Digest:" summary lines. This also drops important warnings emitted by the registry client (e.g., the underscore warning in pkg/registry/client.go that can affect image references). Consider keeping warnings on stderr while suppressing only the summary lines (e.g., add an option to the registry client to disable summary printing, or wrap the writer to filter only the two summary prefixes and forward everything else to cmd.ErrOrStderr()).

Copilot uses AI. Check for mistakes.
pkg/cmd/root.go Outdated
w ...io.Writer,
) (*registry.Client, error) {
out := io.Writer(os.Stderr)
if len(w) > 0 {
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

newRegistryClient accepts an optional writer override via a variadic parameter, but it doesn't guard against callers passing a nil writer (e.g., newRegistryClient(..., nil)), which would later cause panics when the registry client writes output. Consider treating a nil override the same as "not provided" (default to os.Stderr) or explicitly returning an error for nil writers.

Suggested change
if len(w) > 0 {
if len(w) > 0 && w[0] != nil {

Copilot uses AI. Check for mistakes.
Comment on lines 100 to 103
if registry.IsOCI(remote) {
// Don't use the default registry client if tls options are set.
c.Options = append(c.Options, pusher.WithRegistryClient(p.cfg.RegistryClient))
}
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Push.Run can panic if it is constructed without WithPushConfig: when remote is OCI, it unconditionally dereferences p.cfg.RegistryClient even if p.cfg is nil. Since pkg/action is a public API and NewPushWithOpts doesn't enforce cfg, consider returning a clear error when p.cfg is nil (or changing the constructor to require a *Configuration) to avoid a nil-pointer crash.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 6, 2026 13:17
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


// newRegistryClient creates a registry client. The optional w parameter
// overrides where the registry client writes its output (default: os.Stderr).
// Pass io.Discard to suppress the client's built-in push/pull summary lines.
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc comment suggests passing io.Discard only suppresses the registry client's built-in push/pull summary lines, but in practice it will discard all registry client output (including underscore warnings, etc.). Consider rewording to reflect that io.Discard suppresses all output, or documenting the expectation that callers should provide a filtering writer when they want to suppress only specific lines.

Suggested change
// Pass io.Discard to suppress the client's built-in push/pull summary lines.
// Pass io.Discard to suppress all output written by the registry client to
// this writer. To suppress only specific lines, provide a filtering writer.

Copilot uses AI. Check for mistakes.
if p.cfg == nil {
return nil, errors.New("missing action configuration: use WithPushConfig when constructing Push")
}
// Don't use the default registry client if tls options are set.
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment appears inaccurate: the code always injects p.cfg.RegistryClient for OCI remotes, not only when TLS options are set. Please update or remove the comment to match the current behavior so future readers don't assume the registry client selection is conditional on TLS flags.

Suggested change
// Don't use the default registry client if tls options are set.
// Use the configured registry client for OCI remotes.

Copilot uses AI. Check for mistakes.
Mentigen added 2 commits April 6, 2026 16:25
- root.go: guard against nil writer in newRegistryClient variadic
  parameter to prevent panic on explicit nil pass
- push.go (cmd): replace io.Discard with suppressSummaryWriter that
  forwards warnings/errors to stderr while silently dropping the
  registry client's built-in "Pushed:"/"Digest:" summary lines
- push.go (action): return a clear error when Run() is called on an
  OCI remote without WithPushConfig, preventing nil-pointer panic on
  p.cfg.RegistryClient dereference

Signed-off-by: Ilya Kislitsyn <kis-ilya-a@yandex.ru>
Signed-off-by: Ilya Kiselev <kis-ilya-a@yandex.ru>
Fixes revive lint: unnecessary-format.

Signed-off-by: Ilya Kislitsyn <kis-ilya-a@yandex.ru>
Signed-off-by: Ilya Kiselev <kis-ilya-a@yandex.ru>
@Mentigen Mentigen force-pushed the add-helm-push-output-json branch from 051a978 to 2ce8dbd Compare April 6, 2026 13:25
@promptless-for-oss
Copy link
Copy Markdown

Promptless prepared a documentation update related to this change.

Triggered by this PR

Updated the OCI registries topic documentation with a new "Machine-readable output" subsection explaining how to use the --output flag with json/yaml/table formats, including a practical example showing integration with cosign for artifact signing in CI/CD pipelines.

Review at helm/helm-www#2060

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants