Skip to content

Commit a743d0c

Browse files
✨ Implement publish command (#146)
* ✨ Implement publish command `csmctl publish` will generate the release similar to create command but additionally it will push the generated release to the oci repository. For this, we implemented the generic interface for assetsclients that we have in the CSO as well and that is fulfilled both by Github and OCI clients. Signed-off-by: janiskemper <[email protected]> * Add basic auth option for the oci client (#148) Signed-off-by: Roman Hros <[email protected]> --------- Signed-off-by: janiskemper <[email protected]> Signed-off-by: Roman Hros <[email protected]> Co-authored-by: Roman Hros <[email protected]>
1 parent be4643f commit a743d0c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+11095
-121
lines changed

go.mod

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ go 1.21
55
require (
66
github.com/SovereignCloudStack/cluster-stack-operator v0.1.0-alpha.5
77
github.com/google/go-github/v56 v56.0.0
8+
github.com/opencontainers/image-spec v1.1.0
89
github.com/spf13/cobra v1.8.0
910
github.com/valyala/fasttemplate v1.2.2
1011
golang.org/x/mod v0.16.0
1112
golang.org/x/oauth2 v0.18.0
1213
gopkg.in/src-d/go-git.v4 v4.13.1
14+
gopkg.in/yaml.v2 v2.4.0
1315
gopkg.in/yaml.v3 v3.0.1
1416
helm.sh/helm/v3 v3.14.4
17+
oras.land/oras-go/v2 v2.5.0
1518
)
1619

1720
require (
@@ -100,7 +103,6 @@ require (
100103
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
101104
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
102105
github.com/opencontainers/go-digest v1.0.0 // indirect
103-
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
104106
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
105107
github.com/pkg/errors v0.9.1 // indirect
106108
github.com/prometheus/client_golang v1.17.0 // indirect
@@ -128,7 +130,7 @@ require (
128130
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
129131
golang.org/x/crypto v0.21.0 // indirect
130132
golang.org/x/net v0.22.0 // indirect
131-
golang.org/x/sync v0.5.0 // indirect
133+
golang.org/x/sync v0.6.0 // indirect
132134
golang.org/x/sys v0.18.0 // indirect
133135
golang.org/x/term v0.18.0 // indirect
134136
golang.org/x/text v0.14.0 // indirect
@@ -140,7 +142,6 @@ require (
140142
gopkg.in/inf.v0 v0.9.1 // indirect
141143
gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect
142144
gopkg.in/warnings.v0 v0.1.2 // indirect
143-
gopkg.in/yaml.v2 v2.4.0 // indirect
144145
k8s.io/api v0.29.0 // indirect
145146
k8s.io/apiextensions-apiserver v0.29.0 // indirect
146147
k8s.io/apimachinery v0.29.0 // indirect

go.sum

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,8 @@ github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
331331
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
332332
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
333333
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
334-
github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI=
335-
github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
334+
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
335+
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
336336
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
337337
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
338338
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
@@ -488,8 +488,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
488488
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
489489
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
490490
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
491-
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
492-
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
491+
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
492+
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
493493
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
494494
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
495495
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -627,6 +627,8 @@ k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSn
627627
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
628628
oras.land/oras-go v1.2.4 h1:djpBY2/2Cs1PV87GSJlxv4voajVOMZxqqtq9AB8YNvY=
629629
oras.land/oras-go v1.2.4/go.mod h1:DYcGfb3YF1nKjcezfX2SNlDAeQFKSXmf+qrFmrh4324=
630+
oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c=
631+
oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg=
630632
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
631633
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
632634
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0=

pkg/assetsclient/client.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package assetsclient contains interface for talking to assets repositories.
18+
package assetsclient
19+
20+
import (
21+
"context"
22+
)
23+
24+
// Client contains functions to talk to list and download assets.
25+
type Client interface {
26+
DownloadReleaseAssets(ctx context.Context, tag, path string) error
27+
ListRelease(ctx context.Context) ([]string, error)
28+
}
29+
30+
// Factory is a factory to generate assets clients.
31+
type Factory interface {
32+
NewClient(ctx context.Context) (Client, error)
33+
}
34+
35+
// Pusher contains function to push the release assets to the registry.
36+
type Pusher interface {
37+
PushReleaseAssets(ctx context.Context, releaseAssets []ReleaseAsset, tag, dir, artifactType string, metadata map[string]string) error
38+
}
39+
40+
// ReleaseAsset represents a release asset that would together make up the artifact.
41+
type ReleaseAsset struct {
42+
FileName string
43+
MediaType string
44+
}
Lines changed: 32 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package client
17+
// Package github provides utilities to work with github repostories.
18+
package github
1819

1920
import (
2021
"context"
@@ -23,24 +24,12 @@ import (
2324
"net/http"
2425
"os"
2526
"path/filepath"
26-
"strings"
2727

28+
"github.com/SovereignCloudStack/csctl/pkg/assetsclient"
2829
"github.com/google/go-github/v56/github"
2930
"golang.org/x/oauth2"
3031
)
3132

32-
// Client contains all functions to talk to Github API.
33-
type Client interface {
34-
DownloadReleaseAssets(ctx context.Context, release *github.RepositoryRelease, path string, assetlist []string) error
35-
GetReleaseByTag(ctx context.Context, tag string) (*github.RepositoryRelease, *github.Response, error)
36-
ListRelease(ctx context.Context) ([]*github.RepositoryRelease, *github.Response, error)
37-
}
38-
39-
// Factory is a factory to generate Github clients.
40-
type Factory interface {
41-
NewClient(ctx context.Context) (Client, error)
42-
}
43-
4433
type realGhClient struct {
4534
client *github.Client
4635
httpclient *http.Client
@@ -50,18 +39,18 @@ type realGhClient struct {
5039

5140
type factory struct{}
5241

53-
var _ = Client(&realGhClient{})
42+
var _ = assetsclient.Client(&realGhClient{})
5443

55-
var _ = Factory(&factory{})
44+
var _ = assetsclient.Factory(&factory{})
5645

5746
// NewFactory returns a new factory for Github clients.
58-
func NewFactory() Factory {
47+
func NewFactory() assetsclient.Factory {
5948
return &factory{}
6049
}
6150

62-
var _ = Client(&realGhClient{})
51+
var _ = assetsclient.Client(&realGhClient{})
6352

64-
func (*factory) NewClient(ctx context.Context) (Client, error) {
53+
func (*factory) NewClient(ctx context.Context) (assetsclient.Client, error) {
6554
creds, err := NewGitConfig()
6655
if err != nil {
6756
return nil, fmt.Errorf("failed to create git config: %w", err)
@@ -83,16 +72,26 @@ func (*factory) NewClient(ctx context.Context) (Client, error) {
8372
}, nil
8473
}
8574

86-
func (c *realGhClient) ListRelease(ctx context.Context) ([]*github.RepositoryRelease, *github.Response, error) {
75+
func (c *realGhClient) ListRelease(ctx context.Context) ([]string, error) {
8776
repoRelease, response, err := c.client.Repositories.ListReleases(ctx, c.orgName, c.repoName, &github.ListOptions{})
8877
if err != nil {
89-
return nil, nil, fmt.Errorf("failed to list releases: %w", err)
78+
return nil, fmt.Errorf("failed to list releases: %w", err)
9079
}
9180

92-
return repoRelease, response, nil
81+
if response != nil && response.StatusCode != 200 {
82+
return nil, fmt.Errorf("got unexpected status from call to remote repository: %s", response.Status)
83+
}
84+
85+
releases := []string{}
86+
87+
for _, release := range repoRelease {
88+
releases = append(releases, *release.Name)
89+
}
90+
91+
return releases, nil
9392
}
9493

95-
func (c *realGhClient) GetReleaseByTag(ctx context.Context, tag string) (*github.RepositoryRelease, *github.Response, error) {
94+
func (c *realGhClient) getReleaseByTag(ctx context.Context, tag string) (*github.RepositoryRelease, *github.Response, error) {
9695
repoRelease, response, err := c.client.Repositories.GetReleaseByTag(ctx, c.orgName, c.repoName, tag)
9796
if err != nil {
9897
return nil, nil, fmt.Errorf("failed to get release tag: %w", err)
@@ -102,15 +101,21 @@ func (c *realGhClient) GetReleaseByTag(ctx context.Context, tag string) (*github
102101
}
103102

104103
// DownloadReleaseAssets downloads a list of release assets.
105-
func (c *realGhClient) DownloadReleaseAssets(ctx context.Context, release *github.RepositoryRelease, path string, assetlist []string) error {
104+
func (c *realGhClient) DownloadReleaseAssets(ctx context.Context, tag, path string) error {
105+
release, response, err := c.getReleaseByTag(ctx, tag)
106+
if err != nil {
107+
return fmt.Errorf("failed to fetch release tag %s: %w", tag, err)
108+
}
109+
110+
if response.StatusCode != http.StatusOK {
111+
return fmt.Errorf("failed to fetch release tag %s with status code %d: %w", tag, response.StatusCode, err)
112+
}
113+
106114
if err := os.MkdirAll(path, os.ModePerm); err != nil {
107115
return fmt.Errorf("failed to create destination directory: %w", err)
108116
}
109117
// Extract the release assets
110118
for _, asset := range release.Assets {
111-
if !contains(assetlist, asset.GetName()) {
112-
continue
113-
}
114119
assetPath := filepath.Join(path, asset.GetName())
115120
// Create a temporary file (inside the dest dir) to save the downloaded asset file
116121
assetFile, err := os.Create(filepath.Clean(assetPath))
@@ -200,12 +205,3 @@ func verifyAccess(ctx context.Context, client *github.Client, creds GitConfig) e
200205
}
201206
return nil
202207
}
203-
204-
func contains(source []string, ghAsset string) bool {
205-
for _, a := range source {
206-
if a == ghAsset || strings.Contains(ghAsset, a) {
207-
return true
208-
}
209-
}
210-
return false
211-
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
// Package client implements important functions for github client.
18-
package client
17+
package github
1918

2019
import (
2120
"fmt"

0 commit comments

Comments
 (0)