From 7331e0a7adf030efc35eb086967f0c16b47ff0c1 Mon Sep 17 00:00:00 2001 From: JT Archie Date: Thu, 22 Oct 2015 12:27:52 -0400 Subject: [PATCH] filter by drafts in the `check` step The user now opts-in to getting final or draft releases. Default behaviour is final releases. NOTE: There is also strict filtering on only allowing semver supported tags. Signed-off-by: David Jahn --- README.md | 6 +++ check_command.go | 44 ++++++++++------- check_command_test.go | 106 +++++++++++++++++++++++++++++++++++++---- fakes/fake_git_hub.go | 48 +++++++++++++++++-- github.go | 15 ++++++ in_command.go | 14 ++++-- in_command_test.go | 67 +++++++++++++++++++++++--- metadata.go | 14 ++++++ out_command.go | 6 +-- out_command_test.go | 19 ++++++++ resource_suite_test.go | 19 +++++--- resources.go | 4 +- versions.go | 21 +++++++- 13 files changed, 329 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 587f8e2..0145b6d 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,10 @@ Fetches and creates versioned GitHub resources. * `github_api_url`: *Optional.* If you use a non-public GitHub deployment then you can set your API URL here. +* `drafts`: *Optional.* When set to `true` only returns draft releases with + semver compliant tags. Defaults to `false` returning only final releases + with semver compliant tags. + ### Example ``` yaml @@ -93,3 +97,5 @@ matching the patterns in `globs` to the release. * `globs`: *Optional.* A list of globs for files that will be uploaded alongside the created release. + +* `draft`: *Optional.* A boolean to set the release in draft mode or not. diff --git a/check_command.go b/check_command.go index ac202c0..f3a9999 100644 --- a/check_command.go +++ b/check_command.go @@ -2,6 +2,7 @@ package resource import ( "sort" + "strconv" "github.com/blang/semver" "github.com/zachgersh/go-github/github" @@ -27,38 +28,53 @@ func (c *CheckCommand) Run(request CheckRequest) ([]Version, error) { return []Version{}, nil } - sort.Sort(byVersion(releases)) - var filteredReleases []github.RepositoryRelease for _, release := range releases { - draft := *release.Draft - if !draft { - filteredReleases = append(filteredReleases, release) + if request.Source.Drafts != *release.Draft { + continue } + if release.TagName == nil { + continue + } + if _, err := semver.New(determineVersionFromTag(*release.TagName)); err != nil { + continue + } + + filteredReleases = append(filteredReleases, release) } - latestVersion := *filteredReleases[len(filteredReleases)-1].TagName + sort.Sort(byVersion(filteredReleases)) - if request.Version.Tag == "" { + if len(filteredReleases) == 0 { + return []Version{}, nil + } + latestRelease := filteredReleases[len(filteredReleases)-1] + + if (request.Version == Version{}) { return []Version{ - {Tag: latestVersion}, + versionFromDraft(&latestRelease), }, nil } - if latestVersion == request.Version.Tag { + if *latestRelease.TagName == request.Version.Tag { return []Version{}, nil } upToLatest := false reversedVersions := []Version{} for _, release := range filteredReleases { - version := *release.TagName if upToLatest { - reversedVersions = append(reversedVersions, Version{Tag: version}) + reversedVersions = append(reversedVersions, versionFromDraft(&release)) } else { - upToLatest = request.Version.Tag == version + if *release.Draft { + id := *release.ID + upToLatest = request.Version.ID == strconv.Itoa(id) + } else { + version := *release.TagName + upToLatest = request.Version.Tag == version + } } } @@ -76,10 +92,6 @@ func (r byVersion) Swap(i, j int) { } func (r byVersion) Less(i, j int) bool { - if r[i].TagName == nil || r[j].TagName == nil { - return false - } - first, err := semver.New(determineVersionFromTag(*r[i].TagName)) if err != nil { return true diff --git a/check_command_test.go b/check_command_test.go index e13cdfb..ae5f24c 100644 --- a/check_command_test.go +++ b/check_command_test.go @@ -42,12 +42,26 @@ var _ = Describe("Check Command", func() { }) }) + Context("when there are releases that get filtered out", func() { + BeforeEach(func() { + returnedReleases = []github.RepositoryRelease{ + newDraftRepositoryRelease(1, "v0.1.4"), + } + }) + + It("returns no versions", func() { + versions, err := command.Run(resource.CheckRequest{}) + Ω(err).ShouldNot(HaveOccurred()) + Ω(versions).Should(BeEmpty()) + }) + }) + Context("when there are releases", func() { BeforeEach(func() { returnedReleases = []github.RepositoryRelease{ - newRepositoryRelease("v0.4.0"), - newRepositoryRelease("0.1.3"), - newRepositoryRelease("v0.1.2"), + newRepositoryRelease(1, "v0.4.0"), + newRepositoryRelease(2, "0.1.3"), + newRepositoryRelease(3, "v0.1.2"), } }) @@ -82,10 +96,10 @@ var _ = Describe("Check Command", func() { Context("and the releases do not contain a draft release", func() { BeforeEach(func() { returnedReleases = []github.RepositoryRelease{ - newRepositoryRelease("v0.1.4"), - newRepositoryRelease("0.4.0"), - newRepositoryRelease("v0.1.3"), - newRepositoryRelease("0.1.2"), + newRepositoryRelease(1, "v0.1.4"), + newRepositoryRelease(2, "0.4.0"), + newRepositoryRelease(3, "v0.1.3"), + newRepositoryRelease(4, "0.1.2"), } }) @@ -122,9 +136,9 @@ var _ = Describe("Check Command", func() { Context("and one of the releases is a draft", func() { BeforeEach(func() { returnedReleases = []github.RepositoryRelease{ - newDraftRepositoryRelease("v0.1.4"), - newRepositoryRelease("0.4.0"), - newRepositoryRelease("v0.1.3"), + newDraftRepositoryRelease(1, "v0.1.4"), + newRepositoryRelease(2, "0.4.0"), + newRepositoryRelease(3, "v0.1.3"), } }) @@ -143,6 +157,78 @@ var _ = Describe("Check Command", func() { })) }) }) + + Context("when draft releases are allowed", func() { + Context("and one of the releases is a final release", func() { + BeforeEach(func() { + returnedReleases = []github.RepositoryRelease{ + newDraftRepositoryRelease(1, "v0.1.4"), + newDraftRepositoryRelease(3, "v0.1.1"), + newRepositoryRelease(2, "0.4.0"), + } + }) + + It("returns all of the versions that are newer, and only draft", func() { + command := resource.NewCheckCommand(githubClient) + + response, err := command.Run(resource.CheckRequest{ + Version: resource.Version{ID: "3"}, + Source: resource.Source{Drafts: true}, + }) + Ω(err).ShouldNot(HaveOccurred()) + + Ω(response).Should(Equal([]resource.Version{ + {ID: "1"}, + })) + }) + }) + + Context("and non-of them are semver", func() { + BeforeEach(func() { + returnedReleases = []github.RepositoryRelease{ + newDraftRepositoryRelease(1, "abc"), + newDraftRepositoryRelease(2, "123"), + } + }) + + It("returns all of the releases with semver resources", func() { + command := resource.NewCheckCommand(githubClient) + + response, err := command.Run(resource.CheckRequest{ + Version: resource.Version{}, + Source: resource.Source{Drafts: true}, + }) + Ω(err).ShouldNot(HaveOccurred()) + + Ω(response).Should(Equal([]resource.Version{})) + }) + }) + + Context("and one of the releases is not a versioned draft release", func() { + BeforeEach(func() { + returnedReleases = []github.RepositoryRelease{ + newDraftRepositoryRelease(1, "v0.1.4"), + newDraftRepositoryRelease(2, ""), + newDraftWithNilTagRepositoryRelease(3), + newDraftRepositoryRelease(4, "asdf123"), + } + }) + + It("returns all of the releases with semver resources", func() { + command := resource.NewCheckCommand(githubClient) + + response, err := command.Run(resource.CheckRequest{ + Version: resource.Version{}, + Source: resource.Source{Drafts: true}, + }) + Ω(err).ShouldNot(HaveOccurred()) + + Ω(response).Should(Equal([]resource.Version{ + {ID: "1"}, + })) + }) + }) + }) }) }) }) diff --git a/fakes/fake_git_hub.go b/fakes/fake_git_hub.go index 0167741..85a6853 100644 --- a/fakes/fake_git_hub.go +++ b/fakes/fake_git_hub.go @@ -15,7 +15,7 @@ type FakeGitHub struct { ListReleasesStub func() ([]github.RepositoryRelease, error) listReleasesMutex sync.RWMutex listReleasesArgsForCall []struct{} - listReleasesReturns struct { + listReleasesReturns struct { result1 []github.RepositoryRelease result2 error } @@ -28,6 +28,15 @@ type FakeGitHub struct { result1 *github.RepositoryRelease result2 error } + GetReleaseStub func(id int) (*github.RepositoryRelease, error) + getReleaseMutex sync.RWMutex + getReleaseArgsForCall []struct { + id int + } + getReleaseReturns struct { + result1 *github.RepositoryRelease + result2 error + } CreateReleaseStub func(release github.RepositoryRelease) (*github.RepositoryRelease, error) createReleaseMutex sync.RWMutex createReleaseArgsForCall []struct { @@ -160,6 +169,39 @@ func (fake *FakeGitHub) GetReleaseByTagReturns(result1 *github.RepositoryRelease }{result1, result2} } +func (fake *FakeGitHub) GetRelease(id int) (*github.RepositoryRelease, error) { + fake.getReleaseMutex.Lock() + fake.getReleaseArgsForCall = append(fake.getReleaseArgsForCall, struct { + id int + }{id}) + fake.getReleaseMutex.Unlock() + if fake.GetReleaseStub != nil { + return fake.GetReleaseStub(id) + } else { + return fake.getReleaseReturns.result1, fake.getReleaseReturns.result2 + } +} + +func (fake *FakeGitHub) GetReleaseCallCount() int { + fake.getReleaseMutex.RLock() + defer fake.getReleaseMutex.RUnlock() + return len(fake.getReleaseArgsForCall) +} + +func (fake *FakeGitHub) GetReleaseArgsForCall(i int) int { + fake.getReleaseMutex.RLock() + defer fake.getReleaseMutex.RUnlock() + return fake.getReleaseArgsForCall[i].id +} + +func (fake *FakeGitHub) GetReleaseReturns(result1 *github.RepositoryRelease, result2 error) { + fake.GetReleaseStub = nil + fake.getReleaseReturns = struct { + result1 *github.RepositoryRelease + result2 error + }{result1, result2} +} + func (fake *FakeGitHub) CreateRelease(release github.RepositoryRelease) (*github.RepositoryRelease, error) { fake.createReleaseMutex.Lock() fake.createReleaseArgsForCall = append(fake.createReleaseArgsForCall, struct { @@ -364,7 +406,7 @@ func (fake *FakeGitHub) GetTarballLink(tag string) (*url.URL, error) { tag string }{tag}) fake.getTarballLinkMutex.Unlock() - if fake.GetReleaseByTagStub != nil { + if fake.GetTarballLinkStub != nil { return fake.GetTarballLinkStub(tag) } else { return fake.getTarballLinkReturns.result1, fake.getTarballLinkReturns.result2 @@ -397,7 +439,7 @@ func (fake *FakeGitHub) GetZipballLink(tag string) (*url.URL, error) { tag string }{tag}) fake.getZipballLinkMutex.Unlock() - if fake.GetReleaseByTagStub != nil { + if fake.GetZipballLinkStub != nil { return fake.GetZipballLinkStub(tag) } else { return fake.getZipballLinkReturns.result1, fake.getZipballLinkReturns.result2 diff --git a/github.go b/github.go index f8f9592..f82dbd5 100644 --- a/github.go +++ b/github.go @@ -16,6 +16,7 @@ import ( type GitHub interface { ListReleases() ([]github.RepositoryRelease, error) GetReleaseByTag(tag string) (*github.RepositoryRelease, error) + GetRelease(id int) (*github.RepositoryRelease, error) CreateRelease(release github.RepositoryRelease) (*github.RepositoryRelease, error) UpdateRelease(release github.RepositoryRelease) (*github.RepositoryRelease, error) @@ -93,6 +94,20 @@ func (g *GitHubClient) GetReleaseByTag(tag string) (*github.RepositoryRelease, e return release, nil } +func (g *GitHubClient) GetRelease(id int) (*github.RepositoryRelease, error) { + release, res, err := g.client.Repositories.GetRelease(g.user, g.repository, id) + if err != nil { + return &github.RepositoryRelease{}, nil + } + + err = res.Body.Close() + if err != nil { + return nil, err + } + + return release, nil +} + func (g *GitHubClient) CreateRelease(release github.RepositoryRelease) (*github.RepositoryRelease, error) { createdRelease, res, err := g.client.Repositories.CreateRelease(g.user, g.repository, &release) if err != nil { diff --git a/in_command.go b/in_command.go index 3391edb..e8583fe 100644 --- a/in_command.go +++ b/in_command.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "path/filepath" + "strconv" "github.com/zachgersh/go-github/github" ) @@ -32,7 +33,12 @@ func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) { var foundRelease *github.RepositoryRelease - foundRelease, err = c.github.GetReleaseByTag(request.Version.Tag) + if request.Version.Tag != "" { + foundRelease, err = c.github.GetReleaseByTag(request.Version.Tag) + } else { + id, _ := strconv.Atoi(request.Version.ID) + foundRelease, err = c.github.GetRelease(id) + } if err != nil { return InResponse{}, err } @@ -41,7 +47,7 @@ func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) { return InResponse{}, errors.New("no releases") } - if *foundRelease.TagName != "" { + if foundRelease.TagName != nil && *foundRelease.TagName != "" { tagPath := filepath.Join(destDir, "tag") err = ioutil.WriteFile(tagPath, []byte(*foundRelease.TagName), 0644) if err != nil { @@ -116,9 +122,7 @@ func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) { } return InResponse{ - Version: Version{ - Tag: *foundRelease.TagName, - }, + Version: versionFromDraft(foundRelease), Metadata: metadataFromRelease(foundRelease), }, nil } diff --git a/in_command_test.go b/in_command_test.go index 3d27ff4..f7f6e1c 100644 --- a/in_command_test.go +++ b/in_command_test.go @@ -67,6 +67,16 @@ var _ = Describe("In Command", func() { } } + buildNilTagRelease := func(id int) *github.RepositoryRelease { + return &github.RepositoryRelease{ + ID: github.Int(id), + HTMLURL: github.String("http://google.com"), + Name: github.String("release-name"), + Body: github.String("*markdown*"), + Draft: github.Bool(true), + } + } + buildAsset := func(id int, name string) github.ReleaseAsset { return github.ReleaseAsset{ ID: github.Int(id), @@ -116,9 +126,16 @@ var _ = Describe("In Command", func() { resource.MetadataPair{Name: "url", Value: "http://google.com"}, resource.MetadataPair{Name: "name", Value: "release-name", URL: "http://google.com"}, resource.MetadataPair{Name: "body", Value: "*markdown*", Markdown: true}, + resource.MetadataPair{Name: "tag", Value: "v0.35.0"}, )) }) + It("calls #GetReleastByTag with the correct arguments", func() { + command.Run(destDir, inRequest) + + Ω(githubClient.GetReleaseByTagArgsForCall(0)).Should(Equal("v0.35.0")) + }) + It("downloads only the files that match the globs", func() { inResponse, inErr = command.Run(destDir, inRequest) @@ -319,6 +336,7 @@ var _ = Describe("In Command", func() { resource.MetadataPair{Name: "url", Value: "http://google.com"}, resource.MetadataPair{Name: "name", Value: "release-name", URL: "http://google.com"}, resource.MetadataPair{Name: "body", Value: "*markdown*", Markdown: true}, + resource.MetadataPair{Name: "tag", Value: "v0.35.0"}, )) }) @@ -391,9 +409,9 @@ var _ = Describe("In Command", func() { Context("when there is a draft release", func() { Context("which has a tag", func() { BeforeEach(func() { - githubClient.GetReleaseByTagReturns(buildRelease(1, "v0.35.0", true), nil) + githubClient.GetReleaseReturns(buildRelease(1, "v0.35.0", true), nil) - inRequest.Version = &resource.Version{Tag: "v0.35.0"} + inRequest.Version = &resource.Version{ID: "1"} inResponse, inErr = command.Run(destDir, inRequest) }) @@ -402,7 +420,7 @@ var _ = Describe("In Command", func() { }) It("returns the fetched version", func() { - Ω(inResponse.Version).Should(Equal(resource.Version{Tag: "v0.35.0"})) + Ω(inResponse.Version).Should(Equal(resource.Version{ID: "1"})) }) It("has some sweet metadata", func() { @@ -410,6 +428,8 @@ var _ = Describe("In Command", func() { resource.MetadataPair{Name: "url", Value: "http://google.com"}, resource.MetadataPair{Name: "name", Value: "release-name", URL: "http://google.com"}, resource.MetadataPair{Name: "body", Value: "*markdown*", Markdown: true}, + resource.MetadataPair{Name: "tag", Value: "v0.35.0"}, + resource.MetadataPair{Name: "draft", Value: "true"}, )) }) @@ -424,11 +444,11 @@ var _ = Describe("In Command", func() { }) }) - Context("which doesn't have a tag", func() { + Context("which has an empty tag", func() { BeforeEach(func() { - githubClient.GetReleaseByTagReturns(buildRelease(1, "", true), nil) + githubClient.GetReleaseReturns(buildRelease(1, "", true), nil) - inRequest.Version = &resource.Version{} + inRequest.Version = &resource.Version{ID: "1"} inResponse, inErr = command.Run(destDir, inRequest) }) @@ -437,7 +457,7 @@ var _ = Describe("In Command", func() { }) It("returns the fetched version", func() { - Ω(inResponse.Version).Should(Equal(resource.Version{Tag: ""})) + Ω(inResponse.Version).Should(Equal(resource.Version{ID: "1"})) }) It("has some sweet metadata", func() { @@ -445,6 +465,39 @@ var _ = Describe("In Command", func() { resource.MetadataPair{Name: "url", Value: "http://google.com"}, resource.MetadataPair{Name: "name", Value: "release-name", URL: "http://google.com"}, resource.MetadataPair{Name: "body", Value: "*markdown*", Markdown: true}, + resource.MetadataPair{Name: "tag", Value: ""}, + resource.MetadataPair{Name: "draft", Value: "true"}, + )) + }) + + It("does not create the tag and version files", func() { + Ω(path.Join(destDir, "tag")).ShouldNot(BeAnExistingFile()) + Ω(path.Join(destDir, "version")).ShouldNot(BeAnExistingFile()) + }) + }) + + Context("which has a nil tag", func() { + BeforeEach(func() { + githubClient.GetReleaseReturns(buildNilTagRelease(1), nil) + + inRequest.Version = &resource.Version{ID: "1"} + inResponse, inErr = command.Run(destDir, inRequest) + }) + + It("succeeds", func() { + Ω(inErr).ShouldNot(HaveOccurred()) + }) + + It("returns the fetched version", func() { + Ω(inResponse.Version).Should(Equal(resource.Version{ID: "1"})) + }) + + It("has some sweet metadata", func() { + Ω(inResponse.Metadata).Should(ConsistOf( + resource.MetadataPair{Name: "url", Value: "http://google.com"}, + resource.MetadataPair{Name: "name", Value: "release-name", URL: "http://google.com"}, + resource.MetadataPair{Name: "body", Value: "*markdown*", Markdown: true}, + resource.MetadataPair{Name: "draft", Value: "true"}, )) }) diff --git a/metadata.go b/metadata.go index 1139f33..fdc39f3 100644 --- a/metadata.go +++ b/metadata.go @@ -33,5 +33,19 @@ func metadataFromRelease(release *github.RepositoryRelease) []MetadataPair { }) } + if release.TagName != nil { + metadata = append(metadata, MetadataPair{ + Name: "tag", + Value: *release.TagName, + }) + } + + if *release.Draft { + metadata = append(metadata, MetadataPair{ + Name: "draft", + Value: "true", + }) + } + return metadata } diff --git a/out_command.go b/out_command.go index 368d9bd..768bb2c 100644 --- a/out_command.go +++ b/out_command.go @@ -69,7 +69,7 @@ func (c *OutCommand) Run(sourceDir string, request OutRequest) (OutResponse, err var existingRelease *github.RepositoryRelease for _, e := range existingReleases { - if *e.TagName == tag { + if e.TagName != nil && *e.TagName == tag { existingRelease = &e break } @@ -130,9 +130,7 @@ func (c *OutCommand) Run(sourceDir string, request OutRequest) (OutResponse, err } return OutResponse{ - Version: Version{ - Tag: tag, - }, + Version: versionFromDraft(release), Metadata: metadataFromRelease(release), }, nil } diff --git a/out_command_test.go b/out_command_test.go index f89e166..1d38114 100644 --- a/out_command_test.go +++ b/out_command_test.go @@ -76,10 +76,15 @@ var _ = Describe("Out Command", func() { BeforeEach(func() { githubClient.ListReleasesReturns([]github.RepositoryRelease{ + { + ID: github.Int(1), + Draft: github.Bool(true), + }, { ID: github.Int(112), TagName: github.String("some-tag-name"), Assets: existingAssets, + Draft: github.Bool(false), }, }, nil) @@ -228,6 +233,19 @@ var _ = Describe("Out Command", func() { Ω(*release.Body).Should(Equal("")) Ω(*release.Draft).Should(Equal(true)) }) + + It("has some sweet metadata", func() { + outResponse, err := command.Run(sourcesDir, request) + Ω(err).ShouldNot(HaveOccurred()) + + Ω(outResponse.Metadata).Should(ConsistOf( + resource.MetadataPair{Name: "url", Value: "http://google.com"}, + resource.MetadataPair{Name: "name", Value: "release-name", URL: "http://google.com"}, + resource.MetadataPair{Name: "body", Value: "*markdown*", Markdown: true}, + resource.MetadataPair{Name: "tag", Value: "0.3.12"}, + resource.MetadataPair{Name: "draft", Value: "true"}, + )) + }) }) Context("with file globs", func() { @@ -272,6 +290,7 @@ var _ = Describe("Out Command", func() { resource.MetadataPair{Name: "url", Value: "http://google.com"}, resource.MetadataPair{Name: "name", Value: "release-name", URL: "http://google.com"}, resource.MetadataPair{Name: "body", Value: "*markdown*", Markdown: true}, + resource.MetadataPair{Name: "tag", Value: "0.3.12"}, )) }) diff --git a/resource_suite_test.go b/resource_suite_test.go index bd5367d..bd403a4 100644 --- a/resource_suite_test.go +++ b/resource_suite_test.go @@ -13,18 +13,25 @@ func TestGithubReleaseResource(t *testing.T) { RunSpecs(t, "Github Release Resource Suite") } -func newRepositoryRelease(version string) github.RepositoryRelease { - draft := false +func newRepositoryRelease(id int, version string) github.RepositoryRelease { return github.RepositoryRelease{ TagName: github.String(version), - Draft: &draft, + Draft: github.Bool(false), + ID: github.Int(id), } } -func newDraftRepositoryRelease(version string) github.RepositoryRelease { - draft := true +func newDraftRepositoryRelease(id int, version string) github.RepositoryRelease { return github.RepositoryRelease{ TagName: github.String(version), - Draft: &draft, + Draft: github.Bool(true), + ID: github.Int(id), + } +} + +func newDraftWithNilTagRepositoryRelease(id int) github.RepositoryRelease { + return github.RepositoryRelease{ + Draft: github.Bool(true), + ID: github.Int(id), } } diff --git a/resources.go b/resources.go index ca7fe64..65685c5 100644 --- a/resources.go +++ b/resources.go @@ -6,6 +6,7 @@ type Source struct { GitHubAPIURL string `json:"github_api_url"` AccessToken string `json:"access_token"` + Drafts bool `json:"drafts"` } type CheckRequest struct { @@ -51,7 +52,8 @@ type OutResponse struct { } type Version struct { - Tag string `json:"tag"` + Tag string `json:"tag,omitempty"` + ID string `json:"id,omitempty"` } type MetadataPair struct { diff --git a/versions.go b/versions.go index 47d3448..aadacdd 100644 --- a/versions.go +++ b/versions.go @@ -1,10 +1,27 @@ package resource -import "regexp" +import ( + "regexp" + "strconv" + + "github.com/zachgersh/go-github/github" +) // determineVersionFromTag converts git tags v1.2.3 into semver 1.2.3 values func determineVersionFromTag(tag string) string { re := regexp.MustCompile("v?([^v].*)") matches := re.FindStringSubmatch(tag) - return matches[1] + if len(matches) > 0 { + return matches[1] + } else { + return "" + } +} + +func versionFromDraft(release *github.RepositoryRelease) Version { + if *release.Draft { + return Version{ID: strconv.Itoa(*release.ID)} + } else { + return Version{Tag: *release.TagName} + } }