1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-01-24 04:16:27 +02:00
Manuel Vogel eb7ba2a294 feat: add gitlab for releases (#1038)
* outlines gitlab client integration

* makes client parameter more explicit

* adds gitlab url to config

* changes releaseID to string to adapt to gitlab

* updates to latest gitlab client lib 0.18

* fixes copy paster in gitlab upload func

* fixes gitlab typo in config

* adds gitlab token to env and context

* release now uses the client factory method

* skips brew pipe if it is not a github release

* add github tokentype to publish tests

* skips scoop pipe if it is not a github release

* corrects brew skip msg

* adds gitlab token to main test

* adds gitlab to release docs

* validates config and errors accordingly

* adapt release pipe name to include gitlab

* fixes gitlab client after testing

* moves not-configured brew and scoop pipe checks as first check

* adds more debug to gitlab client

* adapts changelog generation for gitlab markdown

* adds debug log for gitlab changelog

* env needs to run before changelog pipe

* moves gitlab default download url to default pipe

* moves multiple releases check to from config to release pipe

* release differs now for github and gitlab

* adds debug gitlab release update msgs

* moves env pipe as second after before because it determines the token type other pipes depend on

* adaptes error check on gitlab release creation

* Revert "adaptes error check on gitlab release creation"

This reverts commit 032024571c76140f8e2207ee01cc08088f37594b.

* simplifies gitlab client logic. removes comments

* skips tls verification for gitlab client if specified in config

* updates the docs

* adds clarification that brew and scoop are not supported if it is a gitlab release

* fixes copy paster in release.md

* adds missing blob pipe in defaults and publish due to missing in merge

* updates comment in gitlab client
2019-06-29 11:02:40 -03:00

175 lines
5.3 KiB
Go

// Package scoop provides a Pipe that generates a scoop.sh App Manifest and pushes it to a bucket
package scoop
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/client"
"github.com/goreleaser/goreleaser/internal/pipe"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pkg/context"
)
// ErrNoWindows when there is no build for windows (goos doesn't contain windows)
var ErrNoWindows = errors.New("scoop requires a windows build")
// Pipe for build
type Pipe struct{}
func (Pipe) String() string {
return "scoop manifest"
}
// Publish scoop manifest
func (Pipe) Publish(ctx *context.Context) error {
client, err := client.New(ctx)
if err != nil {
return err
}
return doRun(ctx, client)
}
// Default sets the pipe defaults
func (Pipe) Default(ctx *context.Context) error {
if ctx.Config.Scoop.Name == "" {
ctx.Config.Scoop.Name = ctx.Config.ProjectName
}
if ctx.Config.Scoop.CommitAuthor.Name == "" {
ctx.Config.Scoop.CommitAuthor.Name = "goreleaserbot"
}
if ctx.Config.Scoop.CommitAuthor.Email == "" {
ctx.Config.Scoop.CommitAuthor.Email = "goreleaser@carlosbecker.com"
}
if ctx.Config.Scoop.URLTemplate == "" {
ctx.Config.Scoop.URLTemplate = fmt.Sprintf(
"%s/%s/%s/releases/download/{{ .Tag }}/{{ .ArtifactName }}",
ctx.Config.GitHubURLs.Download,
ctx.Config.Release.GitHub.Owner,
ctx.Config.Release.GitHub.Name,
)
}
return nil
}
func doRun(ctx *context.Context, client client.Client) error {
if ctx.Config.Scoop.Bucket.Name == "" {
return pipe.Skip("scoop section is not configured")
}
// If we'd use 'ctx.TokenType != context.TokenTypeGitHub' we'd have to adapt all the tests
// For simplicity we use this check because the functionality will be implemented later for
// all types of releases. See https://github.com/goreleaser/goreleaser/pull/1038#issuecomment-498891464
if ctx.TokenType == context.TokenTypeGitLab {
return pipe.Skip("scoop pipe is only configured for github releases")
}
if ctx.Config.Archive.Format == "binary" {
return pipe.Skip("archive format is binary")
}
var archives = ctx.Artifacts.Filter(
artifact.And(
artifact.ByGoos("windows"),
artifact.ByType(artifact.UploadableArchive),
),
).List()
if len(archives) == 0 {
return ErrNoWindows
}
var path = ctx.Config.Scoop.Name + ".json"
content, err := buildManifest(ctx, archives)
if err != nil {
return err
}
if ctx.SkipPublish {
return pipe.ErrSkipPublishEnabled
}
if ctx.Config.Release.Draft {
return pipe.Skip("release is marked as draft")
}
return client.CreateFile(
ctx,
ctx.Config.Scoop.CommitAuthor,
ctx.Config.Scoop.Bucket,
content.Bytes(),
path,
fmt.Sprintf("Scoop update for %s version %s", ctx.Config.ProjectName, ctx.Git.CurrentTag),
)
}
// Manifest represents a scoop.sh App Manifest, more info:
// https://github.com/lukesampson/scoop/wiki/App-Manifests
type Manifest struct {
Version string `json:"version"` // The version of the app that this manifest installs.
Architecture map[string]Resource `json:"architecture"` // `architecture`: If the app has 32- and 64-bit versions, architecture can be used to wrap the differences.
Homepage string `json:"homepage,omitempty"` // `homepage`: The home page for the program.
License string `json:"license,omitempty"` // `license`: The software license for the program. For well-known licenses, this will be a string like "MIT" or "GPL2". For custom licenses, this should be the URL of the license.
Description string `json:"description,omitempty"` // Description of the app
Persist []string `json:"persist,omitempty"` // Persist data between updates
}
// Resource represents a combination of a url and a binary name for an architecture
type Resource struct {
URL string `json:"url"` // URL to the archive
Bin []string `json:"bin"` // name of binary inside the archive
Hash string `json:"hash"` // the archive checksum
}
func buildManifest(ctx *context.Context, artifacts []artifact.Artifact) (bytes.Buffer, error) {
var result bytes.Buffer
var manifest = Manifest{
Version: ctx.Version,
Architecture: map[string]Resource{},
Homepage: ctx.Config.Scoop.Homepage,
License: ctx.Config.Scoop.License,
Description: ctx.Config.Scoop.Description,
Persist: ctx.Config.Scoop.Persist,
}
for _, artifact := range artifacts {
var arch = "64bit"
if artifact.Goarch == "386" {
arch = "32bit"
}
url, err := tmpl.New(ctx).
WithArtifact(artifact, map[string]string{}).
Apply(ctx.Config.Scoop.URLTemplate)
if err != nil {
return result, err
}
sum, err := artifact.Checksum("sha256")
if err != nil {
return result, err
}
manifest.Architecture[arch] = Resource{
URL: url,
Bin: binaries(artifact),
Hash: sum,
}
}
data, err := json.MarshalIndent(manifest, "", " ")
if err != nil {
return result, err
}
_, err = result.Write(data)
return result, err
}
func binaries(a artifact.Artifact) []string {
// nolint: prealloc
var bins []string
for _, b := range a.ExtraOr("Builds", []artifact.Artifact{}).([]artifact.Artifact) {
bins = append(bins, b.ExtraOr("Binary", "").(string)+".exe")
}
return bins
}