github.com/goreleaser/nfpm/v2@v2.44.0/acceptance_test.go (about) 1 //go:build acceptance 2 3 package nfpm_test 4 5 import ( 6 "fmt" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "strings" 11 "testing" 12 13 "github.com/goreleaser/nfpm/v2" 14 _ "github.com/goreleaser/nfpm/v2/apk" 15 _ "github.com/goreleaser/nfpm/v2/arch" 16 _ "github.com/goreleaser/nfpm/v2/deb" 17 _ "github.com/goreleaser/nfpm/v2/ipk" 18 _ "github.com/goreleaser/nfpm/v2/rpm" 19 "github.com/stretchr/testify/require" 20 ) 21 22 // nolint: gochecknoglobals 23 var formatArchs = map[string][]string{ 24 "apk": {"amd64", "arm64", "386", "ppc64le", "armv6", "armv7", "s390x"}, 25 "deb": {"amd64", "arm64", "ppc64le", "armv7", "s390x"}, 26 "ipk": {"x86_64", "aarch64_generic"}, 27 "rpm": {"amd64", "arm64", "ppc64le"}, 28 "archlinux": {"amd64"}, 29 } 30 31 func TestCore(t *testing.T) { 32 t.Parallel() 33 testNames := []string{ 34 "min", 35 "simple", 36 "no-glob", 37 "complex", 38 "env-var-version", 39 "overrides", 40 "meta", 41 "withchangelog", 42 "symlink", 43 "signed", 44 } 45 for _, name := range testNames { 46 for format, architecture := range formatArchs { 47 for _, arch := range architecture { 48 func(t *testing.T, testName, testFormat, testArch string) { 49 t.Run(fmt.Sprintf("%s/%s/%s", testFormat, testArch, testName), func(t *testing.T) { 50 t.Parallel() 51 if testArch == "ppc64le" && os.Getenv("NO_TEST_PPC64LE") == "true" { 52 t.Skip("ppc64le arch not supported in pipeline") 53 } 54 accept(t, acceptParms{ 55 Name: fmt.Sprintf("%s_%s", testName, testArch), 56 Conf: fmt.Sprintf("core.%s.yaml", testName), 57 Format: testFormat, 58 Docker: dockerParams{ 59 File: fmt.Sprintf("%s.dockerfile", testFormat), 60 Target: testName, 61 Arch: testArch, 62 }, 63 }) 64 }) 65 }(t, name, format, arch) 66 } 67 } 68 } 69 } 70 71 func TestUpgrade(t *testing.T) { 72 t.Parallel() 73 testNames := []string{ 74 "upgrade", 75 } 76 for _, name := range testNames { 77 for format, architecture := range formatArchs { 78 for _, arch := range architecture { 79 func(t *testing.T, testName, testFormat, testArch string) { 80 t.Run(fmt.Sprintf("%s/%s/%s", testFormat, testArch, testName), func(t *testing.T) { 81 t.Parallel() 82 if testArch == "ppc64le" && os.Getenv("NO_TEST_PPC64LE") == "true" { 83 t.Skip("ppc64le arch not supported in pipeline") 84 } 85 86 arch := strings.ReplaceAll(testArch, "armv", "arm/") 87 oldpkg := fmt.Sprintf("tmp/%s_%s.v1.%s", testName, testArch, testFormat) 88 target := fmt.Sprintf("./testdata/acceptance/%s", oldpkg) 89 require.NoError(t, os.MkdirAll("./testdata/acceptance/tmp", 0o700)) 90 91 config, err := nfpm.ParseFileWithEnvMapping(fmt.Sprintf("./testdata/acceptance/%s.v1.yaml", testName), 92 func(s string) string { 93 switch s { 94 case "BUILD_ARCH": 95 return strings.ReplaceAll(arch, "/", "") 96 case "SEMVER": 97 return "v1.0.0-0.1.b1+git.abcdefgh" 98 default: 99 return os.Getenv(s) 100 } 101 }, 102 ) 103 require.NoError(t, err) 104 105 info, err := config.Get(testFormat) 106 require.NoError(t, err) 107 require.NoError(t, nfpm.Validate(info)) 108 109 pkg, err := nfpm.Get(testFormat) 110 require.NoError(t, err) 111 112 f, err := os.Create(target) 113 require.NoError(t, err) 114 t.Cleanup(func() { require.NoError(t, f.Close()) }) 115 info.Target = target 116 require.NoError(t, pkg.Package(nfpm.WithDefaults(info), f)) 117 118 accept(t, acceptParms{ 119 Name: fmt.Sprintf("%s_%s.v2", testName, testArch), 120 Conf: fmt.Sprintf("%s.v2.yaml", testName), 121 Format: testFormat, 122 Docker: dockerParams{ 123 File: fmt.Sprintf("%s.dockerfile", testFormat), 124 Target: testName, 125 Arch: testArch, 126 BuildArgs: []string{fmt.Sprintf("oldpackage=%s", oldpkg)}, 127 }, 128 }) 129 }) 130 }(t, name, format, arch) 131 } 132 } 133 } 134 } 135 136 func TestRPMCompression(t *testing.T) { 137 t.Parallel() 138 format := "rpm" 139 compressFormats := []string{"gzip", "xz", "lzma", "zstd"} 140 for _, arch := range formatArchs[format] { 141 for _, compFormat := range compressFormats { 142 func(t *testing.T, testCompFormat, testArch string) { 143 t.Run(fmt.Sprintf("%s/%s/%s", format, testArch, testCompFormat), func(t *testing.T) { 144 t.Parallel() 145 if testArch == "ppc64le" && os.Getenv("NO_TEST_PPC64LE") == "true" { 146 t.Skip("ppc64le arch not supported in pipeline") 147 } 148 accept(t, acceptParms{ 149 Name: fmt.Sprintf("%s_compression_%s", testCompFormat, testArch), 150 Conf: fmt.Sprintf("rpm.%s.compression.yaml", testCompFormat), 151 Format: format, 152 Docker: dockerParams{ 153 File: fmt.Sprintf("%s.dockerfile", format), 154 Target: "compression", 155 Arch: testArch, 156 BuildArgs: []string{fmt.Sprintf("compression=%s", testCompFormat)}, 157 }, 158 }) 159 }) 160 }(t, compFormat, arch) 161 } 162 } 163 } 164 165 func TestDebCompression(t *testing.T) { 166 t.Parallel() 167 format := "deb" 168 compressFormats := []string{"gzip", "xz", "zstd", "none"} 169 for _, arch := range formatArchs[format] { 170 for _, compFormat := range compressFormats { 171 func(t *testing.T, testCompFormat, testArch string) { 172 t.Run(fmt.Sprintf("%s/%s/%s", format, testArch, testCompFormat), func(t *testing.T) { 173 t.Parallel() 174 if testArch == "ppc64le" && os.Getenv("NO_TEST_PPC64LE") == "true" { 175 t.Skip("ppc64le arch not supported in pipeline") 176 } 177 178 accept(t, acceptParms{ 179 Name: fmt.Sprintf("%s_compression_%s", testCompFormat, testArch), 180 Conf: fmt.Sprintf("deb.%s.compression.yaml", testCompFormat), 181 Format: format, 182 Docker: dockerParams{ 183 File: fmt.Sprintf("%s.dockerfile", format), 184 Target: "compression", 185 Arch: testArch, 186 }, 187 }) 188 }) 189 }(t, compFormat, arch) 190 } 191 } 192 } 193 194 func TestRPMSpecific(t *testing.T) { 195 t.Parallel() 196 format := "rpm" 197 testNames := []string{ 198 "release", 199 "directories", 200 "verify", 201 } 202 for _, name := range testNames { 203 for _, arch := range formatArchs[format] { 204 func(t *testing.T, testName, testArch string) { 205 t.Run(fmt.Sprintf("%s/%s/%s", format, testArch, testName), func(t *testing.T) { 206 t.Parallel() 207 if testArch == "ppc64le" && os.Getenv("NO_TEST_PPC64LE") == "true" { 208 t.Skip("ppc64le arch not supported in pipeline") 209 } 210 accept(t, acceptParms{ 211 Name: fmt.Sprintf("%s_%s", testName, testArch), 212 Conf: fmt.Sprintf("%s.%s.yaml", format, testName), 213 Format: format, 214 Docker: dockerParams{ 215 File: fmt.Sprintf("%s.dockerfile", format), 216 Target: testName, 217 Arch: testArch, 218 }, 219 }) 220 }) 221 }(t, name, arch) 222 } 223 } 224 } 225 226 func TestDebSpecific(t *testing.T) { 227 t.Parallel() 228 format := "deb" 229 testNames := []string{ 230 "rules", 231 "triggers", 232 "breaks", 233 "predepends", 234 } 235 for _, name := range testNames { 236 for _, arch := range formatArchs[format] { 237 func(t *testing.T, testName, testArch string) { 238 t.Run(fmt.Sprintf("%s/%s/%s", format, testArch, testName), func(t *testing.T) { 239 t.Parallel() 240 if testArch == "ppc64le" && os.Getenv("NO_TEST_PPC64LE") == "true" { 241 t.Skip("ppc64le arch not supported in pipeline") 242 } 243 accept(t, acceptParms{ 244 Name: fmt.Sprintf("%s_%s", testName, testArch), 245 Conf: fmt.Sprintf("%s.%s.yaml", format, testName), 246 Format: format, 247 Docker: dockerParams{ 248 File: fmt.Sprintf("%s.dockerfile", format), 249 Target: testName, 250 Arch: testArch, 251 }, 252 }) 253 }) 254 }(t, name, arch) 255 } 256 } 257 } 258 259 func TestIPKSpecific(t *testing.T) { 260 t.Parallel() 261 format := "ipk" 262 testNames := []string{ 263 "alternatives", 264 "conflicts", 265 "predepends", 266 } 267 for _, name := range testNames { 268 for _, arch := range formatArchs[format] { 269 func(t *testing.T, testName, testArch string) { 270 t.Run(fmt.Sprintf("%s/%s/%s", format, testArch, testName), func(t *testing.T) { 271 t.Parallel() 272 if testArch == "ppc64le" && os.Getenv("NO_TEST_PPC64LE") == "true" { 273 t.Skip("ppc64le arch not supported in pipeline") 274 } 275 accept(t, acceptParms{ 276 Name: fmt.Sprintf("%s_%s", testName, testArch), 277 Conf: fmt.Sprintf("%s.%s.yaml", format, testName), 278 Format: format, 279 Docker: dockerParams{ 280 File: fmt.Sprintf("%s.dockerfile", format), 281 Target: testName, 282 Arch: testArch, 283 }, 284 }) 285 }) 286 }(t, name, arch) 287 } 288 } 289 } 290 291 func TestRPMSign(t *testing.T) { 292 for _, os := range []string{ 293 "centos9", 294 "centos10", 295 "fedora40", 296 "fedora41", 297 } { 298 os := os 299 t.Run(fmt.Sprintf("rpm/amd64/sign/%s", os), func(t *testing.T) { 300 accept(t, acceptParms{ 301 Name: fmt.Sprintf("sign_%s_amd64", os), 302 Conf: "core.signed.yaml", 303 Format: "rpm", 304 Docker: dockerParams{ 305 File: fmt.Sprintf("rpm_%s.dockerfile", os), 306 Target: "signed", 307 Arch: "amd64", 308 }, 309 }) 310 }) 311 } 312 } 313 314 func TestDebSign(t *testing.T) { 315 t.Parallel() 316 for _, arch := range formatArchs["deb"] { 317 for _, sigtype := range []string{"dpkg-sig", "debsign"} { 318 func(t *testing.T, testSigtype, testArch string) { 319 t.Run(fmt.Sprintf("deb/%s/%s", testArch, testSigtype), func(t *testing.T) { 320 t.Parallel() 321 target := "signed" 322 if testSigtype == "dpkg-sig" { 323 target = "dpkg-signed" 324 } 325 if testArch == "ppc64le" && os.Getenv("NO_TEST_PPC64LE") == "true" { 326 t.Skip("ppc64le arch not supported in pipeline") 327 } 328 accept(t, acceptParms{ 329 Name: fmt.Sprintf("%s_sign_%s", testSigtype, testArch), 330 Conf: fmt.Sprintf("deb.%s.sign.yaml", testSigtype), 331 Format: "deb", 332 Docker: dockerParams{ 333 File: "deb.dockerfile", 334 Target: target, 335 Arch: testArch, 336 }, 337 }) 338 }) 339 }(t, sigtype, arch) 340 } 341 } 342 } 343 344 type acceptParms struct { 345 Name string 346 Conf string 347 Format string 348 Docker dockerParams 349 } 350 351 type dockerParams struct { 352 File string 353 Target string 354 Arch string 355 BuildArgs []string 356 } 357 358 func accept(t *testing.T, params acceptParms) { 359 t.Helper() 360 361 arch := strings.ReplaceAll(params.Docker.Arch, "armv", "arm/") 362 configFile := filepath.Join("./testdata/acceptance/", params.Conf) 363 tmp, err := filepath.Abs("./testdata/acceptance/tmp") 364 require.NoError(t, err) 365 packageName := params.Name + "." + params.Format 366 target := filepath.Join(tmp, packageName) 367 require.NoError(t, os.MkdirAll(tmp, 0o700)) 368 369 envFunc := func(s string) string { 370 switch s { 371 case "BUILD_ARCH": 372 return strings.ReplaceAll(arch, "/", "") 373 case "SEMVER": 374 return "v1.0.0-0.1.b1+git.abcdefgh" 375 default: 376 return os.Getenv(s) 377 } 378 } 379 config, err := nfpm.ParseFileWithEnvMapping(configFile, envFunc) 380 require.NoError(t, err) 381 382 info, err := config.Get(params.Format) 383 require.NoError(t, err) 384 require.NoError(t, nfpm.Validate(info)) 385 386 pkg, err := nfpm.Get(params.Format) 387 require.NoError(t, err) 388 389 cmdArgs := []string{ 390 "build", "--rm", "--force-rm", 391 "--platform", fmt.Sprintf("linux/%s", arch), 392 "-f", params.Docker.File, 393 "--target", params.Docker.Target, 394 "--build-arg", "package=" + filepath.Join("tmp", packageName), 395 } 396 for _, arg := range params.Docker.BuildArgs { 397 cmdArgs = append(cmdArgs, "--build-arg", arg) 398 } 399 cmdArgs = append(cmdArgs, ".") 400 401 f, err := os.OpenFile(target, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o764) 402 require.NoError(t, err) 403 info.Target = target 404 require.NoError(t, pkg.Package(nfpm.WithDefaults(info), f)) 405 //nolint:gosec 406 cmd := exec.Command("docker", cmdArgs...) 407 cmd.Dir = "./testdata/acceptance" 408 bts, err := cmd.CombinedOutput() 409 require.NoError( 410 t, 411 err, 412 "failed: %v; env BUILD_ARCH: %s; package: %s; output: %s", 413 cmd.Args, 414 envFunc("BUILD_ARCH"), 415 target, 416 string(bts), 417 ) 418 }