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