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 }