1
0
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:
Carlos Alexandro Becker 2018-10-01 16:52:16 -03:00 committed by GitHub
parent aded99f621
commit 652645b3bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 75 additions and 28 deletions

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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) {

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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

View File

@ -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)