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