github.com/amane3/goreleaser@v0.182.0/internal/pipe/snapcraft/snapcraft_test.go (about)

     1  package snapcraft
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"syscall"
     9  	"testing"
    10  
    11  	"github.com/amane3/goreleaser/internal/artifact"
    12  	"github.com/amane3/goreleaser/internal/pipe"
    13  	"github.com/amane3/goreleaser/internal/testlib"
    14  	"github.com/amane3/goreleaser/pkg/config"
    15  	"github.com/amane3/goreleaser/pkg/context"
    16  	"github.com/stretchr/testify/require"
    17  	"gopkg.in/yaml.v2"
    18  )
    19  
    20  func TestDescription(t *testing.T) {
    21  	require.NotEmpty(t, Pipe{}.String())
    22  }
    23  
    24  func TestRunPipeMissingInfo(t *testing.T) {
    25  	for eerr, snap := range map[error]config.Snapcraft{
    26  		ErrNoSummary: {
    27  			Description: "dummy desc",
    28  		},
    29  		ErrNoDescription: {
    30  			Summary: "dummy summary",
    31  		},
    32  		pipe.Skip("no summary nor description were provided"): {},
    33  	} {
    34  		t.Run(fmt.Sprintf("testing if %v happens", eerr), func(t *testing.T) {
    35  			var ctx = &context.Context{
    36  				Config: config.Project{
    37  					Snapcrafts: []config.Snapcraft{
    38  						snap,
    39  					},
    40  				},
    41  			}
    42  			require.Equal(t, eerr, Pipe{}.Run(ctx))
    43  		})
    44  	}
    45  }
    46  
    47  func TestRunPipe(t *testing.T) {
    48  	var folder = t.TempDir()
    49  	var dist = filepath.Join(folder, "dist")
    50  	require.NoError(t, os.Mkdir(dist, 0755))
    51  	var ctx = context.New(config.Project{
    52  		ProjectName: "mybin",
    53  		Dist:        dist,
    54  		Snapcrafts: []config.Snapcraft{
    55  			{
    56  				NameTemplate: "foo_{{.Arch}}",
    57  				Summary:      "test summary",
    58  				Description:  "test description",
    59  				Publish:      true,
    60  				Builds:       []string{"foo"},
    61  			},
    62  			{
    63  				NameTemplate: "foo_and_bar_{{.Arch}}",
    64  				Summary:      "test summary",
    65  				Description:  "test description",
    66  				Publish:      true,
    67  				Builds:       []string{"foo", "bar"},
    68  			},
    69  			{
    70  				NameTemplate: "bar_{{.Arch}}",
    71  				Summary:      "test summary",
    72  				Description:  "test description",
    73  				Publish:      true,
    74  				Builds:       []string{"bar"},
    75  			},
    76  		},
    77  	})
    78  	ctx.Git.CurrentTag = "v1.2.3"
    79  	ctx.Version = "v1.2.3"
    80  	addBinaries(t, ctx, "foo", filepath.Join(dist, "foo"))
    81  	addBinaries(t, ctx, "bar", filepath.Join(dist, "bar"))
    82  	require.NoError(t, Pipe{}.Run(ctx))
    83  	list := ctx.Artifacts.Filter(artifact.ByType(artifact.PublishableSnapcraft)).List()
    84  	require.Len(t, list, 9)
    85  }
    86  
    87  func TestRunPipeInvalidNameTemplate(t *testing.T) {
    88  	var folder = t.TempDir()
    89  	var dist = filepath.Join(folder, "dist")
    90  	require.NoError(t, os.Mkdir(dist, 0755))
    91  	var ctx = context.New(config.Project{
    92  		ProjectName: "foo",
    93  		Dist:        dist,
    94  		Snapcrafts: []config.Snapcraft{
    95  			{
    96  				NameTemplate: "foo_{{.Arch}",
    97  				Summary:      "test summary",
    98  				Description:  "test description",
    99  				Builds:       []string{"foo"},
   100  			},
   101  		},
   102  	})
   103  	ctx.Git.CurrentTag = "v1.2.3"
   104  	ctx.Version = "v1.2.3"
   105  	addBinaries(t, ctx, "foo", dist)
   106  	require.EqualError(t, Pipe{}.Run(ctx), `template: tmpl:1: unexpected "}" in operand`)
   107  }
   108  
   109  func TestRunPipeWithName(t *testing.T) {
   110  	var folder = t.TempDir()
   111  	var dist = filepath.Join(folder, "dist")
   112  	require.NoError(t, os.Mkdir(dist, 0755))
   113  	var ctx = context.New(config.Project{
   114  		ProjectName: "testprojectname",
   115  		Dist:        dist,
   116  		Snapcrafts: []config.Snapcraft{
   117  			{
   118  				NameTemplate: "foo_{{.Arch}}",
   119  				Name:         "testsnapname",
   120  				Base:         "core18",
   121  				License:      "MIT",
   122  				Summary:      "test summary",
   123  				Description:  "test description",
   124  				Builds:       []string{"foo"},
   125  			},
   126  		},
   127  	})
   128  	ctx.Git.CurrentTag = "v1.2.3"
   129  	ctx.Version = "v1.2.3"
   130  	addBinaries(t, ctx, "foo", dist)
   131  	require.NoError(t, Pipe{}.Run(ctx))
   132  	yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "foo_amd64", "prime", "meta", "snap.yaml"))
   133  	require.NoError(t, err)
   134  	var metadata Metadata
   135  	err = yaml.Unmarshal(yamlFile, &metadata)
   136  	require.NoError(t, err)
   137  	require.Equal(t, "testsnapname", metadata.Name)
   138  	require.Equal(t, "core18", metadata.Base)
   139  	require.Equal(t, "MIT", metadata.License)
   140  	require.Equal(t, "foo", metadata.Apps["testsnapname"].Command)
   141  }
   142  
   143  func TestRunPipeMetadata(t *testing.T) {
   144  	var folder = t.TempDir()
   145  	var dist = filepath.Join(folder, "dist")
   146  	require.NoError(t, os.Mkdir(dist, 0755))
   147  	var ctx = context.New(config.Project{
   148  		ProjectName: "testprojectname",
   149  		Dist:        dist,
   150  		Snapcrafts: []config.Snapcraft{
   151  			{
   152  				Name:         "testprojectname",
   153  				NameTemplate: "foo_{{.Arch}}",
   154  				Summary:      "test summary",
   155  				Description:  "test description",
   156  				Apps: map[string]config.SnapcraftAppMetadata{
   157  					"foo": {
   158  						Plugs:            []string{"home", "network", "personal-files"},
   159  						Daemon:           "simple",
   160  						Args:             "--foo --bar",
   161  						RestartCondition: "always",
   162  					},
   163  				},
   164  				Plugs: map[string]interface{}{
   165  					"personal-files": map[string]interface{}{
   166  						"read": []string{"$HOME/test"},
   167  					},
   168  				},
   169  				Builds: []string{"foo"},
   170  			},
   171  		},
   172  	})
   173  	ctx.Git.CurrentTag = "v1.2.3"
   174  	ctx.Version = "v1.2.3"
   175  	addBinaries(t, ctx, "foo", dist)
   176  	require.NoError(t, Pipe{}.Run(ctx))
   177  	yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "foo_amd64", "prime", "meta", "snap.yaml"))
   178  	require.NoError(t, err)
   179  	var metadata Metadata
   180  	err = yaml.Unmarshal(yamlFile, &metadata)
   181  	require.NoError(t, err)
   182  	require.Equal(t, []string{"home", "network", "personal-files"}, metadata.Apps["foo"].Plugs)
   183  	require.Equal(t, "simple", metadata.Apps["foo"].Daemon)
   184  	require.Equal(t, "foo --foo --bar", metadata.Apps["foo"].Command)
   185  	require.Equal(t, []string{"home", "network", "personal-files"}, metadata.Apps["foo"].Plugs)
   186  	require.Equal(t, "simple", metadata.Apps["foo"].Daemon)
   187  	require.Equal(t, "foo --foo --bar", metadata.Apps["foo"].Command)
   188  	require.Equal(t, map[interface{}]interface{}{"read": []interface{}{"$HOME/test"}}, metadata.Plugs["personal-files"])
   189  	require.Equal(t, "always", metadata.Apps["foo"].RestartCondition)
   190  }
   191  
   192  func TestNoSnapcraftInPath(t *testing.T) {
   193  	var path = os.Getenv("PATH")
   194  	defer func() {
   195  		require.NoError(t, os.Setenv("PATH", path))
   196  	}()
   197  	require.NoError(t, os.Setenv("PATH", ""))
   198  	var ctx = context.New(config.Project{
   199  		Snapcrafts: []config.Snapcraft{
   200  			{
   201  				Summary:     "dummy",
   202  				Description: "dummy",
   203  			},
   204  		},
   205  	})
   206  	require.EqualError(t, Pipe{}.Run(ctx), ErrNoSnapcraft.Error())
   207  }
   208  
   209  func TestRunNoArguments(t *testing.T) {
   210  	var folder = t.TempDir()
   211  	var dist = filepath.Join(folder, "dist")
   212  	require.NoError(t, os.Mkdir(dist, 0755))
   213  	var ctx = context.New(config.Project{
   214  		ProjectName: "testprojectname",
   215  		Dist:        dist,
   216  		Snapcrafts: []config.Snapcraft{
   217  			{
   218  				NameTemplate: "foo_{{.Arch}}",
   219  				Summary:      "test summary",
   220  				Description:  "test description",
   221  				Apps: map[string]config.SnapcraftAppMetadata{
   222  					"foo": {
   223  						Daemon: "simple",
   224  						Args:   "",
   225  					},
   226  				},
   227  				Builds: []string{"foo"},
   228  			},
   229  		},
   230  	})
   231  	ctx.Git.CurrentTag = "v1.2.3"
   232  	ctx.Version = "v1.2.3"
   233  	addBinaries(t, ctx, "foo", dist)
   234  	require.NoError(t, Pipe{}.Run(ctx))
   235  	yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "foo_amd64", "prime", "meta", "snap.yaml"))
   236  	require.NoError(t, err)
   237  	var metadata Metadata
   238  	err = yaml.Unmarshal(yamlFile, &metadata)
   239  	require.NoError(t, err)
   240  	require.Equal(t, "foo", metadata.Apps["foo"].Command)
   241  }
   242  
   243  func TestCompleter(t *testing.T) {
   244  	var folder = t.TempDir()
   245  	var dist = filepath.Join(folder, "dist")
   246  	require.NoError(t, os.Mkdir(dist, 0755))
   247  	var ctx = context.New(config.Project{
   248  		ProjectName: "testprojectname",
   249  		Dist:        dist,
   250  		Snapcrafts: []config.Snapcraft{
   251  			{
   252  				NameTemplate: "foo_{{.Arch}}",
   253  				Summary:      "test summary",
   254  				Description:  "test description",
   255  				Apps: map[string]config.SnapcraftAppMetadata{
   256  					"foo": {
   257  						Daemon:    "simple",
   258  						Args:      "",
   259  						Completer: "testdata/foo-completer.bash",
   260  					},
   261  				},
   262  				Builds: []string{"foo", "bar"},
   263  			},
   264  		},
   265  	})
   266  	ctx.Git.CurrentTag = "v1.2.3"
   267  	ctx.Version = "v1.2.3"
   268  	addBinaries(t, ctx, "foo", dist)
   269  	addBinaries(t, ctx, "bar", dist)
   270  	require.NoError(t, Pipe{}.Run(ctx))
   271  	yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "foo_amd64", "prime", "meta", "snap.yaml"))
   272  	require.NoError(t, err)
   273  	var metadata Metadata
   274  	err = yaml.Unmarshal(yamlFile, &metadata)
   275  	require.NoError(t, err)
   276  	require.Equal(t, "foo", metadata.Apps["foo"].Command)
   277  	require.Equal(t, "testdata/foo-completer.bash", metadata.Apps["foo"].Completer)
   278  }
   279  
   280  func TestCommand(t *testing.T) {
   281  	var folder = t.TempDir()
   282  	var dist = filepath.Join(folder, "dist")
   283  	require.NoError(t, os.Mkdir(dist, 0755))
   284  	var ctx = context.New(config.Project{
   285  		ProjectName: "testprojectname",
   286  		Dist:        dist,
   287  		Snapcrafts: []config.Snapcraft{
   288  			{
   289  				NameTemplate: "foo_{{.Arch}}",
   290  				Summary:      "test summary",
   291  				Description:  "test description",
   292  				Apps: map[string]config.SnapcraftAppMetadata{
   293  					"foo": {
   294  						Daemon:  "simple",
   295  						Args:    "--bar custom command",
   296  						Command: "foo",
   297  					},
   298  				},
   299  				Builds: []string{"foo"},
   300  			},
   301  		},
   302  	})
   303  	ctx.Git.CurrentTag = "v1.2.3"
   304  	ctx.Version = "v1.2.3"
   305  	addBinaries(t, ctx, "foo", dist)
   306  	require.NoError(t, Pipe{}.Run(ctx))
   307  	yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "foo_amd64", "prime", "meta", "snap.yaml"))
   308  	require.NoError(t, err)
   309  	var metadata Metadata
   310  	err = yaml.Unmarshal(yamlFile, &metadata)
   311  	require.NoError(t, err)
   312  	require.Equal(t, "foo --bar custom command", metadata.Apps["foo"].Command)
   313  }
   314  
   315  func TestExtraFile(t *testing.T) {
   316  	var folder = t.TempDir()
   317  	var dist = filepath.Join(folder, "dist")
   318  	require.NoError(t, os.Mkdir(dist, 0755))
   319  	var ctx = context.New(config.Project{
   320  		ProjectName: "testprojectname",
   321  		Dist:        dist,
   322  		Snapcrafts: []config.Snapcraft{
   323  			{
   324  				NameTemplate: "foo_{{.Arch}}",
   325  				Summary:      "test summary",
   326  				Description:  "test description",
   327  				Files: []config.SnapcraftExtraFiles{
   328  					{
   329  						Source:      "testdata/extra-file.txt",
   330  						Destination: "a/b/c/extra-file.txt",
   331  						Mode:        0755,
   332  					},
   333  					{
   334  						Source: "testdata/extra-file-2.txt",
   335  					},
   336  				},
   337  				Builds: []string{"foo"},
   338  			},
   339  		},
   340  	})
   341  	ctx.Git.CurrentTag = "v1.2.3"
   342  	ctx.Version = "v1.2.3"
   343  	addBinaries(t, ctx, "foo", dist)
   344  	require.NoError(t, Pipe{}.Run(ctx))
   345  
   346  	srcFile, err := os.Stat("testdata/extra-file.txt")
   347  	require.NoError(t, err)
   348  	destFile, err := os.Stat(filepath.Join(dist, "foo_amd64", "prime", "a", "b", "c", "extra-file.txt"))
   349  	require.NoError(t, err)
   350  	require.Equal(t, inode(srcFile), inode(destFile))
   351  	require.Equal(t, destFile.Mode(), os.FileMode(0755))
   352  
   353  	srcFile, err = os.Stat("testdata/extra-file-2.txt")
   354  	require.NoError(t, err)
   355  	destFileWithDefaults, err := os.Stat(filepath.Join(dist, "foo_amd64", "prime", "testdata", "extra-file-2.txt"))
   356  	require.NoError(t, err)
   357  	require.Equal(t, destFileWithDefaults.Mode(), os.FileMode(0644))
   358  	require.Equal(t, inode(srcFile), inode(destFileWithDefaults))
   359  }
   360  
   361  func TestDefault(t *testing.T) {
   362  	var ctx = context.New(config.Project{
   363  		Builds: []config.Build{
   364  			{
   365  				ID: "foo",
   366  			},
   367  		},
   368  		Snapcrafts: []config.Snapcraft{
   369  			{},
   370  		},
   371  	})
   372  	require.NoError(t, Pipe{}.Default(ctx))
   373  	require.Equal(t, defaultNameTemplate, ctx.Config.Snapcrafts[0].NameTemplate)
   374  	require.Equal(t, []string{"foo"}, ctx.Config.Snapcrafts[0].Builds)
   375  }
   376  
   377  func TestPublish(t *testing.T) {
   378  	var ctx = context.New(config.Project{})
   379  	ctx.Artifacts.Add(&artifact.Artifact{
   380  		Name:   "mybin",
   381  		Path:   "nope.snap",
   382  		Goarch: "amd64",
   383  		Goos:   "linux",
   384  		Type:   artifact.PublishableSnapcraft,
   385  	})
   386  	err := Pipe{}.Publish(ctx)
   387  	require.Contains(t, err.Error(), "failed to push nope.snap package")
   388  }
   389  
   390  func TestPublishSkip(t *testing.T) {
   391  	var ctx = context.New(config.Project{})
   392  	ctx.SkipPublish = true
   393  	ctx.Artifacts.Add(&artifact.Artifact{
   394  		Name:   "mybin",
   395  		Path:   "nope.snap",
   396  		Goarch: "amd64",
   397  		Goos:   "linux",
   398  		Type:   artifact.PublishableSnapcraft,
   399  	})
   400  	testlib.AssertSkipped(t, Pipe{}.Publish(ctx))
   401  }
   402  
   403  func TestDefaultSet(t *testing.T) {
   404  	var ctx = context.New(config.Project{
   405  		Snapcrafts: []config.Snapcraft{
   406  			{
   407  				NameTemplate: "foo",
   408  			},
   409  		},
   410  	})
   411  	require.NoError(t, Pipe{}.Default(ctx))
   412  	require.Equal(t, "foo", ctx.Config.Snapcrafts[0].NameTemplate)
   413  }
   414  
   415  func addBinaries(t *testing.T, ctx *context.Context, name, dist string) {
   416  	for _, goos := range []string{"linux", "darwin"} {
   417  		for _, goarch := range []string{"amd64", "386", "arm6"} {
   418  			var folder = goos + goarch
   419  			require.NoError(t, os.MkdirAll(filepath.Join(dist, folder), 0755))
   420  			var binPath = filepath.Join(dist, folder, name)
   421  			_, err := os.Create(binPath)
   422  			require.NoError(t, err)
   423  			ctx.Artifacts.Add(&artifact.Artifact{
   424  				Name:   name,
   425  				Path:   binPath,
   426  				Goarch: goarch,
   427  				Goos:   goos,
   428  				Type:   artifact.Binary,
   429  				Extra: map[string]interface{}{
   430  					"ID": name,
   431  				},
   432  			})
   433  		}
   434  	}
   435  }
   436  
   437  func TestSeveralSnapssWithTheSameID(t *testing.T) {
   438  	var ctx = &context.Context{
   439  		Config: config.Project{
   440  			Snapcrafts: []config.Snapcraft{
   441  				{
   442  					ID: "a",
   443  				},
   444  				{
   445  					ID: "a",
   446  				},
   447  			},
   448  		},
   449  	}
   450  	require.EqualError(t, Pipe{}.Default(ctx), "found 2 snapcrafts with the ID 'a', please fix your config")
   451  }
   452  
   453  func Test_isValidArch(t *testing.T) {
   454  	tests := []struct {
   455  		arch string
   456  		want bool
   457  	}{
   458  		{"s390x", true},
   459  		{"ppc64el", true},
   460  		{"arm64", true},
   461  		{"armhf", true},
   462  		{"amd64", true},
   463  		{"i386", true},
   464  		{"mips", false},
   465  		{"armel", false},
   466  	}
   467  	for _, tt := range tests {
   468  		t.Run(tt.arch, func(t *testing.T) {
   469  			require.Equal(t, tt.want, isValidArch(tt.arch))
   470  		})
   471  	}
   472  }
   473  
   474  func inode(info os.FileInfo) uint64 {
   475  	stat := info.Sys().(*syscall.Stat_t)
   476  	return stat.Ino
   477  }