github.com/goreleaser/goreleaser@v1.25.1/internal/pipe/checksums/checksums_test.go (about) 1 package checksums 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 "syscall" 9 "testing" 10 11 "github.com/goreleaser/goreleaser/internal/artifact" 12 "github.com/goreleaser/goreleaser/internal/testctx" 13 "github.com/goreleaser/goreleaser/internal/testlib" 14 "github.com/goreleaser/goreleaser/pkg/config" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestDescription(t *testing.T) { 19 require.NotEmpty(t, Pipe{}.String()) 20 } 21 22 func TestPipe(t *testing.T) { 23 const binary = "binary" 24 const archive = binary + ".tar.gz" 25 const linuxPackage = binary + ".rpm" 26 const checksums = binary + "_bar_checksums.txt" 27 const sum = "61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc " 28 29 tests := map[string]struct { 30 ids []string 31 want string 32 }{ 33 "default": { 34 want: strings.Join([]string{ 35 sum + binary, 36 sum + linuxPackage, 37 sum + archive, 38 }, "\n") + "\n", 39 }, 40 "select ids": { 41 ids: []string{ 42 "id-1", 43 "id-2", 44 }, 45 want: strings.Join([]string{ 46 sum + binary, 47 sum + archive, 48 }, "\n") + "\n", 49 }, 50 } 51 for name, tt := range tests { 52 t.Run(name, func(t *testing.T) { 53 folder := t.TempDir() 54 file := filepath.Join(folder, binary) 55 require.NoError(t, os.WriteFile(file, []byte("some string"), 0o644)) 56 ctx := testctx.NewWithCfg( 57 config.Project{ 58 Dist: folder, 59 ProjectName: binary, 60 Checksum: config.Checksum{ 61 NameTemplate: "{{ .ProjectName }}_{{ .Env.FOO }}_checksums.txt", 62 Algorithm: "sha256", 63 IDs: tt.ids, 64 }, 65 Env: []string{"FOO=bar"}, 66 }, 67 testctx.WithCurrentTag("1.2.3"), 68 ) 69 ctx.Artifacts.Add(&artifact.Artifact{ 70 Name: binary, 71 Path: file, 72 Type: artifact.UploadableBinary, 73 Extra: map[string]interface{}{ 74 artifact.ExtraID: "id-1", 75 }, 76 }) 77 ctx.Artifacts.Add(&artifact.Artifact{ 78 Name: archive, 79 Path: file, 80 Type: artifact.UploadableArchive, 81 Extra: map[string]interface{}{ 82 artifact.ExtraID: "id-2", 83 }, 84 }) 85 ctx.Artifacts.Add(&artifact.Artifact{ 86 Name: linuxPackage, 87 Path: file, 88 Type: artifact.LinuxPackage, 89 Extra: map[string]interface{}{ 90 artifact.ExtraID: "id-3", 91 }, 92 }) 93 require.NoError(t, Pipe{}.Run(ctx)) 94 var artifacts []string 95 for _, a := range ctx.Artifacts.List() { 96 artifacts = append(artifacts, a.Name) 97 require.NoError(t, a.Refresh(), "refresh should not fail and yield same results as nothing changed") 98 } 99 require.Contains(t, artifacts, checksums, binary) 100 bts, err := os.ReadFile(filepath.Join(folder, checksums)) 101 require.NoError(t, err) 102 require.Contains(t, tt.want, string(bts)) 103 }) 104 } 105 } 106 107 func TestPipeSplit(t *testing.T) { 108 const binary = "binary" 109 const archive = binary + ".tar.gz" 110 const linuxPackage = binary + ".rpm" 111 const sum = "61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc" 112 113 folder := t.TempDir() 114 file := filepath.Join(folder, binary) 115 require.NoError(t, os.WriteFile(file, []byte("some string"), 0o644)) 116 ctx := testctx.NewWithCfg( 117 config.Project{ 118 Dist: folder, 119 ProjectName: "foo", 120 Checksum: config.Checksum{ 121 Split: true, 122 }, 123 }, 124 ) 125 ctx.Artifacts.Add(&artifact.Artifact{ 126 Name: binary, 127 Path: file, 128 Type: artifact.UploadableBinary, 129 Extra: map[string]interface{}{ 130 artifact.ExtraID: "id-1", 131 }, 132 }) 133 ctx.Artifacts.Add(&artifact.Artifact{ 134 Name: archive, 135 Path: file, 136 Type: artifact.UploadableArchive, 137 Extra: map[string]interface{}{ 138 artifact.ExtraID: "id-2", 139 }, 140 }) 141 ctx.Artifacts.Add(&artifact.Artifact{ 142 Name: linuxPackage, 143 Path: file, 144 Type: artifact.LinuxPackage, 145 Extra: map[string]interface{}{ 146 artifact.ExtraID: "id-3", 147 }, 148 }) 149 require.NoError(t, Pipe{}.Default(ctx)) 150 require.NoError(t, Pipe{}.Run(ctx)) 151 152 require.NoError(t, ctx.Artifacts.Visit(func(a *artifact.Artifact) error { 153 return a.Refresh() 154 })) 155 156 checks := ctx.Artifacts.Filter(artifact.ByType(artifact.Checksum)).List() 157 require.Len(t, checks, 3) 158 159 for _, check := range checks { 160 require.NotEmpty(t, check.Extra[artifact.ExtraChecksumOf]) 161 bts, err := os.ReadFile(check.Path) 162 require.NoError(t, err) 163 require.Equal(t, sum, string(bts)) 164 } 165 } 166 167 func TestRefreshModifying(t *testing.T) { 168 const binary = "binary" 169 folder := t.TempDir() 170 file := filepath.Join(folder, binary) 171 require.NoError(t, os.WriteFile(file, []byte("some string"), 0o644)) 172 ctx := testctx.NewWithCfg(config.Project{ 173 Dist: folder, 174 ProjectName: binary, 175 Checksum: config.Checksum{ 176 NameTemplate: "{{ .ProjectName }}_{{ .Env.FOO }}_checksums.txt", 177 Algorithm: "sha256", 178 }, 179 Env: []string{"FOO=bar"}, 180 }, testctx.WithCurrentTag("1.2.3")) 181 ctx.Artifacts.Add(&artifact.Artifact{ 182 Name: binary, 183 Path: file, 184 Type: artifact.UploadableBinary, 185 }) 186 require.NoError(t, Pipe{}.Run(ctx)) 187 checks := ctx.Artifacts.Filter(artifact.ByType(artifact.Checksum)).List() 188 require.Len(t, checks, 1) 189 previous, err := os.ReadFile(checks[0].Path) 190 require.NoError(t, err) 191 require.NoError(t, os.WriteFile(file, []byte("some other string"), 0o644)) 192 require.NoError(t, checks[0].Refresh()) 193 current, err := os.ReadFile(checks[0].Path) 194 require.NoError(t, err) 195 require.NotEqual(t, string(previous), string(current)) 196 } 197 198 func TestRefreshModifyingSplit(t *testing.T) { 199 const binary = "binary" 200 folder := t.TempDir() 201 file := filepath.Join(folder, binary) 202 require.NoError(t, os.WriteFile(file, []byte("some string"), 0o644)) 203 ctx := testctx.NewWithCfg(config.Project{ 204 Dist: folder, 205 ProjectName: binary, 206 Checksum: config.Checksum{ 207 Split: true, 208 }, 209 Env: []string{"FOO=bar"}, 210 }, testctx.WithCurrentTag("1.2.3")) 211 ctx.Artifacts.Add(&artifact.Artifact{ 212 Name: binary, 213 Path: file, 214 Type: artifact.UploadableBinary, 215 }) 216 require.NoError(t, Pipe{}.Default(ctx)) 217 require.NoError(t, Pipe{}.Run(ctx)) 218 checks := ctx.Artifacts.Filter(artifact.ByType(artifact.Checksum)).List() 219 require.Len(t, checks, 1) 220 previous, err := os.ReadFile(checks[0].Path) 221 require.NoError(t, err) 222 require.NoError(t, os.WriteFile(file, []byte("some other string"), 0o644)) 223 require.NoError(t, checks[0].Refresh()) 224 current, err := os.ReadFile(checks[0].Path) 225 require.NoError(t, err) 226 require.NotEqual(t, string(previous), string(current)) 227 } 228 229 func TestPipeFileNotExist(t *testing.T) { 230 folder := t.TempDir() 231 ctx := testctx.NewWithCfg( 232 config.Project{ 233 Dist: folder, 234 Checksum: config.Checksum{ 235 NameTemplate: "checksums.txt", 236 }, 237 }, 238 testctx.WithCurrentTag("1.2.3"), 239 ) 240 ctx.Artifacts.Add(&artifact.Artifact{ 241 Name: "nope", 242 Path: "/nope", 243 Type: artifact.UploadableBinary, 244 }) 245 require.ErrorIs(t, Pipe{}.Run(ctx), os.ErrNotExist) 246 } 247 248 func TestPipeInvalidNameTemplate(t *testing.T) { 249 binFile, err := os.CreateTemp(t.TempDir(), "goreleasertest-bin") 250 require.NoError(t, err) 251 t.Cleanup(func() { require.NoError(t, binFile.Close()) }) 252 _, err = binFile.WriteString("fake artifact") 253 require.NoError(t, err) 254 255 for _, template := range []string{ 256 "{{ .Pro }_checksums.txt", 257 "{{.Env.NOPE}}", 258 } { 259 for _, split := range []bool{true, false} { 260 t.Run(fmt.Sprintf("split_%v_%s", split, template), func(t *testing.T) { 261 folder := t.TempDir() 262 ctx := testctx.NewWithCfg( 263 config.Project{ 264 Dist: folder, 265 ProjectName: "name", 266 Checksum: config.Checksum{ 267 NameTemplate: template, 268 Algorithm: "sha256", 269 Split: split, 270 }, 271 }, 272 testctx.WithCurrentTag("1.2.3"), 273 ) 274 ctx.Artifacts.Add(&artifact.Artifact{ 275 Name: "whatever", 276 Type: artifact.UploadableBinary, 277 Path: binFile.Name(), 278 }) 279 testlib.RequireTemplateError(t, Pipe{}.Run(ctx)) 280 }) 281 } 282 } 283 } 284 285 func TestPipeCouldNotOpenChecksumsTxt(t *testing.T) { 286 folder := t.TempDir() 287 binFile, err := os.CreateTemp(folder, "goreleasertest-bin") 288 require.NoError(t, err) 289 t.Cleanup(func() { require.NoError(t, binFile.Close()) }) 290 _, err = binFile.WriteString("fake artifact") 291 require.NoError(t, err) 292 293 file := filepath.Join(folder, "checksums.txt") 294 require.NoError(t, os.WriteFile(file, []byte("some string"), 0o000)) 295 ctx := testctx.NewWithCfg( 296 config.Project{ 297 Dist: folder, 298 Checksum: config.Checksum{ 299 NameTemplate: "checksums.txt", 300 Algorithm: "sha256", 301 }, 302 }, 303 testctx.WithCurrentTag("1.2.3"), 304 ) 305 ctx.Artifacts.Add(&artifact.Artifact{ 306 Name: "whatever", 307 Type: artifact.UploadableBinary, 308 Path: binFile.Name(), 309 }) 310 err = Pipe{}.Run(ctx) 311 require.Error(t, err) 312 require.ErrorIs(t, Pipe{}.Run(ctx), syscall.EACCES) 313 } 314 315 func TestPipeWhenNoArtifacts(t *testing.T) { 316 ctx := testctx.New() 317 require.NoError(t, Pipe{}.Run(ctx)) 318 require.Empty(t, ctx.Artifacts.List()) 319 } 320 321 func TestDefault(t *testing.T) { 322 ctx := testctx.NewWithCfg(config.Project{ 323 Checksum: config.Checksum{}, 324 }) 325 require.NoError(t, Pipe{}.Default(ctx)) 326 require.Equal( 327 t, 328 "{{ .ProjectName }}_{{ .Version }}_checksums.txt", 329 ctx.Config.Checksum.NameTemplate, 330 ) 331 require.Equal(t, "sha256", ctx.Config.Checksum.Algorithm) 332 } 333 334 func TestDefaultSPlit(t *testing.T) { 335 ctx := testctx.NewWithCfg(config.Project{ 336 Checksum: config.Checksum{ 337 Split: true, 338 }, 339 }) 340 require.NoError(t, Pipe{}.Default(ctx)) 341 require.Equal( 342 t, 343 "{{ .ArtifactName }}.{{ .Algorithm }}", 344 ctx.Config.Checksum.NameTemplate, 345 ) 346 require.Equal(t, "sha256", ctx.Config.Checksum.Algorithm) 347 } 348 349 func TestDefaultSet(t *testing.T) { 350 ctx := testctx.NewWithCfg(config.Project{ 351 Checksum: config.Checksum{ 352 NameTemplate: "checksums.txt", 353 }, 354 }) 355 require.NoError(t, Pipe{}.Default(ctx)) 356 require.Equal(t, "checksums.txt", ctx.Config.Checksum.NameTemplate) 357 } 358 359 func TestPipeChecksumsSortByFilename(t *testing.T) { 360 const binary = "binary" 361 const checksums = "checksums.txt" 362 const filePaths = "./testdata/order/*.txt" 363 364 folder := t.TempDir() 365 file := filepath.Join(folder, binary) 366 require.NoError(t, os.WriteFile(file, []byte("some string"), 0o644)) 367 368 ctx := testctx.NewWithCfg( 369 config.Project{ 370 Dist: folder, 371 ProjectName: binary, 372 Checksum: config.Checksum{ 373 Algorithm: "sha256", 374 NameTemplate: "checksums.txt", 375 ExtraFiles: []config.ExtraFile{ 376 {Glob: filePaths}, 377 }, 378 }, 379 }, 380 ) 381 382 ctx.Artifacts.Add(&artifact.Artifact{ 383 Name: binary, 384 Path: file, 385 Type: artifact.UploadableBinary, 386 }) 387 388 require.NoError(t, Pipe{}.Run(ctx)) 389 390 bts, err := os.ReadFile(filepath.Join(folder, checksums)) 391 require.NoError(t, err) 392 393 lines := strings.Split(string(bts), "\n") 394 395 wantLinesOrder := []string{ 396 "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb a.txt", 397 "3b64db95cb55c763391c707108489ae18b4112d783300de38e033b4c98c3deaf b.txt", 398 "61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc binary", 399 "64daa44ad493ff28a96effab6e77f1732a3d97d83241581b37dbd70a7a4900fe c.txt", 400 "5bf8aa57fc5a6bc547decf1cc6db63f10deb55a3c6c5df497d631fb3d95e1abf d.txt", 401 } 402 403 for i, want := range wantLinesOrder { 404 require.Equal(t, want, lines[i]) 405 } 406 } 407 408 func TestPipeCheckSumsWithExtraFiles(t *testing.T) { 409 const binary = "binary" 410 const checksums = "checksums.txt" 411 const extraFileFooRelPath = "./testdata/foo.txt" 412 const extraFileBarRelPath = "./testdata/**/bar.txt" 413 const extraFileFoo = "foo.txt" 414 const extraFileBar = "bar.txt" 415 416 tests := map[string]struct { 417 extraFiles []config.ExtraFile 418 ids []string 419 want []string 420 }{ 421 "default": { 422 extraFiles: nil, 423 want: []string{ 424 binary, 425 }, 426 }, 427 "one extra file": { 428 extraFiles: []config.ExtraFile{ 429 {Glob: extraFileFooRelPath}, 430 }, 431 want: []string{ 432 extraFileFoo, 433 }, 434 }, 435 "multiple extra files": { 436 extraFiles: []config.ExtraFile{ 437 {Glob: extraFileFooRelPath}, 438 {Glob: extraFileBarRelPath}, 439 }, 440 want: []string{ 441 extraFileFoo, 442 extraFileBar, 443 }, 444 }, 445 "one extra file with no builds": { 446 extraFiles: []config.ExtraFile{ 447 {Glob: extraFileFooRelPath}, 448 }, 449 ids: []string{"yada yada yada"}, 450 want: []string{ 451 extraFileFoo, 452 }, 453 }, 454 } 455 456 for name, tt := range tests { 457 t.Run(name, func(t *testing.T) { 458 folder := t.TempDir() 459 file := filepath.Join(folder, binary) 460 require.NoError(t, os.WriteFile(file, []byte("some string"), 0o644)) 461 ctx := testctx.NewWithCfg( 462 config.Project{ 463 Dist: folder, 464 ProjectName: binary, 465 Checksum: config.Checksum{ 466 Algorithm: "sha256", 467 NameTemplate: "checksums.txt", 468 ExtraFiles: tt.extraFiles, 469 IDs: tt.ids, 470 }, 471 }, 472 ) 473 474 ctx.Artifacts.Add(&artifact.Artifact{ 475 Name: binary, 476 Path: file, 477 Type: artifact.UploadableBinary, 478 Extra: map[string]interface{}{ 479 artifact.ExtraID: "id-1", 480 }, 481 }) 482 483 require.NoError(t, Pipe{}.Run(ctx)) 484 485 bts, err := os.ReadFile(filepath.Join(folder, checksums)) 486 487 require.NoError(t, err) 488 for _, want := range tt.want { 489 if tt.extraFiles == nil { 490 require.Contains(t, string(bts), "61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc "+want) 491 } else { 492 require.Contains(t, string(bts), "3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 "+want) 493 } 494 } 495 496 _ = ctx.Artifacts.Visit(func(a *artifact.Artifact) error { 497 if a.Path != file { 498 return nil 499 } 500 if len(tt.ids) > 0 { 501 return nil 502 } 503 checkSum, err := artifact.Extra[string](*a, artifactChecksumExtra) 504 require.NoError(t, err) 505 require.NotEmptyf(t, checkSum, "failed: %v", a.Path) 506 return nil 507 }) 508 }) 509 } 510 } 511 512 func TestExtraFilesNoMatch(t *testing.T) { 513 dir := t.TempDir() 514 ctx := testctx.NewWithCfg( 515 config.Project{ 516 Dist: dir, 517 ProjectName: "fake", 518 Checksum: config.Checksum{ 519 Algorithm: "sha256", 520 NameTemplate: "checksums.txt", 521 ExtraFiles: []config.ExtraFile{{Glob: "./nope/nope.txt"}}, 522 }, 523 }, 524 ) 525 526 ctx.Artifacts.Add(&artifact.Artifact{ 527 Name: "fake", 528 Path: "fake-path", 529 Type: artifact.UploadableBinary, 530 }) 531 532 require.NoError(t, Pipe{}.Default(ctx)) 533 require.EqualError(t, Pipe{}.Run(ctx), `globbing failed for pattern ./nope/nope.txt: matching "./nope/nope.txt": file does not exist`) 534 } 535 536 func TestSkip(t *testing.T) { 537 t.Run("skip", func(t *testing.T) { 538 ctx := testctx.NewWithCfg(config.Project{ 539 Checksum: config.Checksum{ 540 Disable: true, 541 }, 542 }) 543 require.True(t, Pipe{}.Skip(ctx)) 544 }) 545 546 t.Run("dont skip", func(t *testing.T) { 547 require.False(t, Pipe{}.Skip(testctx.New())) 548 }) 549 } 550 551 // TODO: add tests for LinuxPackage and UploadableSourceArchive