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