Skip to content

Commit

Permalink
Merge pull request #10423 from k8s-infra-cherrypick-robot/cherry-pick…
Browse files Browse the repository at this point in the history
…-10220-to-release-1.7

[release-1.7] 🐛 Verify that there is a release for the tag
  • Loading branch information
k8s-ci-robot committed Apr 11, 2024
2 parents 9c9191e + 3310dd4 commit 1432bbe
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 27 deletions.
203 changes: 199 additions & 4 deletions cmd/clusterctl/client/repository/repository_github_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"fmt"
"net/http"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -428,6 +429,11 @@ func Test_gitHubRepository_getLatestContractRelease(t *testing.T) {
fmt.Fprint(w, `{"id":13, "tag_name": "v0.5.0", "assets": [{"id": 1, "name": "metadata.yaml"}] }`)
})

mux.HandleFunc("/repos/o/r1/releases/tags/v0.3.2", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, `{"id":14, "tag_name": "v0.3.2", "assets": [{"id": 2, "name": "metadata.yaml"}] }`)
})

// Setup a handler for returning a fake release metadata file.
mux.HandleFunc("/repos/o/r1/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
Expand All @@ -436,6 +442,13 @@ func Test_gitHubRepository_getLatestContractRelease(t *testing.T) {
fmt.Fprint(w, "apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3\nreleaseSeries:\n - major: 0\n minor: 4\n contract: v1alpha4\n - major: 0\n minor: 5\n contract: v1alpha4\n - major: 0\n minor: 3\n contract: v1alpha3\n")
})

mux.HandleFunc("/repos/o/r1/releases/assets/2", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename=metadata.yaml")
fmt.Fprint(w, "apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3\nreleaseSeries:\n - major: 0\n minor: 4\n contract: v1alpha4\n - major: 0\n minor: 5\n contract: v1alpha4\n - major: 0\n minor: 3\n contract: v1alpha3\n")
})

scheme, host, muxGoproxy, teardownGoproxy := goproxytest.NewFakeGoproxy()
clientGoproxy := goproxy.NewClient(scheme, host)

Expand Down Expand Up @@ -534,6 +547,9 @@ func Test_gitHubRepository_getLatestRelease(t *testing.T) {
clientGoproxy := goproxy.NewClient(scheme, host)
defer teardownGoproxy()

client, mux, teardown := test.NewFakeGitHub()
defer teardown()

// Setup a handler for returning 4 fake releases.
muxGoproxy.HandleFunc("/github.com/o/r1/@v/list", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
Expand All @@ -543,9 +559,13 @@ func Test_gitHubRepository_getLatestRelease(t *testing.T) {
fmt.Fprint(w, "foo\n") // no semantic version tag
})
// And also expose a release for them
muxGoproxy.HandleFunc("/api.github.com/repos/o/r1/releases/tags/v0.4.2", func(w http.ResponseWriter, r *http.Request) {
mux.HandleFunc("/repos/o/r1/releases/tags/v0.4.2", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "{}\n")
fmt.Fprint(w, `{"id":13, "tag_name": "v0.4.2", "assets": [{"id": 1, "name": "metadata.yaml"}] }`)
})
mux.HandleFunc("/repos/o/r3/releases/tags/v0.1.0-alpha.2", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, `{"id":14, "tag_name": "v0.1.0-alpha.2", "assets": [{"id": 2, "name": "metadata.yaml"}] }`)
})

// Setup a handler for returning no releases.
Expand All @@ -562,6 +582,21 @@ func Test_gitHubRepository_getLatestRelease(t *testing.T) {
fmt.Fprint(w, "v0.1.0-alpha.2\n")
})

// Setup a handler for returning a fake release metadata file.
mux.HandleFunc("/repos/o/r1/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename=metadata.yaml")
fmt.Fprint(w, "apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3\nreleaseSeries:\n - major: 0\n minor: 4\n contract: v1alpha4\n - major: 0\n minor: 5\n contract: v1alpha4\n - major: 0\n minor: 3\n contract: v1alpha3\n")
})

mux.HandleFunc("/repos/o/r3/releases/assets/2", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename=metadata.yaml")
fmt.Fprint(w, "apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3\nreleaseSeries:\n - major: 0\n minor: 4\n contract: v1alpha4\n - major: 0\n minor: 5\n contract: v1alpha4\n - major: 0\n minor: 3\n contract: v1alpha3\n")
})

configVariablesClient := test.NewFakeVariableClient()

type field struct {
Expand Down Expand Up @@ -606,7 +641,7 @@ func Test_gitHubRepository_getLatestRelease(t *testing.T) {

resetCaches()

gRepo, err := NewGitHubRepository(ctx, tt.field.providerConfig, configVariablesClient, injectGoproxyClient(clientGoproxy))
gRepo, err := NewGitHubRepository(ctx, tt.field.providerConfig, configVariablesClient, injectGoproxyClient(clientGoproxy), injectGithubClient(client))
g.Expect(err).ToNot(HaveOccurred())

got, err := latestRelease(ctx, gRepo)
Expand All @@ -628,6 +663,9 @@ func Test_gitHubRepository_getLatestPatchRelease(t *testing.T) {
clientGoproxy := goproxy.NewClient(scheme, host)
defer teardownGoproxy()

client, mux, teardown := test.NewFakeGitHub()
defer teardown()

// Setup a handler for returning 4 fake releases.
muxGoproxy.HandleFunc("/github.com/o/r1/@v/list", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
Expand All @@ -636,6 +674,30 @@ func Test_gitHubRepository_getLatestPatchRelease(t *testing.T) {
fmt.Fprint(w, "v1.3.2\n")
})

// Setup a handler for returning a fake release.
mux.HandleFunc("/repos/o/r1/releases/tags/v0.4.0", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, `{"id":13, "tag_name": "v0.4.0", "assets": [{"id": 1, "name": "metadata.yaml"}] }`)
})

mux.HandleFunc("/repos/o/r1/releases/tags/v0.3.2", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, `{"id":14, "tag_name": "v0.3.2", "assets": [{"id": 1, "name": "metadata.yaml"}] }`)
})

mux.HandleFunc("/repos/o/r1/releases/tags/v1.3.2", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, `{"id":15, "tag_name": "v1.3.2", "assets": [{"id": 1, "name": "metadata.yaml"}] }`)
})

// Setup a handler for returning a fake release metadata file.
mux.HandleFunc("/repos/o/r1/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename=metadata.yaml")
fmt.Fprint(w, "apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3\nreleaseSeries:\n - major: 0\n minor: 4\n contract: v1alpha4\n - major: 0\n minor: 5\n contract: v1alpha4\n - major: 0\n minor: 3\n contract: v1alpha3\n")
})

major0 := uint(0)
minor3 := uint(3)
minor4 := uint(4)
Expand Down Expand Up @@ -692,7 +754,7 @@ func Test_gitHubRepository_getLatestPatchRelease(t *testing.T) {

resetCaches()

gRepo, err := NewGitHubRepository(ctx, tt.field.providerConfig, configVariablesClient, injectGoproxyClient(clientGoproxy))
gRepo, err := NewGitHubRepository(ctx, tt.field.providerConfig, configVariablesClient, injectGoproxyClient(clientGoproxy), injectGithubClient(client))
g.Expect(err).ToNot(HaveOccurred())

got, err := latestPatchRelease(ctx, gRepo, tt.major, tt.minor)
Expand Down Expand Up @@ -913,3 +975,136 @@ func resetCaches() {
cacheReleases = map[string]*github.RepositoryRelease{}
cacheFiles = map[string][]byte{}
}

func Test_gitHubRepository_releaseNotFound(t *testing.T) {
retryableOperationInterval = 200 * time.Millisecond
retryableOperationTimeout = 1 * time.Second

tests := []struct {
name string
releaseTags []string
ghReleases []string
want string
wantErr bool
}{
{
name: "One release",
releaseTags: []string{"v0.4.2"},
ghReleases: []string{"v0.4.2"},
want: "v0.4.2",
wantErr: false,
},
{
name: "Latest tag without a release",
releaseTags: []string{"v0.5.0", "v0.4.2"},
ghReleases: []string{"v0.4.2"},
want: "v0.4.2",
wantErr: false,
},
{
name: "Two tags without releases",
releaseTags: []string{"v0.6.0", "v0.5.0", "v0.4.2"},
ghReleases: []string{"v0.4.2"},
want: "v0.4.2",
wantErr: false,
},
{
name: "Five tags without releases",
releaseTags: []string{"v0.9.0", "v0.8.0", "v0.7.0", "v0.6.0", "v0.5.0", "v0.4.2"},
ghReleases: []string{"v0.4.2"},
wantErr: true,
},
{
name: "Pre-releases have lower priority",
releaseTags: []string{"v0.7.0-alpha", "v0.6.0-alpha", "v0.5.0-alpha", "v0.4.2"},
ghReleases: []string{"v0.4.2"},
want: "v0.4.2",
wantErr: false,
},
{
name: "Two Github releases",
releaseTags: []string{"v0.7.0", "v0.6.0", "v0.5.0", "v0.4.2"},
ghReleases: []string{"v0.5.0", "v0.4.2"},
want: "v0.5.0",
wantErr: false,
},
{
name: "Github release and prerelease",
releaseTags: []string{"v0.6.0", "v0.5.0-alpha", "v0.4.2"},
ghReleases: []string{"v0.5.0-alpha", "v0.4.2"},
want: "v0.4.2",
wantErr: false,
},
{
name: "No Github releases",
releaseTags: []string{"v0.6.0", "v0.5.0", "v0.4.2"},
ghReleases: []string{},
wantErr: true,
},
{
name: "Pre-releases only",
releaseTags: []string{"v0.6.0-alpha", "v0.5.0-alpha", "v0.4.2-alpha"},
ghReleases: []string{"v0.5.0-alpha"},
want: "v0.5.0-alpha",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)

ctx := context.Background()

configVariablesClient := test.NewFakeVariableClient()

resetCaches()

client, mux, teardown := test.NewFakeGitHub()
defer teardown()

providerConfig := config.NewProvider("test", "https://github.com/o/r1/releases/v0.4.1/file.yaml", clusterctlv1.CoreProviderType)

scheme, host, muxGoproxy, teardownGoproxy := goproxytest.NewFakeGoproxy()
clientGoproxy := goproxy.NewClient(scheme, host)

defer teardownGoproxy()

// First, register tags within goproxy.
muxGoproxy.HandleFunc("/github.com/o/r1/@v/list", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
for _, release := range tt.releaseTags {
fmt.Fprint(w, release+"\n")
}
})

// Second, register releases in GitHub.
for _, release := range tt.ghReleases {
mux.HandleFunc(fmt.Sprintf("/repos/o/r1/releases/tags/%s", release), func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
parts := strings.Split(r.RequestURI, "/")
version := parts[len(parts)-1]
fmt.Fprintf(w, "{\"id\":13, \"tag_name\": %q, \"assets\": [{\"id\": 1, \"name\": \"metadata.yaml\"}] }", version)
})
}

// Third, setup a handler for returning a fake release metadata file.
mux.HandleFunc("/repos/o/r1/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
goproxytest.HTTPTestMethod(t, r, "GET")
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename=metadata.yaml")
fmt.Fprint(w, "apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3\nreleaseSeries:\n - major: 0\n minor: 4\n contract: v1alpha4\n - major: 0\n minor: 5\n contract: v1alpha4\n - major: 0\n minor: 3\n contract: v1alpha3\n")
})

gRepo, err := NewGitHubRepository(ctx, providerConfig, configVariablesClient, injectGithubClient(client), injectGoproxyClient(clientGoproxy))
g.Expect(err).ToNot(HaveOccurred())

got, err := latestRelease(ctx, gRepo)
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
return
}
g.Expect(err).ToNot(HaveOccurred())
g.Expect(got).To(Equal(tt.want))
})
}
}
8 changes: 8 additions & 0 deletions cmd/clusterctl/client/repository/repository_local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ import (
"sigs.k8s.io/cluster-api/cmd/clusterctl/internal/test"
)

const (
metadataContents = "apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3\nreleaseSeries:\n - major: 0\n minor: 4\n contract: v1alpha4\n - major: 0\n minor: 5\n contract: v1alpha4\n - major: 0\n minor: 3\n contract: v1alpha3\n"
)

func Test_localRepository_newLocalRepository(t *testing.T) {
type fields struct {
provider config.Provider
Expand Down Expand Up @@ -157,6 +161,7 @@ func Test_localRepository_newLocalRepository_Latest(t *testing.T) {
// Create several release directories
createLocalTestProviderFile(t, tmpDir, "bootstrap-foo/v1.0.0/bootstrap-components.yaml", "foo: bar")
createLocalTestProviderFile(t, tmpDir, "bootstrap-foo/v1.0.1/bootstrap-components.yaml", "foo: bar")
createLocalTestProviderFile(t, tmpDir, "bootstrap-foo/v1.0.1/metadata.yaml", metadataContents)
createLocalTestProviderFile(t, tmpDir, "bootstrap-foo/v2.0.0-alpha.0/bootstrap-components.yaml", "foo: bar")
createLocalTestProviderFile(t, tmpDir, "bootstrap-foo/Foo.Bar/bootstrap-components.yaml", "foo: bar")
createLocalTestProviderFile(t, tmpDir, "bootstrap-foo/foo.file", "foo: bar")
Expand Down Expand Up @@ -185,8 +190,10 @@ func Test_localRepository_GetFile(t *testing.T) {
p1 := config.NewProvider("foo", dst1, clusterctlv1.BootstrapProviderType)

// Provider 2: URL is for the latest release
createLocalTestProviderFile(t, tmpDir, "bootstrap-baz/v1.0.0-alpha.0/metadata.yaml", metadataContents)
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/v1.0.0/bootstrap-components.yaml", "version: v1.0.0")
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/v1.0.1/bootstrap-components.yaml", "version: v1.0.1")
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/v1.0.1/metadata.yaml", metadataContents)
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/v2.0.0-alpha.0/bootstrap-components.yaml", "version: v2.0.0-alpha.0")
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/Foo.Bar/bootstrap-components.yaml", "version: Foo.Bar")
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/foo.file", "foo: bar")
Expand Down Expand Up @@ -323,6 +330,7 @@ func Test_localRepository_GetVersions(t *testing.T) {
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/v1.0.0/bootstrap-components.yaml", "version: v1.0.0")
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/v1.0.1/bootstrap-components.yaml", "version: v1.0.1")
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/v2.0.1/bootstrap-components.yaml", "version: v2.0.1")
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/v2.0.2+exp.sha.5114f85/metadata.yaml", metadataContents)
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/v2.0.2+exp.sha.5114f85/bootstrap-components.yaml", "version: v2.0.2+exp.sha.5114f85")
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/v2.0.3-alpha/bootstrap-components.yaml", "version: v2.0.3-alpha")
createLocalTestProviderFile(t, tmpDir, "bootstrap-bar/Foo.Bar/bootstrap-components.yaml", "version: Foo.Bar")
Expand Down
Loading

0 comments on commit 1432bbe

Please sign in to comment.