Skip to content

Commit 73f28bc

Browse files
cliedemanchristophwitzko
authored andcommitted
refactor: Created repository interface to prepare for gitlab addition
1 parent 46bade6 commit 73f28bc

File tree

5 files changed

+417
-383
lines changed

5 files changed

+417
-383
lines changed

cmd/semantic-release/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func cliHandler(c *cli.Context) error {
5757
ci := condition.NewCI()
5858
logger.Printf("detected CI: %s\n", ci.Name())
5959

60-
repo, err := semrel.NewRepository(context.TODO(), conf.GheHost, conf.Slug, conf.Token)
60+
repo, err := semrel.NewGithubRepository(context.TODO(), conf.GheHost, conf.Slug, conf.Token)
6161
exitIfError(err)
6262

6363
logger.Println("getting default branch...")
@@ -136,7 +136,7 @@ func cliHandler(c *cli.Context) error {
136136
exitIfError(repo.CreateRelease(changelog, newVer, conf.Prerelease, currentBranch, currentSha))
137137

138138
if conf.Ghr {
139-
exitIfError(ioutil.WriteFile(".ghr", []byte(fmt.Sprintf("-u %s -r %s v%s", repo.Owner, repo.Repo, newVer.String())), 0644))
139+
exitIfError(ioutil.WriteFile(".ghr", []byte(fmt.Sprintf("-u %s -r %s v%s", repo.Owner(), repo.Repo(), newVer.String())), 0644))
140140
}
141141

142142
if conf.Vf {

pkg/semrel/github.go

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
package semrel
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"regexp"
8+
"sort"
9+
"strings"
10+
11+
"github.com/Masterminds/semver"
12+
"github.com/google/go-github/v30/github"
13+
"golang.org/x/oauth2"
14+
)
15+
16+
type GithubRepository struct {
17+
owner string
18+
repo string
19+
Ctx context.Context
20+
Client *github.Client
21+
}
22+
23+
func NewGithubRepository(ctx context.Context, gheHost, slug, token string) (*GithubRepository, error) {
24+
if !strings.Contains(slug, "/") {
25+
return nil, errors.New("invalid slug")
26+
}
27+
repo := new(GithubRepository)
28+
splited := strings.Split(slug, "/")
29+
repo.owner = splited[0]
30+
repo.repo = splited[1]
31+
repo.Ctx = ctx
32+
oauthClient := oauth2.NewClient(ctx, oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}))
33+
if gheHost != "" {
34+
gheUrl := fmt.Sprintf("https://%s/api/v3/", gheHost)
35+
rClient, err := github.NewEnterpriseClient(gheUrl, gheUrl, oauthClient)
36+
if err != nil {
37+
return nil, err
38+
}
39+
repo.Client = rClient
40+
} else {
41+
repo.Client = github.NewClient(oauthClient)
42+
}
43+
return repo, nil
44+
}
45+
46+
func (repo *GithubRepository) GetInfo() (string, bool, error) {
47+
r, _, err := repo.Client.Repositories.Get(repo.Ctx, repo.owner, repo.repo)
48+
if err != nil {
49+
return "", false, err
50+
}
51+
return r.GetDefaultBranch(), r.GetPrivate(), nil
52+
}
53+
54+
func (repo *GithubRepository) GetCommits(sha string) ([]*Commit, error) {
55+
opts := &github.CommitsListOptions{
56+
SHA: sha,
57+
ListOptions: github.ListOptions{PerPage: 100},
58+
}
59+
commits, _, err := repo.Client.Repositories.ListCommits(repo.Ctx, repo.owner, repo.repo, opts)
60+
if err != nil {
61+
return nil, err
62+
}
63+
ret := make([]*Commit, len(commits))
64+
for i, commit := range commits {
65+
ret[i] = parseGithubCommit(commit)
66+
}
67+
return ret, nil
68+
}
69+
70+
func (repo *GithubRepository) GetLatestRelease(vrange string, re *regexp.Regexp) (*Release, error) {
71+
allReleases := make(Releases, 0)
72+
opts := &github.ReferenceListOptions{"tags", github.ListOptions{PerPage: 100}}
73+
for {
74+
refs, resp, err := repo.Client.Git.ListRefs(repo.Ctx, repo.owner, repo.repo, opts)
75+
if resp != nil && resp.StatusCode == 404 {
76+
return &Release{"", &semver.Version{}}, nil
77+
}
78+
if err != nil {
79+
return nil, err
80+
}
81+
for _, r := range refs {
82+
tag := strings.TrimPrefix(r.GetRef(), "refs/tags/")
83+
if re != nil && !re.MatchString(tag) {
84+
continue
85+
}
86+
version, err := semver.NewVersion(tag)
87+
if err != nil {
88+
continue
89+
}
90+
allReleases = append(allReleases, &Release{r.Object.GetSHA(), version})
91+
}
92+
if resp.NextPage == 0 {
93+
break
94+
}
95+
opts.Page = resp.NextPage
96+
}
97+
sort.Sort(allReleases)
98+
99+
var lastRelease *Release
100+
for _, r := range allReleases {
101+
if r.Version.Prerelease() == "" {
102+
lastRelease = r
103+
break
104+
}
105+
}
106+
107+
if vrange == "" {
108+
if lastRelease != nil {
109+
return lastRelease, nil
110+
}
111+
return &Release{"", &semver.Version{}}, nil
112+
}
113+
114+
constraint, err := semver.NewConstraint(vrange)
115+
if err != nil {
116+
return nil, err
117+
}
118+
for _, r := range allReleases {
119+
if constraint.Check(r.Version) {
120+
return r, nil
121+
}
122+
}
123+
124+
nver, err := semver.NewVersion(vrange)
125+
if err != nil {
126+
return nil, err
127+
}
128+
129+
splitPre := strings.SplitN(vrange, "-", 2)
130+
if len(splitPre) == 1 {
131+
return &Release{lastRelease.SHA, nver}, nil
132+
}
133+
134+
npver, err := nver.SetPrerelease(splitPre[1])
135+
if err != nil {
136+
return nil, err
137+
}
138+
return &Release{lastRelease.SHA, &npver}, nil
139+
}
140+
141+
func (repo *GithubRepository) CreateRelease(changelog string, newVersion *semver.Version, prerelease bool, branch, sha string) error {
142+
tag := fmt.Sprintf("v%s", newVersion.String())
143+
isPrerelease := prerelease || newVersion.Prerelease() != ""
144+
145+
if branch != sha {
146+
ref := "refs/tags/" + tag
147+
tagOpts := &github.Reference{
148+
Ref: &ref,
149+
Object: &github.GitObject{SHA: &sha},
150+
}
151+
_, _, err := repo.Client.Git.CreateRef(repo.Ctx, repo.owner, repo.repo, tagOpts)
152+
if err != nil {
153+
return err
154+
}
155+
}
156+
157+
opts := &github.RepositoryRelease{
158+
TagName: &tag,
159+
Name: &tag,
160+
TargetCommitish: &branch,
161+
Body: &changelog,
162+
Prerelease: &isPrerelease,
163+
}
164+
_, _, err := repo.Client.Repositories.CreateRelease(repo.Ctx, repo.owner, repo.repo, opts)
165+
if err != nil {
166+
return err
167+
}
168+
return nil
169+
}
170+
171+
func parseGithubCommit(commit *github.RepositoryCommit) *Commit {
172+
c := new(Commit)
173+
c.SHA = commit.GetSHA()
174+
c.Raw = strings.Split(commit.Commit.GetMessage(), "\n")
175+
found := commitPattern.FindAllStringSubmatch(c.Raw[0], -1)
176+
if len(found) < 1 {
177+
return c
178+
}
179+
c.Type = strings.ToLower(found[0][1])
180+
c.Scope = found[0][2]
181+
c.Message = found[0][3]
182+
c.Change = Change{
183+
Major: breakingPattern.MatchString(commit.Commit.GetMessage()),
184+
Minor: c.Type == "feat",
185+
Patch: c.Type == "fix",
186+
}
187+
return c
188+
}
189+
190+
func (repo *GithubRepository) Owner() string {
191+
return repo.owner
192+
}
193+
194+
func (repo *GithubRepository) Repo() string {
195+
return repo.repo
196+
}

0 commit comments

Comments
 (0)