forked from step-security/secure-repo
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgetlatestrelease.go
More file actions
154 lines (134 loc) · 4.13 KB
/
getlatestrelease.go
File metadata and controls
154 lines (134 loc) · 4.13 KB
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package maintainedactions
import (
"context"
"fmt"
"os"
"strings"
"github.com/google/go-github/v40/github"
"golang.org/x/oauth2"
)
type Release struct {
TagName string `json:"tag_name"`
}
func getMajorVersion(version string) string {
hasVPrefix := strings.HasPrefix(version, "v")
version = strings.TrimPrefix(version, "v")
parts := strings.Split(version, ".")
if len(parts) > 0 {
if hasVPrefix {
return "v" + parts[0]
}
return parts[0]
}
if hasVPrefix {
return "v" + version
}
return version
}
func GetLatestRelease(ownerRepo string) (string, error) {
splitOnSlash := strings.Split(ownerRepo, "/")
if len(splitOnSlash) < 2 {
return "", fmt.Errorf("invalid owner/repo format: %s", ownerRepo)
}
owner := splitOnSlash[0]
repo := splitOnSlash[1]
ctx := context.Background()
// First try without token
client := github.NewClient(nil)
release, _, err := client.Repositories.GetLatestRelease(ctx, owner, repo)
if err != nil {
// If failed, try with token
token := os.Getenv("PAT")
if token == "" {
return "", fmt.Errorf("failed to get latest release and no GITHUB_TOKEN available: %w", err)
}
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
)
tc := oauth2.NewClient(ctx, ts)
client = github.NewClient(tc)
release, _, err = client.Repositories.GetLatestRelease(ctx, owner, repo)
if err != nil {
return "", fmt.Errorf("failed to get latest release with token: %w", err)
}
}
return getMajorVersion(release.GetTagName()), nil
}
// GetMajorTagFromSHA finds the major version tag (e.g., "v5") on ownerRepo
// whose commit matches the given SHA, by listing all tags with prefix "tags/v".
// Returns ("", nil) if no matching tag is found.
func GetMajorTagFromSHA(ownerRepo, sha string) (string, error) {
splitOnSlash := strings.Split(ownerRepo, "/")
if len(splitOnSlash) < 2 {
return "", fmt.Errorf("invalid owner/repo format: %s", ownerRepo)
}
owner := splitOnSlash[0]
repo := splitOnSlash[1]
ctx := context.Background()
client := github.NewClient(nil)
token := os.Getenv("PAT")
if token != "" {
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
client = github.NewClient(oauth2.NewClient(ctx, ts))
}
refs, _, err := client.Git.ListMatchingRefs(ctx, owner, repo, &github.ReferenceListOptions{
Ref: "tags/v",
})
if err != nil {
return "", err
}
for _, ref := range refs {
var refSHA string
if ref.GetObject().GetType() == "commit" {
refSHA = ref.GetObject().GetSHA()
} else {
// annotated tag — dereference to get the commit SHA
refSHA, _, err = client.Repositories.GetCommitSHA1(ctx, owner, repo, ref.GetRef(), "")
if err != nil {
continue
}
}
if refSHA == sha {
tag := strings.TrimPrefix(ref.GetRef(), "refs/tags/")
return getMajorVersion(tag), nil
}
}
return "", nil
}
// GetMajorTagIfExists checks whether ownerRepo has a tag exactly matching
// majorVersion (e.g., "v5"). Returns (majorVersion, true, nil) when the tag
// exists, ("", false, nil) when it is absent (404), and ("", false, err) for
// unexpected API failures.
func GetMajorTagIfExists(ownerRepo, majorVersion string) (string, bool, error) {
splitOnSlash := strings.Split(ownerRepo, "/")
if len(splitOnSlash) < 2 {
return "", false, fmt.Errorf("invalid owner/repo format: %s", ownerRepo)
}
owner := splitOnSlash[0]
repo := splitOnSlash[1]
ctx := context.Background()
client := github.NewClient(nil)
_, resp, err := client.Git.GetRef(ctx, owner, repo, "refs/tags/"+majorVersion)
if err == nil {
return majorVersion, true, nil
}
if resp != nil && resp.StatusCode == 404 {
return "", false, nil
}
// First attempt failed for a non-404 reason — retry with token.
token := os.Getenv("PAT")
if token == "" {
return "", false, nil
}
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
tc := oauth2.NewClient(ctx, ts)
client = github.NewClient(tc)
_, resp, err = client.Git.GetRef(ctx, owner, repo, "refs/tags/"+majorVersion)
if err == nil {
return majorVersion, true, nil
}
if resp != nil && resp.StatusCode == 404 {
return "", false, nil
}
return "", false, fmt.Errorf("failed to check tag %s on %s: %w", majorVersion, ownerRepo, err)
}