1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-03-21 21:07:19 +02:00
goreleaser/internal/pipe/blob/openbucket.go
C123R 73b74a3169 feat: add support for pushing artifacts to cloud storage provider( S3, Azure Blob, GCS) (#1036)
* feat: adding support to push artifacts to AWS S3,Azure Blob and Google Cloud Storage

readme for blob publisher

test: add unit test for blob using testify and mockery

test: add unit test for publish method

fix: openbucket instance initialization

remove unwanted packages: go mod tidy

test: add missing unit test for publish method

* doc: add missing comment for func

* fix: add accidental delete file

* fix : add missing Snapcrafts project

* fix: unit test for Azure blob

* fmt: rewrite if-else-if-else chain to switch statement and fix golangci-lint reporeted issue

* fmt: fix linter reporeted issues

fmt: rewrite if-else-if-else chain to switch statement and fix golangci-lint reporeted issue

fmt: linter fix

* test: fix typo in test error string

* feat: add support to provider folder inside bucket, resolves discussed comments
2019-06-05 10:51:01 -03:00

112 lines
3.4 KiB
Go

package blob
import (
"fmt"
"io/ioutil"
"path/filepath"
"github.com/apex/log"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/semerrgroup"
"github.com/goreleaser/goreleaser/pkg/context"
gocdk "gocloud.dev/blob"
// Import the blob packages we want to be able to open.
_ "gocloud.dev/blob/azureblob"
_ "gocloud.dev/blob/gcsblob"
_ "gocloud.dev/blob/s3blob"
)
// OpenBucket is the interface that wraps the BucketConnect and UploadBucket method
type OpenBucket interface {
Connect(ctx *context.Context, bucketURL string) (*gocdk.Bucket, error)
Upload(ctx *context.Context, bucketURL string, folder string) error
}
// Bucket is object which holds connection for Go Bucker Provider
type Bucket struct {
BucketConn *gocdk.Bucket
}
// returns openbucket connection for list of providers
func newOpenBucket() OpenBucket {
return Bucket{}
}
// BucketConnect makes connection with provider
func (b Bucket) Connect(ctx *context.Context, bucketURL string) (*gocdk.Bucket, error) {
bucketConnection, err := gocdk.OpenBucket(ctx, bucketURL)
if err != nil {
return nil, err
}
return bucketConnection, nil
}
// UploadBucket takes connection initilized from newOpenBucket to upload goreleaser artifacts
// Takes goreleaser context(which includes artificats) and bucketURL for upload destination (gs://gorelease-bucket)
func (b Bucket) Upload(ctx *context.Context, bucketURL string, folder string) error {
// Get the openbucket connection for specific provider
openbucketConn, err := b.Connect(ctx, bucketURL)
if err != nil {
return err
}
defer openbucketConn.Close()
var g = semerrgroup.New(ctx.Parallelism)
for _, artifact := range ctx.Artifacts.Filter(
artifact.Or(
artifact.ByType(artifact.UploadableArchive),
artifact.ByType(artifact.UploadableBinary),
artifact.ByType(artifact.Checksum),
artifact.ByType(artifact.Signature),
artifact.ByType(artifact.LinuxPackage),
),
).List() {
artifact := artifact
g.Go(func() error {
// Prepare artifact for upload.
data, err := ioutil.ReadFile(artifact.Path)
if err != nil {
return err
}
log.WithFields(log.Fields{
"provider": bucketURL,
"artifact": artifact.Name,
}).Info("uploading")
w, err := openbucketConn.NewWriter(ctx, filepath.Join(folder, artifact.Path), nil)
if err != nil {
return fmt.Errorf("failed to obtain writer: %s", err)
}
_, err = w.Write(data)
if err != nil {
if errorContains(err, "NoSuchBucket", "ContainerNotFound", "notFound") {
return fmt.Errorf("(%v) provided bucket does not exist", bucketURL)
}
return fmt.Errorf("failed to write to bucket : %s", err)
}
if err = w.Close(); err != nil {
switch {
case errorContains(err, "InvalidAccessKeyId"):
return fmt.Errorf("aws access key id you provided does not exist in our records")
case errorContains(err, "AuthenticationFailed"):
return fmt.Errorf("azure storage key you provided is not valid")
case errorContains(err, "invalid_grant"):
return fmt.Errorf("google app credentials you provided is not valid")
case errorContains(err, "no such host"):
return fmt.Errorf("azure storage account you provided is not valid")
case errorContains(err, "NoSuchBucket", "ContainerNotFound", "notFound"):
return fmt.Errorf("(%v) provided bucket does not exist", bucketURL)
default:
return fmt.Errorf("failed to close Bucket writer: %s", err)
}
}
return err
})
}
return g.Wait()
}