mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-01-24 04:16:27 +02:00
8706fd2e89
Currently, GoReleaser will assume you're running against github, gitea or gitlab. You could set `release.disable: true`, but it would still set and try to use some defaults that could break things up. Now, if you disable the release, goreleaser will not set these defaults. It'll also hard error in some cases in which it would happily produce invalid resources before, namely, if `release.disable` is set, and, for example, `brews.url_template` is empty (in which case it would try to use the one from the release, usually github). closes #4208
172 lines
4.8 KiB
Go
172 lines
4.8 KiB
Go
// Package client contains the client implementations for several providers.
|
|
package client
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/caarlos0/log"
|
|
"github.com/goreleaser/goreleaser/internal/artifact"
|
|
"github.com/goreleaser/goreleaser/internal/tmpl"
|
|
"github.com/goreleaser/goreleaser/pkg/config"
|
|
"github.com/goreleaser/goreleaser/pkg/context"
|
|
)
|
|
|
|
const (
|
|
// maxReleaseBodyLength defines the max characters size of the body
|
|
maxReleaseBodyLength = 125000
|
|
// ellipsis to be used when release notes body is too long
|
|
ellipsis = "..."
|
|
)
|
|
|
|
// ErrNotImplemented is returned when a client does not implement certain feature.
|
|
var ErrNotImplemented = fmt.Errorf("not implemented")
|
|
|
|
// ErrReleaseDisabled happens when a configuration tries to use the default
|
|
// url_template even though the release is disabled.
|
|
var ErrReleaseDisabled = fmt.Errorf("release is disabled, cannot use default url_template")
|
|
|
|
// Info of the repository.
|
|
type Info struct {
|
|
Description string
|
|
Homepage string
|
|
URL string
|
|
}
|
|
|
|
type Repo struct {
|
|
Owner string
|
|
Name string
|
|
Branch string
|
|
GitURL string
|
|
GitSSHCommand string
|
|
PrivateKey string
|
|
}
|
|
|
|
func (r Repo) String() string {
|
|
if r.Owner == "" && r.Name == "" {
|
|
return ""
|
|
}
|
|
return r.Owner + "/" + r.Name
|
|
}
|
|
|
|
// Client interface.
|
|
type Client interface {
|
|
CloseMilestone(ctx *context.Context, repo Repo, title string) (err error)
|
|
CreateRelease(ctx *context.Context, body string) (releaseID string, err error)
|
|
Upload(ctx *context.Context, releaseID string, artifact *artifact.Artifact, file *os.File) (err error)
|
|
Changelog(ctx *context.Context, repo Repo, prev, current string) (string, error)
|
|
ReleaseURLTemplater
|
|
FileCreator
|
|
}
|
|
|
|
// ReleaseURLTemplater provides the release URL as a template, containing the
|
|
// artifact name as well.
|
|
type ReleaseURLTemplater interface {
|
|
ReleaseURLTemplate(ctx *context.Context) (string, error)
|
|
}
|
|
|
|
// RepoFile is a file to be created.
|
|
type RepoFile struct {
|
|
Content []byte
|
|
Path string
|
|
Identifier string // for the use of the caller.
|
|
}
|
|
|
|
// FileCreator can create the given file to some code repository.
|
|
type FileCreator interface {
|
|
CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo Repo, content []byte, path, message string) (err error)
|
|
}
|
|
|
|
// FilesCreator can create the multiple files in some repository and in a single commit.
|
|
type FilesCreator interface {
|
|
FileCreator
|
|
CreateFiles(ctx *context.Context, commitAuthor config.CommitAuthor, repo Repo, message string, files []RepoFile) (err error)
|
|
}
|
|
|
|
// ReleaseNotesGenerator can generate release notes.
|
|
type ReleaseNotesGenerator interface {
|
|
GenerateReleaseNotes(ctx *context.Context, repo Repo, prev, current string) (string, error)
|
|
}
|
|
|
|
// PullRequestOpener can open pull requests.
|
|
type PullRequestOpener interface {
|
|
OpenPullRequest(ctx *context.Context, base, head Repo, title string, draft bool) error
|
|
}
|
|
|
|
// New creates a new client depending on the token type.
|
|
func New(ctx *context.Context) (Client, error) {
|
|
return newWithToken(ctx, ctx.Token)
|
|
}
|
|
|
|
// NewReleaseClient returns a ReleaserURLTemplater, handling the possibility of
|
|
// the release being disabled.
|
|
func NewReleaseClient(ctx *context.Context) (ReleaseURLTemplater, error) {
|
|
disable, err := tmpl.New(ctx).Bool(ctx.Config.Release.Disable)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if disable {
|
|
return errURLTemplater{}, nil
|
|
}
|
|
return New(ctx)
|
|
}
|
|
|
|
var _ ReleaseURLTemplater = errURLTemplater{}
|
|
|
|
type errURLTemplater struct{}
|
|
|
|
func (errURLTemplater) ReleaseURLTemplate(_ *context.Context) (string, error) {
|
|
return "", ErrReleaseDisabled
|
|
}
|
|
|
|
func newWithToken(ctx *context.Context, token string) (Client, error) {
|
|
log.WithField("type", ctx.TokenType).Debug("token type")
|
|
switch ctx.TokenType {
|
|
case context.TokenTypeGitHub:
|
|
return newGitHub(ctx, token)
|
|
case context.TokenTypeGitLab:
|
|
return newGitLab(ctx, token)
|
|
case context.TokenTypeGitea:
|
|
return newGitea(ctx, token)
|
|
default:
|
|
return nil, fmt.Errorf("invalid client token type: %q", ctx.TokenType)
|
|
}
|
|
}
|
|
|
|
func NewIfToken(ctx *context.Context, cli Client, token string) (Client, error) {
|
|
if token == "" {
|
|
return cli, nil
|
|
}
|
|
token, err := tmpl.New(ctx).ApplySingleEnvOnly(token)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
log.Debug("using custom token")
|
|
return newWithToken(ctx, token)
|
|
}
|
|
|
|
func truncateReleaseBody(body string) string {
|
|
if len(body) > maxReleaseBodyLength {
|
|
body = body[1:(maxReleaseBodyLength-len(ellipsis))] + ellipsis
|
|
}
|
|
return body
|
|
}
|
|
|
|
// ErrNoMilestoneFound is an error when no milestone is found.
|
|
type ErrNoMilestoneFound struct {
|
|
Title string
|
|
}
|
|
|
|
func (e ErrNoMilestoneFound) Error() string {
|
|
return fmt.Sprintf("no milestone found: %s", e.Title)
|
|
}
|
|
|
|
// RetriableError is an error that will cause the action to be retried.
|
|
type RetriableError struct {
|
|
Err error
|
|
}
|
|
|
|
func (e RetriableError) Error() string {
|
|
return e.Err.Error()
|
|
}
|