mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-01-10 03:47:03 +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
212 lines
5.3 KiB
Go
212 lines
5.3 KiB
Go
package release
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/caarlos0/log"
|
|
"github.com/goreleaser/goreleaser/internal/artifact"
|
|
"github.com/goreleaser/goreleaser/internal/client"
|
|
"github.com/goreleaser/goreleaser/internal/extrafiles"
|
|
"github.com/goreleaser/goreleaser/internal/git"
|
|
"github.com/goreleaser/goreleaser/internal/pipe"
|
|
"github.com/goreleaser/goreleaser/internal/semerrgroup"
|
|
"github.com/goreleaser/goreleaser/internal/tmpl"
|
|
"github.com/goreleaser/goreleaser/pkg/config"
|
|
"github.com/goreleaser/goreleaser/pkg/context"
|
|
)
|
|
|
|
// ErrMultipleReleases indicates that multiple releases are defined. ATM only one of them is allowed.
|
|
// See https://github.com/goreleaser/goreleaser/pull/809
|
|
var ErrMultipleReleases = errors.New("multiple releases are defined. Only one is allowed")
|
|
|
|
// Pipe for github release.
|
|
type Pipe struct{}
|
|
|
|
func (Pipe) String() string { return "scm releases" }
|
|
|
|
func (Pipe) Skip(ctx *context.Context) (bool, error) {
|
|
return tmpl.New(ctx).Bool(ctx.Config.Release.Disable)
|
|
}
|
|
|
|
// Default sets the pipe defaults.
|
|
func (p Pipe) Default(ctx *context.Context) error {
|
|
if b, _ := p.Skip(ctx); b {
|
|
return pipe.Skip("release is disabled")
|
|
}
|
|
numOfReleases := 0
|
|
if ctx.Config.Release.GitHub.String() != "" {
|
|
numOfReleases++
|
|
}
|
|
if ctx.Config.Release.GitLab.String() != "" {
|
|
numOfReleases++
|
|
}
|
|
if ctx.Config.Release.Gitea.String() != "" {
|
|
numOfReleases++
|
|
}
|
|
if numOfReleases > 1 {
|
|
return ErrMultipleReleases
|
|
}
|
|
|
|
if ctx.Config.Release.NameTemplate == "" {
|
|
ctx.Config.Release.NameTemplate = "{{.Tag}}"
|
|
}
|
|
|
|
switch ctx.TokenType {
|
|
case context.TokenTypeGitLab:
|
|
if err := setupGitLab(ctx); err != nil {
|
|
return err
|
|
}
|
|
case context.TokenTypeGitea:
|
|
if err := setupGitea(ctx); err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
// We keep github as default for now
|
|
if err := setupGitHub(ctx); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Check if we have to check the git tag for an indicator to mark as pre release
|
|
switch ctx.Config.Release.Prerelease {
|
|
case "auto":
|
|
if ctx.Semver.Prerelease != "" {
|
|
ctx.PreRelease = true
|
|
}
|
|
log.Debugf("pre-release was detected for tag %s: %v", ctx.Git.CurrentTag, ctx.PreRelease)
|
|
case "true":
|
|
ctx.PreRelease = true
|
|
}
|
|
log.Debugf("pre-release for tag %s set to %v", ctx.Git.CurrentTag, ctx.PreRelease)
|
|
|
|
return nil
|
|
}
|
|
|
|
func getRepository(ctx *context.Context) (config.Repo, error) {
|
|
repo, err := git.ExtractRepoFromConfig(ctx)
|
|
if err != nil {
|
|
return config.Repo{}, err
|
|
}
|
|
if err := repo.CheckSCM(); err != nil {
|
|
return config.Repo{}, err
|
|
}
|
|
return repo, nil
|
|
}
|
|
|
|
// Publish the release.
|
|
func (Pipe) Publish(ctx *context.Context) error {
|
|
c, err := client.New(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := doPublish(ctx, c); err != nil {
|
|
return err
|
|
}
|
|
log.WithField("url", ctx.ReleaseURL).Info("published")
|
|
return nil
|
|
}
|
|
|
|
func doPublish(ctx *context.Context, client client.Client) error {
|
|
log.WithField("tag", ctx.Git.CurrentTag).
|
|
WithField("repo", ctx.Config.Release.GitHub.String()).
|
|
Info("creating or updating release")
|
|
body, err := describeBody(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
releaseID, err := client.CreateRelease(ctx, body.String())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
skipUpload, err := tmpl.New(ctx).Bool(ctx.Config.Release.SkipUpload)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if skipUpload {
|
|
return pipe.Skip("release.skip_upload is set")
|
|
}
|
|
|
|
extraFiles, err := extrafiles.Find(ctx, ctx.Config.Release.ExtraFiles)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for name, path := range extraFiles {
|
|
if _, err := os.Stat(path); errors.Is(err, fs.ErrNotExist) {
|
|
return fmt.Errorf("failed to upload %s: %w", name, err)
|
|
}
|
|
ctx.Artifacts.Add(&artifact.Artifact{
|
|
Name: name,
|
|
Path: path,
|
|
Type: artifact.UploadableFile,
|
|
})
|
|
}
|
|
|
|
filters := artifact.Or(
|
|
artifact.ByType(artifact.UploadableArchive),
|
|
artifact.ByType(artifact.UploadableBinary),
|
|
artifact.ByType(artifact.UploadableSourceArchive),
|
|
artifact.ByType(artifact.Checksum),
|
|
artifact.ByType(artifact.Signature),
|
|
artifact.ByType(artifact.Certificate),
|
|
artifact.ByType(artifact.LinuxPackage),
|
|
artifact.ByType(artifact.SBOM),
|
|
)
|
|
|
|
if len(ctx.Config.Release.IDs) > 0 {
|
|
filters = artifact.And(filters, artifact.ByIDs(ctx.Config.Release.IDs...))
|
|
}
|
|
|
|
filters = artifact.Or(filters, artifact.ByType(artifact.UploadableFile))
|
|
|
|
g := semerrgroup.New(ctx.Parallelism)
|
|
for _, artifact := range ctx.Artifacts.Filter(filters).List() {
|
|
artifact := artifact
|
|
g.Go(func() error {
|
|
return upload(ctx, client, releaseID, artifact)
|
|
})
|
|
}
|
|
return g.Wait()
|
|
}
|
|
|
|
func upload(ctx *context.Context, cli client.Client, releaseID string, artifact *artifact.Artifact) error {
|
|
var try int
|
|
tryUpload := func() error {
|
|
try++
|
|
file, err := os.Open(artifact.Path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
log.WithField("file", file.Name()).WithField("name", artifact.Name).Info("uploading to release")
|
|
if err := cli.Upload(ctx, releaseID, artifact, file); err != nil {
|
|
log.WithField("try", try).
|
|
WithField("artifact", artifact.Name).
|
|
WithError(err).
|
|
Warnf("failed to upload artifact, will retry")
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var err error
|
|
for try < 10 {
|
|
err = tryUpload()
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if errors.As(err, &client.RetriableError{}) {
|
|
time.Sleep(time.Duration(try*50) * time.Millisecond)
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
|
|
return fmt.Errorf("failed to upload %s after %d tries: %w", artifact.Name, try, err)
|
|
}
|