You've already forked goreleaser
mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-07-17 01:42:37 +02:00
feat: upload to s3
This commit is contained in:
committed by
Carlos Alexandro Becker
parent
58d8ac62ac
commit
1c426847d9
@ -23,12 +23,12 @@ changelog:
|
|||||||
- '^test:'
|
- '^test:'
|
||||||
- Merge pull request
|
- Merge pull request
|
||||||
- Merge branch
|
- Merge branch
|
||||||
dockers:
|
# dockers:
|
||||||
- image: goreleaser/goreleaser
|
# - image: goreleaser/goreleaser
|
||||||
tag_templates:
|
# tag_templates:
|
||||||
- '{{ .Tag }}'
|
# - '{{ .Tag }}'
|
||||||
- 'v{{ .Major }}.{{ .Minor }}'
|
# - 'v{{ .Major }}.{{ .Minor }}'
|
||||||
- 'latest'
|
# - 'latest'
|
||||||
archive:
|
archive:
|
||||||
name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
|
name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
|
||||||
replacements:
|
replacements:
|
||||||
@ -79,3 +79,6 @@ snapcraft:
|
|||||||
wrapped in your favorite CI.
|
wrapped in your favorite CI.
|
||||||
grade: stable
|
grade: stable
|
||||||
confinement: classic
|
confinement: classic
|
||||||
|
s3:
|
||||||
|
- bucket: goreleaser
|
||||||
|
|
||||||
|
47
Gopkg.lock
generated
47
Gopkg.lock
generated
@ -31,6 +31,40 @@
|
|||||||
]
|
]
|
||||||
revision = "ff0f66940b829dc66c81dad34746d4349b83eb9e"
|
revision = "ff0f66940b829dc66c81dad34746d4349b83eb9e"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/aws/aws-sdk-go"
|
||||||
|
packages = [
|
||||||
|
"aws",
|
||||||
|
"aws/awserr",
|
||||||
|
"aws/awsutil",
|
||||||
|
"aws/client",
|
||||||
|
"aws/client/metadata",
|
||||||
|
"aws/corehandlers",
|
||||||
|
"aws/credentials",
|
||||||
|
"aws/credentials/ec2rolecreds",
|
||||||
|
"aws/credentials/endpointcreds",
|
||||||
|
"aws/credentials/stscreds",
|
||||||
|
"aws/defaults",
|
||||||
|
"aws/ec2metadata",
|
||||||
|
"aws/endpoints",
|
||||||
|
"aws/request",
|
||||||
|
"aws/session",
|
||||||
|
"aws/signer/v4",
|
||||||
|
"internal/sdkio",
|
||||||
|
"internal/sdkrand",
|
||||||
|
"internal/shareddefaults",
|
||||||
|
"private/protocol",
|
||||||
|
"private/protocol/query",
|
||||||
|
"private/protocol/query/queryutil",
|
||||||
|
"private/protocol/rest",
|
||||||
|
"private/protocol/restxml",
|
||||||
|
"private/protocol/xml/xmlutil",
|
||||||
|
"service/s3",
|
||||||
|
"service/sts"
|
||||||
|
]
|
||||||
|
revision = "31a85efbe3bc741eb539d6310c8e66030b7c5cb7"
|
||||||
|
version = "v1.13.47"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/blakesmith/ar"
|
name = "github.com/blakesmith/ar"
|
||||||
@ -61,6 +95,12 @@
|
|||||||
revision = "507f6050b8568533fb3f5504de8e5205fa62a114"
|
revision = "507f6050b8568533fb3f5504de8e5205fa62a114"
|
||||||
version = "v1.6.0"
|
version = "v1.6.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/go-ini/ini"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "6529cf7c58879c08d927016dde4477f18a0634cb"
|
||||||
|
version = "v1.36.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/golang/protobuf"
|
name = "github.com/golang/protobuf"
|
||||||
packages = ["proto"]
|
packages = ["proto"]
|
||||||
@ -106,6 +146,11 @@
|
|||||||
revision = "9d5f1277e9a8ed20c3684bda8fde67c05628518c"
|
revision = "9d5f1277e9a8ed20c3684bda8fde67c05628518c"
|
||||||
version = "v0.3.4"
|
version = "v0.3.4"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/jmespath/go-jmespath"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "0b12d6b5"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/masterminds/semver"
|
name = "github.com/masterminds/semver"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
@ -213,6 +258,6 @@
|
|||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "f59fe644e96665a3145d68ef6c134f664ef0b0b4f11c37dd6569cc66ffdee16b"
|
inputs-digest = "a47b30326926a615c574552d71af84d17e5198486ad61bed0d63672ebaba696d"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
@ -53,3 +53,7 @@
|
|||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/alecthomas/kingpin"
|
name = "github.com/alecthomas/kingpin"
|
||||||
version = "~2.2.6"
|
version = "~2.2.6"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/aws/aws-sdk-go"
|
||||||
|
version = "1.13.47"
|
||||||
|
@ -244,6 +244,13 @@ type Before struct {
|
|||||||
Hooks []string `yaml:",omitempty"`
|
Hooks []string `yaml:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// S3 contains s3 config
|
||||||
|
type S3 struct {
|
||||||
|
Region string
|
||||||
|
Bucket string
|
||||||
|
Folder string
|
||||||
|
}
|
||||||
|
|
||||||
// Project includes all project configuration
|
// Project includes all project configuration
|
||||||
type Project struct {
|
type Project struct {
|
||||||
ProjectName string `yaml:"project_name,omitempty"`
|
ProjectName string `yaml:"project_name,omitempty"`
|
||||||
@ -259,6 +266,7 @@ type Project struct {
|
|||||||
Checksum Checksum `yaml:",omitempty"`
|
Checksum Checksum `yaml:",omitempty"`
|
||||||
Dockers []Docker `yaml:",omitempty"`
|
Dockers []Docker `yaml:",omitempty"`
|
||||||
Artifactories []Artifactory `yaml:",omitempty"`
|
Artifactories []Artifactory `yaml:",omitempty"`
|
||||||
|
S3 []S3 `yaml:"s3,omitempty"`
|
||||||
Changelog Changelog `yaml:",omitempty"`
|
Changelog Changelog `yaml:",omitempty"`
|
||||||
Dist string `yaml:",omitempty"`
|
Dist string `yaml:",omitempty"`
|
||||||
Sign Sign `yaml:",omitempty"`
|
Sign Sign `yaml:",omitempty"`
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/google/go-github/github"
|
"github.com/google/go-github/github"
|
||||||
"github.com/goreleaser/goreleaser/config"
|
"github.com/goreleaser/goreleaser/config"
|
||||||
"github.com/goreleaser/goreleaser/context"
|
"github.com/goreleaser/goreleaser/context"
|
||||||
|
"github.com/goreleaser/goreleaser/internal/nametemplate"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ func (c *githubClient) CreateFile(
|
|||||||
|
|
||||||
func (c *githubClient) CreateRelease(ctx *context.Context, body string) (int64, error) {
|
func (c *githubClient) CreateRelease(ctx *context.Context, body string) (int64, error) {
|
||||||
var release *github.RepositoryRelease
|
var release *github.RepositoryRelease
|
||||||
title, err := releaseTitle(ctx)
|
title, err := nametemplate.Apply(ctx, "github", ctx.Config.Release.NameTemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package client
|
package nametemplate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -8,12 +8,12 @@ import (
|
|||||||
"github.com/goreleaser/goreleaser/context"
|
"github.com/goreleaser/goreleaser/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
func releaseTitle(ctx *context.Context) (string, error) {
|
func Apply(ctx *context.Context, name, tmpl string) (string, error) {
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
t, err := template.New("github").
|
t, err := template.New(name).
|
||||||
Option("missingkey=error").
|
Option("missingkey=error").
|
||||||
Funcs(mkFuncMap()).
|
Funcs(mkFuncMap()).
|
||||||
Parse(ctx.Config.Release.NameTemplate)
|
Parse(tmpl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package client
|
package nametemplate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@ -29,8 +29,7 @@ func TestFuncMap(t *testing.T) {
|
|||||||
Name: "MM/DD/YYYY",
|
Name: "MM/DD/YYYY",
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
ctx.Config.Release.NameTemplate = tc.Template
|
out, err := Apply(ctx, "foo", tc.Template)
|
||||||
out, err := releaseTitle(ctx)
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotEmpty(t, out)
|
assert.NotEmpty(t, out)
|
||||||
}
|
}
|
2
main.go
2
main.go
@ -31,6 +31,7 @@ import (
|
|||||||
"github.com/goreleaser/goreleaser/pipeline/git"
|
"github.com/goreleaser/goreleaser/pipeline/git"
|
||||||
"github.com/goreleaser/goreleaser/pipeline/nfpm"
|
"github.com/goreleaser/goreleaser/pipeline/nfpm"
|
||||||
"github.com/goreleaser/goreleaser/pipeline/release"
|
"github.com/goreleaser/goreleaser/pipeline/release"
|
||||||
|
"github.com/goreleaser/goreleaser/pipeline/s3"
|
||||||
"github.com/goreleaser/goreleaser/pipeline/scoop"
|
"github.com/goreleaser/goreleaser/pipeline/scoop"
|
||||||
"github.com/goreleaser/goreleaser/pipeline/sign"
|
"github.com/goreleaser/goreleaser/pipeline/sign"
|
||||||
"github.com/goreleaser/goreleaser/pipeline/snapcraft"
|
"github.com/goreleaser/goreleaser/pipeline/snapcraft"
|
||||||
@ -58,6 +59,7 @@ var pipes = []Piper{
|
|||||||
sign.Pipe{}, // sign artifacts
|
sign.Pipe{}, // sign artifacts
|
||||||
docker.Pipe{}, // create and push docker images
|
docker.Pipe{}, // create and push docker images
|
||||||
artifactory.Pipe{}, // push to artifactory
|
artifactory.Pipe{}, // push to artifactory
|
||||||
|
s3.Pipe{}, // push to s3/minio
|
||||||
release.Pipe{}, // release to github
|
release.Pipe{}, // release to github
|
||||||
brew.Pipe{}, // push to brew tap
|
brew.Pipe{}, // push to brew tap
|
||||||
scoop.Pipe{}, // push to scoop bucket
|
scoop.Pipe{}, // push to scoop bucket
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/goreleaser/goreleaser/pipeline/nfpm"
|
"github.com/goreleaser/goreleaser/pipeline/nfpm"
|
||||||
"github.com/goreleaser/goreleaser/pipeline/project"
|
"github.com/goreleaser/goreleaser/pipeline/project"
|
||||||
"github.com/goreleaser/goreleaser/pipeline/release"
|
"github.com/goreleaser/goreleaser/pipeline/release"
|
||||||
|
"github.com/goreleaser/goreleaser/pipeline/s3"
|
||||||
"github.com/goreleaser/goreleaser/pipeline/scoop"
|
"github.com/goreleaser/goreleaser/pipeline/scoop"
|
||||||
"github.com/goreleaser/goreleaser/pipeline/sign"
|
"github.com/goreleaser/goreleaser/pipeline/sign"
|
||||||
"github.com/goreleaser/goreleaser/pipeline/snapcraft"
|
"github.com/goreleaser/goreleaser/pipeline/snapcraft"
|
||||||
@ -54,6 +55,7 @@ var defaulters = []Defaulter{
|
|||||||
sign.Pipe{},
|
sign.Pipe{},
|
||||||
docker.Pipe{},
|
docker.Pipe{},
|
||||||
artifactory.Pipe{},
|
artifactory.Pipe{},
|
||||||
|
s3.Pipe{},
|
||||||
brew.Pipe{},
|
brew.Pipe{},
|
||||||
scoop.Pipe{},
|
scoop.Pipe{},
|
||||||
}
|
}
|
||||||
|
103
pipeline/s3/s3.go
Normal file
103
pipeline/s3/s3.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// Package s3 provides a Pipe that push artifacts to s3/minio
|
||||||
|
package s3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/apex/log"
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
|
"github.com/aws/aws-sdk-go/service/s3"
|
||||||
|
"github.com/goreleaser/goreleaser/config"
|
||||||
|
"github.com/goreleaser/goreleaser/context"
|
||||||
|
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||||
|
"github.com/goreleaser/goreleaser/internal/nametemplate"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pipe for Artifactory
|
||||||
|
type Pipe struct{}
|
||||||
|
|
||||||
|
// String returns the description of the pipe
|
||||||
|
func (Pipe) String() string {
|
||||||
|
return "releasing to s3"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default sets the pipe defaults
|
||||||
|
func (Pipe) Default(ctx *context.Context) error {
|
||||||
|
for i := range ctx.Config.S3 {
|
||||||
|
s3 := &ctx.Config.S3[i]
|
||||||
|
if s3.Folder == "" {
|
||||||
|
s3.Folder = "{{ .ProjectName }}/{{ .Tag }}"
|
||||||
|
}
|
||||||
|
if s3.Region == "" {
|
||||||
|
s3.Region = "us-east-1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the pipe
|
||||||
|
func (Pipe) Run(ctx *context.Context) error {
|
||||||
|
var g errgroup.Group
|
||||||
|
sem := make(chan bool, ctx.Parallelism)
|
||||||
|
for _, conf := range ctx.Config.S3 {
|
||||||
|
conf := conf
|
||||||
|
sem <- true
|
||||||
|
g.Go(func() error {
|
||||||
|
defer func() {
|
||||||
|
<-sem
|
||||||
|
}()
|
||||||
|
return upload(ctx, conf)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return g.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func upload(ctx *context.Context, conf config.S3) error {
|
||||||
|
sess := session.Must(session.NewSession())
|
||||||
|
svc := s3.New(sess, &aws.Config{
|
||||||
|
Region: aws.String(conf.Region),
|
||||||
|
})
|
||||||
|
folder, err := nametemplate.Apply(ctx, "s3", conf.Folder)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var g errgroup.Group
|
||||||
|
sem := make(chan bool, ctx.Parallelism)
|
||||||
|
for _, artifact := range ctx.Artifacts.Filter(
|
||||||
|
artifact.Or(
|
||||||
|
artifact.ByType(artifact.UploadableArchive),
|
||||||
|
artifact.ByType(artifact.UploadableBinary),
|
||||||
|
artifact.ByType(artifact.Checksum),
|
||||||
|
artifact.ByType(artifact.Signature),
|
||||||
|
artifact.ByType(artifact.LinuxPackage),
|
||||||
|
),
|
||||||
|
).List() {
|
||||||
|
sem <- true
|
||||||
|
artifact := artifact
|
||||||
|
g.Go(func() error {
|
||||||
|
defer func() {
|
||||||
|
<-sem
|
||||||
|
}()
|
||||||
|
f, err := os.Open(artifact.Path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"bucket": conf.Bucket,
|
||||||
|
"folder": folder,
|
||||||
|
"artifact": artifact.Name,
|
||||||
|
}).Info("uploading")
|
||||||
|
_, err = svc.PutObjectWithContext(ctx, &s3.PutObjectInput{
|
||||||
|
Bucket: aws.String(conf.Bucket),
|
||||||
|
Key: aws.String(filepath.Join(folder, artifact.Name)),
|
||||||
|
Body: f,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return g.Wait()
|
||||||
|
}
|
17
pipeline/s3/s3_test.go
Normal file
17
pipeline/s3/s3_test.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package s3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/goreleaser/goreleaser/config"
|
||||||
|
"github.com/goreleaser/goreleaser/context"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDescription(t *testing.T) {
|
||||||
|
assert.NotEmpty(t, Pipe{}.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNoS3(t *testing.T) {
|
||||||
|
assert.NoError(t, Pipe{}.Run(context.New(config.Project{})))
|
||||||
|
}
|
Reference in New Issue
Block a user