diff --git a/cmd/generate.go b/cmd/generate.go
index 554793b..3f2d8ef 100644
--- a/cmd/generate.go
+++ b/cmd/generate.go
@@ -30,13 +30,18 @@ func generateReleaseNote(cmd *cobra.Command, args []string) {
githubOwner, _ := cmd.Flags().GetString("github-owner")
githubRepo, _ := cmd.Flags().GetString("github-repo")
- commitSHA, err := client.FetchLatestReleaseCommitSHA(githubOwner, githubRepo)
+ releaseSHAs, err := client.FetchCommitsFromReleases(githubOwner, githubRepo)
if err != nil {
- failf("failed to fetch latest release commit SHA from github: %s", err)
+ failf("failed to fetch release commit SHAs from github: %s", err)
}
githubBranch, _ := cmd.Flags().GetString("github-branch")
+ commitSHA, err := client.FetchLatestReleaseCommitFromBranch(githubOwner, githubRepo, githubBranch, releaseSHAs)
+ if err != nil {
+ failf("failed to fetch latest release commit from branch: %s", err)
+ }
+
pullRequests, err := client.FetchPullRequestsAfterCommit(githubOwner, githubRepo, githubBranch, commitSHA)
if err != nil {
failf("failed to fetch pull requests: %s", err)
diff --git a/cmd/validate.go b/cmd/validate.go
index 07a21dd..c09650a 100644
--- a/cmd/validate.go
+++ b/cmd/validate.go
@@ -4,8 +4,8 @@ import (
"fmt"
"strconv"
- "github.com/clarafu/release-me/github"
"github.com/clarafu/release-me/generate"
+ "github.com/clarafu/release-me/github"
"github.com/spf13/cobra"
)
@@ -15,7 +15,7 @@ var validateCmd = &cobra.Command{
Long: `Ensures that the pull request given has at least one of the labels
required to properly generate a release note using the "generate"
command.`,
- Run: validate,
+ Run: validate,
}
func init() {
@@ -49,4 +49,3 @@ func validate(cmd *cobra.Command, args []string) {
fmt.Printf("pull request #%d has valid labels\n", prNumber)
}
-
diff --git a/generate/generate.go b/generate/generate.go
index 6293f69..d12c159 100644
--- a/generate/generate.go
+++ b/generate/generate.go
@@ -122,7 +122,7 @@ func Validate(labels []string) bool {
for _, validLabel := range ValidLabels {
validLabelsMap[validLabel] = true
}
-
+
for _, label := range labels {
if _, exists := validLabelsMap[label]; exists {
return true
@@ -130,4 +130,4 @@ func Validate(labels []string) bool {
}
return false
-}
\ No newline at end of file
+}
diff --git a/generate/template.go b/generate/template.go
index df69dfd..896d85c 100644
--- a/generate/template.go
+++ b/generate/template.go
@@ -31,7 +31,7 @@ const rawTemplate = `
## {{$section.Icon}} {{$section.Title}}
{{ range $pr := $section.PRs }}
-* **{{$pr.Title}} (#{{$pr.Number}})** @{{$pr.Author}} :link:
+* {{$pr.Title}} (#{{$pr.Number}}) @{{$pr.Author}} :link:
{{ $pr.ReleaseNote | indent 2 }}
{{end}}
{{end}}
diff --git a/github/github.go b/github/github.go
index fbc9e70..2ba57f6 100644
--- a/github/github.go
+++ b/github/github.go
@@ -42,40 +42,8 @@ func New(token string) GitHub {
}
}
-func (g GitHub) FetchLabelsForPullRequest(owner, repo string, pullRequestNumber int) ([]string, error) {
- var PullRequestlabelsQuery struct {
- Repository struct {
- PullRequest struct {
- Labels struct {
- Nodes []struct {
- Name string
- }
- } `graphql:"labels(first: 10)"`
- } `graphql:"pullRequest(number: $prNumber)"`
- } `graphql:"repository(owner: $owner, name: $name)"`
- }
-
- PRVariables := map[string]interface{}{
- "owner": githubv4.String(owner),
- "name": githubv4.String(repo),
- "prNumber": githubv4.Int(pullRequestNumber),
- }
-
- err := g.client.Query(context.Background(), &PullRequestlabelsQuery, PRVariables)
- if err != nil {
- return nil, err
- }
-
- var labels []string
- for _, node := range PullRequestlabelsQuery.Repository.PullRequest.Labels.Nodes {
- labels = append(labels, node.Name)
- }
-
- return labels, nil
-}
-
-func (g GitHub) FetchLatestReleaseCommitSHA(owner, repo string) (string, error) {
- var releaseSHAQuery struct {
+func (g GitHub) FetchCommitsFromReleases(owner, repo string) (map[string]bool, error) {
+ var releaseSHAsQuery struct {
Repository struct {
Releases struct {
Nodes []struct {
@@ -85,60 +53,81 @@ func (g GitHub) FetchLatestReleaseCommitSHA(owner, repo string) (string, error)
}
}
}
- } `graphql:"releases(last: 1, orderBy:{direction: ASC, field: NAME})"`
+ } `graphql:"releases(first: 50, orderBy: {direction: DESC, field: CREATED_AT})"`
} `graphql:"repository(owner: $owner, name: $name)"`
}
- releaseSHAVariables := map[string]interface{}{
+ releaseSHAsVariables := map[string]interface{}{
"owner": githubv4.String(owner),
"name": githubv4.String(repo),
}
- err := g.client.Query(context.Background(), &releaseSHAQuery, releaseSHAVariables)
+ err := g.client.Query(context.Background(), &releaseSHAsQuery, releaseSHAsVariables)
if err != nil {
- return "", err
+ return nil, err
}
- // If the repository does not have a release, return an empty string
- var releaseSHA string
- if len(releaseSHAQuery.Repository.Releases.Nodes) > 0 {
- releaseSHA = releaseSHAQuery.Repository.Releases.Nodes[0].Tag.Target.Oid
+ releaseSHAs := map[string]bool{}
+ for _, release := range releaseSHAsQuery.Repository.Releases.Nodes {
+ releaseSHAs[release.Tag.Target.Oid] = true
}
- return releaseSHA, nil
+ return releaseSHAs, nil
}
-func (g GitHub) FetchCommitFromTag(owner, repo, tag string) (string, error) {
- var releaseSHAQuery struct {
+func (g GitHub) FetchLatestReleaseCommitFromBranch(owner, repo, branch string, releaseSHAs map[string]bool) (string, error) {
+ var commitsQuery struct {
Repository struct {
- Refs struct {
- Nodes []struct {
- Target struct {
- Oid string
- }
+ Ref struct {
+ Target struct {
+ Commit struct {
+ History struct {
+ Nodes []struct {
+ Oid string
+ }
+ PageInfo struct {
+ EndCursor githubv4.String
+ HasNextPage bool
+ }
+ } `graphql:"history(first: 100, after: $commitCursor)"`
+ } `graphql:"... on Commit"`
}
- } `graphql:"refs(refPrefix: "refs/tags/", first: 1, query: $tag)"`
+ } `graphql:"ref(qualifiedName: $branch)"`
} `graphql:"repository(owner: $owner, name: $name)"`
}
- releaseSHAVariables := map[string]interface{}{
- "owner": githubv4.String(owner),
- "name": githubv4.String(repo),
- "tag": githubv4.String(tag),
+ commitsVariables := map[string]interface{}{
+ "owner": githubv4.String(owner),
+ "name": githubv4.String(repo),
+ "branch": githubv4.String(branch),
+ "commitCursor": (*githubv4.String)(nil),
}
- err := g.client.Query(context.Background(), &releaseSHAQuery, releaseSHAVariables)
- if err != nil {
- return "", err
- }
+ var lastCommit string
+ for {
+ err := g.client.Query(context.Background(), &commitsQuery, commitsVariables)
+ if err != nil {
+ return "", fmt.Errorf("failed to fetch commits from github: %w", err)
+ }
+
+ history := commitsQuery.Repository.Ref.Target.Commit.History
+ for _, commit := range history.Nodes {
+ lastCommit = commit.Oid
+
+ if _, found := releaseSHAs[commit.Oid]; found {
+ return commit.Oid, nil
+ }
+ }
+
+ if !history.PageInfo.HasNextPage {
+ fmt.Printf("could not find a commit from the latest release, generating release note using all commits in branch %s\n", branch)
+ break
+ }
- // If the repository does not have a release, return an empty string
- var releaseSHA string
- if len(releaseSHAQuery.Repository.Refs.Nodes) > 0 {
- releaseSHA = releaseSHAQuery.Repository.Refs.Nodes[0].Target.Oid
+ commitsVariables["commitCursor"] = history.PageInfo.EndCursor
}
- return releaseSHA, nil
+ return lastCommit, nil
}
func (g GitHub) FetchPullRequestsAfterCommit(owner, repo, branch, commitSHA string) ([]PullRequest, error) {
@@ -241,3 +230,35 @@ func (g GitHub) FetchPullRequestsAfterCommit(owner, repo, branch, commitSHA stri
}
return pullRequests, nil
}
+
+func (g GitHub) FetchLabelsForPullRequest(owner, repo string, pullRequestNumber int) ([]string, error) {
+ var PullRequestlabelsQuery struct {
+ Repository struct {
+ PullRequest struct {
+ Labels struct {
+ Nodes []struct {
+ Name string
+ }
+ } `graphql:"labels(first: 10)"`
+ } `graphql:"pullRequest(number: $prNumber)"`
+ } `graphql:"repository(owner: $owner, name: $name)"`
+ }
+
+ PRVariables := map[string]interface{}{
+ "owner": githubv4.String(owner),
+ "name": githubv4.String(repo),
+ "prNumber": githubv4.Int(pullRequestNumber),
+ }
+
+ err := g.client.Query(context.Background(), &PullRequestlabelsQuery, PRVariables)
+ if err != nil {
+ return nil, err
+ }
+
+ var labels []string
+ for _, node := range PullRequestlabelsQuery.Repository.PullRequest.Labels.Nodes {
+ labels = append(labels, node.Name)
+ }
+
+ return labels, nil
+}