Skip to content

Commit 5787f0f

Browse files
committed
add publish stage for pushing OCI helm chart
Signed-off-by: Ashley Davis <[email protected]>
1 parent 273b776 commit 5787f0f

File tree

6 files changed

+482
-41
lines changed

6 files changed

+482
-41
lines changed

cmd/cmrel/cmd/gcb_publish.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package cmd
1919
import (
2020
"bytes"
2121
"context"
22+
"errors"
2223
"fmt"
2324
"log"
2425
"os"
@@ -33,6 +34,9 @@ import (
3334
"github.com/spf13/cobra"
3435
flag "github.com/spf13/pflag"
3536
"golang.org/x/oauth2"
37+
"helm.sh/helm/v3/pkg/pusher"
38+
helmregistry "helm.sh/helm/v3/pkg/registry"
39+
"helm.sh/helm/v3/pkg/uploader"
3640
"k8s.io/apimachinery/pkg/util/sets"
3741
"k8s.io/utils/pointer"
3842

@@ -98,6 +102,9 @@ type gcbPublishOptions struct {
98102
// release will be published to.
99103
PublishedGitHubRepo string
100104

105+
// PublishedOCIHelmChartRegistry is the registry to which helm charts should be published
106+
PublishedOCIHelmChartRegistry string
107+
101108
// SkipSigning, if true, will skip trying to sign artifacts using KMS
102109
SkipSigning bool
103110

@@ -185,6 +192,7 @@ func (o *gcbPublishOptions) AddFlags(fs *flag.FlagSet, markRequired func(string)
185192
fs.StringVar(&o.PublishedHelmChartGitHubBranch, "published-helm-chart-github-branch", release.DefaultHelmChartGitHubBranch, "The name of the main branch in the GitHub repository for Helm charts.")
186193
fs.StringVar(&o.PublishedGitHubOrg, "published-github-org", release.DefaultGitHubOrg, "The org of the repository where the release wil be published to.")
187194
fs.StringVar(&o.PublishedGitHubRepo, "published-github-repo", release.DefaultGitHubRepo, "The repo name in the provided org where the release will be published to.")
195+
fs.StringVar(&o.PublishedOCIHelmChartRegistry, "published-oci-chart-registry", release.DefaultOCIHelmChartRegistry, "The OCI registry to which the Helm chart should be pushed")
188196
fs.StringVar(&o.CosignPath, "cosign-path", "cosign", "Full path to the cosign binary. Defaults to searching in $PATH for a binary called 'cosign'")
189197
fs.StringVar(&o.SigningKMSKey, "signing-kms-key", defaultKMSKey, "Full name of the GCP KMS key to use for signing.")
190198
fs.BoolVar(&o.SkipSigning, "skip-signing", false, "Skip signing container images.")
@@ -200,6 +208,7 @@ func (o *gcbPublishOptions) print() {
200208
log.Printf(" PublishedHelmChartGitHubRepo: %q", o.PublishedHelmChartGitHubRepo)
201209
log.Printf(" PublishedHelmChartGitHubOwner: %q", o.PublishedHelmChartGitHubOwner)
202210
log.Printf(" PublishedHelmChartGitHubBranch: %q", o.PublishedHelmChartGitHubBranch)
211+
log.Printf(" PublishedOCIHelmChartRegistry: %q", o.PublishedOCIHelmChartRegistry)
203212
log.Printf(" PublishedGitHubOrg: %q", o.PublishedGitHubOrg)
204213
log.Printf(" PublishedGitHubRepo: %q", o.PublishedGitHubRepo)
205214
log.Printf(" CosignPath: %q", o.CosignPath)
@@ -256,6 +265,7 @@ func canonicalizeAndVerifyPublishActions(rawActions []string) ([]string, error)
256265

257266
var publishActionMap map[string]publishAction = map[string]publishAction{
258267
"helmchartpr": pushHelmChartPR,
268+
"helmchartoci": pushOCIHelmChart,
259269
"githubrelease": pushGitHubRelease,
260270
"pushcontainerimages": pushContainerImages,
261271
}
@@ -403,6 +413,41 @@ func pushHelmChartPR(ctx context.Context, o *gcbPublishOptions, rel *release.Unp
403413
return nil
404414
}
405415

416+
func pushOCIHelmChart(ctx context.Context, o *gcbPublishOptions, rel *release.Unpacked) error {
417+
// based on https://github.com/helm/helm/blob/v3.17.1/pkg/action/push.go
418+
charts := rel.Charts
419+
420+
var errs []error
421+
422+
for _, chart := range charts {
423+
var out strings.Builder
424+
425+
c := uploader.ChartUploader{
426+
Out: &out,
427+
Pushers: pusher.Providers{
428+
pusher.Provider{
429+
Schemes: []string{helmregistry.OCIScheme},
430+
New: pusher.NewOCIPusher,
431+
},
432+
},
433+
Options: []pusher.Option{},
434+
}
435+
436+
chartPath := chart.Path()
437+
438+
err := c.UploadTo(chartPath, o.PublishedOCIHelmChartRegistry)
439+
if err != nil {
440+
log.Printf("failed to upload OCI chart %s to %s: %v", chartPath, o.PublishedOCIHelmChartRegistry, err)
441+
errs = append(errs, err)
442+
continue
443+
}
444+
445+
log.Printf("helm OCI push logs for %s: %s", chartPath, out.String())
446+
}
447+
448+
return errors.Join(errs...)
449+
}
450+
406451
func pushGitHubRelease(ctx context.Context, o *gcbPublishOptions, rel *release.Unpacked) error {
407452
githubClient, err := o.GitHubClient(ctx)
408453
if err != nil {

cmd/cmrel/cmd/publish.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ type publishOptions struct {
9393
// release will be published to.
9494
PublishedGitHubRepo string
9595

96+
// PublishedOCIHelmChartRegistry is the registry to which helm charts should be published
97+
PublishedOCIHelmChartRegistry string
98+
9699
// PublishActions is a list of publishing actions which should be taken,
97100
// or else "*" - the default - to mean "all actions"
98101
PublishActions []string
@@ -104,6 +107,10 @@ type publishOptions struct {
104107
// projects/<PROJECT_NAME>/locations/<LOCATION>/keyRings/<KEYRING_NAME>/cryptoKeys/<KEY_NAME>/versions/<KEY_VERSION>
105108
// This must be set if SkipSigning is not set to true
106109
SigningKMSKey string
110+
111+
// CmrelRepoRef allows the ref for the cmrel repo to be specified; this
112+
// allows running "cmrel gcb publish" using a branch on the main cmrel repo
113+
CmrelRepoRef string
107114
}
108115

109116
func (o *publishOptions) AddFlags(fs *flag.FlagSet, markRequired func(string)) {
@@ -119,9 +126,12 @@ func (o *publishOptions) AddFlags(fs *flag.FlagSet, markRequired func(string)) {
119126
fs.StringVar(&o.PublishedHelmChartGitHubBranch, "published-helm-chart-github-branch", release.DefaultHelmChartGitHubBranch, "The name of the main branch in the GitHub repository for Helm charts.")
120127
fs.StringVar(&o.PublishedGitHubOrg, "published-github-org", release.DefaultGitHubOrg, "The org of the repository where the release wil be published to.")
121128
fs.StringVar(&o.PublishedGitHubRepo, "published-github-repo", release.DefaultGitHubRepo, "The repo name in the provided org where the release will be published to.")
129+
fs.StringVar(&o.PublishedOCIHelmChartRegistry, "published-oci-chart-registry", release.DefaultOCIHelmChartRegistry, "The OCI registry to which the Helm chart should be pushed")
122130
fs.StringVar(&o.SigningKMSKey, "signing-kms-key", defaultKMSKey, "Full name of the GCP KMS key to use for signing.")
123131
fs.BoolVar(&o.SkipSigning, "skip-signing", false, "Skip signing container images.")
124132
fs.StringSliceVar(&o.PublishActions, "publish-actions", []string{"*"}, fmt.Sprintf("Comma-separated list of actions to take, or '*' to do everything. Only meaningful if nomock is set. Order of operations is preserved if given, or is alphabetical by default. Actions can be removed with a prefix of '-'. Options: %s", strings.Join(allPublishActionNames(), ", ")))
133+
134+
fs.StringVar(&o.CmrelRepoRef, "cmrel-repo-ref", "master", "The ref on the cert-manager/release repo to use when building cmrel in GCB")
125135
}
126136

127137
func (o *publishOptions) print() {
@@ -135,9 +145,11 @@ func (o *publishOptions) print() {
135145
log.Printf(" PublishedHelmChartGitHubRepo: %q", o.PublishedHelmChartGitHubRepo)
136146
log.Printf(" PublishedHelmChartGitHubOwner: %q", o.PublishedHelmChartGitHubOwner)
137147
log.Printf(" PublishedHelmChartGitHubBranch: %q", o.PublishedHelmChartGitHubBranch)
148+
log.Printf(" PublishedOCIHelmChartRegistry: %q", o.PublishedOCIHelmChartRegistry)
138149
log.Printf(" PublishedGitHubOrg: %q", o.PublishedGitHubOrg)
139150
log.Printf(" PublishedGitHubRepo: %q", o.PublishedGitHubRepo)
140151
log.Printf(" PublishActions: %q", strings.Join(o.PublishActions, ","))
152+
log.Printf(" CmrelRepoRef: %q", o.CmrelRepoRef)
141153
}
142154

143155
func publishCmd(rootOpts *rootOptions) *cobra.Command {
@@ -201,10 +213,12 @@ func runPublish(rootOpts *rootOptions, o *publishOptions) error {
201213
build.Substitutions["_PUBLISHED_HELM_CHART_GITHUB_OWNER"] = o.PublishedHelmChartGitHubOwner
202214
build.Substitutions["_PUBLISHED_HELM_CHART_GITHUB_REPO"] = o.PublishedHelmChartGitHubRepo
203215
build.Substitutions["_PUBLISHED_HELM_CHART_GITHUB_BRANCH"] = o.PublishedHelmChartGitHubBranch
216+
build.Substitutions["_PUBLISHED_OCI_HELM_CHART_REGISTRY"] = o.PublishedOCIHelmChartRegistry
204217
build.Substitutions["_PUBLISHED_IMAGE_REPO"] = o.PublishedImageRepository
205218
build.Substitutions["_PUBLISH_ACTIONS"] = strings.Join(o.PublishActions, ",")
206219
build.Substitutions["_SKIP_SIGNING"] = fmt.Sprintf("%v", o.SkipSigning)
207220
build.Substitutions["_KMS_KEY"] = o.SigningKMSKey
221+
build.Substitutions["_RELEASE_REPO_REF"] = o.CmrelRepoRef
208222

209223
log.Printf("DEBUG: building google cloud build API client")
210224
svc, err := cloudbuild.NewService(ctx)

gcb/publish/cloudbuild.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ steps:
5858
- --published-helm-chart-github-owner=${_PUBLISHED_HELM_CHART_GITHUB_OWNER}
5959
- --published-helm-chart-github-repo=${_PUBLISHED_HELM_CHART_GITHUB_REPO}
6060
- --published-helm-chart-github-branch=${_PUBLISHED_HELM_CHART_GITHUB_BRANCH}
61+
- --published-oci-chart-registry=${_PUBLISHED_OCI_HELM_CHART_REGISTRY}
6162
- --published-image-repo=${_PUBLISHED_IMAGE_REPO}
6263
- --publish-actions=${_PUBLISH_ACTIONS}
6364
- --signing-kms-key=${_KMS_KEY}
@@ -88,6 +89,7 @@ substitutions:
8889
_PUBLISHED_HELM_CHART_GITHUB_OWNER: ""
8990
_PUBLISHED_HELM_CHART_GITHUB_REPO: ""
9091
_PUBLISHED_HELM_CHART_GITHUB_BRANCH: ""
92+
_PUBLISHED_OCI_HELM_CHART_REGISTRY: ""
9193
_PUBLISHED_IMAGE_REPO: ""
9294
## Used to control the exact artifacts which will be published
9395
_PUBLISH_ACTIONS: "*"

go.mod

Lines changed: 91 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
module github.com/cert-manager/release
22

3-
go 1.23
4-
5-
toolchain go1.23.4
3+
go 1.23.0
64

75
require (
86
cloud.google.com/go/storage v1.43.0
@@ -14,15 +12,15 @@ require (
1412
github.com/pkg/errors v0.9.1
1513
github.com/spf13/cobra v1.8.1
1614
github.com/spf13/pflag v1.0.5
17-
github.com/stretchr/testify v1.9.0
15+
github.com/stretchr/testify v1.10.0
1816
golang.org/x/crypto v0.32.0
19-
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
20-
golang.org/x/mod v0.19.0
17+
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
18+
golang.org/x/mod v0.21.0
2119
golang.org/x/oauth2 v0.23.0
2220
google.golang.org/api v0.187.0
23-
helm.sh/helm/v3 v3.15.3
24-
k8s.io/apimachinery v0.30.3
25-
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
21+
helm.sh/helm/v3 v3.17.1
22+
k8s.io/apimachinery v0.32.1
23+
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
2624
sigs.k8s.io/yaml v1.4.0
2725
)
2826

@@ -32,37 +30,114 @@ require (
3230
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
3331
cloud.google.com/go/compute/metadata v0.5.2 // indirect
3432
cloud.google.com/go/iam v1.1.8 // indirect
35-
github.com/Masterminds/semver/v3 v3.2.1 // indirect
36-
github.com/davecgh/go-spew v1.1.1 // indirect
33+
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
34+
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
35+
github.com/MakeNowJust/heredoc v1.0.0 // indirect
36+
github.com/Masterminds/semver/v3 v3.3.0 // indirect
37+
github.com/beorn7/perks v1.0.1 // indirect
38+
github.com/blang/semver/v4 v4.0.0 // indirect
39+
github.com/cespare/xxhash/v2 v2.3.0 // indirect
40+
github.com/chai2010/gettext-go v1.0.2 // indirect
41+
github.com/containerd/containerd v1.7.24 // indirect
42+
github.com/containerd/errdefs v0.3.0 // indirect
43+
github.com/containerd/log v0.1.0 // indirect
44+
github.com/containerd/platforms v0.2.1 // indirect
45+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
46+
github.com/distribution/reference v0.6.0 // indirect
47+
github.com/docker/cli v25.0.1+incompatible // indirect
48+
github.com/docker/distribution v2.8.3+incompatible // indirect
49+
github.com/docker/docker v25.0.6+incompatible // indirect
50+
github.com/docker/docker-credential-helpers v0.7.0 // indirect
51+
github.com/docker/go-connections v0.5.0 // indirect
52+
github.com/docker/go-metrics v0.0.1 // indirect
53+
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
54+
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
55+
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
3756
github.com/felixge/httpsnoop v1.0.4 // indirect
57+
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
58+
github.com/go-errors/errors v1.4.2 // indirect
3859
github.com/go-logr/logr v1.4.2 // indirect
3960
github.com/go-logr/stdr v1.2.2 // indirect
61+
github.com/go-openapi/jsonpointer v0.21.0 // indirect
62+
github.com/go-openapi/jsonreference v0.20.2 // indirect
63+
github.com/go-openapi/swag v0.23.0 // indirect
64+
github.com/gogo/protobuf v1.3.2 // indirect
4065
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
4166
github.com/golang/protobuf v1.5.4 // indirect
67+
github.com/google/btree v1.0.1 // indirect
68+
github.com/google/gnostic-models v0.6.8 // indirect
69+
github.com/google/go-cmp v0.6.0 // indirect
4270
github.com/google/go-querystring v1.0.0 // indirect
71+
github.com/google/gofuzz v1.2.0 // indirect
4372
github.com/google/s2a-go v0.1.7 // indirect
73+
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
4474
github.com/google/uuid v1.6.0 // indirect
4575
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
4676
github.com/googleapis/gax-go/v2 v2.12.5 // indirect
77+
github.com/gorilla/mux v1.8.0 // indirect
78+
github.com/gorilla/websocket v1.5.0 // indirect
79+
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
80+
github.com/hashicorp/errwrap v1.1.0 // indirect
81+
github.com/hashicorp/go-multierror v1.1.1 // indirect
4782
github.com/inconshreveable/mousetrap v1.1.0 // indirect
48-
github.com/pmezard/go-difflib v1.0.0 // indirect
83+
github.com/josharian/intern v1.0.0 // indirect
84+
github.com/json-iterator/go v1.1.12 // indirect
85+
github.com/klauspost/compress v1.16.7 // indirect
86+
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
87+
github.com/mailru/easyjson v0.7.7 // indirect
88+
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
89+
github.com/moby/locker v1.0.1 // indirect
90+
github.com/moby/spdystream v0.5.0 // indirect
91+
github.com/moby/term v0.5.0 // indirect
92+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
93+
github.com/modern-go/reflect2 v1.0.2 // indirect
94+
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
95+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
96+
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
97+
github.com/opencontainers/go-digest v1.0.0 // indirect
98+
github.com/opencontainers/image-spec v1.1.0 // indirect
99+
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
100+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
101+
github.com/prometheus/client_golang v1.19.1 // indirect
102+
github.com/prometheus/client_model v0.6.1 // indirect
103+
github.com/prometheus/common v0.55.0 // indirect
104+
github.com/prometheus/procfs v0.15.1 // indirect
105+
github.com/russross/blackfriday/v2 v2.1.0 // indirect
106+
github.com/sirupsen/logrus v1.9.3 // indirect
107+
github.com/x448/float16 v0.8.4 // indirect
108+
github.com/xlab/treeprint v1.2.0 // indirect
49109
go.opencensus.io v0.24.0 // indirect
50-
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
51-
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
110+
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
111+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
52112
go.opentelemetry.io/otel v1.31.0 // indirect
53113
go.opentelemetry.io/otel/metric v1.31.0 // indirect
54114
go.opentelemetry.io/otel/trace v1.31.0 // indirect
55115
golang.org/x/net v0.34.0 // indirect
56116
golang.org/x/sync v0.10.0 // indirect
57117
golang.org/x/sys v0.29.0 // indirect
118+
golang.org/x/term v0.28.0 // indirect
58119
golang.org/x/text v0.21.0 // indirect
59-
golang.org/x/time v0.5.0 // indirect
120+
golang.org/x/time v0.7.0 // indirect
60121
google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d // indirect
61122
google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect
62123
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
63124
google.golang.org/grpc v1.69.4 // indirect
64125
google.golang.org/protobuf v1.36.3 // indirect
126+
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
127+
gopkg.in/inf.v0 v0.9.1 // indirect
65128
gopkg.in/yaml.v2 v2.4.0 // indirect
66129
gopkg.in/yaml.v3 v3.0.1 // indirect
67-
k8s.io/klog/v2 v2.120.1 // indirect
130+
k8s.io/api v0.32.1 // indirect
131+
k8s.io/apiextensions-apiserver v0.32.1 // indirect
132+
k8s.io/cli-runtime v0.32.1 // indirect
133+
k8s.io/client-go v0.32.1 // indirect
134+
k8s.io/component-base v0.32.1 // indirect
135+
k8s.io/klog/v2 v2.130.1 // indirect
136+
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
137+
k8s.io/kubectl v0.32.1 // indirect
138+
oras.land/oras-go v1.2.5 // indirect
139+
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
140+
sigs.k8s.io/kustomize/api v0.18.0 // indirect
141+
sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect
142+
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
68143
)

0 commit comments

Comments
 (0)