mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-01-16 03:52:12 +02:00
Merge branch 'master' into organizing
This commit is contained in:
commit
ac3dabbe4c
@ -3,12 +3,14 @@ package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
h "net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
@ -97,6 +99,10 @@ func CheckConfig(ctx *context.Context, put *config.Put, kind string) error {
|
||||
return misconfigured(kind, put, fmt.Sprintf("missing %s environment variable", envName))
|
||||
}
|
||||
|
||||
if put.TrustedCerts != "" && !x509.NewCertPool().AppendCertsFromPEM([]byte(put.TrustedCerts)) {
|
||||
return misconfigured(kind, put, "no certificate could be added from the specified trusted_certificates configuration")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
@ -143,7 +149,7 @@ func Upload(ctx *context.Context, puts []config.Put, kind string, check Response
|
||||
}).Error(err.Error())
|
||||
return err
|
||||
}
|
||||
if err := uploadWithFilter(ctx, put, artifact.Or(filters...), kind, check); err != nil {
|
||||
if err := uploadWithFilter(ctx, &put, artifact.Or(filters...), kind, check); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -151,7 +157,7 @@ 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, put *config.Put, filter artifact.Filter, kind string, check ResponseChecker) error {
|
||||
var g = semerrgroup.New(ctx.Parallelism)
|
||||
for _, artifact := range ctx.Artifacts.Filter(filter).List() {
|
||||
artifact := artifact
|
||||
@ -163,7 +169,7 @@ func uploadWithFilter(ctx *context.Context, put config.Put, filter artifact.Filt
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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 == "" {
|
||||
@ -193,7 +199,7 @@ func uploadAsset(ctx *context.Context, put config.Put, artifact artifact.Artifac
|
||||
}
|
||||
targetURL += artifact.Name
|
||||
|
||||
_, err = uploadAssetToServer(ctx, targetURL, username, secret, asset, check)
|
||||
_, err = uploadAssetToServer(ctx, put, targetURL, username, secret, asset, check)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("%s: upload failed", kind)
|
||||
log.WithError(err).WithFields(log.Fields{
|
||||
@ -212,22 +218,18 @@ func uploadAsset(ctx *context.Context, put config.Put, artifact artifact.Artifac
|
||||
}
|
||||
|
||||
// uploadAssetToServer uploads the asset file to target
|
||||
func uploadAssetToServer(ctx *context.Context, target, username, secret string, a *asset, check ResponseChecker) (*h.Response, error) {
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return executeHTTPRequest(ctx, req, check)
|
||||
return executeHTTPRequest(ctx, put, req, check)
|
||||
}
|
||||
|
||||
// newUploadRequest creates a new h.Request for uploading
|
||||
func newUploadRequest(target, username, secret string, a *asset) (*h.Request, error) {
|
||||
u, err := url.Parse(target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req, err := h.NewRequest("PUT", u.String(), a.ReadCloser)
|
||||
req, err := h.NewRequest("PUT", target, a.ReadCloser)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -238,9 +240,36 @@ func newUploadRequest(target, username, secret string, a *asset) (*h.Request, er
|
||||
return req, err
|
||||
}
|
||||
|
||||
func getHTTPClient(put *config.Put) (*h.Client, error) {
|
||||
if put.TrustedCerts == "" {
|
||||
return h.DefaultClient, nil
|
||||
}
|
||||
pool, err := x509.SystemCertPool()
|
||||
if err != nil {
|
||||
if runtime.GOOS == "windows" {
|
||||
// on windows ignore errors until golang issues #16736 & #18609 get fixed
|
||||
pool = x509.NewCertPool()
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
pool.AppendCertsFromPEM([]byte(put.TrustedCerts)) // already validated certs checked by CheckConfig
|
||||
return &h.Client{
|
||||
Transport: &h.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: pool,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// executeHTTPRequest processes the http call with respect of context ctx
|
||||
func executeHTTPRequest(ctx *context.Context, req *h.Request, check ResponseChecker) (*h.Response, error) {
|
||||
resp, err := h.DefaultClient.Do(req)
|
||||
func executeHTTPRequest(ctx *context.Context, put *config.Put, req *h.Request, check ResponseChecker) (*h.Response, error) {
|
||||
client, err := getHTTPClient(put)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
// If we got an error, and the context has been canceled,
|
||||
// the context's error is probably more useful.
|
||||
@ -249,7 +278,6 @@ func executeHTTPRequest(ctx *context.Context, req *h.Request, check ResponseChec
|
||||
return nil, ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -280,21 +308,21 @@ 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
|
||||
func resolveTargetTemplate(ctx *context.Context, artifactory config.Put, artifact artifact.Artifact) (string, error) {
|
||||
func resolveTargetTemplate(ctx *context.Context, put *config.Put, artifact artifact.Artifact) (string, error) {
|
||||
data := targetData{
|
||||
Version: ctx.Version,
|
||||
Tag: ctx.Git.CurrentTag,
|
||||
ProjectName: ctx.Config.ProjectName,
|
||||
}
|
||||
|
||||
if artifactory.Mode == ModeBinary {
|
||||
if put.Mode == ModeBinary {
|
||||
data.Os = replace(ctx.Config.Archive.Replacements, artifact.Goos)
|
||||
data.Arch = replace(ctx.Config.Archive.Replacements, artifact.Goarch)
|
||||
data.Arm = replace(ctx.Config.Archive.Replacements, artifact.Goarm)
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
t, err := template.New(ctx.Config.ProjectName).Parse(artifactory.Target)
|
||||
t, err := template.New(ctx.Config.ProjectName).Parse(put.Target)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -2,12 +2,14 @@ package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
h "net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
@ -18,20 +20,6 @@ import (
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
)
|
||||
|
||||
var (
|
||||
mux *h.ServeMux
|
||||
srv *httptest.Server
|
||||
)
|
||||
|
||||
func setup() {
|
||||
mux = h.NewServeMux()
|
||||
srv = httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
func teardown() {
|
||||
srv.Close()
|
||||
}
|
||||
|
||||
func TestAssetOpenDefault(t *testing.T) {
|
||||
tf, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
@ -112,6 +100,7 @@ func TestCheckConfig(t *testing.T) {
|
||||
{"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},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@ -196,11 +185,10 @@ func doCheck(c check, r *h.Request) error {
|
||||
}
|
||||
|
||||
func TestUpload(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
content := []byte("blah!")
|
||||
requests := []*h.Request{}
|
||||
var m sync.Mutex
|
||||
mux := h.NewServeMux()
|
||||
mux.Handle("/", h.HandlerFunc(func(w h.ResponseWriter, r *h.Request) {
|
||||
bs, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
@ -247,37 +235,93 @@ func TestUpload(t *testing.T) {
|
||||
} {
|
||||
ctx.Artifacts.Add(artifact.Artifact{Name: "a." + a.ext, Path: "/a/a." + a.ext, Type: a.typ})
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
ctx *context.Context
|
||||
wantErr bool
|
||||
put config.Put
|
||||
check func(r []*h.Request) error
|
||||
name string
|
||||
tryPlain bool
|
||||
tryTLS bool
|
||||
wantErrPlain bool
|
||||
wantErrTLS bool
|
||||
setup func(*httptest.Server) (*context.Context, config.Put)
|
||||
check func(r []*h.Request) error
|
||||
}{
|
||||
{"wrong-mode", ctx, true,
|
||||
config.Put{Mode: "wrong-mode", Name: "a", Target: srv.URL + "/{{.ProjectName}}/{{.Version}}/", Username: "u1"},
|
||||
{"wrong-mode", true, true, true, true,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
Mode: "wrong-mode",
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
Username: "u1",
|
||||
TrustedCerts: cert(s),
|
||||
}
|
||||
},
|
||||
checks(),
|
||||
},
|
||||
{"username-from-env", ctx, false,
|
||||
config.Put{Mode: ModeArchive, Name: "a", Target: srv.URL + "/{{.ProjectName}}/{{.Version}}/"},
|
||||
{"username-from-env", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
Mode: ModeArchive,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
TrustedCerts: cert(s),
|
||||
}
|
||||
},
|
||||
checks(
|
||||
check{"/blah/2.1.0/a.deb", "u2", "x", content},
|
||||
check{"/blah/2.1.0/a.tar", "u2", "x", content},
|
||||
),
|
||||
},
|
||||
{"archive", ctx, false,
|
||||
config.Put{Mode: ModeArchive, Name: "a", Target: srv.URL + "/{{.ProjectName}}/{{.Version}}/", Username: "u1"},
|
||||
{"archive", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
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},
|
||||
check{"/blah/2.1.0/a.tar", "u1", "x", content},
|
||||
),
|
||||
},
|
||||
{"binary", ctx, false,
|
||||
config.Put{Mode: ModeBinary, Name: "a", Target: srv.URL + "/{{.ProjectName}}/{{.Version}}/", Username: "u2"},
|
||||
{"binary", 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",
|
||||
TrustedCerts: cert(s),
|
||||
}
|
||||
},
|
||||
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content}),
|
||||
},
|
||||
{"archive-with-checksum-and-signature", ctx, false,
|
||||
config.Put{Mode: ModeArchive, Name: "a", Target: srv.URL + "/{{.ProjectName}}/{{.Version}}/", Username: "u3", Checksum: true, Signature: true},
|
||||
{"binary-add-ending-bar", 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",
|
||||
TrustedCerts: cert(s),
|
||||
}
|
||||
},
|
||||
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content}),
|
||||
},
|
||||
{"archive-with-checksum-and-signature", true, true, false, false,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
Mode: ModeArchive,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
Username: "u3",
|
||||
Checksum: true,
|
||||
Signature: true,
|
||||
TrustedCerts: cert(s),
|
||||
}
|
||||
},
|
||||
checks(
|
||||
check{"/blah/2.1.0/a.deb", "u3", "x", content},
|
||||
check{"/blah/2.1.0/a.tar", "u3", "x", content},
|
||||
@ -285,16 +329,100 @@ func TestUpload(t *testing.T) {
|
||||
check{"/blah/2.1.0/a.sig", "u3", "x", content},
|
||||
),
|
||||
},
|
||||
{"bad-template", true, true, true, true,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
Mode: ModeBinary,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectNameXXX}}/{{.VersionXXX}}/",
|
||||
Username: "u3",
|
||||
Checksum: true,
|
||||
Signature: true,
|
||||
TrustedCerts: cert(s),
|
||||
}
|
||||
},
|
||||
checks(),
|
||||
},
|
||||
{"failed-request", true, true, true, true,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
Mode: ModeBinary,
|
||||
Name: "a",
|
||||
Target: s.URL[0:strings.LastIndex(s.URL, ":")] + "/{{.ProjectName}}/{{.Version}}/",
|
||||
Username: "u3",
|
||||
Checksum: true,
|
||||
Signature: true,
|
||||
TrustedCerts: cert(s),
|
||||
}
|
||||
},
|
||||
checks(),
|
||||
},
|
||||
{"broken-cert", false, true, false, true,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
return ctx, config.Put{
|
||||
Mode: ModeBinary,
|
||||
Name: "a",
|
||||
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
||||
Username: "u3",
|
||||
Checksum: false,
|
||||
Signature: false,
|
||||
TrustedCerts: "bad certs!",
|
||||
}
|
||||
},
|
||||
checks(),
|
||||
},
|
||||
{"skip-publishing", true, true, true, true,
|
||||
func(s *httptest.Server) (*context.Context, config.Put) {
|
||||
c := *ctx
|
||||
c.SkipPublish = true
|
||||
return &c, config.Put{}
|
||||
},
|
||||
checks(),
|
||||
},
|
||||
}
|
||||
|
||||
uploadAndCheck := func(setup func(*httptest.Server) (*context.Context, config.Put), wantErrPlain, wantErrTLS bool, check func(r []*h.Request) error, srv *httptest.Server) {
|
||||
requests = nil
|
||||
ctx, put := setup(srv)
|
||||
wantErr := wantErrPlain
|
||||
if srv.Certificate() != nil {
|
||||
wantErr = wantErrTLS
|
||||
}
|
||||
if err := Upload(ctx, []config.Put{put}, "test", is2xx); (err != nil) != wantErr {
|
||||
t.Errorf("Upload() error = %v, wantErr %v", err, wantErr)
|
||||
}
|
||||
if err := check(requests); err != nil {
|
||||
t.Errorf("Upload() request invalid. Error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
requests = nil
|
||||
if err := Upload(tt.ctx, []config.Put{tt.put}, "test", is2xx); (err != nil) != tt.wantErr {
|
||||
t.Errorf("Upload() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
if err := tt.check(requests); err != nil {
|
||||
t.Errorf("Upload() request invalid. Error: %v", err)
|
||||
}
|
||||
})
|
||||
if tt.tryPlain {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
srv := httptest.NewServer(mux)
|
||||
defer srv.Close()
|
||||
uploadAndCheck(tt.setup, tt.wantErrPlain, tt.wantErrTLS, tt.check, srv)
|
||||
})
|
||||
}
|
||||
if tt.tryTLS {
|
||||
t.Run(tt.name+"-tls", func(t *testing.T) {
|
||||
srv := httptest.NewUnstartedServer(mux)
|
||||
srv.StartTLS()
|
||||
defer srv.Close()
|
||||
uploadAndCheck(tt.setup, tt.wantErrPlain, tt.wantErrTLS, tt.check, srv)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func cert(srv *httptest.Server) string {
|
||||
if srv == nil || srv.Certificate() == nil {
|
||||
return ""
|
||||
}
|
||||
block := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: srv.Certificate().Raw,
|
||||
}
|
||||
return string(pem.EncodeToMemory(block))
|
||||
}
|
||||
|
@ -287,12 +287,13 @@ 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"`
|
||||
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"`
|
||||
}
|
||||
|
||||
// Project includes all project configuration
|
||||
|
@ -88,6 +88,34 @@ If your instance is named `production`, you need to store the secret in the
|
||||
environment variable `ARTIFACTORY_PRODUCTION_SECRET`.
|
||||
The name will be transformed to uppercase.
|
||||
|
||||
### Server authentication
|
||||
|
||||
You can authenticate your Artifactory TLS server adding a trusted X.509
|
||||
certificate chain in your 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 artifactory section with PEM encoded certificates on a YAML literal
|
||||
block like this:
|
||||
|
||||
```yaml
|
||||
puts:
|
||||
- name: "some artifactory server with a private TLS certificate"
|
||||
#...(other settings)...
|
||||
trusted_certificates: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
|
||||
...(edited content)...
|
||||
TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
|
||||
...(edited content)...
|
||||
TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
|
||||
-----END CERTIFICATE-----
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
Of course, you can customize a lot of things:
|
||||
@ -112,6 +140,13 @@ artifactories:
|
||||
checksum: true
|
||||
# Upload signatures (defaults to false)
|
||||
signature: true
|
||||
# Certificate chain used to validate server certificates
|
||||
trusted_certificates: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
|
||||
...(edited content)...
|
||||
TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
|
||||
-----END CERTIFICATE-----
|
||||
```
|
||||
|
||||
These settings should allow you to push your artifacts into multiple Artifactories.
|
||||
|
@ -5,7 +5,6 @@ hideFromIndex: true
|
||||
weight: 120
|
||||
---
|
||||
|
||||
Since [vX.Y.Z](https://github.com/goreleaser/goreleaser/releases/tag/vX.Y.Z),
|
||||
GoReleaser supports building and pushing artifacts to HTTP servers using simple HTTP PUT requests.
|
||||
|
||||
## How it works
|
||||
@ -85,6 +84,34 @@ If your instance is named `production`, you need to store the secret in the
|
||||
environment variable `PUT_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.
|
||||
|
||||
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
|
||||
like this:
|
||||
|
||||
```yaml
|
||||
puts:
|
||||
- name: "some HTTP/TLS server"
|
||||
#...(other settings)...
|
||||
trusted_certificates: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
|
||||
...(edited content)...
|
||||
TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
|
||||
...(edited content)...
|
||||
TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
|
||||
-----END CERTIFICATE-----
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
Of course, you can customize a lot of things:
|
||||
@ -102,13 +129,20 @@ puts:
|
||||
# Default is `archive`.
|
||||
mode: archive
|
||||
# URL to be used as target of the HTTP PUT request
|
||||
target: http://some.server/some/path/example-repo-local/{{ .ProjectName }}/{{ .Version }}/
|
||||
target: https://some.server/some/path/example-repo-local/{{ .ProjectName }}/{{ .Version }}/
|
||||
# User that will be used for the deployment
|
||||
username: deployuser
|
||||
# Upload checksums (defaults to false)
|
||||
checksum: true
|
||||
# Upload signatures (defaults to false)
|
||||
signature: true
|
||||
# Certificate chain used to validate server certificates
|
||||
trusted_certificates: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
|
||||
...(edited content)...
|
||||
TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
|
||||
-----END CERTIFICATE-----
|
||||
```
|
||||
|
||||
These settings should allow you to push your artifacts into multiple HTTP servers.
|
||||
|
Loading…
Reference in New Issue
Block a user