mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-01-30 04:50:45 +02:00
feat: support github release notes (#2638)
* feat: support github release notes * chore: godoc * test: cover it with tests * chore: fmt * refactor: remove unused code
This commit is contained in:
parent
17a6bb8dfb
commit
8eae8b013a
@ -46,6 +46,12 @@ type Client interface {
|
||||
Changelog(ctx *context.Context, repo Repo, prev, current string) (string, error)
|
||||
}
|
||||
|
||||
// GitHubClient is the client with GitHub-only features.
|
||||
type GitHubClient interface {
|
||||
Client
|
||||
GenerateReleaseNotes(ctx *context.Context, repo Repo, prev, current string) (string, error)
|
||||
}
|
||||
|
||||
// New creates a new client depending on the token type.
|
||||
func New(ctx *context.Context) (Client, error) {
|
||||
return newWithToken(ctx, ctx.Token)
|
||||
|
@ -25,14 +25,8 @@ type githubClient struct {
|
||||
client *github.Client
|
||||
}
|
||||
|
||||
// NewUnauthenticatedGitHub returns a github client that is not authenticated.
|
||||
// Used in tests only.
|
||||
func NewUnauthenticatedGitHub() Client {
|
||||
return &githubClient{client: github.NewClient(nil)}
|
||||
}
|
||||
|
||||
// NewGitHub returns a github client implementation.
|
||||
func NewGitHub(ctx *context.Context, token string) (Client, error) {
|
||||
func NewGitHub(ctx *context.Context, token string) (GitHubClient, error) {
|
||||
ts := oauth2.StaticTokenSource(
|
||||
&oauth2.Token{AccessToken: token},
|
||||
)
|
||||
@ -58,6 +52,17 @@ func NewGitHub(ctx *context.Context, token string) (Client, error) {
|
||||
return &githubClient{client: client}, nil
|
||||
}
|
||||
|
||||
func (c *githubClient) GenerateReleaseNotes(ctx *context.Context, repo Repo, prev, current string) (string, error) {
|
||||
notes, _, err := c.client.Repositories.GenerateReleaseNotes(ctx, repo.Owner, repo.Name, &github.GenerateNotesOptions{
|
||||
TagName: current,
|
||||
PreviousTagName: github.String(prev),
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return notes.Body, err
|
||||
}
|
||||
|
||||
func (c *githubClient) Changelog(ctx *context.Context, repo Repo, prev, current string) (string, error) {
|
||||
var log []string
|
||||
|
||||
|
@ -16,17 +16,6 @@ import (
|
||||
)
|
||||
|
||||
func TestNewGitHubClient(t *testing.T) {
|
||||
t.Run("unauthenticated", func(t *testing.T) {
|
||||
ctx := context.New(config.Project{})
|
||||
repo := Repo{
|
||||
Owner: "goreleaser",
|
||||
Name: "goreleaser",
|
||||
}
|
||||
b, err := NewUnauthenticatedGitHub().GetDefaultBranch(ctx, repo)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "master", b)
|
||||
})
|
||||
|
||||
t.Run("good urls", func(t *testing.T) {
|
||||
githubURL := "https://github.mycompany.com"
|
||||
ctx := context.New(config.Project{
|
||||
@ -302,3 +291,35 @@ func TestChangelog(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "6dcb09b5b57875f334f61aebed695e2e4193db5e: Fix all the bugs (@octocat)", log)
|
||||
}
|
||||
|
||||
func TestReleaseNotes(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
|
||||
if r.URL.Path == "/repos/someone/something/releases/generate-notes" {
|
||||
r, err := os.Open("testdata/github/releasenotes.json")
|
||||
require.NoError(t, err)
|
||||
_, err = io.Copy(w, r)
|
||||
require.NoError(t, err)
|
||||
return
|
||||
}
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
ctx := context.New(config.Project{
|
||||
GitHubURLs: config.GitHubURLs{
|
||||
API: srv.URL + "/",
|
||||
},
|
||||
})
|
||||
client, err := NewGitHub(ctx, "test-token")
|
||||
require.NoError(t, err)
|
||||
repo := Repo{
|
||||
Owner: "someone",
|
||||
Name: "something",
|
||||
Branch: "somebranch",
|
||||
}
|
||||
|
||||
log, err := client.GenerateReleaseNotes(ctx, repo, "v1.0.0", "v1.1.0")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "**Full Changelog**: https://github.com/someone/something/compare/v1.0.0...v1.1.0", log)
|
||||
}
|
||||
|
@ -12,6 +12,11 @@ import (
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
)
|
||||
|
||||
var (
|
||||
_ Client = &Mock{}
|
||||
_ GitHubClient = &Mock{}
|
||||
)
|
||||
|
||||
func NewMock() *Mock {
|
||||
return &Mock{}
|
||||
}
|
||||
@ -30,9 +35,21 @@ type Mock struct {
|
||||
Lock sync.Mutex
|
||||
ClosedMilestone string
|
||||
FailToCloseMilestone bool
|
||||
Changes string
|
||||
ReleaseNotes string
|
||||
}
|
||||
|
||||
func (c *Mock) Changelog(ctx *context.Context, repo Repo, prev, current string) (string, error) {
|
||||
if c.Changes != "" {
|
||||
return c.Changes, nil
|
||||
}
|
||||
return "", ErrNotImplemented
|
||||
}
|
||||
|
||||
func (c *Mock) GenerateReleaseNotes(ctx *context.Context, repo Repo, prev, current string) (string, error) {
|
||||
if c.ReleaseNotes != "" {
|
||||
return c.ReleaseNotes, nil
|
||||
}
|
||||
return "", ErrNotImplemented
|
||||
}
|
||||
|
||||
|
1
internal/client/testdata/github/releasenotes.json
vendored
Normal file
1
internal/client/testdata/github/releasenotes.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"name":"v1.1.0","body":"**Full Changelog**: https://github.com/someone/something/compare/v1.0.0...v1.1.0"}
|
@ -191,11 +191,31 @@ func getChangeloger(ctx *context.Context) (changeloger, error) {
|
||||
fallthrough
|
||||
case "gitlab":
|
||||
return newSCMChangeloger(ctx)
|
||||
case "github-native":
|
||||
return newGithubChangeloger(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid changelog.use: %q", ctx.Config.Changelog.Use)
|
||||
}
|
||||
}
|
||||
|
||||
func newGithubChangeloger(ctx *context.Context) (changeloger, error) {
|
||||
cli, err := client.NewGitHub(ctx, ctx.Token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repo, err := git.ExtractRepoFromConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &githubNativeChangeloger{
|
||||
client: cli,
|
||||
repo: client.Repo{
|
||||
Owner: repo.Owner,
|
||||
Name: repo.Name,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newSCMChangeloger(ctx *context.Context) (changeloger, error) {
|
||||
cli, err := client.New(ctx)
|
||||
if err != nil {
|
||||
@ -270,3 +290,12 @@ type scmChangeloger struct {
|
||||
func (c *scmChangeloger) Log(ctx *context.Context, prev, current string) (string, error) {
|
||||
return c.client.Changelog(ctx, c.repo, prev, current)
|
||||
}
|
||||
|
||||
type githubNativeChangeloger struct {
|
||||
client client.GitHubClient
|
||||
repo client.Repo
|
||||
}
|
||||
|
||||
func (c *githubNativeChangeloger) Log(ctx *context.Context, prev, current string) (string, error) {
|
||||
return c.client.GenerateReleaseNotes(ctx, c.repo, prev, current)
|
||||
}
|
||||
|
@ -437,8 +437,11 @@ func TestGetChangelogGitHub(t *testing.T) {
|
||||
},
|
||||
})
|
||||
|
||||
expected := "c90f1085f255d0af0b055160bfff5ee40f47af79: fix: do not skip any defaults (#2521) (@caarlos0)"
|
||||
mock := client.NewMock()
|
||||
mock.Changes = expected
|
||||
l := scmChangeloger{
|
||||
client: client.NewUnauthenticatedGitHub(),
|
||||
client: mock,
|
||||
repo: client.Repo{
|
||||
Owner: "goreleaser",
|
||||
Name: "goreleaser",
|
||||
@ -446,7 +449,29 @@ func TestGetChangelogGitHub(t *testing.T) {
|
||||
}
|
||||
log, err := l.Log(ctx, "v0.180.1", "v0.180.2")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "c90f1085f255d0af0b055160bfff5ee40f47af79: fix: do not skip any defaults (#2521) (@caarlos0)", log)
|
||||
require.Equal(t, expected, log)
|
||||
}
|
||||
|
||||
func TestGetChangelogGitHubNative(t *testing.T) {
|
||||
ctx := context.New(config.Project{
|
||||
Changelog: config.Changelog{
|
||||
Use: "github-native",
|
||||
},
|
||||
})
|
||||
|
||||
expected := "**Full Changelog**: https://github.com/gorelease/goreleaser/compare/v0.180.1...v0.180.2"
|
||||
mock := client.NewMock()
|
||||
mock.ReleaseNotes = expected
|
||||
l := githubNativeChangeloger{
|
||||
client: mock,
|
||||
repo: client.Repo{
|
||||
Owner: "goreleaser",
|
||||
Name: "goreleaser",
|
||||
},
|
||||
}
|
||||
log, err := l.Log(ctx, "v0.180.1", "v0.180.2")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, log)
|
||||
}
|
||||
|
||||
func TestGetChangeloger(t *testing.T) {
|
||||
@ -478,6 +503,18 @@ func TestGetChangeloger(t *testing.T) {
|
||||
require.IsType(t, c, &scmChangeloger{})
|
||||
})
|
||||
|
||||
t.Run("github-native", func(t *testing.T) {
|
||||
ctx := context.New(config.Project{
|
||||
Changelog: config.Changelog{
|
||||
Use: "github-native",
|
||||
},
|
||||
})
|
||||
ctx.TokenType = context.TokenTypeGitHub
|
||||
c, err := getChangeloger(ctx)
|
||||
require.NoError(t, err)
|
||||
require.IsType(t, c, &githubNativeChangeloger{})
|
||||
})
|
||||
|
||||
t.Run("gitlab", func(t *testing.T) {
|
||||
ctx := context.New(config.Project{
|
||||
Changelog: config.Changelog{
|
||||
|
@ -15,6 +15,7 @@ changelog:
|
||||
# - `git`: uses `git log`;
|
||||
# - `github`: uses the compare GitHub API, appending the author login to the changelog.
|
||||
# - `gitlab`: uses the compare GitLab API, appending the author name and email to the changelog.
|
||||
# - `github-native`: uses the GitHub release notes generation API.
|
||||
#
|
||||
# Defaults to `git`.
|
||||
use: github
|
||||
|
Loading…
x
Reference in New Issue
Block a user