-
Notifications
You must be signed in to change notification settings - Fork 444
/
upgrade_utils.go
125 lines (111 loc) · 4.5 KB
/
upgrade_utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package upgrade
import (
"context"
"fmt"
"os"
"path/filepath"
"runtime"
"sort"
"strings"
"time"
"github.com/google/go-github/v32/github"
errors "github.com/rotisserie/eris"
"github.com/solo-io/go-utils/changelogutils"
"github.com/solo-io/go-utils/githubutils"
"github.com/solo-io/go-utils/versionutils"
)
var (
FirstReleaseError = "First Release of Minor"
)
// Type used to sort Versions
type ByVersion []*versionutils.Version
func (a ByVersion) Len() int { return len(a) }
func (a ByVersion) Less(i, j int) bool {
var version1 = *a[i]
var version2 = *a[j]
return version2.MustIsGreaterThan(version1)
}
func (a ByVersion) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func GetUpgradeVersions(ctx context.Context, repoName string) (lastMinorLatestPatchVersion *versionutils.Version, currentMinorLatestPatchVersion *versionutils.Version, err error) {
currentMinorLatestPatchVersion, curMinorErr := getLastReleaseOfCurrentMinor()
if curMinorErr != nil {
if curMinorErr.Error() != FirstReleaseError {
return nil, nil, curMinorErr
}
}
// we may get a changelog value that does not have a github release - get the latest release for current minor
currentMinorLatestRelease, currentMinorLatestReleaseError := getLatestReleasedVersion(ctx, repoName, currentMinorLatestPatchVersion.Major, currentMinorLatestPatchVersion.Minor)
if currentMinorLatestReleaseError != nil {
return nil, nil, currentMinorLatestReleaseError
}
lastMinorLatestPatchVersion, lastMinorErr := getLatestReleasedVersion(ctx, repoName, currentMinorLatestPatchVersion.Major, currentMinorLatestPatchVersion.Minor-1)
if lastMinorErr != nil {
return nil, nil, lastMinorErr
}
return lastMinorLatestPatchVersion, currentMinorLatestRelease, curMinorErr
}
func getLastReleaseOfCurrentMinor() (*versionutils.Version, error) {
// pull out to const
_, filename, _, _ := runtime.Caller(0) //get info about what is calling the function
fParts := strings.Split(filename, string(os.PathSeparator))
splitIdx := 0
// In all cases the home of the project will be one level above test - this handles forks as well as the standard case /home/runner/work/gloo/gloo/test/kube2e/upgrade/junit.xml
for idx, dir := range fParts {
if dir == "test" {
splitIdx = idx - 1
}
}
pathToChangelogs := filepath.Join(fParts[:splitIdx+1]...)
pathToChangelogs = filepath.Join(pathToChangelogs, changelogutils.ChangelogDirectory)
pathToChangelogs = string(os.PathSeparator) + pathToChangelogs
files, err := os.ReadDir(pathToChangelogs)
if err != nil {
return nil, changelogutils.ReadChangelogDirError(err)
}
versions := make([]*versionutils.Version, len(files)-1) //ignore validation file
for idx, f := range files {
if f.Name() != "validation.yaml" {
version, err := versionutils.ParseVersion(f.Name())
if err != nil {
return nil, errors.Errorf("Could not get version for changelog folder: %s\n", f.Name())
}
versions[idx] = version
}
}
sort.Sort(ByVersion(versions))
//first release of minor
if versions[len(versions)-1].Minor != versions[len(versions)-2].Minor {
return versions[len(versions)-1], errors.Errorf(FirstReleaseError)
}
return versions[len(versions)-2], nil
}
type latestPatchForMinorPredicate struct {
versionPrefix string
}
func (s *latestPatchForMinorPredicate) Apply(release *github.RepositoryRelease) bool {
return strings.HasPrefix(*release.Name, s.versionPrefix) &&
!release.GetPrerelease() && // we don't want a prerelease version
!strings.Contains(release.GetBody(), "This release build failed") && // we don't want a failed build
release.GetPublishedAt().Before(time.Now().In(time.UTC).Add(time.Duration(-60)*time.Minute))
}
func newLatestPatchForMinorPredicate(versionPrefix string) *latestPatchForMinorPredicate {
return &latestPatchForMinorPredicate{
versionPrefix: versionPrefix,
}
}
func getLatestReleasedVersion(ctx context.Context, repoName string, majorVersion, minorVersion int) (*versionutils.Version, error) {
client, err := githubutils.GetClient(ctx)
if err != nil {
return nil, errors.Wrapf(err, "unable to create github client")
}
versionPrefix := fmt.Sprintf("v%d.%d", majorVersion, minorVersion)
releases, err := githubutils.GetRepoReleasesWithPredicateAndMax(ctx, client, "solo-io", repoName, newLatestPatchForMinorPredicate(versionPrefix), 1)
if len(releases) == 0 {
return nil, errors.Errorf("Could not find a recent release with version prefix: %s", versionPrefix)
}
v, err := versionutils.ParseVersion(*releases[0].Name)
if err != nil {
return nil, errors.Wrapf(err, "error parsing release name")
}
return v, nil
}