diff --git a/README.md b/README.md index beb1d09..ed27b46 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,11 @@ Fetches and creates versioned GitHub resources. will be detected and published. Note that releases must have semver compliant tags to be detected, even if they're drafts. +* `tag_filter`: *Optional. If set, override default tag filter regular + expression of `v?([^v].*)`. If the filter includes a capture group, the capture + group is used as the release version; otherwise, the entire matching substring + is used as the version. + ### Example ``` yaml @@ -74,6 +79,17 @@ To get a specific version of a release: version: { tag: 'v0.0.1' } ``` +To set a custom tag filter: + +```yaml +- name: gh-release + type: github-release + source: + owner: concourse + repository: concourse + tag_filter: "version-(.*)" +``` + ## Behavior ### `check`: Check for released versions. diff --git a/check_command.go b/check_command.go index 3131144..8c35f44 100644 --- a/check_command.go +++ b/check_command.go @@ -31,6 +31,11 @@ func (c *CheckCommand) Run(request CheckRequest) ([]Version, error) { var filteredReleases []*github.RepositoryRelease + versionParser, err := newVersionParser(request.Source.TagFilter) + if err != nil { + return []Version{}, err + } + for _, release := range releases { if request.Source.Drafts != *release.Draft { continue @@ -46,14 +51,26 @@ func (c *CheckCommand) Run(request CheckRequest) ([]Version, error) { if release.TagName == nil { continue } - if _, err := version.NewVersionFromString(determineVersionFromTag(*release.TagName)); err != nil { + if _, err := version.NewVersionFromString(versionParser.parse(*release.TagName)); err != nil { continue } filteredReleases = append(filteredReleases, release) } - sort.Sort(byVersion(filteredReleases)) + sort.Slice(filteredReleases, func(i, j int) bool { + first, err := version.NewVersionFromString(versionParser.parse(*filteredReleases[i].TagName)) + if err != nil { + return true + } + + second, err := version.NewVersionFromString(versionParser.parse(*filteredReleases[j].TagName)) + if err != nil { + return false + } + + return first.IsLt(second) + }) if len(filteredReleases) == 0 { return []Version{}, nil @@ -99,27 +116,3 @@ func (c *CheckCommand) Run(request CheckRequest) ([]Version, error) { return reversedVersions, nil } - -type byVersion []*github.RepositoryRelease - -func (r byVersion) Len() int { - return len(r) -} - -func (r byVersion) Swap(i, j int) { - r[i], r[j] = r[j], r[i] -} - -func (r byVersion) Less(i, j int) bool { - first, err := version.NewVersionFromString(determineVersionFromTag(*r[i].TagName)) - if err != nil { - return true - } - - second, err := version.NewVersionFromString(determineVersionFromTag(*r[j].TagName)) - if err != nil { - return false - } - - return first.IsLt(second) -} diff --git a/check_command_test.go b/check_command_test.go index 59271c0..dde2953 100644 --- a/check_command_test.go +++ b/check_command_test.go @@ -93,6 +93,34 @@ var _ = Describe("Check Command", func() { }) Context("when there are releases", func() { + Context("and there is a custom tag filter", func() { + BeforeEach(func() { + returnedReleases = []*github.RepositoryRelease{ + newRepositoryRelease(1, "package-0.1.4"), + newRepositoryRelease(2, "package-0.4.0"), + newRepositoryRelease(3, "package-0.1.3"), + newRepositoryRelease(4, "package-0.1.2"), + } + }) + + It("returns all of the versions that are newer", func() { + command := resource.NewCheckCommand(githubClient) + + response, err := command.Run(resource.CheckRequest{ + Version: resource.Version{ + Tag: "package-0.1.3", + }, + }) + Ω(err).ShouldNot(HaveOccurred()) + + Ω(response).Should(Equal([]resource.Version{ + {Tag: "package-0.1.3"}, + {Tag: "package-0.1.4"}, + {Tag: "package-0.4.0"}, + })) + }) + }) + Context("and the releases do not contain a draft release", func() { BeforeEach(func() { returnedReleases = []*github.RepositoryRelease{ diff --git a/in_command.go b/in_command.go index f302fe7..b1bf35f 100644 --- a/in_command.go +++ b/in_command.go @@ -55,7 +55,11 @@ func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) { return InResponse{}, err } - version := determineVersionFromTag(*foundRelease.TagName) + versionParser, err := newVersionParser(request.Source.TagFilter) + if err != nil { + return InResponse{}, err + } + version := versionParser.parse(*foundRelease.TagName) versionPath := filepath.Join(destDir, "version") err = ioutil.WriteFile(versionPath, []byte(version), 0644) if err != nil { diff --git a/in_command_test.go b/in_command_test.go index f1f1108..c64e76d 100644 --- a/in_command_test.go +++ b/in_command_test.go @@ -180,6 +180,35 @@ var _ = Describe("In Command", func() { Ω(string(contents)).Should(Equal("*markdown*")) }) + Context("when there is a custom tag filter", func() { + BeforeEach(func() { + inRequest.Source = resource.Source{ + TagFilter: "package-(.*)", + } + githubClient.GetReleaseByTagReturns(buildRelease(1, "package-0.35.0", false), nil) + githubClient.GetRefReturns(buildTagRef("package-0.35.0", "f28085a4a8f744da83411f5e09fd7b1709149eee"), nil) + inResponse, inErr = command.Run(destDir, inRequest) + }) + + It("succeeds", func() { + inResponse, inErr = command.Run(destDir, inRequest) + + Expect(inErr).ToNot(HaveOccurred()) + }) + + It("does create the body, tag and version files", func() { + inResponse, inErr = command.Run(destDir, inRequest) + + contents, err := ioutil.ReadFile(path.Join(destDir, "tag")) + Ω(err).ShouldNot(HaveOccurred()) + Ω(string(contents)).Should(Equal("package-0.35.0")) + + contents, err = ioutil.ReadFile(path.Join(destDir, "version")) + Ω(err).ShouldNot(HaveOccurred()) + Ω(string(contents)).Should(Equal("0.35.0")) + }) + }) + Context("when include_source_tarball is true", func() { var tarballUrl *url.URL diff --git a/resources.go b/resources.go index a54aacc..b55f9eb 100644 --- a/resources.go +++ b/resources.go @@ -14,6 +14,8 @@ type Source struct { PreRelease bool `json:"pre_release"` Release bool `json:"release"` Insecure bool `json:"insecure"` + + TagFilter string `json:"tag_filter"` } type CheckRequest struct { diff --git a/versions.go b/versions.go index a405d13..c148122 100644 --- a/versions.go +++ b/versions.go @@ -7,15 +7,29 @@ import ( "github.com/google/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) - if len(matches) > 0 { - return matches[1] - } else { - return "" +var defaultTagFilter = "^v?([^v].*)" + +type versionParser struct { + re *regexp.Regexp +} + +func newVersionParser(filter string) (versionParser, error) { + if filter == "" { + filter = defaultTagFilter } + re, err := regexp.Compile(filter) + if err != nil { + return versionParser{}, err + } + return versionParser{re: re}, nil +} + +func (vp *versionParser) parse(tag string) string { + matches := vp.re.FindStringSubmatch(tag) + if len(matches) > 0 { + return matches[len(matches)-1] + } + return "" } func versionFromRelease(release *github.RepositoryRelease) Version {