mirror of
https://github.com/goreleaser/goreleaser.git
synced 2024-12-27 01:33:39 +02:00
feat: artifactory checksum header (#772)
* feat: artifactory checksum header * fix: merge fixes
This commit is contained in:
parent
aded99f621
commit
652645b3bf
@ -9,6 +9,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Type defines the type of an artifact
|
||||
@ -67,13 +68,13 @@ func (a Artifact) Checksum() (string, error) {
|
||||
log.Debugf("calculating sha256sum for %s", a.Path)
|
||||
file, err := os.Open(a.Path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", errors.Wrap(err, "failed to checksum")
|
||||
}
|
||||
defer file.Close() // nolint: errcheck
|
||||
var hash = sha256.New()
|
||||
_, err = io.Copy(hash, file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", errors.Wrap(err, "failed to checksum")
|
||||
}
|
||||
return hex.EncodeToString(hash.Sum(nil)), nil
|
||||
}
|
||||
|
@ -159,6 +159,6 @@ func TestChecksumFileDoesntExist(t *testing.T) {
|
||||
Path: "/tmp/adasdasdas/asdasd/asdas",
|
||||
}
|
||||
sum, err := artifact.Checksum()
|
||||
require.EqualError(t, err, `open /tmp/adasdasdas/asdasd/asdas: no such file or directory`)
|
||||
require.EqualError(t, err, `failed to checksum: open /tmp/adasdasdas/asdasd/asdas: no such file or directory`)
|
||||
require.Empty(t, sum)
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ func Upload(ctx *context.Context, puts []config.Put, kind string, check Response
|
||||
|
||||
func uploadWithFilter(ctx *context.Context, put *config.Put, filter artifact.Filter, kind string, check ResponseChecker) error {
|
||||
var artifacts = ctx.Artifacts.Filter(filter).List()
|
||||
log.Infof("will upload %d artifacts", len(artifacts))
|
||||
log.Debugf("will upload %d artifacts", len(artifacts))
|
||||
var g = semerrgroup.New(ctx.Parallelism)
|
||||
for _, artifact := range artifacts {
|
||||
artifact := artifact
|
||||
@ -201,7 +201,16 @@ func uploadAsset(ctx *context.Context, put *config.Put, artifact artifact.Artifa
|
||||
}
|
||||
targetURL += artifact.Name
|
||||
|
||||
_, err = uploadAssetToServer(ctx, put, targetURL, username, secret, asset, check)
|
||||
var headers = map[string]string{}
|
||||
if put.ChecksumHeader != "" {
|
||||
sum, err := artifact.Checksum()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headers[put.ChecksumHeader] = sum
|
||||
}
|
||||
|
||||
_, err = uploadAssetToServer(ctx, put, targetURL, username, secret, headers, asset, check)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("%s: upload failed", kind)
|
||||
log.WithError(err).WithFields(log.Fields{
|
||||
@ -220,8 +229,8 @@ func uploadAsset(ctx *context.Context, put *config.Put, artifact artifact.Artifa
|
||||
}
|
||||
|
||||
// uploadAssetToServer uploads the asset file to target
|
||||
func uploadAssetToServer(ctx *context.Context, put *config.Put, target, username, secret string, a *asset, check ResponseChecker) (*h.Response, error) {
|
||||
req, err := newUploadRequest(target, username, secret, a)
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -230,15 +239,18 @@ func uploadAssetToServer(ctx *context.Context, put *config.Put, target, username
|
||||
}
|
||||
|
||||
// newUploadRequest creates a new h.Request for uploading
|
||||
func newUploadRequest(target, username, secret string, a *asset) (*h.Request, error) {
|
||||
func newUploadRequest(target, username, secret string, headers map[string]string, a *asset) (*h.Request, error) {
|
||||
req, err := h.NewRequest("PUT", target, a.ReadCloser)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.ContentLength = a.Size
|
||||
req.SetBasicAuth(username, secret)
|
||||
|
||||
for k, v := range headers {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
|
||||
return req, err
|
||||
}
|
||||
|
||||
|
@ -9,11 +9,13 @@ import (
|
||||
h "net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/pkg/config"
|
||||
@ -133,6 +135,7 @@ type check struct {
|
||||
user string
|
||||
pass string
|
||||
content []byte
|
||||
headers map[string]string
|
||||
}
|
||||
|
||||
func checks(checks ...check) func(rs []*h.Request) error {
|
||||
@ -181,6 +184,11 @@ func doCheck(c check, r *h.Request) error {
|
||||
if u, p, ok := r.BasicAuth(); !ok || u != c.user || p != c.pass {
|
||||
return errors.Errorf("bad basic auth credentials: %s/%s", u, p)
|
||||
}
|
||||
for k, v := range c.headers {
|
||||
if r.Header.Get(k) != v {
|
||||
return errors.Errorf("bad header value for %s: expected %s, got %s", k, v, r.Header.Get(k))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -221,6 +229,8 @@ func TestUpload(t *testing.T) {
|
||||
ctx.Env["TEST_A_USERNAME"] = "u2"
|
||||
ctx.Version = "2.1.0"
|
||||
ctx.Artifacts = artifact.New()
|
||||
folder, err := ioutil.TempDir("", "goreleasertest")
|
||||
require.NoError(t, err)
|
||||
for _, a := range []struct {
|
||||
ext string
|
||||
typ artifact.Type
|
||||
@ -233,7 +243,9 @@ func TestUpload(t *testing.T) {
|
||||
{"sum", artifact.Checksum},
|
||||
{"sig", artifact.Signature},
|
||||
} {
|
||||
ctx.Artifacts.Add(artifact.Artifact{Name: "a." + a.ext, Path: "/a/a." + a.ext, Type: a.typ})
|
||||
var file = filepath.Join(folder, "a."+a.ext)
|
||||
require.NoError(t, ioutil.WriteFile(file, []byte("lorem ipsum"), 0644))
|
||||
ctx.Artifacts.Add(artifact.Artifact{Name: "a." + a.ext, Path: file, Type: a.typ})
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
@ -267,8 +279,8 @@ func TestUpload(t *testing.T) {
|
||||
}
|
||||
},
|
||||
checks(
|
||||
check{"/blah/2.1.0/a.deb", "u2", "x", content},
|
||||
check{"/blah/2.1.0/a.tar", "u2", "x", content},
|
||||
check{"/blah/2.1.0/a.deb", "u2", "x", content, map[string]string{}},
|
||||
check{"/blah/2.1.0/a.tar", "u2", "x", content, map[string]string{}},
|
||||
),
|
||||
},
|
||||
{"archive", true, true, false, false,
|
||||
@ -282,8 +294,8 @@ func TestUpload(t *testing.T) {
|
||||
}
|
||||
},
|
||||
checks(
|
||||
check{"/blah/2.1.0/a.deb", "u1", "x", content},
|
||||
check{"/blah/2.1.0/a.tar", "u1", "x", content},
|
||||
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{}},
|
||||
),
|
||||
},
|
||||
{"binary", true, true, false, false,
|
||||
@ -296,7 +308,7 @@ func TestUpload(t *testing.T) {
|
||||
TrustedCerts: cert(s),
|
||||
}
|
||||
},
|
||||
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content}),
|
||||
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) {
|
||||
@ -308,7 +320,7 @@ func TestUpload(t *testing.T) {
|
||||
TrustedCerts: cert(s),
|
||||
}
|
||||
},
|
||||
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content}),
|
||||
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) {
|
||||
@ -323,10 +335,10 @@ func TestUpload(t *testing.T) {
|
||||
}
|
||||
},
|
||||
checks(
|
||||
check{"/blah/2.1.0/a.deb", "u3", "x", content},
|
||||
check{"/blah/2.1.0/a.tar", "u3", "x", content},
|
||||
check{"/blah/2.1.0/a.sum", "u3", "x", content},
|
||||
check{"/blah/2.1.0/a.sig", "u3", "x", content},
|
||||
check{"/blah/2.1.0/a.deb", "u3", "x", content, map[string]string{}},
|
||||
check{"/blah/2.1.0/a.tar", "u3", "x", content, map[string]string{}},
|
||||
check{"/blah/2.1.0/a.sum", "u3", "x", content, map[string]string{}},
|
||||
check{"/blah/2.1.0/a.sig", "u3", "x", content, map[string]string{}},
|
||||
),
|
||||
},
|
||||
{"bad-template", true, true, true, true,
|
||||
@ -379,6 +391,19 @@ func TestUpload(t *testing.T) {
|
||||
},
|
||||
checks(),
|
||||
},
|
||||
{"checksumheader", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
Mode: ModeBinary,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
Username: "u2",
|
||||
ChecksumHeader: "-x-sha256",
|
||||
TrustedCerts: cert(s),
|
||||
}
|
||||
},
|
||||
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{"-x-sha256": "5e2bf57d3f40c4b6df69daf1936cb766f832374b4fc0259a7cbff06e2f70f269"}}),
|
||||
},
|
||||
}
|
||||
|
||||
uploadAndCheck := func(setup func(*httptest.Server) (*context.Context, config.Put), wantErrPlain, wantErrTLS bool, check func(r []*h.Request) error, srv *httptest.Server) {
|
||||
|
@ -45,6 +45,9 @@ func (Pipe) String() string {
|
||||
|
||||
// Default sets the pipe defaults
|
||||
func (Pipe) Default(ctx *context.Context) error {
|
||||
for i := range ctx.Config.Artifactories {
|
||||
ctx.Config.Artifactories[i].ChecksumHeader = "X-Checksum-SHA256"
|
||||
}
|
||||
return http.Defaults(ctx.Config.Artifactories)
|
||||
}
|
||||
|
||||
|
@ -786,4 +786,5 @@ func TestDefaultSet(t *testing.T) {
|
||||
assert.Len(t, ctx.Config.Artifactories, 1)
|
||||
var artifactory = ctx.Config.Artifactories[0]
|
||||
assert.Equal(t, "custom", artifactory.Mode)
|
||||
assert.Equal(t, "X-Checksum-SHA256", artifactory.ChecksumHeader)
|
||||
}
|
||||
|
@ -288,13 +288,14 @@ type S3 struct {
|
||||
|
||||
// Put HTTP upload configuration
|
||||
type Put struct {
|
||||
Name string `yaml:",omitempty"`
|
||||
Target string `yaml:",omitempty"`
|
||||
Username string `yaml:",omitempty"`
|
||||
Mode string `yaml:",omitempty"`
|
||||
Checksum bool `yaml:",omitempty"`
|
||||
Signature bool `yaml:",omitempty"`
|
||||
TrustedCerts string `yaml:"trusted_certificates,omitempty"`
|
||||
Name string `yaml:",omitempty"`
|
||||
Target string `yaml:",omitempty"`
|
||||
Username string `yaml:",omitempty"`
|
||||
Mode string `yaml:",omitempty"`
|
||||
ChecksumHeader string `yaml:"checksum_header,omitempty"`
|
||||
TrustedCerts string `yaml:"trusted_certificates,omitempty"`
|
||||
Checksum bool `yaml:",omitempty"`
|
||||
Signature bool `yaml:",omitempty"`
|
||||
}
|
||||
|
||||
// Project includes all project configuration
|
||||
|
@ -49,7 +49,7 @@ Supported variables:
|
||||
- Arch
|
||||
- Arm
|
||||
|
||||
_Attention_: Variables _Os_, _Arch_ and _Arm_ are only supported in upload mode `binary`.
|
||||
> **Warning**: Variables `Os`, `Arch` and `Arm` are only supported in upload mode `binary`.
|
||||
|
||||
### Username
|
||||
|
||||
@ -132,6 +132,10 @@ puts:
|
||||
target: https://some.server/some/path/example-repo-local/{{ .ProjectName }}/{{ .Version }}/
|
||||
# User that will be used for the deployment
|
||||
username: deployuser
|
||||
# An optional header you can use to tell GoReleaser to pass the artifact's
|
||||
# SHA256 checksum withing the upload request.
|
||||
# Default is empty.
|
||||
checksum_header: -X-SHA256-Sum
|
||||
# Upload checksums (defaults to false)
|
||||
checksum: true
|
||||
# Upload signatures (defaults to false)
|
||||
|
Loading…
Reference in New Issue
Block a user