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