github.com/goreleaser/goreleaser@v1.25.1/internal/exec/exec_test.go (about) 1 package exec 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 "testing" 9 10 "github.com/goreleaser/goreleaser/internal/artifact" 11 "github.com/goreleaser/goreleaser/internal/pipe" 12 "github.com/goreleaser/goreleaser/internal/testctx" 13 "github.com/goreleaser/goreleaser/internal/tmpl" 14 "github.com/goreleaser/goreleaser/pkg/config" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestExecute(t *testing.T) { 19 ctx := testctx.NewWithCfg(config.Project{ 20 ProjectName: "blah", 21 Env: []string{ 22 "TEST_A_SECRET=x", 23 "TEST_A_USERNAME=u2", 24 }, 25 }, testctx.WithVersion("2.1.0")) 26 27 // Preload artifacts 28 folder := t.TempDir() 29 for _, a := range []struct { 30 id string 31 ext string 32 typ artifact.Type 33 }{ 34 {"debpkg", "deb", artifact.LinuxPackage}, 35 {"binary", "bin", artifact.Binary}, 36 {"archive", "tar", artifact.UploadableArchive}, 37 {"ubinary", "ubi", artifact.UploadableBinary}, 38 {"checksum", "sum", artifact.Checksum}, 39 {"metadata", "json", artifact.Metadata}, 40 {"signature", "sig", artifact.Signature}, 41 {"signature", "pem", artifact.Certificate}, 42 } { 43 file := filepath.Join(folder, "a."+a.ext) 44 require.NoError(t, os.WriteFile(file, []byte("lorem ipsum"), 0o644)) 45 ctx.Artifacts.Add(&artifact.Artifact{ 46 Name: "a." + a.ext, 47 Goos: "linux", 48 Goarch: "amd64", 49 Path: file, 50 Type: a.typ, 51 Extra: map[string]interface{}{ 52 artifact.ExtraID: a.id, 53 }, 54 }) 55 } 56 57 ctx.Artifacts.Add(&artifact.Artifact{ 58 Name: "foo/bar:amd64", 59 Goos: "linux", 60 Goarch: "amd64", 61 Path: "foo/bar:amd64", 62 Type: artifact.DockerImage, 63 Extra: map[string]interface{}{ 64 artifact.ExtraID: "img", 65 }, 66 }) 67 ctx.Artifacts.Add(&artifact.Artifact{ 68 Name: "foo/bar", 69 Path: "foo/bar", 70 Type: artifact.DockerManifest, 71 Extra: map[string]interface{}{ 72 artifact.ExtraID: "mnf", 73 }, 74 }) 75 76 osEnv := func(ignores ...string) []string { 77 var result []string 78 outer: 79 for _, key := range passthroughEnvVars { 80 for _, ignore := range ignores { 81 if key == ignore { 82 continue outer 83 } 84 } 85 if value := os.Getenv(key); value != "" { 86 result = append(result, key+"="+value) 87 } 88 } 89 return result 90 } 91 92 testCases := []struct { 93 name string 94 publishers []config.Publisher 95 expectErr error 96 expectErrAs any 97 }{ 98 { 99 "filter by IDs", 100 []config.Publisher{ 101 { 102 Name: "test", 103 IDs: []string{"archive"}, 104 Cmd: MockCmd + " {{ .ArtifactName }}", 105 Env: []string{ 106 MarshalMockEnv(&MockData{ 107 AnyOf: []MockCall{ 108 {ExpectedArgs: []string{"a.tar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 109 }, 110 }), 111 }, 112 }, 113 }, 114 nil, 115 nil, 116 }, 117 { 118 "no filter", 119 []config.Publisher{ 120 { 121 Name: "test", 122 Cmd: MockCmd + " {{ .ArtifactName }}", 123 Disable: "false", 124 Env: []string{ 125 MarshalMockEnv(&MockData{ 126 AnyOf: []MockCall{ 127 {ExpectedArgs: []string{"a.deb"}, ExitCode: 0, ExpectedEnv: osEnv()}, 128 {ExpectedArgs: []string{"a.ubi"}, ExitCode: 0, ExpectedEnv: osEnv()}, 129 {ExpectedArgs: []string{"a.tar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 130 {ExpectedArgs: []string{"foo/bar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 131 {ExpectedArgs: []string{"foo/bar:amd64"}, ExitCode: 0, ExpectedEnv: osEnv()}, 132 }, 133 }), 134 }, 135 }, 136 }, 137 nil, 138 nil, 139 }, 140 { 141 "disabled", 142 []config.Publisher{ 143 { 144 Name: "test", 145 Cmd: MockCmd + " {{ .ArtifactName }}", 146 Disable: "true", 147 Env: []string{}, 148 }, 149 }, 150 pipe.ErrSkip{}, 151 nil, 152 }, 153 { 154 "disabled invalid tmpl", 155 []config.Publisher{ 156 { 157 Name: "test", 158 Cmd: MockCmd + " {{ .ArtifactName }}", 159 Disable: "{{ .NOPE }}", 160 Env: []string{}, 161 }, 162 }, 163 nil, 164 &tmpl.Error{}, 165 }, 166 { 167 "include checksum", 168 []config.Publisher{ 169 { 170 Name: "test", 171 Checksum: true, 172 Cmd: MockCmd + " {{ .ArtifactName }}", 173 Env: []string{ 174 MarshalMockEnv(&MockData{ 175 AnyOf: []MockCall{ 176 {ExpectedArgs: []string{"a.deb"}, ExitCode: 0, ExpectedEnv: osEnv()}, 177 {ExpectedArgs: []string{"a.ubi"}, ExitCode: 0, ExpectedEnv: osEnv()}, 178 {ExpectedArgs: []string{"a.tar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 179 {ExpectedArgs: []string{"a.sum"}, ExitCode: 0, ExpectedEnv: osEnv()}, 180 {ExpectedArgs: []string{"foo/bar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 181 {ExpectedArgs: []string{"foo/bar:amd64"}, ExitCode: 0, ExpectedEnv: osEnv()}, 182 }, 183 }), 184 }, 185 }, 186 }, 187 nil, 188 nil, 189 }, 190 { 191 "include metadata", 192 []config.Publisher{ 193 { 194 Name: "test", 195 Meta: true, 196 Cmd: MockCmd + " {{ .ArtifactName }}", 197 Env: []string{ 198 MarshalMockEnv(&MockData{ 199 AnyOf: []MockCall{ 200 {ExpectedArgs: []string{"a.deb"}, ExitCode: 0, ExpectedEnv: osEnv()}, 201 {ExpectedArgs: []string{"a.ubi"}, ExitCode: 0, ExpectedEnv: osEnv()}, 202 {ExpectedArgs: []string{"a.tar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 203 {ExpectedArgs: []string{"a.json"}, ExitCode: 0, ExpectedEnv: osEnv()}, 204 {ExpectedArgs: []string{"foo/bar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 205 {ExpectedArgs: []string{"foo/bar:amd64"}, ExitCode: 0, ExpectedEnv: osEnv()}, 206 }, 207 }), 208 }, 209 }, 210 }, 211 nil, 212 nil, 213 }, 214 { 215 "include signatures", 216 []config.Publisher{ 217 { 218 Name: "test", 219 Signature: true, 220 Cmd: MockCmd + " {{ .ArtifactName }}", 221 Env: []string{ 222 MarshalMockEnv(&MockData{ 223 AnyOf: []MockCall{ 224 {ExpectedArgs: []string{"a.deb"}, ExitCode: 0, ExpectedEnv: osEnv()}, 225 {ExpectedArgs: []string{"a.ubi"}, ExitCode: 0, ExpectedEnv: osEnv()}, 226 {ExpectedArgs: []string{"a.tar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 227 {ExpectedArgs: []string{"a.sig"}, ExitCode: 0, ExpectedEnv: osEnv()}, 228 {ExpectedArgs: []string{"a.pem"}, ExitCode: 0, ExpectedEnv: osEnv()}, 229 {ExpectedArgs: []string{"foo/bar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 230 {ExpectedArgs: []string{"foo/bar:amd64"}, ExitCode: 0, ExpectedEnv: osEnv()}, 231 }, 232 }), 233 }, 234 }, 235 }, 236 nil, 237 nil, 238 }, 239 { 240 "docker", 241 []config.Publisher{ 242 { 243 Name: "test", 244 IDs: []string{"img", "mnf"}, 245 Cmd: MockCmd + " {{ .ArtifactName }}", 246 Env: []string{ 247 MarshalMockEnv(&MockData{ 248 AnyOf: []MockCall{ 249 {ExpectedArgs: []string{"foo/bar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 250 {ExpectedArgs: []string{"foo/bar:amd64"}, ExitCode: 0, ExpectedEnv: osEnv()}, 251 }, 252 }), 253 }, 254 }, 255 }, 256 nil, 257 nil, 258 }, 259 { 260 "extra files", 261 []config.Publisher{ 262 { 263 Name: "test", 264 Cmd: MockCmd + " {{ .ArtifactName }}", 265 Env: []string{ 266 MarshalMockEnv(&MockData{ 267 AnyOf: []MockCall{ 268 {ExpectedArgs: []string{"a.deb"}, ExitCode: 0, ExpectedEnv: osEnv()}, 269 {ExpectedArgs: []string{"a.ubi"}, ExitCode: 0, ExpectedEnv: osEnv()}, 270 {ExpectedArgs: []string{"a.tar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 271 {ExpectedArgs: []string{"a.txt"}, ExitCode: 0, ExpectedEnv: osEnv()}, 272 {ExpectedArgs: []string{"foo/bar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 273 {ExpectedArgs: []string{"foo/bar:amd64"}, ExitCode: 0, ExpectedEnv: osEnv()}, 274 }, 275 }), 276 }, 277 ExtraFiles: []config.ExtraFile{ 278 {Glob: filepath.Join("testdata", "*.txt")}, 279 }, 280 }, 281 }, 282 nil, 283 nil, 284 }, 285 { 286 "extra files with rename", 287 []config.Publisher{ 288 { 289 Name: "test", 290 Cmd: MockCmd + " {{ .ArtifactName }}", 291 Env: []string{ 292 MarshalMockEnv(&MockData{ 293 AnyOf: []MockCall{ 294 {ExpectedArgs: []string{"a.deb"}, ExitCode: 0, ExpectedEnv: osEnv()}, 295 {ExpectedArgs: []string{"a.ubi"}, ExitCode: 0, ExpectedEnv: osEnv()}, 296 {ExpectedArgs: []string{"a.tar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 297 {ExpectedArgs: []string{"b.txt"}, ExitCode: 0, ExpectedEnv: osEnv()}, 298 {ExpectedArgs: []string{"foo/bar"}, ExitCode: 0, ExpectedEnv: osEnv()}, 299 {ExpectedArgs: []string{"foo/bar:amd64"}, ExitCode: 0, ExpectedEnv: osEnv()}, 300 }, 301 }), 302 }, 303 ExtraFiles: []config.ExtraFile{ 304 { 305 Glob: filepath.Join("testdata", "*.txt"), 306 NameTemplate: "b.txt", 307 }, 308 }, 309 }, 310 }, 311 nil, 312 nil, 313 }, 314 { 315 "try dir templating", 316 []config.Publisher{ 317 { 318 Name: "test", 319 Signature: true, 320 IDs: []string{"debpkg"}, 321 Dir: "{{ dir .ArtifactPath }}", 322 Cmd: MockCmd + " {{ .ArtifactName }}", 323 Env: []string{ 324 MarshalMockEnv(&MockData{ 325 AnyOf: []MockCall{ 326 {ExpectedArgs: []string{"a.deb"}, ExitCode: 0, ExpectedEnv: osEnv()}, 327 }, 328 }), 329 }, 330 }, 331 }, 332 nil, 333 nil, 334 }, 335 { 336 "check env templating", 337 []config.Publisher{ 338 { 339 Name: "test", 340 IDs: []string{"debpkg"}, 341 Cmd: MockCmd, 342 Env: []string{ 343 "PROJECT={{.ProjectName}}", 344 "ARTIFACT={{.ArtifactName}}", 345 "SECRET={{.Env.TEST_A_SECRET}}", 346 MarshalMockEnv(&MockData{ 347 AnyOf: []MockCall{ 348 { 349 ExpectedEnv: append( 350 []string{"PROJECT=blah", "ARTIFACT=a.deb", "SECRET=x"}, 351 osEnv()..., 352 ), 353 ExitCode: 0, 354 }, 355 }, 356 }), 357 }, 358 }, 359 }, 360 nil, 361 nil, 362 }, 363 { 364 "override path", 365 []config.Publisher{ 366 { 367 Name: "test", 368 IDs: []string{"debpkg"}, 369 Cmd: MockCmd, 370 Env: []string{ 371 "PATH=/something-else", 372 MarshalMockEnv(&MockData{ 373 AnyOf: []MockCall{ 374 { 375 ExpectedEnv: append( 376 []string{"PATH=/something-else"}, 377 osEnv("PATH")..., 378 ), 379 ExitCode: 0, 380 }, 381 }, 382 }), 383 }, 384 }, 385 }, 386 nil, 387 nil, 388 }, 389 { 390 "command error", 391 []config.Publisher{ 392 { 393 Disable: "true", 394 }, 395 { 396 Name: "test", 397 IDs: []string{"debpkg"}, 398 Cmd: MockCmd + " {{.ArtifactName}}", 399 Env: []string{ 400 MarshalMockEnv(&MockData{ 401 AnyOf: []MockCall{ 402 { 403 ExpectedArgs: []string{"a.deb"}, 404 ExpectedEnv: osEnv(), 405 Stderr: "test error", 406 ExitCode: 1, 407 }, 408 }, 409 }), 410 }, 411 }, 412 }, 413 // stderr is sent to output via logger 414 fmt.Errorf(`publishing: %s failed: exit status 1: test error`, MockCmd), 415 nil, 416 }, 417 } 418 419 for i, tc := range testCases { 420 t.Run(fmt.Sprintf("%d-%s", i, tc.name), func(t *testing.T) { 421 err := Execute(ctx, tc.publishers) 422 if tc.expectErr != nil { 423 require.Error(t, err) 424 require.True(t, strings.HasPrefix(err.Error(), tc.expectErr.Error()), err.Error()) 425 return 426 } 427 if tc.expectErrAs != nil { 428 require.ErrorAs(t, err, tc.expectErrAs) 429 return 430 } 431 require.NoError(t, err) 432 }) 433 } 434 }