github.com/amane3/goreleaser@v0.182.0/internal/pipe/artifactory/artifactory_test.go (about)

     1  package artifactory
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"os"
     9  	"path/filepath"
    10  	"sync"
    11  	"testing"
    12  
    13  	"github.com/amane3/goreleaser/internal/artifact"
    14  	"github.com/amane3/goreleaser/internal/pipe"
    15  	"github.com/amane3/goreleaser/pkg/config"
    16  	"github.com/amane3/goreleaser/pkg/context"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  var (
    21  	// mux is the HTTP request multiplexer used with the test server.
    22  	mux *http.ServeMux
    23  
    24  	// server is a test HTTP server used to provide mock API responses.
    25  	server *httptest.Server
    26  )
    27  
    28  func setup() {
    29  	// test server
    30  	mux = http.NewServeMux()
    31  	server = httptest.NewServer(mux)
    32  }
    33  
    34  // teardown closes the test HTTP server.
    35  func teardown() {
    36  	server.Close()
    37  }
    38  
    39  func testMethod(t *testing.T, r *http.Request, want string) {
    40  	if got := r.Method; got != want {
    41  		t.Errorf("Request method: %v, want %v", got, want)
    42  	}
    43  }
    44  
    45  func testHeader(t *testing.T, r *http.Request, header, want string) {
    46  	if got := r.Header.Get(header); got != want {
    47  		t.Errorf("Header.Get(%q) returned %q, want %q", header, got, want)
    48  	}
    49  }
    50  
    51  // TODO: improve all tests bellow by checking wether the mocked handlers
    52  // were called or not.
    53  
    54  func TestRunPipe_ModeBinary(t *testing.T) {
    55  	setup()
    56  	defer teardown()
    57  
    58  	var folder = t.TempDir()
    59  	var dist = filepath.Join(folder, "dist")
    60  	require.NoError(t, os.Mkdir(dist, 0755))
    61  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
    62  	var binPath = filepath.Join(dist, "mybin", "mybin")
    63  	d1 := []byte("hello\ngo\n")
    64  	require.NoError(t, ioutil.WriteFile(binPath, d1, 0666))
    65  
    66  	// Dummy artifactories
    67  	mux.HandleFunc("/example-repo-local/mybin/darwin/amd64/mybin", func(w http.ResponseWriter, r *http.Request) {
    68  		testMethod(t, r, http.MethodPut)
    69  		testHeader(t, r, "Content-Length", "9")
    70  		// Basic auth of user "deployuser" with secret "deployuser-secret"
    71  		testHeader(t, r, "Authorization", "Basic ZGVwbG95dXNlcjpkZXBsb3l1c2VyLXNlY3JldA==")
    72  
    73  		w.WriteHeader(http.StatusCreated)
    74  		fmt.Fprint(w, `{
    75  			"repo" : "example-repo-local",
    76  			"path" : "/mybin/darwin/amd64/mybin",
    77  			"created" : "2017-12-02T19:30:45.436Z",
    78  			"createdBy" : "deployuser",
    79  			"downloadUri" : "http://127.0.0.1:56563/example-repo-local/mybin/darwin/amd64/mybin",
    80  			"mimeType" : "application/octet-stream",
    81  			"size" : "9",
    82  			"checksums" : {
    83  			  "sha1" : "65d01857a69f14ade727fe1ceee0f52a264b6e57",
    84  			  "md5" : "a55e303e7327dc871a8e2a84f30b9983",
    85  			  "sha256" : "ead9b172aec5c24ca6c12e85a1e6fc48dd341d8fac38c5ba00a78881eabccf0e"
    86  			},
    87  			"originalChecksums" : {
    88  			  "sha256" : "ead9b172aec5c24ca6c12e85a1e6fc48dd341d8fac38c5ba00a78881eabccf0e"
    89  			},
    90  			"uri" : "http://127.0.0.1:56563/example-repo-local/mybin/darwin/amd64/mybin"
    91  		  }`)
    92  	})
    93  	mux.HandleFunc("/example-repo-local/mybin/linux/amd64/mybin", func(w http.ResponseWriter, r *http.Request) {
    94  		testMethod(t, r, http.MethodPut)
    95  		testHeader(t, r, "Content-Length", "9")
    96  		// Basic auth of user "deployuser" with secret "deployuser-secret"
    97  		testHeader(t, r, "Authorization", "Basic ZGVwbG95dXNlcjpkZXBsb3l1c2VyLXNlY3JldA==")
    98  
    99  		w.WriteHeader(http.StatusCreated)
   100  		fmt.Fprint(w, `{
   101  			"repo" : "example-repo-local",
   102  			"path" : "mybin/linux/amd64/mybin",
   103  			"created" : "2017-12-02T19:30:46.436Z",
   104  			"createdBy" : "deployuser",
   105  			"downloadUri" : "http://127.0.0.1:56563/example-repo-local/mybin/linux/amd64/mybin",
   106  			"mimeType" : "application/octet-stream",
   107  			"size" : "9",
   108  			"checksums" : {
   109  			  "sha1" : "65d01857a69f14ade727fe1ceee0f52a264b6e57",
   110  			  "md5" : "a55e303e7327dc871a8e2a84f30b9983",
   111  			  "sha256" : "ead9b172aec5c24ca6c12e85a1e6fc48dd341d8fac38c5ba00a78881eabccf0e"
   112  			},
   113  			"originalChecksums" : {
   114  			  "sha256" : "ead9b172aec5c24ca6c12e85a1e6fc48dd341d8fac38c5ba00a78881eabccf0e"
   115  			},
   116  			"uri" : "http://127.0.0.1:56563/example-repo-local/mybin/linux/amd64/mybin"
   117  		  }`)
   118  	})
   119  	mux.HandleFunc("/production-repo-remote/mybin/darwin/amd64/mybin", func(w http.ResponseWriter, r *http.Request) {
   120  		testMethod(t, r, http.MethodPut)
   121  		testHeader(t, r, "Content-Length", "9")
   122  		// Basic auth of user "productionuser" with secret "productionuser-apikey"
   123  		testHeader(t, r, "Authorization", "Basic cHJvZHVjdGlvbnVzZXI6cHJvZHVjdGlvbnVzZXItYXBpa2V5")
   124  
   125  		w.WriteHeader(http.StatusCreated)
   126  		fmt.Fprint(w, `{
   127  			"repo" : "production-repo-remote",
   128  			"path" : "mybin/darwin/amd64/mybin",
   129  			"created" : "2017-12-02T19:30:46.436Z",
   130  			"createdBy" : "productionuser",
   131  			"downloadUri" : "http://127.0.0.1:56563/production-repo-remote/mybin/darwin/amd64/mybin",
   132  			"mimeType" : "application/octet-stream",
   133  			"size" : "9",
   134  			"checksums" : {
   135  			  "sha1" : "65d01857a69f14ade727fe1ceee0f52a264b6e57",
   136  			  "md5" : "a55e303e7327dc871a8e2a84f30b9983",
   137  			  "sha256" : "ead9b172aec5c24ca6c12e85a1e6fc48dd341d8fac38c5ba00a78881eabccf0e"
   138  			},
   139  			"originalChecksums" : {
   140  			  "sha256" : "ead9b172aec5c24ca6c12e85a1e6fc48dd341d8fac38c5ba00a78881eabccf0e"
   141  			},
   142  			"uri" : "http://127.0.0.1:56563/production-repo-remote/mybin/darwin/amd64/mybin"
   143  		  }`)
   144  	})
   145  	mux.HandleFunc("/production-repo-remote/mybin/linux/amd64/mybin", func(w http.ResponseWriter, r *http.Request) {
   146  		testMethod(t, r, http.MethodPut)
   147  		testHeader(t, r, "Content-Length", "9")
   148  		// Basic auth of user "productionuser" with secret "productionuser-apikey"
   149  		testHeader(t, r, "Authorization", "Basic cHJvZHVjdGlvbnVzZXI6cHJvZHVjdGlvbnVzZXItYXBpa2V5")
   150  
   151  		w.WriteHeader(http.StatusCreated)
   152  		fmt.Fprint(w, `{
   153  			"repo" : "production-repo-remote",
   154  			"path" : "mybin/linux/amd64/mybin",
   155  			"created" : "2017-12-02T19:30:46.436Z",
   156  			"createdBy" : "productionuser",
   157  			"downloadUri" : "http://127.0.0.1:56563/production-repo-remote/mybin/linux/amd64/mybin",
   158  			"mimeType" : "application/octet-stream",
   159  			"size" : "9",
   160  			"checksums" : {
   161  			  "sha1" : "65d01857a69f14ade727fe1ceee0f52a264b6e57",
   162  			  "md5" : "a55e303e7327dc871a8e2a84f30b9983",
   163  			  "sha256" : "ead9b172aec5c24ca6c12e85a1e6fc48dd341d8fac38c5ba00a78881eabccf0e"
   164  			},
   165  			"originalChecksums" : {
   166  			  "sha256" : "ead9b172aec5c24ca6c12e85a1e6fc48dd341d8fac38c5ba00a78881eabccf0e"
   167  			},
   168  			"uri" : "http://127.0.0.1:56563/production-repo-remote/mybin/linux/amd64/mybin"
   169  		  }`)
   170  	})
   171  
   172  	var ctx = context.New(config.Project{
   173  		ProjectName: "mybin",
   174  		Dist:        dist,
   175  		Artifactories: []config.Upload{
   176  			{
   177  				Name:     "production-us",
   178  				Mode:     "binary",
   179  				Target:   fmt.Sprintf("%s/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}", server.URL),
   180  				Username: "deployuser",
   181  			},
   182  			{
   183  				Name:     "production-eu",
   184  				Mode:     "binary",
   185  				Target:   fmt.Sprintf("%s/production-repo-remote/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}", server.URL),
   186  				Username: "productionuser",
   187  			},
   188  		},
   189  		Archives: []config.Archive{
   190  			{},
   191  		},
   192  	})
   193  	ctx.Env = map[string]string{
   194  		"ARTIFACTORY_PRODUCTION-US_SECRET": "deployuser-secret",
   195  		"ARTIFACTORY_PRODUCTION-EU_SECRET": "productionuser-apikey",
   196  	}
   197  	for _, goos := range []string{"linux", "darwin"} {
   198  		ctx.Artifacts.Add(&artifact.Artifact{
   199  			Name:   "mybin",
   200  			Path:   binPath,
   201  			Goarch: "amd64",
   202  			Goos:   goos,
   203  			Type:   artifact.UploadableBinary,
   204  		})
   205  	}
   206  
   207  	require.NoError(t, Pipe{}.Default(ctx))
   208  	require.NoError(t, Pipe{}.Publish(ctx))
   209  }
   210  
   211  func TestRunPipe_ModeArchive(t *testing.T) {
   212  	setup()
   213  	defer teardown()
   214  
   215  	var folder = t.TempDir()
   216  	tarfile, err := os.Create(filepath.Join(folder, "bin.tar.gz"))
   217  	require.NoError(t, err)
   218  	debfile, err := os.Create(filepath.Join(folder, "bin.deb"))
   219  	require.NoError(t, err)
   220  
   221  	var ctx = context.New(config.Project{
   222  		ProjectName: "goreleaser",
   223  		Dist:        folder,
   224  		Artifactories: []config.Upload{
   225  			{
   226  				Name:     "production",
   227  				Mode:     "archive",
   228  				Target:   fmt.Sprintf("%s/example-repo-local/{{ .ProjectName }}/{{ .Version }}/", server.URL),
   229  				Username: "deployuser",
   230  			},
   231  		},
   232  		Archives: []config.Archive{
   233  			{},
   234  		},
   235  	})
   236  	ctx.Env = map[string]string{
   237  		"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
   238  	}
   239  	ctx.Version = "1.0.0"
   240  	ctx.Artifacts.Add(&artifact.Artifact{
   241  		Type: artifact.UploadableArchive,
   242  		Name: "bin.tar.gz",
   243  		Path: tarfile.Name(),
   244  	})
   245  	ctx.Artifacts.Add(&artifact.Artifact{
   246  		Type: artifact.LinuxPackage,
   247  		Name: "bin.deb",
   248  		Path: debfile.Name(),
   249  	})
   250  
   251  	var uploads sync.Map
   252  
   253  	// Dummy artifactories
   254  	mux.HandleFunc("/example-repo-local/goreleaser/1.0.0/bin.tar.gz", func(w http.ResponseWriter, r *http.Request) {
   255  		testMethod(t, r, http.MethodPut)
   256  		// Basic auth of user "deployuser" with secret "deployuser-secret"
   257  		testHeader(t, r, "Authorization", "Basic ZGVwbG95dXNlcjpkZXBsb3l1c2VyLXNlY3JldA==")
   258  
   259  		w.WriteHeader(http.StatusCreated)
   260  		fmt.Fprint(w, `{
   261  			"repo" : "example-repo-local",
   262  			"path" : "/goreleaser/bin.tar.gz",
   263  			"created" : "2017-12-02T19:30:45.436Z",
   264  			"createdBy" : "deployuser",
   265  			"downloadUri" : "http://127.0.0.1:56563/example-repo-local/goreleaser/bin.tar.gz",
   266  			"mimeType" : "application/octet-stream",
   267  			"size" : "9",
   268  			"checksums" : {
   269  			  "sha1" : "65d01857a69f14ade727fe1ceee0f52a264b6e57",
   270  			  "md5" : "a55e303e7327dc871a8e2a84f30b9983",
   271  			  "sha256" : "ead9b172aec5c24ca6c12e85a1e6fc48dd341d8fac38c5ba00a78881eabccf0e"
   272  			},
   273  			"originalChecksums" : {
   274  			  "sha256" : "ead9b172aec5c24ca6c12e85a1e6fc48dd341d8fac38c5ba00a78881eabccf0e"
   275  			},
   276  			"uri" : "http://127.0.0.1:56563/example-repo-local/goreleaser/bin.tar.gz"
   277  		  }`)
   278  		uploads.Store("targz", true)
   279  	})
   280  	mux.HandleFunc("/example-repo-local/goreleaser/1.0.0/bin.deb", func(w http.ResponseWriter, r *http.Request) {
   281  		testMethod(t, r, http.MethodPut)
   282  		// Basic auth of user "deployuser" with secret "deployuser-secret"
   283  		testHeader(t, r, "Authorization", "Basic ZGVwbG95dXNlcjpkZXBsb3l1c2VyLXNlY3JldA==")
   284  
   285  		w.WriteHeader(http.StatusCreated)
   286  		fmt.Fprint(w, `{
   287  			"repo" : "example-repo-local",
   288  			"path" : "goreleaser/bin.deb",
   289  			"created" : "2017-12-02T19:30:46.436Z",
   290  			"createdBy" : "deployuser",
   291  			"downloadUri" : "http://127.0.0.1:56563/example-repo-local/goreleaser/bin.deb",
   292  			"mimeType" : "application/octet-stream",
   293  			"size" : "9",
   294  			"checksums" : {
   295  			  "sha1" : "65d01857a69f14ade727fe1ceee0f52a264b6e57",
   296  			  "md5" : "a55e303e7327dc871a8e2a84f30b9983",
   297  			  "sha256" : "ead9b172aec5c24ca6c12e85a1e6fc48dd341d8fac38c5ba00a78881eabccf0e"
   298  			},
   299  			"originalChecksums" : {
   300  			  "sha256" : "ead9b172aec5c24ca6c12e85a1e6fc48dd341d8fac38c5ba00a78881eabccf0e"
   301  			},
   302  			"uri" : "http://127.0.0.1:56563/example-repo-local/goreleaser/bin.deb"
   303  		  }`)
   304  		uploads.Store("deb", true)
   305  	})
   306  
   307  	require.NoError(t, Pipe{}.Default(ctx))
   308  	require.NoError(t, Pipe{}.Publish(ctx))
   309  	_, ok := uploads.Load("targz")
   310  	require.True(t, ok, "tar.gz file was not uploaded")
   311  	_, ok = uploads.Load("deb")
   312  	require.True(t, ok, "deb file was not uploaded")
   313  }
   314  
   315  func TestRunPipe_ArtifactoryDown(t *testing.T) {
   316  	var folder = t.TempDir()
   317  	tarfile, err := os.Create(filepath.Join(folder, "bin.tar.gz"))
   318  	require.NoError(t, err)
   319  
   320  	var ctx = context.New(config.Project{
   321  		ProjectName: "goreleaser",
   322  		Dist:        folder,
   323  		Artifactories: []config.Upload{
   324  			{
   325  				Name:     "production",
   326  				Mode:     "archive",
   327  				Target:   "http://localhost:1234/example-repo-local/{{ .ProjectName }}/{{ .Version }}/",
   328  				Username: "deployuser",
   329  			},
   330  		},
   331  	})
   332  	ctx.Version = "2.0.0"
   333  	ctx.Env = map[string]string{
   334  		"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
   335  	}
   336  	ctx.Artifacts.Add(&artifact.Artifact{
   337  		Type: artifact.UploadableArchive,
   338  		Name: "bin.tar.gz",
   339  		Path: tarfile.Name(),
   340  	})
   341  
   342  	require.NoError(t, Pipe{}.Default(ctx))
   343  	err = Pipe{}.Publish(ctx)
   344  	require.Error(t, err)
   345  	require.Contains(t, err.Error(), "connection refused")
   346  }
   347  
   348  func TestRunPipe_TargetTemplateError(t *testing.T) {
   349  	var folder = t.TempDir()
   350  	var dist = filepath.Join(folder, "dist")
   351  	var binPath = filepath.Join(dist, "mybin", "mybin")
   352  
   353  	var ctx = context.New(config.Project{
   354  		ProjectName: "mybin",
   355  		Dist:        dist,
   356  		Artifactories: []config.Upload{
   357  			{
   358  				Name: "production",
   359  				Mode: "binary",
   360  				// This template is not correct and should fail
   361  				Target:   "http://storage.company.com/example-repo-local/{{ .ProjectName /{{ .Version }}/",
   362  				Username: "deployuser",
   363  			},
   364  		},
   365  		Archives: []config.Archive{
   366  			{},
   367  		},
   368  	})
   369  	ctx.Env = map[string]string{
   370  		"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
   371  	}
   372  	ctx.Artifacts.Add(&artifact.Artifact{
   373  		Name:   "mybin",
   374  		Path:   binPath,
   375  		Goarch: "amd64",
   376  		Goos:   "darwin",
   377  		Type:   artifact.UploadableBinary,
   378  	})
   379  
   380  	require.NoError(t, Pipe{}.Default(ctx))
   381  	require.EqualError(t, Pipe{}.Publish(ctx), `artifactory: error while building the target url: template: tmpl:1: unexpected "/" in operand`)
   382  }
   383  
   384  func TestRunPipe_BadCredentials(t *testing.T) {
   385  	setup()
   386  	defer teardown()
   387  
   388  	var folder = t.TempDir()
   389  	var dist = filepath.Join(folder, "dist")
   390  	require.NoError(t, os.Mkdir(dist, 0755))
   391  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
   392  	var binPath = filepath.Join(dist, "mybin", "mybin")
   393  	d1 := []byte("hello\ngo\n")
   394  	require.NoError(t, ioutil.WriteFile(binPath, d1, 0666))
   395  
   396  	// Dummy artifactories
   397  	mux.HandleFunc("/example-repo-local/mybin/darwin/amd64/mybin", func(w http.ResponseWriter, r *http.Request) {
   398  		testMethod(t, r, http.MethodPut)
   399  		testHeader(t, r, "Content-Length", "9")
   400  		// Basic auth of user "deployuser" with secret "deployuser-secret"
   401  		testHeader(t, r, "Authorization", "Basic ZGVwbG95dXNlcjpkZXBsb3l1c2VyLXNlY3JldA==")
   402  
   403  		w.WriteHeader(http.StatusUnauthorized)
   404  		fmt.Fprint(w, `{
   405  			"errors" : [ {
   406  			  "status" : 401,
   407  			  "message" : "Bad credentials"
   408  			} ]
   409  		  }`)
   410  	})
   411  
   412  	var ctx = context.New(config.Project{
   413  		ProjectName: "mybin",
   414  		Dist:        dist,
   415  		Artifactories: []config.Upload{
   416  			{
   417  				Name:     "production",
   418  				Mode:     "binary",
   419  				Target:   fmt.Sprintf("%s/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}", server.URL),
   420  				Username: "deployuser",
   421  			},
   422  		},
   423  		Archives: []config.Archive{
   424  			{},
   425  		},
   426  	})
   427  	ctx.Env = map[string]string{
   428  		"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
   429  	}
   430  	ctx.Artifacts.Add(&artifact.Artifact{
   431  		Name:   "mybin",
   432  		Path:   binPath,
   433  		Goarch: "amd64",
   434  		Goos:   "darwin",
   435  		Type:   artifact.UploadableBinary,
   436  	})
   437  
   438  	require.NoError(t, Pipe{}.Default(ctx))
   439  	var err = Pipe{}.Publish(ctx)
   440  	require.Error(t, err)
   441  	require.Contains(t, err.Error(), "Bad credentials")
   442  }
   443  
   444  func TestRunPipe_UnparsableErrorResponse(t *testing.T) {
   445  	setup()
   446  	defer teardown()
   447  
   448  	var folder = t.TempDir()
   449  	var dist = filepath.Join(folder, "dist")
   450  	require.NoError(t, os.Mkdir(dist, 0755))
   451  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
   452  	var binPath = filepath.Join(dist, "mybin", "mybin")
   453  	d1 := []byte("hello\ngo\n")
   454  	require.NoError(t, ioutil.WriteFile(binPath, d1, 0666))
   455  
   456  	// Dummy artifactories
   457  	mux.HandleFunc("/example-repo-local/mybin/darwin/amd64/mybin", func(w http.ResponseWriter, r *http.Request) {
   458  		testMethod(t, r, http.MethodPut)
   459  		testHeader(t, r, "Content-Length", "9")
   460  		// Basic auth of user "deployuser" with secret "deployuser-secret"
   461  		testHeader(t, r, "Authorization", "Basic ZGVwbG95dXNlcjpkZXBsb3l1c2VyLXNlY3JldA==")
   462  
   463  		w.WriteHeader(http.StatusUnauthorized)
   464  		fmt.Fprint(w, `...{
   465  			"errors" : [ {
   466  			 ...
   467  			} ]
   468  		  }`)
   469  	})
   470  
   471  	var ctx = context.New(config.Project{
   472  		ProjectName: "mybin",
   473  		Dist:        dist,
   474  		Artifactories: []config.Upload{
   475  			{
   476  				Name:     "production",
   477  				Mode:     "binary",
   478  				Target:   fmt.Sprintf("%s/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}", server.URL),
   479  				Username: "deployuser",
   480  			},
   481  		},
   482  		Archives: []config.Archive{
   483  			{},
   484  		},
   485  	})
   486  	ctx.Env = map[string]string{
   487  		"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
   488  	}
   489  	ctx.Artifacts.Add(&artifact.Artifact{
   490  		Name:   "mybin",
   491  		Path:   binPath,
   492  		Goarch: "amd64",
   493  		Goos:   "darwin",
   494  		Type:   artifact.UploadableBinary,
   495  	})
   496  
   497  	require.NoError(t, Pipe{}.Default(ctx))
   498  	require.EqualError(t, Pipe{}.Publish(ctx), `artifactory: upload failed: invalid character '.' looking for beginning of value`)
   499  }
   500  
   501  func TestRunPipe_FileNotFound(t *testing.T) {
   502  	var ctx = context.New(config.Project{
   503  		ProjectName: "mybin",
   504  		Dist:        "archivetest/dist",
   505  		Artifactories: []config.Upload{
   506  			{
   507  				Name:     "production",
   508  				Mode:     "binary",
   509  				Target:   "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
   510  				Username: "deployuser",
   511  			},
   512  		},
   513  		Archives: []config.Archive{
   514  			{},
   515  		},
   516  	})
   517  	ctx.Env = map[string]string{
   518  		"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
   519  	}
   520  	ctx.Artifacts.Add(&artifact.Artifact{
   521  		Name:   "mybin",
   522  		Path:   "archivetest/dist/mybin/mybin",
   523  		Goarch: "amd64",
   524  		Goos:   "darwin",
   525  		Type:   artifact.UploadableBinary,
   526  	})
   527  
   528  	require.NoError(t, Pipe{}.Default(ctx))
   529  	require.EqualError(t, Pipe{}.Publish(ctx), `open archivetest/dist/mybin/mybin: no such file or directory`)
   530  }
   531  
   532  func TestRunPipe_UnparsableTarget(t *testing.T) {
   533  	var folder = t.TempDir()
   534  	var dist = filepath.Join(folder, "dist")
   535  	require.NoError(t, os.Mkdir(dist, 0755))
   536  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
   537  	var binPath = filepath.Join(dist, "mybin", "mybin")
   538  	d1 := []byte("hello\ngo\n")
   539  	require.NoError(t, ioutil.WriteFile(binPath, d1, 0666))
   540  
   541  	var ctx = context.New(config.Project{
   542  		ProjectName: "mybin",
   543  		Dist:        dist,
   544  		Artifactories: []config.Upload{
   545  			{
   546  				Name:     "production",
   547  				Mode:     "binary",
   548  				Target:   "://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
   549  				Username: "deployuser",
   550  			},
   551  		},
   552  		Archives: []config.Archive{
   553  			{},
   554  		},
   555  	})
   556  	ctx.Env = map[string]string{
   557  		"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
   558  	}
   559  	ctx.Artifacts.Add(&artifact.Artifact{
   560  		Name:   "mybin",
   561  		Path:   binPath,
   562  		Goarch: "amd64",
   563  		Goos:   "darwin",
   564  		Type:   artifact.UploadableBinary,
   565  	})
   566  
   567  	require.NoError(t, Pipe{}.Default(ctx))
   568  	require.EqualError(t, Pipe{}.Publish(ctx), `artifactory: upload failed: parse "://artifacts.company.com/example-repo-local/mybin/darwin/amd64/mybin": missing protocol scheme`)
   569  }
   570  
   571  func TestRunPipe_SkipWhenPublishFalse(t *testing.T) {
   572  	var ctx = context.New(config.Project{
   573  		Artifactories: []config.Upload{
   574  			{
   575  				Name:     "production",
   576  				Mode:     "binary",
   577  				Target:   "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
   578  				Username: "deployuser",
   579  			},
   580  		},
   581  		Archives: []config.Archive{
   582  			{},
   583  		},
   584  	})
   585  	ctx.Env = map[string]string{
   586  		"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
   587  	}
   588  	ctx.SkipPublish = true
   589  
   590  	require.NoError(t, Pipe{}.Default(ctx))
   591  	err := Pipe{}.Publish(ctx)
   592  	require.True(t, pipe.IsSkip(err))
   593  	require.EqualError(t, err, pipe.ErrSkipPublishEnabled.Error())
   594  }
   595  
   596  func TestRunPipe_DirUpload(t *testing.T) {
   597  	var folder = t.TempDir()
   598  	var dist = filepath.Join(folder, "dist")
   599  	require.NoError(t, os.Mkdir(dist, 0755))
   600  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
   601  	var binPath = filepath.Join(dist, "mybin")
   602  
   603  	var ctx = context.New(config.Project{
   604  		ProjectName: "mybin",
   605  		Dist:        dist,
   606  		Artifactories: []config.Upload{
   607  			{
   608  				Name:     "production",
   609  				Mode:     "binary",
   610  				Target:   "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
   611  				Username: "deployuser",
   612  			},
   613  		},
   614  		Archives: []config.Archive{
   615  			{},
   616  		},
   617  	})
   618  	ctx.Env = map[string]string{
   619  		"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
   620  	}
   621  	ctx.Artifacts.Add(&artifact.Artifact{
   622  		Name:   "mybin",
   623  		Path:   filepath.Dir(binPath),
   624  		Goarch: "amd64",
   625  		Goos:   "darwin",
   626  		Type:   artifact.UploadableBinary,
   627  	})
   628  
   629  	require.NoError(t, Pipe{}.Default(ctx))
   630  	require.EqualError(t, Pipe{}.Publish(ctx), `artifactory: upload failed: the asset to upload can't be a directory`)
   631  }
   632  
   633  func TestDescription(t *testing.T) {
   634  	require.NotEmpty(t, Pipe{}.String())
   635  }
   636  
   637  func TestNoArtifactories(t *testing.T) {
   638  	var ctx = context.New(config.Project{})
   639  	require.NoError(t, Pipe{}.Default(ctx))
   640  	require.True(t, pipe.IsSkip(Pipe{}.Publish(ctx)))
   641  }
   642  
   643  func TestArtifactoriesWithoutTarget(t *testing.T) {
   644  	var ctx = &context.Context{
   645  		Env: map[string]string{
   646  			"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
   647  		},
   648  		Config: config.Project{
   649  			Artifactories: []config.Upload{
   650  				{
   651  					Name:     "production",
   652  					Username: "deployuser",
   653  				},
   654  			},
   655  		},
   656  	}
   657  
   658  	require.NoError(t, Pipe{}.Default(ctx))
   659  	require.True(t, pipe.IsSkip(Pipe{}.Publish(ctx)))
   660  }
   661  
   662  func TestArtifactoriesWithoutUsername(t *testing.T) {
   663  	var ctx = &context.Context{
   664  		Env: map[string]string{
   665  			"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
   666  		},
   667  		Config: config.Project{
   668  			Artifactories: []config.Upload{
   669  				{
   670  					Name:   "production",
   671  					Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
   672  				},
   673  			},
   674  		},
   675  	}
   676  
   677  	require.NoError(t, Pipe{}.Default(ctx))
   678  	require.True(t, pipe.IsSkip(Pipe{}.Publish(ctx)))
   679  }
   680  
   681  func TestArtifactoriesWithoutName(t *testing.T) {
   682  	var ctx = context.New(config.Project{
   683  		Artifactories: []config.Upload{
   684  			{
   685  				Username: "deployuser",
   686  				Target:   "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
   687  			},
   688  		},
   689  	})
   690  	require.NoError(t, Pipe{}.Default(ctx))
   691  	require.True(t, pipe.IsSkip(Pipe{}.Publish(ctx)))
   692  }
   693  
   694  func TestArtifactoriesWithoutSecret(t *testing.T) {
   695  	var ctx = context.New(config.Project{
   696  		Artifactories: []config.Upload{
   697  			{
   698  				Name:     "production",
   699  				Target:   "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
   700  				Username: "deployuser",
   701  			},
   702  		},
   703  	})
   704  	require.NoError(t, Pipe{}.Default(ctx))
   705  	require.True(t, pipe.IsSkip(Pipe{}.Publish(ctx)))
   706  }
   707  
   708  func TestArtifactoriesWithInvalidMode(t *testing.T) {
   709  	var ctx = &context.Context{
   710  		Env: map[string]string{
   711  			"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
   712  		},
   713  		Config: config.Project{
   714  			Artifactories: []config.Upload{
   715  				{
   716  					Name:     "production",
   717  					Mode:     "does-not-exists",
   718  					Target:   "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
   719  					Username: "deployuser",
   720  				},
   721  			},
   722  		},
   723  	}
   724  
   725  	require.NoError(t, Pipe{}.Default(ctx))
   726  	require.Error(t, Pipe{}.Publish(ctx))
   727  }
   728  
   729  func TestDefault(t *testing.T) {
   730  	var ctx = &context.Context{
   731  		Config: config.Project{
   732  			Artifactories: []config.Upload{
   733  				{
   734  					Name:     "production",
   735  					Target:   "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
   736  					Username: "deployuser",
   737  				},
   738  			},
   739  		},
   740  	}
   741  
   742  	require.NoError(t, Pipe{}.Default(ctx))
   743  	require.Len(t, ctx.Config.Artifactories, 1)
   744  	var artifactory = ctx.Config.Artifactories[0]
   745  	require.Equal(t, "archive", artifactory.Mode)
   746  }
   747  
   748  func TestDefaultNoArtifactories(t *testing.T) {
   749  	var ctx = &context.Context{
   750  		Config: config.Project{
   751  			Artifactories: []config.Upload{},
   752  		},
   753  	}
   754  	require.NoError(t, Pipe{}.Default(ctx))
   755  	require.Empty(t, ctx.Config.Artifactories)
   756  }
   757  
   758  func TestDefaultSet(t *testing.T) {
   759  	var ctx = &context.Context{
   760  		Config: config.Project{
   761  			Artifactories: []config.Upload{
   762  				{
   763  					Mode: "custom",
   764  				},
   765  			},
   766  		},
   767  	}
   768  	require.NoError(t, Pipe{}.Default(ctx))
   769  	require.Len(t, ctx.Config.Artifactories, 1)
   770  	var artifactory = ctx.Config.Artifactories[0]
   771  	require.Equal(t, "custom", artifactory.Mode)
   772  	require.Equal(t, "X-Checksum-SHA256", artifactory.ChecksumHeader)
   773  }