Repository: helm/helm (go)

Issue:
Add support for `helm list --no-headers`
Add support for helm list --no-headers.

One frequently used kubectl option is --no-headers, it would be more convenient for users if helm also supports it.

Pull request description:
Add support for`helm list --no-headers`
<!--  Thanks for sending a pull request!  Here are some tips for you:
1. Make sure to read the Contributing Guide before submitting your PR: https://github.com/helm/helm/blob/main/CONTRIBUTING.md
2. If this PR closes another issue, add 'closes #<issue number>' somewhere in the PR summary. GitHub will automatically close that issue when this PR gets merged. Alternatively, adding 'refs #<issue number>' will not close the issue, but help provide the reviewer more context.-->

**What this PR does / why we need it**:

Fix #10548 

Some other changes in the PR:

1. `newReleaseListWriter` is changed to return a struct instead, because it's a tiny struct and we don't need to update it in place, so there's no need to use pointer semantic here.

**Special notes for your reviewer**:

**If applicable**:
- [ ] this PR contains documentation
- [ ] this PR contains unit tests
- [x] this PR has been tested for backwards compatibility


Patch:
diff --git a/cmd/helm/list.go b/cmd/helm/list.go
index 2f0e3da0b..5ca3de18e 100644
--- a/cmd/helm/list.go
+++ b/cmd/helm/list.go
@@ -83,8 +83,7 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
 			}
 
 			if client.Short {
-
-				names := make([]string, 0)
+				names := make([]string, 0, len(results))
 				for _, res := range results {
 					names = append(names, res.Name)
 				}
@@ -103,17 +102,16 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
 						fmt.Fprintln(out, res.Name)
 					}
 					return nil
-				default:
-					return outfmt.Write(out, newReleaseListWriter(results, client.TimeFormat))
 				}
 			}
 
-			return outfmt.Write(out, newReleaseListWriter(results, client.TimeFormat))
+			return outfmt.Write(out, newReleaseListWriter(results, client.TimeFormat, client.NoHeaders))
 		},
 	}
 
 	f := cmd.Flags()
 	f.BoolVarP(&client.Short, "short", "q", false, "output short (quiet) listing format")
+	f.BoolVarP(&client.NoHeaders, "no-headers", "", false, "don't print headers when using the default output format")
 	f.StringVar(&client.TimeFormat, "time-format", "", `format time using golang time formatter. Example: --time-format "2006-01-02 15:04:05Z0700"`)
 	f.BoolVarP(&client.ByDate, "date", "d", false, "sort by release date")
 	f.BoolVarP(&client.SortReverse, "reverse", "r", false, "reverse the sort order")
@@ -145,10 +143,11 @@ type releaseElement struct {
 }
 
 type releaseListWriter struct {
-	releases []releaseElement
+	releases  []releaseElement
+	noHeaders bool
 }
 
-func newReleaseListWriter(releases []*release.Release, timeFormat string) *releaseListWriter {
+func newReleaseListWriter(releases []*release.Release, timeFormat string, noHeaders bool) *releaseListWriter {
 	// Initialize the array so no results returns an empty array instead of null
 	elements := make([]releaseElement, 0, len(releases))
 	for _, r := range releases {
@@ -173,12 +172,14 @@ func newReleaseListWriter(releases []*release.Release, timeFormat string) *relea
 
 		elements = append(elements, element)
 	}
-	return &releaseListWriter{elements}
+	return &releaseListWriter{elements, noHeaders}
 }
 
 func (r *releaseListWriter) WriteTable(out io.Writer) error {
 	table := uitable.New()
-	table.AddRow("NAME", "NAMESPACE", "REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION")
+	if !r.noHeaders {
+		table.AddRow("NAME", "NAMESPACE", "REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION")
+	}
 	for _, r := range r.releases {
 		table.AddRow(r.Name, r.Namespace, r.Revision, r.Updated, r.Status, r.Chart, r.AppVersion)
 	}
diff --git a/pkg/action/list.go b/pkg/action/list.go
index c9e6e364a..af0725c4a 100644
--- a/pkg/action/list.go
+++ b/pkg/action/list.go
@@ -125,6 +125,7 @@ type List struct {
 	// Filter is a filter that is applied to the results
 	Filter       string
 	Short        bool
+	NoHeaders    bool
 	TimeFormat   string
 	Uninstalled  bool
 	Superseded   bool


Test patch:
diff --git a/cmd/helm/list_test.go b/cmd/helm/list_test.go
index b3b29356e..97a1e284f 100644
--- a/cmd/helm/list_test.go
+++ b/cmd/helm/list_test.go
@@ -148,6 +148,11 @@ func TestListCmd(t *testing.T) {
 		cmd:    "list",
 		golden: "output/list.txt",
 		rels:   releaseFixture,
+	}, {
+		name:   "list without headers",
+		cmd:    "list --no-headers",
+		golden: "output/list-no-headers.txt",
+		rels:   releaseFixture,
 	}, {
 		name:   "list all releases",
 		cmd:    "list --all",
diff --git a/cmd/helm/testdata/output/list-no-headers.txt b/cmd/helm/testdata/output/list-no-headers.txt
new file mode 100644
index 000000000..9d11d0caf
--- /dev/null
+++ b/cmd/helm/testdata/output/list-no-headers.txt
@@ -0,0 +1,4 @@
+hummingbird	default	1	2016-01-16 00:00:03 +0000 UTC	deployed	chickadee-1.0.0	0.0.1
+iguana     	default	2	2016-01-16 00:00:04 +0000 UTC	deployed	chickadee-1.0.0	0.0.1
+rocket     	default	1	2016-01-16 00:00:02 +0000 UTC	failed  	chickadee-1.0.0	0.0.1
+starlord   	default	2	2016-01-16 00:00:01 +0000 UTC	deployed	chickadee-1.0.0	0.0.1