refactor: move commit analyzing out of forge

This commit is contained in:
Julian Tölle 2024-08-17 16:26:40 +02:00
parent f2a982d7a0
commit 5882a6bf2c
11 changed files with 152 additions and 188 deletions

117
forge.go
View file

@ -25,12 +25,6 @@ const (
GitHubLabelColor = "dedede"
)
type Changeset struct {
URL string
Identifier string
ChangelogEntries []AnalyzedCommit
}
type Forge interface {
RepoURL() string
CloneURL() string
@ -46,9 +40,6 @@ type Forge interface {
// function should return all commits.
CommitsSince(context.Context, *Tag) ([]Commit, error)
// Changesets looks up the Pull/Merge Requests for each commit, returning its parsed metadata.
Changesets(context.Context, []Commit) ([]Changeset, error)
// EnsureLabelsExist verifies that all desired labels are available on the repository. If labels are missing, they
// are created them.
EnsureLabelsExist(context.Context, []Label) error
@ -184,10 +175,16 @@ func (g *GitHub) CommitsSince(ctx context.Context, tag *Tag) ([]Commit, error) {
var commits = make([]Commit, 0, len(repositoryCommits))
for _, ghCommit := range repositoryCommits {
commits = append(commits, Commit{
commit := Commit{
Hash: ghCommit.GetSHA(),
Message: ghCommit.GetCommit().GetMessage(),
})
}
commit.PullRequest, err = g.prForCommit(ctx, commit)
if err != nil {
return nil, fmt.Errorf("failed to check for commit pull request: %w", err)
}
commits = append(commits, commit)
}
return commits, nil
@ -272,73 +269,49 @@ func (g *GitHub) commitsSinceInit(ctx context.Context) ([]*github.RepositoryComm
return repositoryCommits, nil
}
func (g *GitHub) Changesets(ctx context.Context, commits []Commit) ([]Changeset, error) {
func (g *GitHub) prForCommit(ctx context.Context, commit Commit) (*PullRequest, error) {
// We naively look up the associated PR for each commit through the "List pull requests associated with a commit"
// endpoint. This requires len(commits) requests.
// Using the "List pull requests" endpoint might be faster, as it allows us to fetch 100 arbitrary PRs per request,
// but worst case we need to look up all PRs made in the repository ever.
changesets := make([]Changeset, 0, len(commits))
log := g.log.With("commit.hash", commit.Hash)
page := 1
var associatedPRs []*github.PullRequest
for _, commit := range commits {
log := g.log.With("commit.hash", commit.Hash)
page := 1
var associatedPRs []*github.PullRequest
for {
log.Debug("fetching pull requests associated with commit", "page", page)
prs, resp, err := g.client.PullRequests.ListPullRequestsWithCommit(
ctx, g.options.Owner, g.options.Repo,
commit.Hash, &github.ListOptions{
Page: page,
PerPage: GitHubPerPageMax,
})
if err != nil {
return nil, err
}
associatedPRs = append(associatedPRs, prs...)
if page == resp.LastPage || resp.LastPage == 0 {
break
}
page = resp.NextPage
}
var pullrequest *github.PullRequest
for _, pr := range associatedPRs {
// We only look for the PR that has this commit set as the "merge commit" => The result of squashing this branch onto main
if pr.GetMergeCommitSHA() == commit.Hash {
pullrequest = pr
break
}
}
if pullrequest == nil {
log.Warn("did not find associated pull request, not considering it for changesets")
// No pull request was found for this commit, nothing to do here
// TODO: We could also return the minimal changeset for this commit, so at least it would come up in the changelog.
continue
}
log = log.With("pullrequest.id", pullrequest.GetID())
// TODO: Parse PR description for overrides
changelogEntries, err := NewConventionalCommitsParser().AnalyzeCommits([]Commit{commit})
if err != nil {
log.Warn("unable to parse changelog entries", "error", err)
continue
}
if len(changelogEntries) > 0 {
changesets = append(changesets, Changeset{
URL: pullrequest.GetHTMLURL(),
Identifier: fmt.Sprintf("#%d", pullrequest.GetNumber()),
ChangelogEntries: changelogEntries,
for {
log.Debug("fetching pull requests associated with commit", "page", page)
prs, resp, err := g.client.PullRequests.ListPullRequestsWithCommit(
ctx, g.options.Owner, g.options.Repo,
commit.Hash, &github.ListOptions{
Page: page,
PerPage: GitHubPerPageMax,
})
if err != nil {
return nil, err
}
associatedPRs = append(associatedPRs, prs...)
if page == resp.LastPage || resp.LastPage == 0 {
break
}
page = resp.NextPage
}
return changesets, nil
var pullrequest *github.PullRequest
for _, pr := range associatedPRs {
// We only look for the PR that has this commit set as the "merge commit" => The result of squashing this branch onto main
if pr.GetMergeCommitSHA() == commit.Hash {
pullrequest = pr
break
}
}
if pullrequest == nil {
return nil, nil
}
return gitHubPRToPullRequest(pullrequest), nil
}
func (g *GitHub) EnsureLabelsExist(ctx context.Context, labels []Label) error {
@ -578,6 +551,14 @@ func (g *GitHub) CreateRelease(ctx context.Context, commit Commit, title, change
return nil
}
func gitHubPRToPullRequest(pr *github.PullRequest) *PullRequest {
return &PullRequest{
ID: pr.GetNumber(),
Title: pr.GetTitle(),
Description: pr.GetBody(),
}
}
func gitHubPRToReleasePullRequest(pr *github.PullRequest) *ReleasePullRequest {
labels := make([]Label, 0, len(pr.Labels))
for _, label := range pr.Labels {