mirror of
https://github.com/apricote/releaser-pleaser.git
synced 2026-01-13 21:21:03 +00:00
feat: tag releases on merged prs
This commit is contained in:
parent
fe871a0213
commit
6120821631
5 changed files with 337 additions and 33 deletions
|
|
@ -40,9 +40,16 @@ func init() {
|
||||||
runCmd.PersistentFlags().StringVar(&flagRepo, "repo", "", "")
|
runCmd.PersistentFlags().StringVar(&flagRepo, "repo", "", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(cmd *cobra.Command, args []string) error {
|
func run(cmd *cobra.Command, _ []string) error {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
|
|
||||||
|
logger.DebugContext(ctx, "run called",
|
||||||
|
"forge", flagForge,
|
||||||
|
"branch", flagBranch,
|
||||||
|
"owner", flagOwner,
|
||||||
|
"repo", flagRepo,
|
||||||
|
)
|
||||||
|
|
||||||
var f rp.Forge
|
var f rp.Forge
|
||||||
|
|
||||||
forgeOptions := rp.ForgeOptions{
|
forgeOptions := rp.ForgeOptions{
|
||||||
|
|
@ -54,6 +61,7 @@ func run(cmd *cobra.Command, args []string) error {
|
||||||
//case "gitlab":
|
//case "gitlab":
|
||||||
//f = rp.NewGitLab(forgeOptions)
|
//f = rp.NewGitLab(forgeOptions)
|
||||||
case "github":
|
case "github":
|
||||||
|
logger.DebugContext(ctx, "using forge GitHub")
|
||||||
f = rp.NewGitHub(logger, &rp.GitHubOptions{
|
f = rp.NewGitHub(logger, &rp.GitHubOptions{
|
||||||
ForgeOptions: forgeOptions,
|
ForgeOptions: forgeOptions,
|
||||||
Owner: flagOwner,
|
Owner: flagOwner,
|
||||||
|
|
@ -61,6 +69,11 @@ func run(cmd *cobra.Command, args []string) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := createPendingReleases(ctx, f)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create pending releases: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
changesets, releases, err := getChangesetsFromForge(ctx, f)
|
changesets, releases, err := getChangesetsFromForge(ctx, f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get changesets: %w", err)
|
return fmt.Errorf("failed to get changesets: %w", err)
|
||||||
|
|
@ -74,6 +87,70 @@ func run(cmd *cobra.Command, args []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createPendingReleases(ctx context.Context, forge rp.Forge) error {
|
||||||
|
logger.InfoContext(ctx, "checking for pending releases")
|
||||||
|
prs, err := forge.PendingReleases(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(prs) == 0 {
|
||||||
|
logger.InfoContext(ctx, "No pending releases found")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.InfoContext(ctx, "Found pending releases", "length", len(prs))
|
||||||
|
|
||||||
|
for _, pr := range prs {
|
||||||
|
err = createPendingRelease(ctx, forge, pr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createPendingRelease(ctx context.Context, forge rp.Forge, pr *rp.ReleasePullRequest) error {
|
||||||
|
logger := logger.With("pr.id", pr.ID, "pr.title", pr.Title)
|
||||||
|
|
||||||
|
if pr.ReleaseCommit == nil {
|
||||||
|
return fmt.Errorf("pull request is missing the merge commit")
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Creating release", "commit.hash", pr.ReleaseCommit.Hash)
|
||||||
|
|
||||||
|
version, err := pr.Version()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
changelog, err := pr.ChangelogText()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: pre-release & latest
|
||||||
|
|
||||||
|
logger.DebugContext(ctx, "Creating release on forge")
|
||||||
|
err = forge.CreateRelease(ctx, *pr.ReleaseCommit, version, changelog, false, true)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create release on forge: %w", err)
|
||||||
|
}
|
||||||
|
logger.DebugContext(ctx, "created release", "release.title", version, "release.url", forge.ReleaseURL(version))
|
||||||
|
|
||||||
|
logger.DebugContext(ctx, "updating pr labels")
|
||||||
|
err = forge.SetPullRequestLabels(ctx, pr, []string{rp.LabelReleasePending}, []string{rp.LabelReleaseTagged})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger.DebugContext(ctx, "updated pr labels")
|
||||||
|
|
||||||
|
logger.InfoContext(ctx, "Created release", "release.title", version, "release.url", forge.ReleaseURL(version))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func getChangesetsFromForge(ctx context.Context, forge rp.Forge) ([]rp.Changeset, rp.Releases, error) {
|
func getChangesetsFromForge(ctx context.Context, forge rp.Forge) ([]rp.Changeset, rp.Releases, error) {
|
||||||
releases, err := forge.LatestTags(ctx)
|
releases, err := forge.LatestTags(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -123,6 +200,20 @@ func reconcileReleasePR(ctx context.Context, forge rp.Forge, changesets []rp.Cha
|
||||||
logger.InfoContext(ctx, "found existing release pull request", "pr.id", pr.ID, "pr.title", pr.Title)
|
logger.InfoContext(ctx, "found existing release pull request", "pr.id", pr.ID, "pr.title", pr.Title)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(changesets) == 0 {
|
||||||
|
if pr != nil {
|
||||||
|
logger.InfoContext(ctx, "closing existing pull requests, no changesets available", "pr.id", pr.ID, "pr.title", pr.Title)
|
||||||
|
err = forge.ClosePullRequest(ctx, pr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.InfoContext(ctx, "No changesets available for release")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var releaseOverrides rp.ReleaseOverrides
|
var releaseOverrides rp.ReleaseOverrides
|
||||||
if pr != nil {
|
if pr != nil {
|
||||||
releaseOverrides, err = pr.GetOverrides()
|
releaseOverrides, err = pr.GetOverrides()
|
||||||
|
|
|
||||||
184
forge.go
184
forge.go
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/blang/semver/v4"
|
"github.com/blang/semver/v4"
|
||||||
|
|
@ -15,10 +16,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
GitHubPerPageMax = 100
|
GitHubPerPageMax = 100
|
||||||
GitHubPRStateOpen = "open"
|
GitHubPRStateOpen = "open"
|
||||||
GitHubEnvAPIToken = "GITHUB_TOKEN"
|
GitHubPRStateClosed = "closed"
|
||||||
GitHubEnvUsername = "GITHUB_USER"
|
GitHubEnvAPIToken = "GITHUB_TOKEN"
|
||||||
|
GitHubEnvUsername = "GITHUB_USER"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Changeset struct {
|
type Changeset struct {
|
||||||
|
|
@ -51,6 +53,12 @@ type Forge interface {
|
||||||
|
|
||||||
CreatePullRequest(context.Context, *ReleasePullRequest) error
|
CreatePullRequest(context.Context, *ReleasePullRequest) error
|
||||||
UpdatePullRequest(context.Context, *ReleasePullRequest) error
|
UpdatePullRequest(context.Context, *ReleasePullRequest) error
|
||||||
|
SetPullRequestLabels(ctx context.Context, pr *ReleasePullRequest, remove, add []string) error
|
||||||
|
ClosePullRequest(context.Context, *ReleasePullRequest) error
|
||||||
|
|
||||||
|
PendingReleases(context.Context) ([]*ReleasePullRequest, error)
|
||||||
|
|
||||||
|
CreateRelease(ctx context.Context, commit Commit, title, changelog string, prelease, latest bool) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type ForgeOptions struct {
|
type ForgeOptions struct {
|
||||||
|
|
@ -334,18 +342,7 @@ func (g *GitHub) PullRequestForBranch(ctx context.Context, branch string) (*Rele
|
||||||
|
|
||||||
for _, pr := range prs {
|
for _, pr := range prs {
|
||||||
if pr.GetBase().GetRef() == g.options.BaseBranch && pr.GetHead().GetRef() == branch && pr.GetState() == GitHubPRStateOpen {
|
if pr.GetBase().GetRef() == g.options.BaseBranch && pr.GetHead().GetRef() == branch && pr.GetState() == GitHubPRStateOpen {
|
||||||
labels := make([]string, 0, len(pr.Labels))
|
return gitHubPRToReleasePullRequest(pr), nil
|
||||||
for _, label := range pr.Labels {
|
|
||||||
labels = append(labels, label.GetName())
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ReleasePullRequest{
|
|
||||||
ID: pr.GetNumber(),
|
|
||||||
Title: pr.GetTitle(),
|
|
||||||
Description: pr.GetBody(),
|
|
||||||
Labels: labels,
|
|
||||||
Head: pr.GetHead().GetRef(),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -359,7 +356,6 @@ func (g *GitHub) PullRequestForBranch(ctx context.Context, branch string) (*Rele
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GitHub) CreatePullRequest(ctx context.Context, pr *ReleasePullRequest) error {
|
func (g *GitHub) CreatePullRequest(ctx context.Context, pr *ReleasePullRequest) error {
|
||||||
// TODO: Labels
|
|
||||||
ghPR, _, err := g.client.PullRequests.Create(
|
ghPR, _, err := g.client.PullRequests.Create(
|
||||||
ctx, g.options.Owner, g.options.Repo,
|
ctx, g.options.Owner, g.options.Repo,
|
||||||
&github.NewPullRequest{
|
&github.NewPullRequest{
|
||||||
|
|
@ -373,24 +369,21 @@ func (g *GitHub) CreatePullRequest(ctx context.Context, pr *ReleasePullRequest)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, err = g.client.Issues.AddLabelsToIssue(
|
// TODO: String ID?
|
||||||
ctx, g.options.Owner, g.options.Repo,
|
pr.ID = ghPR.GetNumber()
|
||||||
ghPR.GetNumber(), pr.Labels,
|
|
||||||
)
|
err = g.SetPullRequestLabels(ctx, pr, []string{}, pr.Labels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: String ID?
|
|
||||||
pr.ID = ghPR.GetNumber()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GitHub) UpdatePullRequest(ctx context.Context, pr *ReleasePullRequest) error {
|
func (g *GitHub) UpdatePullRequest(ctx context.Context, pr *ReleasePullRequest) error {
|
||||||
_, _, err := g.client.PullRequests.Edit(
|
_, _, err := g.client.PullRequests.Edit(
|
||||||
ctx, g.options.Owner, g.options.Repo, pr.ID,
|
ctx, g.options.Owner, g.options.Repo,
|
||||||
&github.PullRequest{
|
pr.ID, &github.PullRequest{
|
||||||
Title: &pr.Title,
|
Title: &pr.Title,
|
||||||
Body: &pr.Description,
|
Body: &pr.Description,
|
||||||
},
|
},
|
||||||
|
|
@ -402,6 +395,141 @@ func (g *GitHub) UpdatePullRequest(ctx context.Context, pr *ReleasePullRequest)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *GitHub) SetPullRequestLabels(ctx context.Context, pr *ReleasePullRequest, remove, add []string) error {
|
||||||
|
for _, label := range remove {
|
||||||
|
_, err := g.client.Issues.RemoveLabelForIssue(
|
||||||
|
ctx, g.options.Owner, g.options.Repo,
|
||||||
|
pr.ID, label,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err := g.client.Issues.AddLabelsToIssue(
|
||||||
|
ctx, g.options.Owner, g.options.Repo,
|
||||||
|
pr.ID, add,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GitHub) ClosePullRequest(ctx context.Context, pr *ReleasePullRequest) error {
|
||||||
|
_, _, err := g.client.PullRequests.Edit(
|
||||||
|
ctx, g.options.Owner, g.options.Repo,
|
||||||
|
pr.ID, &github.PullRequest{
|
||||||
|
State: Pointer(GitHubPRStateClosed),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GitHub) PendingReleases(ctx context.Context) ([]*ReleasePullRequest, error) {
|
||||||
|
page := 1
|
||||||
|
|
||||||
|
var prs []*ReleasePullRequest
|
||||||
|
|
||||||
|
for {
|
||||||
|
ghPRs, resp, err := g.client.PullRequests.List(
|
||||||
|
ctx, g.options.Owner, g.options.Repo,
|
||||||
|
&github.PullRequestListOptions{
|
||||||
|
State: GitHubPRStateClosed,
|
||||||
|
Base: g.options.BaseBranch,
|
||||||
|
ListOptions: github.ListOptions{
|
||||||
|
Page: page,
|
||||||
|
PerPage: GitHubPerPageMax,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if prs == nil && resp.LastPage > 0 {
|
||||||
|
// Pre-initialize slice on first request
|
||||||
|
g.log.Debug("found pending releases", "pages", resp.LastPage)
|
||||||
|
prs = make([]*ReleasePullRequest, 0, (resp.LastPage-1)*GitHubPerPageMax)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pr := range ghPRs {
|
||||||
|
pending := slices.ContainsFunc(pr.Labels, func(l *github.Label) bool {
|
||||||
|
return l.GetName() == LabelReleasePending
|
||||||
|
})
|
||||||
|
if !pending {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// pr.Merged is always nil :(
|
||||||
|
if pr.MergedAt == nil {
|
||||||
|
// Closed and not merged
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
prs = append(prs, gitHubPRToReleasePullRequest(pr))
|
||||||
|
}
|
||||||
|
|
||||||
|
if page == resp.LastPage || resp.LastPage == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
page = resp.NextPage
|
||||||
|
}
|
||||||
|
|
||||||
|
return prs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GitHub) CreateRelease(ctx context.Context, commit Commit, title, changelog string, preRelease, latest bool) error {
|
||||||
|
makeLatest := ""
|
||||||
|
if latest {
|
||||||
|
makeLatest = "true"
|
||||||
|
} else {
|
||||||
|
makeLatest = "false"
|
||||||
|
}
|
||||||
|
_, _, err := g.client.Repositories.CreateRelease(
|
||||||
|
ctx, g.options.Owner, g.options.Repo,
|
||||||
|
&github.RepositoryRelease{
|
||||||
|
TagName: &title,
|
||||||
|
TargetCommitish: &commit.Hash,
|
||||||
|
Name: &title,
|
||||||
|
Body: &changelog,
|
||||||
|
Prerelease: &preRelease,
|
||||||
|
MakeLatest: &makeLatest,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func gitHubPRToReleasePullRequest(pr *github.PullRequest) *ReleasePullRequest {
|
||||||
|
labels := make([]string, 0, len(pr.Labels))
|
||||||
|
for _, label := range pr.Labels {
|
||||||
|
labels = append(labels, label.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
var releaseCommit *Commit
|
||||||
|
if pr.MergeCommitSHA != nil {
|
||||||
|
releaseCommit = &Commit{Hash: pr.GetMergeCommitSHA()}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ReleasePullRequest{
|
||||||
|
ID: pr.GetNumber(),
|
||||||
|
Title: pr.GetTitle(),
|
||||||
|
Description: pr.GetBody(),
|
||||||
|
Labels: labels,
|
||||||
|
|
||||||
|
Head: pr.GetHead().GetRef(),
|
||||||
|
ReleaseCommit: releaseCommit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (g *GitHubOptions) autodiscover() {
|
func (g *GitHubOptions) autodiscover() {
|
||||||
if apiToken := os.Getenv(GitHubEnvAPIToken); apiToken != "" {
|
if apiToken := os.Getenv(GitHubEnvAPIToken); apiToken != "" {
|
||||||
g.APIToken = apiToken
|
g.APIToken = apiToken
|
||||||
|
|
@ -462,3 +590,7 @@ func NewGitLab(options ForgeOptions) *GitLab {
|
||||||
func (g *GitLab) RepoURL() string {
|
func (g *GitLab) RepoURL() string {
|
||||||
return fmt.Sprintf("https://gitlab.com/%s", g.options.Repository)
|
return fmt.Sprintf("https://gitlab.com/%s", g.options.Repository)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Pointer[T any](value T) *T {
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
|
||||||
71
releasepr.go
71
releasepr.go
|
|
@ -5,6 +5,7 @@ import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"regexp"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/yuin/goldmark/ast"
|
"github.com/yuin/goldmark/ast"
|
||||||
|
|
@ -35,7 +36,8 @@ type ReleasePullRequest struct {
|
||||||
Description string
|
Description string
|
||||||
Labels []string
|
Labels []string
|
||||||
|
|
||||||
Head string
|
Head string
|
||||||
|
ReleaseCommit *Commit
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReleasePullRequest(head, branch, version, changelogEntry string) (*ReleasePullRequest, error) {
|
func NewReleasePullRequest(head, branch, version, changelogEntry string) (*ReleasePullRequest, error) {
|
||||||
|
|
@ -104,6 +106,15 @@ const (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MarkdownSectionOverrides = "overrides"
|
MarkdownSectionOverrides = "overrides"
|
||||||
|
MarkdownSectionChangelog = "changelog"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TitleFormat = "chore(%s): release %s"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
TitleRegex = regexp.MustCompile("chore(.*): release (.*)")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (pr *ReleasePullRequest) GetOverrides() (ReleaseOverrides, error) {
|
func (pr *ReleasePullRequest) GetOverrides() (ReleaseOverrides, error) {
|
||||||
|
|
@ -169,7 +180,7 @@ func (pr *ReleasePullRequest) parseDescription(overrides ReleaseOverrides) (Rele
|
||||||
return overrides, nil
|
return overrides, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pr *ReleasePullRequest) getCurrentOverridesText() (string, error) {
|
func (pr *ReleasePullRequest) overridesText() (string, error) {
|
||||||
source := []byte(pr.Description)
|
source := []byte(pr.Description)
|
||||||
gm := markdown.New()
|
gm := markdown.New()
|
||||||
descriptionAST := gm.Parser().Parse(text.NewReader(source))
|
descriptionAST := gm.Parser().Parse(text.NewReader(source))
|
||||||
|
|
@ -214,6 +225,51 @@ func (pr *ReleasePullRequest) getCurrentOverridesText() (string, error) {
|
||||||
return outputBuffer.String(), nil
|
return outputBuffer.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pr *ReleasePullRequest) ChangelogText() (string, error) {
|
||||||
|
source := []byte(pr.Description)
|
||||||
|
gm := markdown.New()
|
||||||
|
descriptionAST := gm.Parser().Parse(text.NewReader(source))
|
||||||
|
|
||||||
|
var section *east.Section
|
||||||
|
|
||||||
|
err := ast.Walk(descriptionAST, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||||
|
if !entering {
|
||||||
|
return ast.WalkContinue, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.Type() != ast.TypeBlock || n.Kind() != east.KindSection {
|
||||||
|
return ast.WalkContinue, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
anySection, ok := n.(*east.Section)
|
||||||
|
if !ok {
|
||||||
|
return ast.WalkStop, fmt.Errorf("node has unexpected type: %T", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if anySection.Name != MarkdownSectionChangelog {
|
||||||
|
return ast.WalkContinue, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
section = anySection
|
||||||
|
return ast.WalkStop, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if section == nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
outputBuffer := new(bytes.Buffer)
|
||||||
|
err = gm.Renderer().Render(outputBuffer, source, section)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputBuffer.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func textFromLines(source []byte, n ast.Node) string {
|
func textFromLines(source []byte, n ast.Node) string {
|
||||||
content := make([]byte, 0)
|
content := make([]byte, 0)
|
||||||
|
|
||||||
|
|
@ -230,8 +286,17 @@ func (pr *ReleasePullRequest) SetTitle(branch, version string) {
|
||||||
pr.Title = fmt.Sprintf("chore(%s): release %s", branch, version)
|
pr.Title = fmt.Sprintf("chore(%s): release %s", branch, version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pr *ReleasePullRequest) Version() (string, error) {
|
||||||
|
matches := TitleRegex.FindStringSubmatch(pr.Title)
|
||||||
|
if len(matches) != 3 {
|
||||||
|
return "", fmt.Errorf("title has unexpected format")
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches[2], nil
|
||||||
|
}
|
||||||
|
|
||||||
func (pr *ReleasePullRequest) SetDescription(changelogEntry string) error {
|
func (pr *ReleasePullRequest) SetDescription(changelogEntry string) error {
|
||||||
overrides, err := pr.getCurrentOverridesText()
|
overrides, err := pr.overridesText()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- section-start changelog -->
|
||||||
{{ .Changelog }}
|
{{ .Changelog }}
|
||||||
|
<!-- section-end changelog -->
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,11 @@ func TestReleasePullRequest_SetDescription(t *testing.T) {
|
||||||
name: "empty description",
|
name: "empty description",
|
||||||
pr: &ReleasePullRequest{},
|
pr: &ReleasePullRequest{},
|
||||||
changelogEntry: `## v1.0.0`,
|
changelogEntry: `## v1.0.0`,
|
||||||
want: `## v1.0.0
|
want: `---
|
||||||
|
|
||||||
|
<!-- section-start changelog -->
|
||||||
|
## v1.0.0
|
||||||
|
<!-- section-end changelog -->
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -87,11 +91,15 @@ func TestReleasePullRequest_SetDescription(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "existing overrides",
|
name: "existing overrides",
|
||||||
pr: &ReleasePullRequest{
|
pr: &ReleasePullRequest{
|
||||||
Description: `## v0.1.0
|
Description: `---
|
||||||
|
|
||||||
|
<!-- section-start changelog -->
|
||||||
|
## v0.1.0
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- bedazzle
|
- bedazzle
|
||||||
|
<!-- section-end changelog -->
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -117,7 +125,11 @@ This release is awesome!
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
changelogEntry: `## v1.0.0`,
|
changelogEntry: `## v1.0.0`,
|
||||||
want: `## v1.0.0
|
want: `---
|
||||||
|
|
||||||
|
<!-- section-start changelog -->
|
||||||
|
## v1.0.0
|
||||||
|
<!-- section-end changelog -->
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue