diff --git a/hack/tools/release/internal/update_providers/provider_issues.go b/hack/tools/release/internal/update_providers/provider_issues.go index 62ba18184069..6616cf2dea1a 100644 --- a/hack/tools/release/internal/update_providers/provider_issues.go +++ b/hack/tools/release/internal/update_providers/provider_issues.go @@ -32,6 +32,8 @@ import ( "strings" "text/template" "time" + + "github.com/pkg/errors" ) const ( @@ -59,28 +61,6 @@ var ( } ) -// Exiter is a simple interface to exit the program. -type Exiter interface { - Exit(code int) -} - -// RealExiter is the real implementation of the Exiter interface. -type RealExiter struct{} - -// Exit exits the program with the given code. -func (re *RealExiter) Exit(code int) { - os.Exit(code) -} - -// ProviderIssues is a struct that contains the Exiter interface. -type ProviderIssues struct { - Exiter Exiter -} - -func newProviderIssues() *ProviderIssues { - return &ProviderIssues{Exiter: &RealExiter{}} -} - // Issue is the struct for the issue. type Issue struct { Title string `json:"title"` @@ -132,8 +112,11 @@ func main() { fmt.Printf("\n") // get release details - m := newProviderIssues() - details := m.getReleaseDetails() + details, releaseDetailsErr := getReleaseDetails() + if releaseDetailsErr != nil { + fmt.Println(releaseDetailsErr.Error()) + os.Exit(1) + } // generate title titleBuffer := bytes.NewBuffer([]byte{}) @@ -274,21 +257,18 @@ func continueOrAbort() { } // getReleaseDetails returns the release details from the environment variables. -func (m *ProviderIssues) getReleaseDetails() releaseDetails { +func getReleaseDetails() (releaseDetails, error) { // Parse the release tag releaseSemVer, keySet := os.LookupEnv("RELEASE_TAG") if !keySet || releaseSemVer == "" { - fmt.Println("RELEASE_TAG is a required environmental variable.") - fmt.Println("Refer to README.md in folder for more information.") - m.Exiter.Exit(1) + return releaseDetails{}, errors.New("release tag is a required. Refer to README.md in folder for more information") } // allow patterns like v1.7.0-beta.0 pattern := `^v\d+\.\d+\.\d+-beta\.\d+$` match, err := regexp.MatchString(pattern, releaseSemVer) if err != nil || !match { - fmt.Println("RELEASE_TAG must be in format `^v\\d+\\.\\d+\\.\\d+-beta\\.\\d+$` e.g. v1.7.0-beta.0") - m.Exiter.Exit(1) + return releaseDetails{}, errors.New("release tag must be in format `^v\\d+\\.\\d+\\.\\d+-beta\\.\\d+$` e.g. v1.7.0-beta.0") } major, minor, patch := "", "", "" @@ -300,23 +280,18 @@ func (m *ProviderIssues) getReleaseDetails() releaseDetails { minor = releaseSemVerMatch[2] patch = releaseSemVerMatch[3] } else { - fmt.Println("RELEASE_TAG contains invalid Major.Minor.Patch SemVer. It must be in format v(\\d+)\\.(\\d+)\\.(\\d+) e.g. v1.7.0") - m.Exiter.Exit(1) + return releaseDetails{}, errors.New("release tag contains invalid Major.Minor.Patch SemVer. It must be in format v(\\d+)\\.(\\d+)\\.(\\d+) e.g. v1.7.0") } // Parse the release date releaseDate, keySet := os.LookupEnv("RELEASE_DATE") if !keySet || releaseDate == "" { - fmt.Println("RELEASE_DATE is a required environmental variable.") - fmt.Println("Refer to README.md in folder for more information.") - m.Exiter.Exit(1) + return releaseDetails{}, errors.New("release date is a required environmental variable. Refer to README.md in folder for more information") } formattedReleaseDate, err := formatDate(releaseDate) if err != nil { - fmt.Println("Unable to parse the date.", err) - fmt.Println("Refer to README.md in folder for more information.") - m.Exiter.Exit(1) + return releaseDetails{}, errors.New("unable to parse the date") } majorMinorWithoutPrefixV := fmt.Sprintf("%s.%s", major, minor) // e.g. 1.7 . Note that there is no "v" in the majorMinor @@ -331,7 +306,7 @@ func (m *ProviderIssues) getReleaseDetails() releaseDetails { BetaTag: betaTag, ReleaseLink: releaseLink, ReleaseNotesLink: releaseNotesLink, - } + }, nil } // formatDate takes a date in ISO format i.e "2006-01-02" and returns it in the format "Monday 2nd January 2006". diff --git a/hack/tools/release/internal/update_providers/provider_issues_test.go b/hack/tools/release/internal/update_providers/provider_issues_test.go index 477bbe704101..4e40aa4ed344 100644 --- a/hack/tools/release/internal/update_providers/provider_issues_test.go +++ b/hack/tools/release/internal/update_providers/provider_issues_test.go @@ -26,25 +26,14 @@ import ( . "github.com/onsi/gomega" ) -// MockExiter is a mock implementation of the Exiter interface. -type MockExiter struct { - ExitCalled bool - ExitCode int -} - -// Exit is a mock implementation of the Exiter interface. -func (me *MockExiter) Exit(code int) { - me.ExitCalled = true - me.ExitCode = code -} - func Test_GetReleaseDetails(t *testing.T) { tests := []struct { name string releaseTag string releaseDate string want releaseDetails - expectExit bool + expectErr bool + err string }{ { name: "Correct RELEASE_TAG and RELEASE_DATE are set", @@ -57,62 +46,63 @@ func Test_GetReleaseDetails(t *testing.T) { ReleaseLink: "https://github.com/kubernetes-sigs/cluster-api/tree/main/docs/release/releases/release-1.7.md#timeline", ReleaseNotesLink: "https://github.com/kubernetes-sigs/cluster-api/releases/tag/v1.7.0-beta.0", }, - expectExit: false, + expectErr: false, }, { name: "RELEASE_TAG is not in the format ^v\\d+\\.\\d+\\.\\d+-beta\\.\\d+$", releaseTag: "v1.7.0.1", releaseDate: "2024-04-16", - expectExit: true, + expectErr: true, + err: "release tag must be in format `^v\\d+\\.\\d+\\.\\d+-beta\\.\\d+$` e.g. v1.7.0-beta.0", }, { name: "RELEASE_TAG does not have prefix 'v' in its semver", releaseTag: "1.7.0-beta.0", releaseDate: "2024-04-16", - expectExit: true, + expectErr: true, + err: "release tag must be in format `^v\\d+\\.\\d+\\.\\d+-beta\\.\\d+$` e.g. v1.7.0-beta.0", }, { name: "RELEASE_TAG contains invalid Major.Minor.Patch SemVer", releaseTag: "v1.x.0-beta.0", releaseDate: "2024-04-16", - expectExit: true, + expectErr: true, + err: "release tag must be in format `^v\\d+\\.\\d+\\.\\d+-beta\\.\\d+$` e.g. v1.7.0-beta.0", }, { name: "invalid yyyy-dd-mm RELEASE_DATE entered", releaseTag: "v1.7.0-beta.0", releaseDate: "2024-16-4", - expectExit: true, + expectErr: true, + err: "unable to parse the date", }, { name: "invalid yyyy/dd/mm RELEASE_DATE entered", releaseTag: "v1.7.0-beta.0", releaseDate: "2024/16/4", - expectExit: true, + expectErr: true, + err: "unable to parse the date", }, { name: "invalid yyyy/mm/dd RELEASE_DATE entered", releaseTag: "v1.7.0-beta.0", releaseDate: "2024/4/16", - expectExit: true, + expectErr: true, + err: "unable to parse the date", }, } for _, tt := range tests { - mockExiter := &MockExiter{} - m := &ProviderIssues{Exiter: mockExiter} - t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) _ = os.Setenv("RELEASE_TAG", tt.releaseTag) _ = os.Setenv("RELEASE_DATE", tt.releaseDate) - got := m.getReleaseDetails() - if tt.expectExit { - g.Expect(mockExiter.ExitCalled).To(BeTrue()) - g.Expect(mockExiter.ExitCode).To(Equal(1)) + got, err := getReleaseDetails() + if tt.expectErr { + g.Expect(err.Error()).To(Equal(tt.err)) } else { - g.Expect(mockExiter.ExitCalled).To(BeFalse()) g.Expect(got.ReleaseDate).To(Equal(tt.want.ReleaseDate)) g.Expect(got.ReleaseTag).To(Equal(tt.want.ReleaseTag)) g.Expect(got.BetaTag).To(Equal(tt.want.BetaTag))