github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/ci/packages/package.go (about) 1 /* 2 * Copyright (C) 2019 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package packages 19 20 import ( 21 "fmt" 22 "os" 23 "path" 24 "strings" 25 "text/template" 26 27 "github.com/magefile/mage/mg" 28 "github.com/magefile/mage/sh" 29 "github.com/rs/zerolog/log" 30 31 "github.com/mysteriumnetwork/go-ci/env" 32 "github.com/mysteriumnetwork/go-ci/job" 33 "github.com/mysteriumnetwork/go-ci/shell" 34 "github.com/mysteriumnetwork/node/ci/deb" 35 "github.com/mysteriumnetwork/node/ci/storage" 36 "github.com/mysteriumnetwork/node/logconfig" 37 ) 38 39 // PackageLinuxAmd64 builds and stores linux amd64 package 40 func PackageLinuxAmd64() error { 41 logconfig.Bootstrap() 42 if err := packageStandalone("build/myst/myst_linux_amd64", "linux", "amd64", nil); err != nil { 43 return err 44 } 45 return env.IfRelease(storage.UploadArtifacts) 46 } 47 48 // PackageLinuxArm builds and stores linux arm package 49 func PackageLinuxArm() error { 50 logconfig.Bootstrap() 51 if err := packageStandalone("build/myst/myst_linux_arm", "linux", "arm", nil); err != nil { 52 return err 53 } 54 return env.IfRelease(storage.UploadArtifacts) 55 } 56 57 // PackageLinuxArmv6l builds and stores linux armv6 package 58 func PackageLinuxArmv6l() error { 59 logconfig.Bootstrap() 60 extraEnv := map[string]string{ 61 "GOARM": "6", 62 } 63 if err := packageStandalone("build/myst/myst_linux_armv6l", "linux", "arm", extraEnv); err != nil { 64 return err 65 } 66 return env.IfRelease(storage.UploadArtifacts) 67 } 68 69 // PackageLinuxDebianAmd64 builds and stores debian amd64 package 70 func PackageLinuxDebianAmd64() error { 71 logconfig.Bootstrap() 72 if err := goGet("github.com/debber/debber-v0.3/cmd/debber"); err != nil { 73 return err 74 } 75 envi := map[string]string{ 76 "GOOS": "linux", 77 "GOARCH": "amd64", 78 } 79 if err := sh.RunWith(envi, "bin/build"); err != nil { 80 return err 81 } 82 if err := packageDebian("build/myst/myst", "amd64"); err != nil { 83 return err 84 } 85 return env.IfRelease(storage.UploadArtifacts) 86 } 87 88 // PackageLinuxDebianArm builds and stores debian armv7l+ package 89 func PackageLinuxDebianArm() error { 90 logconfig.Bootstrap() 91 if err := goGet("github.com/debber/debber-v0.3/cmd/debber"); err != nil { 92 return err 93 } 94 envi := map[string]string{ 95 "GOOS": "linux", 96 "GOARCH": "arm", 97 } 98 if err := sh.RunWith(envi, "bin/build"); err != nil { 99 return err 100 } 101 if err := packageDebian("build/myst/myst", "armhf"); err != nil { 102 return err 103 } 104 return env.IfRelease(storage.UploadArtifacts) 105 } 106 107 // PackageLinuxDebianArmv6l builds and stores debian armv6l package 108 func PackageLinuxDebianArmv6l() error { 109 logconfig.Bootstrap() 110 if err := goGet("github.com/debber/debber-v0.3/cmd/debber"); err != nil { 111 return err 112 } 113 envi := map[string]string{ 114 "GOOS": "linux", 115 "GOARCH": "arm", 116 "GOARM": "6", 117 } 118 if err := sh.RunWith(envi, "bin/build"); err != nil { 119 return err 120 } 121 if err := packageDebian("build/myst/myst", "armv6l"); err != nil { 122 return err 123 } 124 return env.IfRelease(storage.UploadArtifacts) 125 } 126 127 // PackageLinuxDebianArm64 builds and stores debian arm64 package 128 func PackageLinuxDebianArm64() error { 129 logconfig.Bootstrap() 130 if err := goGet("github.com/debber/debber-v0.3/cmd/debber"); err != nil { 131 return err 132 } 133 envi := map[string]string{ 134 "GOOS": "linux", 135 "GOARCH": "arm64", 136 } 137 if err := sh.RunWith(envi, "bin/build"); err != nil { 138 return err 139 } 140 if err := packageDebian("build/myst/myst", "arm64"); err != nil { 141 return err 142 } 143 return env.IfRelease(storage.UploadArtifacts) 144 } 145 146 // PackageMacOSAmd64 builds and stores macOS amd64 package 147 func PackageMacOSAmd64() error { 148 logconfig.Bootstrap() 149 if err := packageStandalone("build/myst/myst_darwin_amd64", "darwin", "amd64", nil); err != nil { 150 return err 151 } 152 return env.IfRelease(storage.UploadArtifacts) 153 } 154 155 // PackageMacOSArm64 builds and stores macOS arm64 package 156 func PackageMacOSArm64() error { 157 logconfig.Bootstrap() 158 if err := packageStandalone("build/myst/myst_darwin_arm64", "darwin", "arm64", nil); err != nil { 159 return err 160 } 161 return env.IfRelease(storage.UploadArtifacts) 162 } 163 164 // PackageWindowsAmd64 builds and stores Windows amd64 package 165 func PackageWindowsAmd64() error { 166 logconfig.Bootstrap() 167 if err := packageStandalone("build/myst/myst_windows_amd64.exe", "windows", "amd64", nil); err != nil { 168 return err 169 } 170 return env.IfRelease(storage.UploadArtifacts) 171 } 172 173 // PackageAndroid builds and stores Android package 174 func PackageAndroid() error { 175 job.Precondition(func() bool { 176 pr, _ := env.IsPR() 177 fullBuild, _ := env.IsFullBuild() 178 return !pr || fullBuild 179 }) 180 logconfig.Bootstrap() 181 182 if err := sh.RunV("bin/package_android", "amd64"); err != nil { 183 return err 184 } 185 186 // Artifacts created by xgo (docker) on CI environment are owned by root. 187 // Chown package folder so we can create a POM (see below) in it. 188 if _, isCI := os.LookupEnv("CI"); isCI { 189 err := shell.NewCmd("sudo chown -R gitlab-runner:gitlab-runner build/package").Run() 190 if err != nil { 191 return err 192 } 193 } 194 195 err := env.EnsureEnvVars(env.BuildVersion) 196 if err != nil { 197 return err 198 } 199 pomTemplate, err := template.ParseFiles("bin/package/android/mvn.pom") 200 if err != nil { 201 return err 202 } 203 204 buildVersion := env.Str(env.BuildVersion) 205 log.Info().Msgf("Package Android SDK version: %s", buildVersion) 206 207 pomFileOut, err := os.Create(fmt.Sprintf("build/package/mobile-node-%s.pom", buildVersion)) 208 if err != nil { 209 return err 210 } 211 defer pomFileOut.Close() 212 213 err = pomTemplate.Execute(pomFileOut, struct { 214 BuildVersion string 215 }{ 216 BuildVersion: buildVersion, 217 }) 218 if err != nil { 219 return err 220 } 221 222 return env.IfRelease(storage.UploadArtifacts) 223 } 224 225 // PackageAndroidProvider builds and stores Android Provider package 226 func PackageAndroidProvider() error { 227 job.Precondition(func() bool { 228 pr, _ := env.IsPR() 229 fullBuild, _ := env.IsFullBuild() 230 return !pr || fullBuild 231 }) 232 logconfig.Bootstrap() 233 234 if err := sh.RunV("bin/package_android_provider", "amd64"); err != nil { 235 return err 236 } 237 238 // Artifacts created by xgo (docker) on CI environment are owned by root. 239 // Chown package folder so we can create a POM (see below) in it. 240 if _, isCI := os.LookupEnv("CI"); isCI { 241 err := shell.NewCmd("sudo chown -R gitlab-runner:gitlab-runner build/package").Run() 242 if err != nil { 243 return err 244 } 245 } 246 247 err := env.EnsureEnvVars(env.BuildVersion) 248 if err != nil { 249 return err 250 } 251 pomTemplate, err := template.ParseFiles("bin/package/android_provider/mvn.pom") 252 if err != nil { 253 return err 254 } 255 256 buildVersion := env.Str(env.BuildVersion) 257 log.Info().Msgf("Package Android Provider SDK version: %s", buildVersion) 258 259 pomFileOut, err := os.Create(fmt.Sprintf("build/package/provider-mobile-node-%s.pom", buildVersion)) 260 if err != nil { 261 return err 262 } 263 defer pomFileOut.Close() 264 265 err = pomTemplate.Execute(pomFileOut, struct { 266 BuildVersion string 267 }{ 268 BuildVersion: buildVersion, 269 }) 270 if err != nil { 271 return err 272 } 273 274 return env.IfRelease(storage.UploadArtifacts) 275 } 276 277 func binFmtSupport() error { 278 return sh.RunV("docker", "run", "--rm", "--privileged", "linuxkit/binfmt:v0.8") 279 } 280 281 func makeCacheRef(cacheRepo string) string { 282 return cacheRepo + ":build-cache" 283 } 284 285 func buildDockerImage(dockerfile string, buildArgs map[string]string, cacheRepo string, tags []string, push bool, platforms []string) error { 286 mg.Deps(binFmtSupport) 287 288 if platforms == nil { 289 platforms = []string{ 290 "linux/amd64", 291 "linux/arm64", 292 "linux/arm", 293 } 294 } 295 296 args := []string{ 297 "docker", "buildx", "build", 298 "--file", dockerfile, 299 "--platform", strings.Join(platforms, ","), 300 "--output", fmt.Sprintf("type=image,push=%v", push), 301 } 302 for buildArgKey, buildArgValue := range buildArgs { 303 args = append(args, "--build-arg", buildArgKey+"="+buildArgValue) 304 } 305 for _, tag := range tags { 306 args = append(args, "--tag", tag) 307 } 308 309 if cacheRepo != "" { 310 args = append(args, "--cache-to=type=registry,mode=max,ref="+makeCacheRef(cacheRepo)) 311 args = append(args, "--cache-from=type=registry,ref="+makeCacheRef(cacheRepo)) 312 } 313 314 args = append(args, ".") 315 316 return sh.RunV(args[0], args[1:]...) 317 } 318 319 // BuildMystAlpineImage wraps buildDockerImage with required 320 // parameters to build myst on Alpine 321 func BuildMystAlpineImage(tags []string, push bool) error { 322 return buildDockerImage( 323 path.Join("bin", "docker", "alpine", "Dockerfile"), 324 map[string]string{ 325 string(env.BuildBranch): env.Str(env.BuildBranch), 326 string(env.BuildCommit): env.Str(env.BuildCommit), 327 string(env.BuildNumber): env.Str(env.BuildNumber), 328 string(env.BuildVersion): env.Str(env.BuildVersion), 329 }, 330 "mysteriumnetwork/myst", 331 tags, 332 push, 333 nil, 334 ) 335 } 336 337 // BuildMystDocumentationImage wraps buildDockerImage with required 338 // parameters to build TequilAPI ReDoc image 339 func BuildMystDocumentationImage(tags []string, push bool) error { 340 return buildDockerImage( 341 path.Join("bin", "docs_docker", "Dockerfile"), 342 nil, 343 "mysteriumnetwork/documentation", 344 tags, 345 push, 346 []string{ 347 "linux/amd64", 348 }, 349 ) 350 } 351 352 // PackageDockerAlpine builds and stores docker alpine image 353 func PackageDockerAlpine() error { 354 logconfig.Bootstrap() 355 return BuildMystAlpineImage([]string{"myst:alpine"}, false) 356 } 357 358 // PackageDockerSwaggerRedoc builds and stores docker swagger redoc image 359 func PackageDockerSwaggerRedoc() error { 360 logconfig.Bootstrap() 361 362 err := BuildMystDocumentationImage([]string{"tequilapi"}, false) 363 if err != nil { 364 return err 365 } 366 367 return env.IfRelease(func() error { 368 return storage.UploadSingleArtifact("tequilapi/docs/swagger.json") 369 }) 370 } 371 372 func goGet(pkg string) error { 373 return sh.RunWith(map[string]string{"GO111MODULE": "off"}, "go", "get", "-u", pkg) 374 } 375 376 func packageStandalone(binaryPath, os, arch string, extraEnvs map[string]string) error { 377 log.Info().Msgf("Packaging %s %s %s", binaryPath, os, arch) 378 var err error 379 if os == "linux" { 380 filename := path.Base(binaryPath) 381 binaryPath = path.Join("build", filename, filename) 382 err = buildBinaryFor(path.Join("cmd", "mysterium_node", "mysterium_node.go"), filename, os, arch, extraEnvs, true) 383 } else { 384 err = buildCrossBinary(os, arch) 385 } 386 if err != nil { 387 return err 388 } 389 390 err = buildBinaryFor(path.Join("cmd", "supervisor", "supervisor.go"), "myst_supervisor", os, arch, extraEnvs, true) 391 if err != nil { 392 return err 393 } 394 395 envs := map[string]string{ 396 "BINARY": binaryPath, 397 } 398 return sh.RunWith(envs, "bin/package_standalone", os) 399 } 400 401 func packageDebian(binaryPath, arch string) error { 402 if err := env.EnsureEnvVars(env.BuildVersion); err != nil { 403 return err 404 } 405 envs := map[string]string{ 406 "BINARY": binaryPath, 407 } 408 409 if err := deb.TermsTemplateFile("bin/package/installation/templates"); err != nil { 410 return err 411 } 412 413 return sh.RunWith(envs, "bin/package_debian", env.Str(env.BuildVersion), arch) 414 }