mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-01-16 03:52:12 +02:00
feat: http POST (#1246)
* feat: http POST Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com> * feat: http POST Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com> * fix: deprecate Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com> * fix: upload tests Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com> * fix: artifactory Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com> * fix: http username validation Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com> * fix: renames Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>
This commit is contained in:
parent
173edbac54
commit
b0481a14e0
1
go.sum
1
go.sum
@ -168,6 +168,7 @@ github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUr
|
||||
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
|
||||
github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
|
@ -68,47 +68,74 @@ func assetOpenDefault(kind string, a *artifact.Artifact) (*asset, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Defaults sets default configuration options on Put structs
|
||||
func Defaults(puts []config.Put) error {
|
||||
for i := range puts {
|
||||
defaults(&puts[i])
|
||||
// Defaults sets default configuration options on upload structs
|
||||
func Defaults(uploads []config.Upload) error {
|
||||
for i := range uploads {
|
||||
defaults(&uploads[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func defaults(put *config.Put) {
|
||||
if put.Mode == "" {
|
||||
put.Mode = ModeArchive
|
||||
func defaults(upload *config.Upload) {
|
||||
if upload.Mode == "" {
|
||||
upload.Mode = ModeArchive
|
||||
}
|
||||
if upload.Method == "" {
|
||||
upload.Method = h.MethodPut
|
||||
}
|
||||
}
|
||||
|
||||
// CheckConfig validates a Put configuration returning a descriptive error when appropriate
|
||||
func CheckConfig(ctx *context.Context, put *config.Put, kind string) error {
|
||||
if put.Target == "" {
|
||||
return misconfigured(kind, put, "missing target")
|
||||
// CheckConfig validates an upload configuration returning a descriptive error when appropriate
|
||||
func CheckConfig(ctx *context.Context, upload *config.Upload, kind string) error {
|
||||
if upload.Target == "" {
|
||||
return misconfigured(kind, upload, "missing target")
|
||||
}
|
||||
|
||||
if put.Name == "" {
|
||||
return misconfigured(kind, put, "missing name")
|
||||
if upload.Name == "" {
|
||||
return misconfigured(kind, upload, "missing name")
|
||||
}
|
||||
|
||||
if put.Mode != ModeArchive && put.Mode != ModeBinary {
|
||||
return misconfigured(kind, put, "mode must be 'binary' or 'archive'")
|
||||
if upload.Mode != ModeArchive && upload.Mode != ModeBinary {
|
||||
return misconfigured(kind, upload, "mode must be 'binary' or 'archive'")
|
||||
}
|
||||
|
||||
envName := fmt.Sprintf("%s_%s_SECRET", strings.ToUpper(kind), strings.ToUpper(put.Name))
|
||||
if _, ok := ctx.Env[envName]; !ok {
|
||||
return misconfigured(kind, put, fmt.Sprintf("missing %s environment variable", envName))
|
||||
if _, err := getUsername(ctx, upload, kind); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if put.TrustedCerts != "" && !x509.NewCertPool().AppendCertsFromPEM([]byte(put.TrustedCerts)) {
|
||||
return misconfigured(kind, put, "no certificate could be added from the specified trusted_certificates configuration")
|
||||
if _, err := getPassword(ctx, upload, kind); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if upload.TrustedCerts != "" && !x509.NewCertPool().AppendCertsFromPEM([]byte(upload.TrustedCerts)) {
|
||||
return misconfigured(kind, upload, "no certificate could be added from the specified trusted_certificates configuration")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func misconfigured(kind string, upload *config.Put, reason string) error {
|
||||
func getUsername(ctx *context.Context, upload *config.Upload, kind string) (string, error) {
|
||||
if upload.Username != "" {
|
||||
return upload.Username, nil
|
||||
}
|
||||
var key = fmt.Sprintf("%s_%s_USERNAME", strings.ToUpper(kind), strings.ToUpper(upload.Name))
|
||||
user, ok := ctx.Env[key]
|
||||
if !ok {
|
||||
return "", misconfigured(kind, upload, fmt.Sprintf("missing username or %s environment variable", key))
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func getPassword(ctx *context.Context, upload *config.Upload, kind string) (string, error) {
|
||||
var key = fmt.Sprintf("%s_%s_SECRET", strings.ToUpper(kind), strings.ToUpper(upload.Name))
|
||||
pwd, ok := ctx.Env[key]
|
||||
if !ok {
|
||||
return "", misconfigured(kind, upload, fmt.Sprintf("missing %s environment variable", key))
|
||||
}
|
||||
return pwd, nil
|
||||
}
|
||||
|
||||
func misconfigured(kind string, upload *config.Upload, reason string) error {
|
||||
return pipe.Skip(fmt.Sprintf("%s section '%s' is not configured properly (%s)", kind, upload.Name, reason))
|
||||
}
|
||||
|
||||
@ -117,25 +144,25 @@ func misconfigured(kind string, upload *config.Put, reason string) error {
|
||||
type ResponseChecker func(*h.Response) error
|
||||
|
||||
// Upload does the actual uploading work
|
||||
func Upload(ctx *context.Context, puts []config.Put, kind string, check ResponseChecker) error {
|
||||
func Upload(ctx *context.Context, uploads []config.Upload, kind string, check ResponseChecker) error {
|
||||
if ctx.SkipPublish {
|
||||
return pipe.ErrSkipPublishEnabled
|
||||
}
|
||||
|
||||
// Handle every configured put
|
||||
for _, put := range puts {
|
||||
put := put
|
||||
// Handle every configured upload
|
||||
for _, upload := range uploads {
|
||||
upload := upload
|
||||
filters := []artifact.Filter{}
|
||||
if put.Checksum {
|
||||
if upload.Checksum {
|
||||
filters = append(filters, artifact.ByType(artifact.Checksum))
|
||||
}
|
||||
if put.Signature {
|
||||
if upload.Signature {
|
||||
filters = append(filters, artifact.ByType(artifact.Signature))
|
||||
}
|
||||
// We support two different modes
|
||||
// - "archive": Upload all artifacts
|
||||
// - "binary": Upload only the raw binaries
|
||||
switch v := strings.ToLower(put.Mode); v {
|
||||
switch v := strings.ToLower(upload.Mode); v {
|
||||
case ModeArchive:
|
||||
filters = append(filters,
|
||||
artifact.ByType(artifact.UploadableArchive),
|
||||
@ -146,17 +173,17 @@ func Upload(ctx *context.Context, puts []config.Put, kind string, check Response
|
||||
default:
|
||||
err := fmt.Errorf("%s: mode \"%s\" not supported", kind, v)
|
||||
log.WithFields(log.Fields{
|
||||
kind: put.Name,
|
||||
kind: upload.Name,
|
||||
"mode": v,
|
||||
}).Error(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
var filter = artifact.Or(filters...)
|
||||
if len(put.IDs) > 0 {
|
||||
filter = artifact.And(filter, artifact.ByIDs(put.IDs...))
|
||||
if len(upload.IDs) > 0 {
|
||||
filter = artifact.And(filter, artifact.ByIDs(upload.IDs...))
|
||||
}
|
||||
if err := uploadWithFilter(ctx, &put, filter, kind, check); err != nil {
|
||||
if err := uploadWithFilter(ctx, &upload, filter, kind, check); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -164,34 +191,36 @@ func Upload(ctx *context.Context, puts []config.Put, kind string, check Response
|
||||
return nil
|
||||
}
|
||||
|
||||
func uploadWithFilter(ctx *context.Context, put *config.Put, filter artifact.Filter, kind string, check ResponseChecker) error {
|
||||
func uploadWithFilter(ctx *context.Context, upload *config.Upload, filter artifact.Filter, kind string, check ResponseChecker) error {
|
||||
var artifacts = ctx.Artifacts.Filter(filter).List()
|
||||
log.Debugf("will upload %d artifacts", len(artifacts))
|
||||
var g = semerrgroup.New(ctx.Parallelism)
|
||||
for _, artifact := range artifacts {
|
||||
artifact := artifact
|
||||
g.Go(func() error {
|
||||
return uploadAsset(ctx, put, artifact, kind, check)
|
||||
return uploadAsset(ctx, upload, artifact, kind, check)
|
||||
})
|
||||
}
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
// uploadAsset uploads file to target and logs all actions
|
||||
func uploadAsset(ctx *context.Context, put *config.Put, artifact *artifact.Artifact, kind string, check ResponseChecker) error {
|
||||
envBase := fmt.Sprintf("%s_%s_", strings.ToUpper(kind), strings.ToUpper(put.Name))
|
||||
username := put.Username
|
||||
if username == "" {
|
||||
// username not configured: using env
|
||||
username = ctx.Env[envBase+"USERNAME"]
|
||||
func uploadAsset(ctx *context.Context, upload *config.Upload, artifact *artifact.Artifact, kind string, check ResponseChecker) error {
|
||||
username, err := getUsername(ctx, upload, kind)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secret, err := getPassword(ctx, upload, kind)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secret := ctx.Env[envBase+"SECRET"]
|
||||
|
||||
// Generate the target url
|
||||
targetURL, err := resolveTargetTemplate(ctx, put, artifact)
|
||||
targetURL, err := resolveTargetTemplate(ctx, upload, artifact)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("%s: error while building the target url", kind)
|
||||
log.WithField("instance", put.Name).WithError(err).Error(msg)
|
||||
log.WithField("instance", upload.Name).WithError(err).Error(msg)
|
||||
return errors.Wrap(err, msg)
|
||||
}
|
||||
|
||||
@ -209,19 +238,19 @@ func uploadAsset(ctx *context.Context, put *config.Put, artifact *artifact.Artif
|
||||
targetURL += artifact.Name
|
||||
|
||||
var headers = map[string]string{}
|
||||
if put.ChecksumHeader != "" {
|
||||
if upload.ChecksumHeader != "" {
|
||||
sum, err := artifact.Checksum("sha256")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headers[put.ChecksumHeader] = sum
|
||||
headers[upload.ChecksumHeader] = sum
|
||||
}
|
||||
|
||||
res, err := uploadAssetToServer(ctx, put, targetURL, username, secret, headers, asset, check)
|
||||
res, err := uploadAssetToServer(ctx, upload, targetURL, username, secret, headers, asset, check)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("%s: upload failed", kind)
|
||||
log.WithError(err).WithFields(log.Fields{
|
||||
"instance": put.Name,
|
||||
"instance": upload.Name,
|
||||
"username": username,
|
||||
}).Error(msg)
|
||||
return errors.Wrap(err, msg)
|
||||
@ -231,26 +260,26 @@ func uploadAsset(ctx *context.Context, put *config.Put, artifact *artifact.Artif
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"instance": put.Name,
|
||||
"mode": put.Mode,
|
||||
"instance": upload.Name,
|
||||
"mode": upload.Mode,
|
||||
}).Info("uploaded successful")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// uploadAssetToServer uploads the asset file to target
|
||||
func uploadAssetToServer(ctx *context.Context, put *config.Put, target, username, secret string, headers map[string]string, a *asset, check ResponseChecker) (*h.Response, error) {
|
||||
req, err := newUploadRequest(target, username, secret, headers, a)
|
||||
func uploadAssetToServer(ctx *context.Context, upload *config.Upload, target, username, secret string, headers map[string]string, a *asset, check ResponseChecker) (*h.Response, error) {
|
||||
req, err := newUploadRequest(upload.Method, target, username, secret, headers, a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return executeHTTPRequest(ctx, put, req, check)
|
||||
return executeHTTPRequest(ctx, upload, req, check)
|
||||
}
|
||||
|
||||
// newUploadRequest creates a new h.Request for uploading
|
||||
func newUploadRequest(target, username, secret string, headers map[string]string, a *asset) (*h.Request, error) {
|
||||
req, err := h.NewRequest(h.MethodPut, target, a.ReadCloser)
|
||||
func newUploadRequest(method, target, username, secret string, headers map[string]string, a *asset) (*h.Request, error) {
|
||||
req, err := h.NewRequest(method, target, a.ReadCloser)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -264,8 +293,8 @@ func newUploadRequest(target, username, secret string, headers map[string]string
|
||||
return req, err
|
||||
}
|
||||
|
||||
func getHTTPClient(put *config.Put) (*h.Client, error) {
|
||||
if put.TrustedCerts == "" {
|
||||
func getHTTPClient(upload *config.Upload) (*h.Client, error) {
|
||||
if upload.TrustedCerts == "" {
|
||||
return h.DefaultClient, nil
|
||||
}
|
||||
pool, err := x509.SystemCertPool()
|
||||
@ -277,7 +306,7 @@ func getHTTPClient(put *config.Put) (*h.Client, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
pool.AppendCertsFromPEM([]byte(put.TrustedCerts)) // already validated certs checked by CheckConfig
|
||||
pool.AppendCertsFromPEM([]byte(upload.TrustedCerts)) // already validated certs checked by CheckConfig
|
||||
return &h.Client{
|
||||
Transport: &h.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
@ -288,8 +317,8 @@ func getHTTPClient(put *config.Put) (*h.Client, error) {
|
||||
}
|
||||
|
||||
// executeHTTPRequest processes the http call with respect of context ctx
|
||||
func executeHTTPRequest(ctx *context.Context, put *config.Put, req *h.Request, check ResponseChecker) (*h.Response, error) {
|
||||
client, err := getHTTPClient(put)
|
||||
func executeHTTPRequest(ctx *context.Context, upload *config.Upload, req *h.Request, check ResponseChecker) (*h.Response, error) {
|
||||
client, err := getHTTPClient(upload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -334,14 +363,14 @@ type targetData struct {
|
||||
// resolveTargetTemplate returns the resolved target template with replaced variables
|
||||
// Those variables can be replaced by the given context, goos, goarch, goarm and more
|
||||
// TODO: replace this with our internal template pkg
|
||||
func resolveTargetTemplate(ctx *context.Context, put *config.Put, artifact *artifact.Artifact) (string, error) {
|
||||
func resolveTargetTemplate(ctx *context.Context, upload *config.Upload, artifact *artifact.Artifact) (string, error) {
|
||||
data := targetData{
|
||||
Version: ctx.Version,
|
||||
Tag: ctx.Git.CurrentTag,
|
||||
ProjectName: ctx.Config.ProjectName,
|
||||
}
|
||||
|
||||
if put.Mode == ModeBinary {
|
||||
if upload.Mode == ModeBinary {
|
||||
// TODO: multiple archives here
|
||||
data.Os = replace(ctx.Config.Archive.Replacements, artifact.Goos)
|
||||
data.Arch = replace(ctx.Config.Archive.Replacements, artifact.Goarch)
|
||||
@ -349,7 +378,7 @@ func resolveTargetTemplate(ctx *context.Context, put *config.Put, artifact *arti
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
t, err := template.New(ctx.Config.ProjectName).Parse(put.Target)
|
||||
t, err := template.New(ctx.Config.ProjectName).Parse(upload.Target)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func TestAssetOpenDefault(t *testing.T) {
|
||||
|
||||
func TestDefaults(t *testing.T) {
|
||||
type args struct {
|
||||
puts []config.Put
|
||||
uploads []config.Upload
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -66,16 +66,16 @@ func TestDefaults(t *testing.T) {
|
||||
wantErr bool
|
||||
wantMode string
|
||||
}{
|
||||
{"set default", args{[]config.Put{{Name: "a", Target: "http://"}}}, false, ModeArchive},
|
||||
{"keep value", args{[]config.Put{{Name: "a", Target: "http://...", Mode: ModeBinary}}}, false, ModeBinary},
|
||||
{"set default", args{[]config.Upload{{Name: "a", Target: "http://"}}}, false, ModeArchive},
|
||||
{"keep value", args{[]config.Upload{{Name: "a", Target: "http://...", Mode: ModeBinary}}}, false, ModeBinary},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := Defaults(tt.args.puts); (err != nil) != tt.wantErr {
|
||||
if err := Defaults(tt.args.uploads); (err != nil) != tt.wantErr {
|
||||
t.Errorf("Defaults() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
if tt.wantMode != tt.args.puts[0].Mode {
|
||||
t.Errorf("Incorrect Defaults() mode %q , wanted %q", tt.args.puts[0].Mode, tt.wantMode)
|
||||
if tt.wantMode != tt.args.uploads[0].Mode {
|
||||
t.Errorf("Incorrect Defaults() mode %q , wanted %q", tt.args.uploads[0].Mode, tt.wantMode)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -86,7 +86,7 @@ func TestCheckConfig(t *testing.T) {
|
||||
ctx.Env["TEST_A_SECRET"] = "x"
|
||||
type args struct {
|
||||
ctx *context.Context
|
||||
upload *config.Put
|
||||
upload *config.Upload
|
||||
kind string
|
||||
}
|
||||
tests := []struct {
|
||||
@ -94,13 +94,13 @@ func TestCheckConfig(t *testing.T) {
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", args{ctx, &config.Put{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, false},
|
||||
{"secret missing", args{ctx, &config.Put{Name: "b", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true},
|
||||
{"target missing", args{ctx, &config.Put{Name: "a", Username: "pepe", Mode: ModeArchive}, "test"}, true},
|
||||
{"name missing", args{ctx, &config.Put{Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true},
|
||||
{"mode missing", args{ctx, &config.Put{Name: "a", Target: "http://blabla", Username: "pepe"}, "test"}, true},
|
||||
{"mode invalid", args{ctx, &config.Put{Name: "a", Target: "http://blabla", Username: "pepe", Mode: "blabla"}, "test"}, true},
|
||||
{"cert invalid", args{ctx, &config.Put{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeBinary, TrustedCerts: "bad cert!"}, "test"}, true},
|
||||
{"ok", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, false},
|
||||
{"secret missing", args{ctx, &config.Upload{Name: "b", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true},
|
||||
{"target missing", args{ctx, &config.Upload{Name: "a", Username: "pepe", Mode: ModeArchive}, "test"}, true},
|
||||
{"name missing", args{ctx, &config.Upload{Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true},
|
||||
{"mode missing", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe"}, "test"}, true},
|
||||
{"mode invalid", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: "blabla"}, "test"}, true},
|
||||
{"cert invalid", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeBinary, TrustedCerts: "bad cert!"}, "test"}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@ -242,12 +242,12 @@ func TestUpload(t *testing.T) {
|
||||
tryTLS bool
|
||||
wantErrPlain bool
|
||||
wantErrTLS bool
|
||||
setup func(*httptest.Server) (*context.Context, config.Put)
|
||||
setup func(*httptest.Server) (*context.Context, config.Upload)
|
||||
check func(r []*h.Request) error
|
||||
}{
|
||||
{"wrong-mode", true, true, true, true,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Mode: "wrong-mode",
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
@ -258,8 +258,8 @@ func TestUpload(t *testing.T) {
|
||||
checks(),
|
||||
},
|
||||
{"username-from-env", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Mode: ModeArchive,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
@ -271,9 +271,25 @@ func TestUpload(t *testing.T) {
|
||||
check{"/blah/2.1.0/a.tar", "u2", "x", content, map[string]string{}},
|
||||
),
|
||||
},
|
||||
{"post", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Method: h.MethodPost,
|
||||
Mode: ModeArchive,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
Username: "u1",
|
||||
TrustedCerts: cert(s),
|
||||
}
|
||||
},
|
||||
checks(
|
||||
check{"/blah/2.1.0/a.deb", "u1", "x", content, map[string]string{}},
|
||||
check{"/blah/2.1.0/a.tar", "u1", "x", content, map[string]string{}},
|
||||
),
|
||||
},
|
||||
{"archive", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Mode: ModeArchive,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
@ -287,8 +303,8 @@ func TestUpload(t *testing.T) {
|
||||
),
|
||||
},
|
||||
{"archive_with_ids", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Mode: ModeArchive,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
@ -303,8 +319,8 @@ func TestUpload(t *testing.T) {
|
||||
),
|
||||
},
|
||||
{"binary", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Mode: ModeBinary,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
@ -315,8 +331,8 @@ func TestUpload(t *testing.T) {
|
||||
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{}}),
|
||||
},
|
||||
{"binary_with_ids", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Mode: ModeBinary,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
@ -328,8 +344,8 @@ func TestUpload(t *testing.T) {
|
||||
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{}}),
|
||||
},
|
||||
{"binary-add-ending-bar", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Mode: ModeBinary,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}",
|
||||
@ -340,8 +356,8 @@ func TestUpload(t *testing.T) {
|
||||
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{}}),
|
||||
},
|
||||
{"archive-with-checksum-and-signature", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Mode: ModeArchive,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
@ -359,8 +375,8 @@ func TestUpload(t *testing.T) {
|
||||
),
|
||||
},
|
||||
{"bad-template", true, true, true, true,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Mode: ModeBinary,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectNameXXX}}/{{.VersionXXX}}/",
|
||||
@ -373,8 +389,8 @@ func TestUpload(t *testing.T) {
|
||||
checks(),
|
||||
},
|
||||
{"failed-request", true, true, true, true,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Mode: ModeBinary,
|
||||
Name: "a",
|
||||
Target: s.URL[0:strings.LastIndex(s.URL, ":")] + "/{{.ProjectName}}/{{.Version}}/",
|
||||
@ -387,8 +403,8 @@ func TestUpload(t *testing.T) {
|
||||
checks(),
|
||||
},
|
||||
{"broken-cert", false, true, false, true,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Mode: ModeBinary,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
@ -401,16 +417,16 @@ func TestUpload(t *testing.T) {
|
||||
checks(),
|
||||
},
|
||||
{"skip-publishing", true, true, true, true,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
c := *ctx
|
||||
c.SkipPublish = true
|
||||
return &c, config.Put{}
|
||||
return &c, config.Upload{}
|
||||
},
|
||||
checks(),
|
||||
},
|
||||
{"checksumheader", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
func(s *httptest.Server) (*context.Context, config.Upload) {
|
||||
return ctx, config.Upload{
|
||||
Mode: ModeBinary,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
@ -423,14 +439,14 @@ func TestUpload(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
uploadAndCheck := func(t *testing.T, setup func(*httptest.Server) (*context.Context, config.Put), wantErrPlain, wantErrTLS bool, check func(r []*h.Request) error, srv *httptest.Server) {
|
||||
uploadAndCheck := func(t *testing.T, setup func(*httptest.Server) (*context.Context, config.Upload), wantErrPlain, wantErrTLS bool, check func(r []*h.Request) error, srv *httptest.Server) {
|
||||
requests = nil
|
||||
ctx, put := setup(srv)
|
||||
ctx, upload := setup(srv)
|
||||
wantErr := wantErrPlain
|
||||
if srv.Certificate() != nil {
|
||||
wantErr = wantErrTLS
|
||||
}
|
||||
if err := Upload(ctx, []config.Put{put}, "test", is2xx); (err != nil) != wantErr {
|
||||
if err := Upload(ctx, []config.Upload{upload}, "test", is2xx); (err != nil) != wantErr {
|
||||
t.Errorf("Upload() error = %v, wantErr %v", err, wantErr)
|
||||
}
|
||||
if err := check(requests); err != nil {
|
||||
|
@ -47,6 +47,7 @@ func (Pipe) String() string {
|
||||
func (Pipe) Default(ctx *context.Context) error {
|
||||
for i := range ctx.Config.Artifactories {
|
||||
ctx.Config.Artifactories[i].ChecksumHeader = "X-Checksum-SHA256"
|
||||
ctx.Config.Artifactories[i].Method = h.MethodPut
|
||||
}
|
||||
return http.Defaults(ctx.Config.Artifactories)
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ func TestRunPipe_ModeBinary(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production-us",
|
||||
Mode: "binary",
|
||||
@ -203,6 +203,7 @@ func TestRunPipe_ModeBinary(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.NoError(t, Pipe{}.Publish(ctx))
|
||||
}
|
||||
|
||||
@ -220,7 +221,7 @@ func TestRunPipe_ModeArchive(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "goreleaser",
|
||||
Dist: folder,
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "archive",
|
||||
@ -300,6 +301,7 @@ func TestRunPipe_ModeArchive(t *testing.T) {
|
||||
uploads.Store("deb", true)
|
||||
})
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.NoError(t, Pipe{}.Publish(ctx))
|
||||
_, ok := uploads.Load("targz")
|
||||
assert.True(t, ok, "tar.gz file was not uploaded")
|
||||
@ -316,7 +318,7 @@ func TestRunPipe_ArtifactoryDown(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "goreleaser",
|
||||
Dist: folder,
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "archive",
|
||||
@ -334,6 +336,8 @@ func TestRunPipe_ArtifactoryDown(t *testing.T) {
|
||||
Name: "bin.tar.gz",
|
||||
Path: tarfile.Name(),
|
||||
})
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
err = Pipe{}.Publish(ctx)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "connection refused")
|
||||
@ -348,7 +352,7 @@ func TestRunPipe_TargetTemplateError(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
@ -369,6 +373,7 @@ func TestRunPipe_TargetTemplateError(t *testing.T) {
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.EqualError(t, Pipe{}.Publish(ctx), `artifactory: error while building the target url: template: mybin:1: unexpected "/" in operand`)
|
||||
}
|
||||
|
||||
@ -405,7 +410,7 @@ func TestRunPipe_BadCredentials(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
@ -425,6 +430,7 @@ func TestRunPipe_BadCredentials(t *testing.T) {
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
err = Pipe{}.Publish(ctx)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "Bad credentials")
|
||||
@ -462,7 +468,7 @@ func TestRunPipe_UnparsableErrorResponse(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
@ -482,6 +488,7 @@ func TestRunPipe_UnparsableErrorResponse(t *testing.T) {
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.EqualError(t, Pipe{}.Publish(ctx), `artifactory: upload failed: invalid character '.' looking for beginning of value`)
|
||||
}
|
||||
|
||||
@ -516,7 +523,7 @@ func TestRunPipe_UnparsableResponse(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
@ -536,6 +543,7 @@ func TestRunPipe_UnparsableResponse(t *testing.T) {
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.EqualError(t, Pipe{}.Publish(ctx), `artifactory: upload failed: invalid character 'i' looking for beginning of value`)
|
||||
}
|
||||
|
||||
@ -543,7 +551,7 @@ func TestRunPipe_FileNotFound(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: "archivetest/dist",
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
@ -563,6 +571,7 @@ func TestRunPipe_FileNotFound(t *testing.T) {
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.EqualError(t, Pipe{}.Publish(ctx), `open archivetest/dist/mybin/mybin: no such file or directory`)
|
||||
}
|
||||
|
||||
@ -580,7 +589,7 @@ func TestRunPipe_UnparsableTarget(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
@ -600,12 +609,13 @@ func TestRunPipe_UnparsableTarget(t *testing.T) {
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.EqualError(t, Pipe{}.Publish(ctx), `artifactory: upload failed: parse ://artifacts.company.com/example-repo-local/mybin/darwin/amd64/mybin: missing protocol scheme`)
|
||||
}
|
||||
|
||||
func TestRunPipe_SkipWhenPublishFalse(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
@ -619,6 +629,7 @@ func TestRunPipe_SkipWhenPublishFalse(t *testing.T) {
|
||||
}
|
||||
ctx.SkipPublish = true
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
err := Pipe{}.Publish(ctx)
|
||||
assert.True(t, pipe.IsSkip(err))
|
||||
assert.EqualError(t, err, pipe.ErrSkipPublishEnabled.Error())
|
||||
@ -635,7 +646,7 @@ func TestRunPipe_DirUpload(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
@ -655,6 +666,7 @@ func TestRunPipe_DirUpload(t *testing.T) {
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.EqualError(t, Pipe{}.Publish(ctx), `artifactory: upload failed: the asset to upload can't be a directory`)
|
||||
}
|
||||
|
||||
@ -663,7 +675,9 @@ func TestDescription(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNoArtifactories(t *testing.T) {
|
||||
assert.True(t, pipe.IsSkip(Pipe{}.Publish(context.New(config.Project{}))))
|
||||
var ctx = context.New(config.Project{})
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.True(t, pipe.IsSkip(Pipe{}.Publish(ctx)))
|
||||
}
|
||||
|
||||
func TestArtifactoriesWithoutTarget(t *testing.T) {
|
||||
@ -672,7 +686,7 @@ func TestArtifactoriesWithoutTarget(t *testing.T) {
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Username: "deployuser",
|
||||
@ -681,6 +695,7 @@ func TestArtifactoriesWithoutTarget(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.True(t, pipe.IsSkip(Pipe{}.Publish(ctx)))
|
||||
}
|
||||
|
||||
@ -690,7 +705,7 @@ func TestArtifactoriesWithoutUsername(t *testing.T) {
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
@ -699,30 +714,35 @@ func TestArtifactoriesWithoutUsername(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.True(t, pipe.IsSkip(Pipe{}.Publish(ctx)))
|
||||
}
|
||||
|
||||
func TestArtifactoriesWithoutName(t *testing.T) {
|
||||
assert.True(t, pipe.IsSkip(Pipe{}.Publish(context.New(config.Project{
|
||||
Artifactories: []config.Put{
|
||||
var ctx = context.New(config.Project{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Username: "deployuser",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
},
|
||||
},
|
||||
}))))
|
||||
})
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.True(t, pipe.IsSkip(Pipe{}.Publish(ctx)))
|
||||
}
|
||||
|
||||
func TestArtifactoriesWithoutSecret(t *testing.T) {
|
||||
assert.True(t, pipe.IsSkip(Pipe{}.Publish(context.New(config.Project{
|
||||
Artifactories: []config.Put{
|
||||
var ctx = context.New(config.Project{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
}))))
|
||||
})
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.True(t, pipe.IsSkip(Pipe{}.Publish(ctx)))
|
||||
}
|
||||
|
||||
func TestArtifactoriesWithInvalidMode(t *testing.T) {
|
||||
@ -731,7 +751,7 @@ func TestArtifactoriesWithInvalidMode(t *testing.T) {
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "does-not-exists",
|
||||
@ -741,13 +761,15 @@ func TestArtifactoriesWithInvalidMode(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.Error(t, Pipe{}.Publish(ctx))
|
||||
}
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
@ -756,6 +778,7 @@ func TestDefault(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.Len(t, ctx.Config.Artifactories, 1)
|
||||
var artifactory = ctx.Config.Artifactories[0]
|
||||
@ -765,7 +788,7 @@ func TestDefault(t *testing.T) {
|
||||
func TestDefaultNoArtifactories(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Artifactories: []config.Put{},
|
||||
Artifactories: []config.Upload{},
|
||||
},
|
||||
}
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
@ -775,7 +798,7 @@ func TestDefaultNoArtifactories(t *testing.T) {
|
||||
func TestDefaultSet(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Artifactories: []config.Put{
|
||||
Artifactories: []config.Upload{
|
||||
{
|
||||
Mode: "custom",
|
||||
},
|
||||
|
@ -10,11 +10,11 @@ import (
|
||||
"github.com/goreleaser/goreleaser/internal/pipe/blob"
|
||||
"github.com/goreleaser/goreleaser/internal/pipe/brew"
|
||||
"github.com/goreleaser/goreleaser/internal/pipe/docker"
|
||||
"github.com/goreleaser/goreleaser/internal/pipe/put"
|
||||
"github.com/goreleaser/goreleaser/internal/pipe/release"
|
||||
"github.com/goreleaser/goreleaser/internal/pipe/s3"
|
||||
"github.com/goreleaser/goreleaser/internal/pipe/scoop"
|
||||
"github.com/goreleaser/goreleaser/internal/pipe/snapcraft"
|
||||
"github.com/goreleaser/goreleaser/internal/pipe/upload"
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -38,7 +38,7 @@ type Publisher interface {
|
||||
var publishers = []Publisher{
|
||||
s3.Pipe{},
|
||||
blob.Pipe{},
|
||||
put.Pipe{},
|
||||
upload.Pipe{},
|
||||
artifactory.Pipe{},
|
||||
docker.Pipe{},
|
||||
snapcraft.Pipe{},
|
||||
|
@ -1,9 +1,11 @@
|
||||
// Package put provides a Pipe that push using HTTP PUT
|
||||
package put
|
||||
// Package upload provides a Pipe that push using HTTP
|
||||
package upload
|
||||
|
||||
import (
|
||||
h "net/http"
|
||||
|
||||
"github.com/goreleaser/goreleaser/internal/deprecate"
|
||||
|
||||
"github.com/goreleaser/goreleaser/internal/http"
|
||||
"github.com/goreleaser/goreleaser/internal/pipe"
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
@ -15,30 +17,34 @@ type Pipe struct{}
|
||||
|
||||
// String returns the description of the pipe
|
||||
func (Pipe) String() string {
|
||||
return "HTTP PUT"
|
||||
return "HTTP Upload"
|
||||
}
|
||||
|
||||
// Default sets the pipe defaults
|
||||
func (Pipe) Default(ctx *context.Context) error {
|
||||
return http.Defaults(ctx.Config.Puts)
|
||||
if len(ctx.Config.Puts) > 0 {
|
||||
deprecate.Notice("puts")
|
||||
ctx.Config.Uploads = append(ctx.Config.Uploads, ctx.Config.Puts...)
|
||||
}
|
||||
return http.Defaults(ctx.Config.Uploads)
|
||||
}
|
||||
|
||||
// Publish artifacts
|
||||
func (Pipe) Publish(ctx *context.Context) error {
|
||||
if len(ctx.Config.Puts) == 0 {
|
||||
return pipe.Skip("put section is not configured")
|
||||
if len(ctx.Config.Uploads) == 0 {
|
||||
return pipe.Skip("uploads section is not configured")
|
||||
}
|
||||
|
||||
// Check requirements for every instance we have configured.
|
||||
// If not fulfilled, we can skip this pipeline
|
||||
for _, instance := range ctx.Config.Puts {
|
||||
for _, instance := range ctx.Config.Uploads {
|
||||
instance := instance
|
||||
if skip := http.CheckConfig(ctx, &instance, "put"); skip != nil {
|
||||
if skip := http.CheckConfig(ctx, &instance, "upload"); skip != nil {
|
||||
return pipe.Skip(skip.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return http.Upload(ctx, ctx.Config.Puts, "put", func(res *h.Response) error {
|
||||
return http.Upload(ctx, ctx.Config.Uploads, "upload", func(res *h.Response) error {
|
||||
if c := res.StatusCode; c < 200 || 299 < c {
|
||||
return errors.Errorf("unexpected http response status: %s", res.Status)
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
package put
|
||||
package upload
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
h "net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -106,14 +107,16 @@ func TestRunPipe_ModeBinary(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Name: "production-us",
|
||||
Mode: "binary",
|
||||
Target: fmt.Sprintf("%s/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}", server.URL),
|
||||
Username: "deployuser",
|
||||
},
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Name: "production-eu",
|
||||
Mode: "binary",
|
||||
Target: fmt.Sprintf("%s/production-repo-remote/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}", server.URL),
|
||||
@ -122,8 +125,8 @@ func TestRunPipe_ModeBinary(t *testing.T) {
|
||||
},
|
||||
})
|
||||
ctx.Env = map[string]string{
|
||||
"PUT_PRODUCTION-US_SECRET": "deployuser-secret",
|
||||
"PUT_PRODUCTION-EU_SECRET": "productionuser-apikey",
|
||||
"UPLOAD_PRODUCTION-US_SECRET": "deployuser-secret",
|
||||
"UPLOAD_PRODUCTION-EU_SECRET": "productionuser-apikey",
|
||||
}
|
||||
for _, goos := range []string{"linux", "darwin"} {
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
@ -152,8 +155,9 @@ func TestRunPipe_ModeArchive(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "goreleaser",
|
||||
Dist: folder,
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Name: "production",
|
||||
Mode: "archive",
|
||||
Target: fmt.Sprintf("%s/example-repo-local/{{ .ProjectName }}/{{ .Version }}/", server.URL),
|
||||
@ -162,7 +166,7 @@ func TestRunPipe_ModeArchive(t *testing.T) {
|
||||
},
|
||||
})
|
||||
ctx.Env = map[string]string{
|
||||
"PUT_PRODUCTION_SECRET": "deployuser-secret",
|
||||
"UPLOAD_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.Version = "1.0.0"
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
@ -214,8 +218,9 @@ func TestRunPipe_ArtifactoryDown(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "goreleaser",
|
||||
Dist: folder,
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Name: "production",
|
||||
Mode: "archive",
|
||||
Target: "http://localhost:1234/example-repo-local/{{ .ProjectName }}/{{ .Version }}/",
|
||||
@ -225,7 +230,7 @@ func TestRunPipe_ArtifactoryDown(t *testing.T) {
|
||||
})
|
||||
ctx.Version = "2.0.0"
|
||||
ctx.Env = map[string]string{
|
||||
"PUT_PRODUCTION_SECRET": "deployuser-secret",
|
||||
"UPLOAD_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Type: artifact.UploadableArchive,
|
||||
@ -246,10 +251,11 @@ func TestRunPipe_TargetTemplateError(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
Method: h.MethodPut,
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
// This template is not correct and should fail
|
||||
Target: "http://storage.company.com/example-repo-local/{{ .ProjectName /{{ .Version }}/",
|
||||
Username: "deployuser",
|
||||
@ -257,7 +263,7 @@ func TestRunPipe_TargetTemplateError(t *testing.T) {
|
||||
},
|
||||
})
|
||||
ctx.Env = map[string]string{
|
||||
"PUT_PRODUCTION_SECRET": "deployuser-secret",
|
||||
"UPLOAD_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: "mybin",
|
||||
@ -268,7 +274,7 @@ func TestRunPipe_TargetTemplateError(t *testing.T) {
|
||||
})
|
||||
err = Pipe{}.Publish(ctx)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), `put: error while building the target url: template: mybin:1: unexpected "/" in operand`)
|
||||
assert.Contains(t, err.Error(), `upload: error while building the target url: template: mybin:1: unexpected "/" in operand`)
|
||||
}
|
||||
|
||||
func TestRunPipe_BadCredentials(t *testing.T) {
|
||||
@ -298,8 +304,9 @@ func TestRunPipe_BadCredentials(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
Target: fmt.Sprintf("%s/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}", server.URL),
|
||||
@ -308,7 +315,7 @@ func TestRunPipe_BadCredentials(t *testing.T) {
|
||||
},
|
||||
})
|
||||
ctx.Env = map[string]string{
|
||||
"PUT_PRODUCTION_SECRET": "deployuser-secret",
|
||||
"UPLOAD_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: "mybin",
|
||||
@ -327,8 +334,9 @@ func TestRunPipe_FileNotFound(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: "archivetest/dist",
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
@ -337,7 +345,7 @@ func TestRunPipe_FileNotFound(t *testing.T) {
|
||||
},
|
||||
})
|
||||
ctx.Env = map[string]string{
|
||||
"PUT_PRODUCTION_SECRET": "deployuser-secret",
|
||||
"UPLOAD_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: "mybin",
|
||||
@ -364,8 +372,9 @@ func TestRunPipe_UnparsableTarget(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
Target: "://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
@ -374,7 +383,7 @@ func TestRunPipe_UnparsableTarget(t *testing.T) {
|
||||
},
|
||||
})
|
||||
ctx.Env = map[string]string{
|
||||
"PUT_PRODUCTION_SECRET": "deployuser-secret",
|
||||
"UPLOAD_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: "mybin",
|
||||
@ -384,12 +393,12 @@ func TestRunPipe_UnparsableTarget(t *testing.T) {
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.EqualError(t, Pipe{}.Publish(ctx), `put: upload failed: parse ://artifacts.company.com/example-repo-local/mybin/darwin/amd64/mybin: missing protocol scheme`)
|
||||
assert.EqualError(t, Pipe{}.Publish(ctx), `upload: upload failed: parse ://artifacts.company.com/example-repo-local/mybin/darwin/amd64/mybin: missing protocol scheme`)
|
||||
}
|
||||
|
||||
func TestRunPipe_SkipWhenPublishFalse(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
@ -399,7 +408,7 @@ func TestRunPipe_SkipWhenPublishFalse(t *testing.T) {
|
||||
},
|
||||
})
|
||||
ctx.Env = map[string]string{
|
||||
"PUT_PRODUCTION_SECRET": "deployuser-secret",
|
||||
"UPLOAD_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.SkipPublish = true
|
||||
|
||||
@ -419,8 +428,9 @@ func TestRunPipe_DirUpload(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
@ -429,7 +439,7 @@ func TestRunPipe_DirUpload(t *testing.T) {
|
||||
},
|
||||
})
|
||||
ctx.Env = map[string]string{
|
||||
"PUT_PRODUCTION_SECRET": "deployuser-secret",
|
||||
"UPLOAD_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: "mybin",
|
||||
@ -439,7 +449,7 @@ func TestRunPipe_DirUpload(t *testing.T) {
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.EqualError(t, Pipe{}.Publish(ctx), `put: upload failed: the asset to upload can't be a directory`)
|
||||
assert.EqualError(t, Pipe{}.Publish(ctx), `upload: upload failed: the asset to upload can't be a directory`)
|
||||
}
|
||||
|
||||
func TestDescription(t *testing.T) {
|
||||
@ -453,11 +463,12 @@ func TestNoPuts(t *testing.T) {
|
||||
func TestPutsWithoutTarget(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Env: map[string]string{
|
||||
"PUT_PRODUCTION_SECRET": "deployuser-secret",
|
||||
"UPLOAD_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Name: "production",
|
||||
Username: "deployuser",
|
||||
},
|
||||
@ -471,11 +482,12 @@ func TestPutsWithoutTarget(t *testing.T) {
|
||||
func TestPutsWithoutUsername(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Env: map[string]string{
|
||||
"PUT_PRODUCTION_SECRET": "deployuser-secret",
|
||||
"UPLOAD_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Name: "production",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
},
|
||||
@ -488,8 +500,9 @@ func TestPutsWithoutUsername(t *testing.T) {
|
||||
|
||||
func TestPutsWithoutName(t *testing.T) {
|
||||
assert.True(t, pipe.IsSkip(Pipe{}.Publish(context.New(config.Project{
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Username: "deployuser",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
},
|
||||
@ -499,8 +512,9 @@ func TestPutsWithoutName(t *testing.T) {
|
||||
|
||||
func TestPutsWithoutSecret(t *testing.T) {
|
||||
assert.True(t, pipe.IsSkip(Pipe{}.Publish(context.New(config.Project{
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Name: "production",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
Username: "deployuser",
|
||||
@ -512,11 +526,12 @@ func TestPutsWithoutSecret(t *testing.T) {
|
||||
func TestPutsWithInvalidMode(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Env: map[string]string{
|
||||
"PUT_PRODUCTION_SECRET": "deployuser-secret",
|
||||
"UPLOAD_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Method: h.MethodPut,
|
||||
Name: "production",
|
||||
Mode: "does-not-exists",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
@ -531,7 +546,7 @@ func TestPutsWithInvalidMode(t *testing.T) {
|
||||
func TestDefault(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Name: "production",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
@ -541,33 +556,36 @@ func TestDefault(t *testing.T) {
|
||||
},
|
||||
}
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.Len(t, ctx.Config.Puts, 1)
|
||||
var put = ctx.Config.Puts[0]
|
||||
assert.Equal(t, "archive", put.Mode)
|
||||
assert.Len(t, ctx.Config.Uploads, 1)
|
||||
var upload = ctx.Config.Uploads[0]
|
||||
assert.Equal(t, "archive", upload.Mode)
|
||||
assert.Equal(t, h.MethodPut, upload.Method)
|
||||
}
|
||||
|
||||
func TestDefaultNoPuts(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Puts: []config.Put{},
|
||||
Uploads: []config.Upload{},
|
||||
},
|
||||
}
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.Empty(t, ctx.Config.Puts)
|
||||
assert.Empty(t, ctx.Config.Uploads)
|
||||
}
|
||||
|
||||
func TestDefaultSet(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Puts: []config.Put{
|
||||
Uploads: []config.Upload{
|
||||
{
|
||||
Mode: "custom",
|
||||
Method: h.MethodPost,
|
||||
Mode: "custom",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.Len(t, ctx.Config.Puts, 1)
|
||||
var put = ctx.Config.Puts[0]
|
||||
assert.Equal(t, "custom", put.Mode)
|
||||
assert.Len(t, ctx.Config.Uploads, 1)
|
||||
var upload = ctx.Config.Uploads[0]
|
||||
assert.Equal(t, "custom", upload.Mode)
|
||||
assert.Equal(t, h.MethodPost, upload.Method)
|
||||
}
|
@ -331,13 +331,14 @@ type Blob struct {
|
||||
IDs []string `yaml:"ids,omitempty"`
|
||||
}
|
||||
|
||||
// Put HTTP upload configuration
|
||||
type Put struct {
|
||||
// Upload configuration
|
||||
type Upload struct {
|
||||
Name string `yaml:",omitempty"`
|
||||
IDs []string `yaml:"ids,omitempty"`
|
||||
Target string `yaml:",omitempty"`
|
||||
Username string `yaml:",omitempty"`
|
||||
Mode string `yaml:",omitempty"`
|
||||
Method string `yaml:",omitempty"`
|
||||
ChecksumHeader string `yaml:"checksum_header,omitempty"`
|
||||
TrustedCerts string `yaml:"trusted_certificates,omitempty"`
|
||||
Checksum bool `yaml:",omitempty"`
|
||||
@ -362,8 +363,9 @@ type Project struct {
|
||||
Snapshot Snapshot `yaml:",omitempty"`
|
||||
Checksum Checksum `yaml:",omitempty"`
|
||||
Dockers []Docker `yaml:",omitempty"`
|
||||
Artifactories []Put `yaml:",omitempty"`
|
||||
Puts []Put `yaml:",omitempty"`
|
||||
Artifactories []Upload `yaml:",omitempty"`
|
||||
Uploads []Upload `yaml:",omitempty"`
|
||||
Puts []Upload `yaml:",omitempty"` // TODO: remove this
|
||||
S3 []S3 `yaml:"s3,omitempty"`
|
||||
Blob []Blob `yaml:"blob,omitempty"` // TODO: remove this
|
||||
Blobs []Blob `yaml:"blobs,omitempty"`
|
||||
|
@ -39,6 +39,31 @@ to this:
|
||||
|
||||
-->
|
||||
|
||||
|
||||
### puts
|
||||
|
||||
> since 2019-11-15
|
||||
|
||||
The HTTP upload support was extended to also accept `POST` as a method,
|
||||
so the name `puts` kind of lost its meaning.
|
||||
|
||||
Change this:
|
||||
|
||||
```yaml
|
||||
puts:
|
||||
- ...
|
||||
```
|
||||
|
||||
to this:
|
||||
|
||||
```yaml
|
||||
uploads:
|
||||
- ...
|
||||
```
|
||||
|
||||
Also note that secrets environment variable name prefixes have changed from
|
||||
`PUT_` to `UPLOAD_`.
|
||||
|
||||
### nfpms.name_template
|
||||
|
||||
> since 2019-11-15
|
||||
|
@ -1,22 +1,23 @@
|
||||
---
|
||||
title: HTTP Put
|
||||
title: HTTP Upload
|
||||
series: customization
|
||||
hideFromIndex: true
|
||||
weight: 120
|
||||
---
|
||||
|
||||
GoReleaser supports building and pushing artifacts to HTTP servers using simple HTTP PUT requests.
|
||||
GoReleaser supports building and pushing artifacts to HTTP servers using simple
|
||||
HTTP requests.
|
||||
|
||||
## How it works
|
||||
|
||||
You can declare multiple Put instances.
|
||||
All binaries generated by your `builds` section will be pushed to each configured Put.
|
||||
You can declare multiple `uploads` instances. All binaries generated by your
|
||||
`builds` section will be pushed to each configured upload.
|
||||
|
||||
If you have only one Put instance, the configuration is as easy as adding the
|
||||
upload target and a username to your `.goreleaser.yml` file:
|
||||
If you have only one `uploads` instance, the configuration is as easy as adding
|
||||
the upload target and a username to your `.goreleaser.yml` file:
|
||||
|
||||
```yaml
|
||||
puts:
|
||||
uploads:
|
||||
- name: production
|
||||
target: http://some.server/some/path/example-repo-local/{{ .ProjectName }}/{{ .Version }}/
|
||||
username: goreleaser
|
||||
@ -24,8 +25,8 @@ puts:
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- An HTTP server accepting PUT requests
|
||||
- A user + password with grants to upload an artifact using PUT requests (if the server requires it)
|
||||
- An HTTP server accepting HTTP requests
|
||||
- A user + password with grants to upload an artifact using HTTP requests (if the server requires it)
|
||||
|
||||
### Target
|
||||
|
||||
@ -63,9 +64,9 @@ This way we support auth for multiple instances.
|
||||
This also means that the `name` per configured instance needs to be unique
|
||||
per goreleaser configuration.
|
||||
|
||||
The name of the environment variable will be `PUT_NAME_USERNAME`.
|
||||
The name of the environment variable will be `UPLOAD_NAME_USERNAME`.
|
||||
If your instance is named `production`, you can store the username in the
|
||||
environment variable `PUT_PRODUCTION_USERNAME`.
|
||||
environment variable `UPLOAD_PRODUCTION_USERNAME`.
|
||||
The name will be transformed to uppercase.
|
||||
|
||||
If a configured username is found in the configuration file, then the
|
||||
@ -79,24 +80,24 @@ This way we support auth for multiple instances.
|
||||
This also means that the `name` per configured instance needs to be unique
|
||||
per goreleaser configuration.
|
||||
|
||||
The name of the environment variable will be `PUT_NAME_SECRET`.
|
||||
The name of the environment variable will be `UPLOAD_NAME_SECRET`.
|
||||
If your instance is named `production`, you need to store the secret in the
|
||||
environment variable `PUT_PRODUCTION_SECRET`.
|
||||
environment variable `UPLOAD_PRODUCTION_SECRET`.
|
||||
The name will be transformed to uppercase.
|
||||
|
||||
### Server authentication
|
||||
|
||||
You can authenticate your TLS server adding a trusted X.509 certificate chain
|
||||
in your put configuration.
|
||||
in your upload configuration.
|
||||
|
||||
The trusted certificate chain will be used to validate the server certificates.
|
||||
|
||||
You can set the trusted certificate chain using the `trusted_certificates`
|
||||
setting the put section with PEM encoded certificates on a YAML literal block
|
||||
setting the upload section with PEM encoded certificates on a YAML literal block
|
||||
like this:
|
||||
|
||||
```yaml
|
||||
puts:
|
||||
uploads:
|
||||
- name: "some HTTP/TLS server"
|
||||
#...(other settings)...
|
||||
trusted_certificates: |
|
||||
@ -118,13 +119,17 @@ Of course, you can customize a lot of things:
|
||||
|
||||
```yaml
|
||||
# .goreleaser.yml
|
||||
puts:
|
||||
# You can have multiple Put instances.
|
||||
uploads:
|
||||
# You can have multiple upload instances.
|
||||
-
|
||||
# Unique name of your Put instance. Used to identify the instance.
|
||||
# Unique name of your upload instance. Used to identify the instance.
|
||||
name: production
|
||||
|
||||
# IDs of the artifacts you want to PUT.
|
||||
# HTTP method to use.
|
||||
# Default: PUT
|
||||
method: POST
|
||||
|
||||
# IDs of the artifacts you want to upload.
|
||||
ids:
|
||||
- foo
|
||||
- bar
|
||||
@ -135,7 +140,7 @@ puts:
|
||||
# Default is `archive`.
|
||||
mode: archive
|
||||
|
||||
# URL to be used as target of the HTTP PUT request
|
||||
# URL to be used as target of the HTTP request
|
||||
target: https://some.server/some/path/example-repo-local/{{ .ProjectName }}/{{ .Version }}/
|
||||
|
||||
# User that will be used for the deployment
|
Loading…
Reference in New Issue
Block a user