Skip to content

Commit

Permalink
feat: more stable get-latest-release functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
christophwitzko committed May 24, 2017
1 parent 82994ac commit 83a9f0f
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 29 deletions.
2 changes: 1 addition & 1 deletion cmd/semantic-release/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func main() {
}

logger.Println("getting latest release...")
release, err := repo.GetLatestRelease()
release, err := repo.GetLatestRelease("")
exitIfError(err)
logger.Println("found version: " + release.Version.String())

Expand Down
116 changes: 95 additions & 21 deletions semrel.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"golang.org/x/oauth2"
"regexp"
"sort"
"strconv"
"strings"
"time"
)
Expand All @@ -34,6 +35,20 @@ type Release struct {
Version *semver.Version
}

type Releases []*Release

func (r Releases) Len() int {
return len(r)
}

func (r Releases) Less(i, j int) bool {
return r[j].Version.LessThan(r[i].Version)
}

func (r Releases) Swap(i, j int) {
r[i], r[j] = r[j], r[i]
}

type Repository struct {
Owner string
Repo string
Expand Down Expand Up @@ -98,20 +113,64 @@ func (repo *Repository) GetCommits() ([]*Commit, error) {
return ret, nil
}

func (repo *Repository) GetLatestRelease() (*Release, error) {
opts := &github.ListOptions{PerPage: 1}
tags, _, err := repo.Client.Repositories.ListTags(repo.Ctx, repo.Owner, repo.Repo, opts)
func (repo *Repository) GetLatestRelease(vrange string) (*Release, error) {
allReleases := make(Releases, 0)
opts := &github.ReferenceListOptions{"tags", github.ListOptions{PerPage: 100}}
for {
refs, resp, err := repo.Client.Git.ListRefs(repo.Ctx, repo.Owner, repo.Repo, opts)
if resp != nil && resp.StatusCode == 404 {
return &Release{"", &semver.Version{}}, nil
}
if err != nil {
return nil, err
}
for _, r := range refs {
version, err := semver.NewVersion(strings.TrimPrefix(r.GetRef(), "refs/tags/"))
if err != nil {
continue
}
allReleases = append(allReleases, &Release{r.Object.GetSHA(), version})
}
if resp.NextPage == 0 {
break
}
opts.Page = resp.NextPage
}
sort.Sort(allReleases)
if vrange == "" {
for _, r := range allReleases {
if r.Version.Prerelease() == "" {
return r, nil
}
}
return &Release{"", &semver.Version{}}, nil
}

constraint, err := semver.NewConstraint(vrange)
if err != nil {
return nil, err
}
if len(tags) == 0 {
return &Release{"", &semver.Version{}}, nil
for _, r := range allReleases {
if constraint.Check(r.Version) {
return r, nil
}
}
version, verr := semver.NewVersion(tags[0].GetName())
if verr != nil {
return nil, verr

nver, err := semver.NewVersion(vrange)
if err != nil {
return nil, err
}
return &Release{tags[0].Commit.GetSHA(), version}, nil

splitPre := strings.SplitN(vrange, "-", 2)
if len(splitPre) == 1 {
return &Release{"", nver}, nil
}

npver, err := nver.SetPrerelease(splitPre[1])
if err != nil {
return nil, err
}
return &Release{"", &npver}, nil
}

func (repo *Repository) CreateRelease(commits []*Commit, latestRelease *Release, newVersion *semver.Version) error {
Expand Down Expand Up @@ -146,19 +205,34 @@ func ApplyChange(version *semver.Version, change Change) *semver.Version {
change.Major = true
}
var newVersion semver.Version
switch {
case change.Major:
newVersion = version.IncMajor()
break
case change.Minor:
newVersion = version.IncMinor()
break
case change.Patch:
newVersion = version.IncPatch()
break
default:
return nil
preRel := version.Prerelease()
if preRel == "" {
switch {
case change.Major:
newVersion = version.IncMajor()
break
case change.Minor:
newVersion = version.IncMinor()
break
case change.Patch:
newVersion = version.IncPatch()
break
default:
return nil
}
return &newVersion
}
preRelVer := strings.Split(preRel, ".")
if len(preRelVer) > 1 {
idx, err := strconv.ParseInt(preRelVer[1], 10, 32)
if err != nil {
idx = 0
}
preRel = fmt.Sprintf("%s.%d", preRelVer[0], idx+1)
} else {
preRel += ".1"
}
newVersion, _ = version.SetPrerelease(preRel)
return &newVersion
}

Expand Down
61 changes: 54 additions & 7 deletions semrel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ func createCommit(sha, message string) *github.RepositoryCommit {
return &github.RepositoryCommit{SHA: &sha, Commit: &github.Commit{Message: &message}}
}

func createRef(ref, sha string) *github.Reference {
return &github.Reference{Ref: &ref, Object: &github.GitObject{SHA: &sha}}
}

var (
GITHUB_REPO_PRIVATE = true
GITHUB_DEFAULTBRANCH = "master"
Expand All @@ -38,9 +42,14 @@ var (
createCommit("cdba", "Initial commit"),
createCommit("efcd", "chore: break\nBREAKING CHANGE: breaks everything"),
}
GITHUB_TAG_SHA = "be10"
GITHUB_TAG_NAME = "v1.0.0"
GITHUB_TAG = github.RepositoryTag{Commit: &github.Commit{SHA: &GITHUB_TAG_SHA}, Name: &GITHUB_TAG_NAME}
GITHUB_TAGS = []*github.Reference{
createRef("refs/tags/test-tag", "deadbeef"),
createRef("refs/tags/v1.0.0", "deadbeef"),
createRef("refs/tags/v2.0.0", "deadbeef"),
createRef("refs/tags/v2.1.0-beta", "deadbeef"),
createRef("refs/tags/v3.0.0-beta.2", "deadbeef"),
createRef("refs/tags/v3.0.0-beta.1", "deadbeef"),
}
)

func githubHandler(w http.ResponseWriter, r *http.Request) {
Expand All @@ -56,8 +65,8 @@ func githubHandler(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(GITHUB_COMMITS)
return
}
if r.Method == "GET" && r.URL.Path == "/repos/owner/test-repo/tags" {
json.NewEncoder(w).Encode([]*github.RepositoryTag{&GITHUB_TAG})
if r.Method == "GET" && r.URL.Path == "/repos/owner/test-repo/git/refs/tags" {
json.NewEncoder(w).Encode(GITHUB_TAGS)
return
}
if r.Method == "POST" && r.URL.Path == "/repos/owner/test-repo/releases" {
Expand Down Expand Up @@ -131,11 +140,34 @@ func TestGetCommits(t *testing.T) {
func TestGetLatestRelease(t *testing.T) {
repo, ts := getNewTestRepo(t)
defer ts.Close()
release, err := repo.GetLatestRelease()
release, err := repo.GetLatestRelease("")
if err != nil {
t.Fatal(err)
}
if release.SHA != "deadbeef" || release.Version.String() != "2.0.0" {
t.Fatal("invalid tag")
}
release, err = repo.GetLatestRelease("2-beta")
if err != nil {
t.Fatal(err)
}
if release.SHA != GITHUB_TAG_SHA || release.Version.String() != "1.0.0" {
if release.SHA != "deadbeef" || release.Version.String() != "2.1.0-beta" {
t.Fatal("invalid tag")
}

release, err = repo.GetLatestRelease("3-beta")
if err != nil {
t.Fatal(err)
}
if release.SHA != "deadbeef" || release.Version.String() != "3.0.0-beta.2" {
t.Fatal("invalid tag")
}

release, err = repo.GetLatestRelease("4-beta")
if err != nil {
t.Fatal(err)
}
if release.SHA != "" || release.Version.String() != "4.0.0-beta" {
t.Fatal("invalid tag")
}
}
Expand Down Expand Up @@ -194,6 +226,21 @@ func TestApplyChange(t *testing.T) {
if newVersion.String() != "1.0.0" {
t.Fail()
}
version, _ = semver.NewVersion("2.0.0-beta")
newVersion = ApplyChange(version, Change{true, true, true})
if newVersion.String() != "2.0.0-beta.1" {
t.Fail()
}
version, _ = semver.NewVersion("2.0.0-beta.2")
newVersion = ApplyChange(version, Change{true, true, true})
if newVersion.String() != "2.0.0-beta.3" {
t.Fail()
}
version, _ = semver.NewVersion("2.0.0-beta.1.1")
newVersion = ApplyChange(version, Change{true, true, true})
if newVersion.String() != "2.0.0-beta.2" {
t.Fail()
}
}

func TestGetChangelog(t *testing.T) {
Expand Down

0 comments on commit 83a9f0f

Please sign in to comment.