github.com/amane3/goreleaser@v0.182.0/internal/pipe/blob/blob_minio_test.go (about)

     1  package blob
     2  
     3  // this is pretty much copied from the s3 pipe to ensure both work the same way
     4  // only differences are that it sets `blobs` instead of `s3` on test cases and
     5  // the test setup and teardown
     6  
     7  import (
     8  	"io"
     9  	"io/ioutil"
    10  	"net"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"strings"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/amane3/goreleaser/internal/artifact"
    19  	"github.com/amane3/goreleaser/pkg/config"
    20  	"github.com/amane3/goreleaser/pkg/context"
    21  	"github.com/stretchr/testify/require"
    22  	"gocloud.dev/blob"
    23  )
    24  
    25  func TestMinioUpload(t *testing.T) {
    26  	var listen = randomListen(t)
    27  	var folder = t.TempDir()
    28  	srcpath := filepath.Join(folder, "source.tar.gz")
    29  	tgzpath := filepath.Join(folder, "bin.tar.gz")
    30  	debpath := filepath.Join(folder, "bin.deb")
    31  	checkpath := filepath.Join(folder, "check.txt")
    32  	require.NoError(t, ioutil.WriteFile(checkpath, []byte("fake checksums"), 0744))
    33  	require.NoError(t, ioutil.WriteFile(srcpath, []byte("fake\nsrc"), 0744))
    34  	require.NoError(t, ioutil.WriteFile(tgzpath, []byte("fake\ntargz"), 0744))
    35  	require.NoError(t, ioutil.WriteFile(debpath, []byte("fake\ndeb"), 0744))
    36  	var ctx = context.New(config.Project{
    37  		Dist:        folder,
    38  		ProjectName: "testupload",
    39  		Blobs: []config.Blob{
    40  			{
    41  				Provider: "s3",
    42  				Bucket:   "test",
    43  				Region:   "us-east",
    44  				Endpoint: "http://" + listen,
    45  				IDs:      []string{"foo", "bar"},
    46  			},
    47  		},
    48  	})
    49  	ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
    50  	ctx.Artifacts.Add(&artifact.Artifact{
    51  		Type: artifact.Checksum,
    52  		Name: "checksum.txt",
    53  		Path: checkpath,
    54  	})
    55  	ctx.Artifacts.Add(&artifact.Artifact{
    56  		Type: artifact.UploadableSourceArchive,
    57  		Name: "source.tar.gz",
    58  		Path: srcpath,
    59  		Extra: map[string]interface{}{
    60  			"Format": "tar.gz",
    61  		},
    62  	})
    63  	ctx.Artifacts.Add(&artifact.Artifact{
    64  		Type: artifact.UploadableArchive,
    65  		Name: "bin.tar.gz",
    66  		Path: tgzpath,
    67  		Extra: map[string]interface{}{
    68  			"ID": "foo",
    69  		},
    70  	})
    71  	ctx.Artifacts.Add(&artifact.Artifact{
    72  		Type: artifact.LinuxPackage,
    73  		Name: "bin.deb",
    74  		Path: debpath,
    75  		Extra: map[string]interface{}{
    76  			"ID": "bar",
    77  		},
    78  	})
    79  	var name = "test_upload"
    80  	start(t, name, listen)
    81  	prepareEnv()
    82  	require.NoError(t, Pipe{}.Default(ctx))
    83  	require.NoError(t, Pipe{}.Publish(ctx))
    84  
    85  	require.Subset(t, getFiles(t, ctx, ctx.Config.Blobs[0]), []string{
    86  		"testupload/v1.0.0/bin.deb",
    87  		"testupload/v1.0.0/bin.tar.gz",
    88  		"testupload/v1.0.0/checksum.txt",
    89  		"testupload/v1.0.0/source.tar.gz",
    90  	})
    91  }
    92  
    93  func TestMinioUploadCustomBucketID(t *testing.T) {
    94  	var listen = randomListen(t)
    95  	var folder = t.TempDir()
    96  	tgzpath := filepath.Join(folder, "bin.tar.gz")
    97  	debpath := filepath.Join(folder, "bin.deb")
    98  	require.NoError(t, ioutil.WriteFile(tgzpath, []byte("fake\ntargz"), 0744))
    99  	require.NoError(t, ioutil.WriteFile(debpath, []byte("fake\ndeb"), 0744))
   100  	// Set custom BUCKET_ID env variable.
   101  	require.NoError(t, os.Setenv("BUCKET_ID", "test"))
   102  	var ctx = context.New(config.Project{
   103  		Dist:        folder,
   104  		ProjectName: "testupload",
   105  		Blobs: []config.Blob{
   106  			{
   107  				Provider: "s3",
   108  				Bucket:   "{{.Env.BUCKET_ID}}",
   109  				Endpoint: "http://" + listen,
   110  			},
   111  		},
   112  	})
   113  	ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
   114  	ctx.Artifacts.Add(&artifact.Artifact{
   115  		Type: artifact.UploadableArchive,
   116  		Name: "bin.tar.gz",
   117  		Path: tgzpath,
   118  	})
   119  	ctx.Artifacts.Add(&artifact.Artifact{
   120  		Type: artifact.LinuxPackage,
   121  		Name: "bin.deb",
   122  		Path: debpath,
   123  	})
   124  	var name = "custom_bucket_id"
   125  	start(t, name, listen)
   126  	prepareEnv()
   127  	require.NoError(t, Pipe{}.Default(ctx))
   128  	require.NoError(t, Pipe{}.Publish(ctx))
   129  }
   130  
   131  func TestMinioUploadInvalidCustomBucketID(t *testing.T) {
   132  	var listen = randomListen(t)
   133  	var folder = t.TempDir()
   134  	tgzpath := filepath.Join(folder, "bin.tar.gz")
   135  	debpath := filepath.Join(folder, "bin.deb")
   136  	require.NoError(t, ioutil.WriteFile(tgzpath, []byte("fake\ntargz"), 0744))
   137  	require.NoError(t, ioutil.WriteFile(debpath, []byte("fake\ndeb"), 0744))
   138  	var ctx = context.New(config.Project{
   139  		Dist:        folder,
   140  		ProjectName: "testupload",
   141  		Blobs: []config.Blob{
   142  			{
   143  				Provider: "s3",
   144  				Bucket:   "{{.Bad}}",
   145  				Endpoint: "http://" + listen,
   146  			},
   147  		},
   148  	})
   149  	ctx.Git = context.GitInfo{CurrentTag: "v1.1.0"}
   150  	ctx.Artifacts.Add(&artifact.Artifact{
   151  		Type: artifact.UploadableArchive,
   152  		Name: "bin.tar.gz",
   153  		Path: tgzpath,
   154  	})
   155  	ctx.Artifacts.Add(&artifact.Artifact{
   156  		Type: artifact.LinuxPackage,
   157  		Name: "bin.deb",
   158  		Path: debpath,
   159  	})
   160  	var name = "invalid_bucket_id"
   161  	start(t, name, listen)
   162  	prepareEnv()
   163  	require.NoError(t, Pipe{}.Default(ctx))
   164  	require.Error(t, Pipe{}.Publish(ctx))
   165  }
   166  
   167  func TestMinioUploadSkipPublish(t *testing.T) {
   168  	var listen = randomListen(t)
   169  	var folder = t.TempDir()
   170  	srcpath := filepath.Join(folder, "source.tar.gz")
   171  	tgzpath := filepath.Join(folder, "bin.tar.gz")
   172  	debpath := filepath.Join(folder, "bin.deb")
   173  	checkpath := filepath.Join(folder, "check.txt")
   174  	require.NoError(t, ioutil.WriteFile(checkpath, []byte("fake checksums"), 0744))
   175  	require.NoError(t, ioutil.WriteFile(srcpath, []byte("fake\nsrc"), 0744))
   176  	require.NoError(t, ioutil.WriteFile(tgzpath, []byte("fake\ntargz"), 0744))
   177  	require.NoError(t, ioutil.WriteFile(debpath, []byte("fake\ndeb"), 0744))
   178  	var ctx = context.New(config.Project{
   179  		Dist:        folder,
   180  		ProjectName: "testupload",
   181  		Blobs: []config.Blob{
   182  			{
   183  				Provider: "s3",
   184  				Bucket:   "test",
   185  				Region:   "us-east",
   186  				Endpoint: "http://" + listen,
   187  				IDs:      []string{"foo", "bar"},
   188  			},
   189  		},
   190  	})
   191  	ctx.SkipPublish = true
   192  	ctx.Git = context.GitInfo{CurrentTag: "v1.2.0"}
   193  	ctx.Artifacts.Add(&artifact.Artifact{
   194  		Type: artifact.Checksum,
   195  		Name: "checksum.txt",
   196  		Path: checkpath,
   197  	})
   198  	ctx.Artifacts.Add(&artifact.Artifact{
   199  		Type: artifact.UploadableSourceArchive,
   200  		Name: "source.tar.gz",
   201  		Path: srcpath,
   202  		Extra: map[string]interface{}{
   203  			"Format": "tar.gz",
   204  		},
   205  	})
   206  	ctx.Artifacts.Add(&artifact.Artifact{
   207  		Type: artifact.UploadableArchive,
   208  		Name: "bin.tar.gz",
   209  		Path: tgzpath,
   210  		Extra: map[string]interface{}{
   211  			"ID": "foo",
   212  		},
   213  	})
   214  	ctx.Artifacts.Add(&artifact.Artifact{
   215  		Type: artifact.LinuxPackage,
   216  		Name: "bin.deb",
   217  		Path: debpath,
   218  		Extra: map[string]interface{}{
   219  			"ID": "bar",
   220  		},
   221  	})
   222  	var name = "test_upload"
   223  	start(t, name, listen)
   224  	prepareEnv()
   225  	require.NoError(t, Pipe{}.Default(ctx))
   226  	require.NoError(t, Pipe{}.Publish(ctx))
   227  
   228  	require.NotContains(t, getFiles(t, ctx, ctx.Config.Blobs[0]), []string{
   229  		"testupload/v1.2.0/bin.deb",
   230  		"testupload/v1.2.0/bin.tar.gz",
   231  		"testupload/v1.2.0/checksum.txt",
   232  		"testupload/v1.2.0/source.tar.gz",
   233  	})
   234  }
   235  
   236  func randomListen(t *testing.T) string {
   237  	listener, err := net.Listen("tcp", "127.0.0.1:0")
   238  	require.NoError(t, err)
   239  	listener.Close()
   240  	return listener.Addr().String()
   241  }
   242  
   243  func prepareEnv() {
   244  	os.Setenv("AWS_ACCESS_KEY_ID", "minio")
   245  	os.Setenv("AWS_SECRET_ACCESS_KEY", "miniostorage")
   246  	os.Setenv("AWS_REGION", "us-east-1")
   247  }
   248  
   249  func start(t testing.TB, name, listen string) {
   250  	wd, err := os.Getwd()
   251  	require.NoError(t, err)
   252  
   253  	removeTestData()
   254  
   255  	t.Cleanup(func() {
   256  		if out, err := exec.Command("docker", "stop", name).CombinedOutput(); err != nil {
   257  			t.Fatalf("failed to stop minio: %s", string(out))
   258  		}
   259  		removeTestData()
   260  	})
   261  
   262  	if out, err := exec.Command(
   263  		"docker", "run", "-d", "--rm",
   264  		"-v", filepath.Join(wd, "testdata/data")+":/data",
   265  		"--name", name,
   266  		"-p", listen+":9000",
   267  		"-e", "MINIO_ACCESS_KEY=minio",
   268  		"-e", "MINIO_SECRET_KEY=miniostorage",
   269  		"--health-interval", "1s",
   270  		"--health-cmd=curl --silent --fail http://localhost:9000/minio/health/ready || exit 1",
   271  		"minio/minio",
   272  		"server", "/data",
   273  	).CombinedOutput(); err != nil {
   274  		t.Fatalf("failed to start minio: %s", string(out))
   275  	}
   276  
   277  	for range time.Tick(time.Second) {
   278  		out, err := exec.Command("docker", "inspect", "--format='{{json .State.Health}}'", name).CombinedOutput()
   279  		if err != nil {
   280  			t.Fatalf("failed to check minio status: %s", string(out))
   281  		}
   282  		if strings.Contains(string(out), `"Status":"healthy"`) {
   283  			t.Log("minio is healthy")
   284  			break
   285  		}
   286  		t.Log("waiting for minio to be healthy")
   287  	}
   288  }
   289  
   290  func removeTestData() {
   291  	_ = os.RemoveAll("./testdata/data/test/testupload") // dont care if it fails
   292  }
   293  
   294  func getFiles(t *testing.T, ctx *context.Context, cfg config.Blob) []string {
   295  	url, err := urlFor(ctx, cfg)
   296  	require.NoError(t, err)
   297  	conn, err := blob.OpenBucket(ctx, url)
   298  	require.NoError(t, err)
   299  	defer conn.Close()
   300  	var iter = conn.List(nil)
   301  	var files []string
   302  	for {
   303  		file, err := iter.Next(ctx)
   304  		if err != nil && err == io.EOF {
   305  			break
   306  		}
   307  		require.NoError(t, err)
   308  		files = append(files, file.Key)
   309  	}
   310  	return files
   311  }