From e1836efe88fda4f8a03d06d3d7ccea277fd66ded Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 01:27:56 +0530 Subject: [PATCH 01/20] super fast crossbuilds --- dev-tools/mage/build.go | 8 +-- dev-tools/mage/check.go | 2 +- dev-tools/mage/clean.go | 3 +- dev-tools/mage/common.go | 69 ++++++++----------- dev-tools/mage/config.go | 13 ++-- dev-tools/mage/crossbuild.go | 118 +++++++++++++++++++++----------- dev-tools/mage/dockerbuilder.go | 71 +++++++++---------- dev-tools/mage/platforms.go | 24 ++++--- 8 files changed, 168 insertions(+), 140 deletions(-) diff --git a/dev-tools/mage/build.go b/dev-tools/mage/build.go index 263299671fd..bcfddef7d37 100644 --- a/dev-tools/mage/build.go +++ b/dev-tools/mage/build.go @@ -21,7 +21,6 @@ import ( "errors" "fmt" "go/build" - "log" "os" "path/filepath" "strings" @@ -124,8 +123,7 @@ func DefaultGolangCrossBuildArgs() BuildArgs { // environment. func GolangCrossBuild(params BuildArgs) error { if os.Getenv("GOLANG_CROSSBUILD") != "1" { - return errors.New("Use the crossBuild target. golangCrossBuild can " + - "only be executed within the golang-crossbuild docker environment.") + return errors.New("use the crossBuild target. golangCrossBuild can only be executed within the golang-crossbuild docker environment") } defer DockerChown(filepath.Join(params.OutputDir, params.Name+binaryExtension(GOOS))) @@ -206,7 +204,7 @@ func Build(params BuildArgs) error { } if GOOS == "windows" && params.WinMetadata { - log.Println("Generating a .syso containing Windows file metadata.") + fmt.Println("Generating a .syso containing Windows file metadata.") syso, err := MakeWindowsSysoFile() if err != nil { return fmt.Errorf("failed generating Windows .syso metadata file: %w", err) @@ -214,7 +212,7 @@ func Build(params BuildArgs) error { defer os.Remove(syso) } - log.Println("Adding build environment vars:", env) + fmt.Println("Adding build environment vars:", env) return sh.RunWith(env, "go", args...) } diff --git a/dev-tools/mage/check.go b/dev-tools/mage/check.go index a9547634eb5..e01e98c16e1 100644 --- a/dev-tools/mage/check.go +++ b/dev-tools/mage/check.go @@ -253,7 +253,7 @@ func checkDashboardForErrors(file string, d []byte) bool { var dashboard DashboardObject err := json.Unmarshal(d, &dashboard) if err != nil { - fmt.Println(fmt.Sprintf("failed to parse dashboard from %s: %s", file, err)) + fmt.Printf("failed to parse dashboard from %s: %s\n", file, err) return true } diff --git a/dev-tools/mage/clean.go b/dev-tools/mage/clean.go index c58a7b56ab0..c8794b72066 100644 --- a/dev-tools/mage/clean.go +++ b/dev-tools/mage/clean.go @@ -53,8 +53,7 @@ func Clean(pathLists ...[]string) error { if err := sh.Rm(f); err != nil { if errors.Is(err, os.ErrPermission) || strings.Contains(err.Error(), "permission denied") { - fmt.Printf("warn: cannot delete %q: %v, proceeding anyway\n", - f, err) + fmt.Printf("warn: cannot delete %q: %v, proceeding anyway\n", f, err) continue } return err diff --git a/dev-tools/mage/common.go b/dev-tools/mage/common.go index 1c1ca25d95b..2fc2122547d 100644 --- a/dev-tools/mage/common.go +++ b/dev-tools/mage/common.go @@ -459,7 +459,7 @@ func Tar(src string, targetFile string) error { func untar(sourceFile, destinationDir string) error { file, err := os.Open(sourceFile) if err != nil { - return err + return fmt.Errorf("failed to open source file: %w", err) } defer file.Close() @@ -467,7 +467,7 @@ func untar(sourceFile, destinationDir string) error { if strings.HasSuffix(sourceFile, ".gz") { if fileReader, err = gzip.NewReader(file); err != nil { - return err + return fmt.Errorf("failed to create gzip reader: %w", err) } defer fileReader.Close() } @@ -480,38 +480,31 @@ func untar(sourceFile, destinationDir string) error { if err == io.EOF { break } - return err + return fmt.Errorf("error reading tar: %w", err) } path := filepath.Join(destinationDir, header.Name) - if !strings.HasPrefix(path, destinationDir) { + if !strings.HasPrefix(path, filepath.Clean(destinationDir)+string(os.PathSeparator)) { return fmt.Errorf("illegal file path in tar: %v", header.Name) } switch header.Typeflag { case tar.TypeDir: if err = os.MkdirAll(path, os.FileMode(header.Mode)); err != nil { - return err + return fmt.Errorf("failed to create directory: %w", err) } case tar.TypeReg: - writer, err := os.Create(path) + writer, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(header.Mode)) if err != nil { - return err - } - - if _, err = io.Copy(writer, tarReader); err != nil { - return err - } - - if err = os.Chmod(path, os.FileMode(header.Mode)); err != nil { - return err + return fmt.Errorf("failed to create file: %w", err) } - - if err = writer.Close(); err != nil { - return err + _, err = io.Copy(writer, tarReader) + writer.Close() + if err != nil { + return fmt.Errorf("failed to write file contents: %w", err) } default: - return fmt.Errorf("unable to untar type=%c in file=%s", header.Typeflag, path) + return fmt.Errorf("unsupported tar entry type: %c for file: %s", header.Typeflag, path) } } @@ -585,7 +578,7 @@ func ParallelCtx(ctx context.Context, fns ...interface{}) { } var mu sync.Mutex - var errs []string + var errs []error var wg sync.WaitGroup for _, fw := range fnWrappers { @@ -594,7 +587,7 @@ func ParallelCtx(ctx context.Context, fns ...interface{}) { defer func() { if v := recover(); v != nil { mu.Lock() - errs = append(errs, fmt.Sprint(v)) + errs = append(errs, fmt.Errorf("%s", v)) mu.Unlock() } wg.Done() @@ -602,10 +595,10 @@ func ParallelCtx(ctx context.Context, fns ...interface{}) { }() waitStart := time.Now() parallelJobs() <- 1 - log.Println("Parallel job waited", time.Since(waitStart), "before starting.") + fmt.Printf("Parallel job waited %v before starting.\n", time.Since(waitStart)) if err := fw(ctx); err != nil { mu.Lock() - errs = append(errs, fmt.Sprint(err)) + errs = append(errs, err) mu.Unlock() } }(fw) @@ -613,7 +606,7 @@ func ParallelCtx(ctx context.Context, fns ...interface{}) { wg.Wait() if len(errs) > 0 { - panic(fmt.Errorf(strings.Join(errs, "\n"))) + panic(errors.Join(errs...)) } } @@ -675,7 +668,6 @@ func FindFilesRecursive(match func(path string, info os.FileInfo) bool) ([]strin } if !info.Mode().IsRegular() { - // continue return nil } @@ -696,31 +688,25 @@ func FileConcat(out string, perm os.FileMode, files ...string) error { defer f.Close() w := bufio.NewWriter(f) + defer w.Flush() - append := func(file string) error { + for _, file := range files { in, err := os.Open(file) if err != nil { - return err + return fmt.Errorf("failed to open input file %s: %w", file, err) } defer in.Close() if _, err := io.Copy(w, in); err != nil { - return err + return fmt.Errorf("failed to copy from %s: %w", file, err) } - - return nil } - for _, in := range files { - if err := append(in); err != nil { - return err - } + if err := w.Flush(); err != nil { + return fmt.Errorf("failed to flush writer: %w", err) } - if err = w.Flush(); err != nil { - return err - } - return f.Close() + return nil } // MustFileConcat invokes FileConcat and panics if an error occurs. @@ -748,11 +734,10 @@ func VerifySHA256(file string, hash string) error { expectedHash := strings.TrimSpace(hash) if computedHash != expectedHash { - return fmt.Errorf("SHA256 verification of %v failed. Expected=%v, "+ - "but computed=%v", f.Name(), expectedHash, computedHash) + return fmt.Errorf("SHA256 verification of %v failed. Expected=%v, computed=%v", f.Name(), expectedHash, computedHash) } - log.Println("SHA256 OK:", f.Name()) + fmt.Printf("SHA256 OK: %s\n", f.Name()) return nil } @@ -773,7 +758,7 @@ func CreateSHA512File(file string) error { computedHash := hex.EncodeToString(sum.Sum(nil)) out := fmt.Sprintf("%v %v", computedHash, filepath.Base(file)) - return ioutil.WriteFile(file+".sha512", []byte(out), 0644) + return os.WriteFile(file+".sha512", []byte(out), 0644) } // Mage executes mage targets in the specified directory. diff --git a/dev-tools/mage/config.go b/dev-tools/mage/config.go index 822e7f0f163..251db63eea8 100644 --- a/dev-tools/mage/config.go +++ b/dev-tools/mage/config.go @@ -21,7 +21,6 @@ import ( "bytes" "errors" "fmt" - "io/ioutil" "os" "path/filepath" "regexp" @@ -136,7 +135,7 @@ func makeConfigTemplate(destination string, mode os.FileMode, confParams ConfigF confFile = confParams.Docker tmplParams = map[string]interface{}{"Docker": true} default: - panic(fmt.Errorf("Invalid config file type: %v", typ)) + panic(fmt.Errorf("invalid config file type: %v", typ)) } // Build the dependencies. @@ -196,7 +195,7 @@ func makeConfigTemplate(destination string, mode os.FileMode, confParams ConfigF } } - data, err := ioutil.ReadFile(confFile.Template) + data, err := os.ReadFile(confFile.Template) if err != nil { return fmt.Errorf("failed to read config template %q: %w", confFile.Template, err) } @@ -265,7 +264,7 @@ type moduleFieldsYmlData []struct { } func readModuleFieldsYml(path string) (title string, useShort bool, err error) { - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { return "", false, err } @@ -302,7 +301,7 @@ func moduleDashes(name string) string { func GenerateModuleReferenceConfig(out string, moduleDirs ...string) error { var moduleConfigs []moduleConfigTemplateData for _, dir := range moduleDirs { - modules, err := ioutil.ReadDir(dir) + modules, err := os.ReadDir(dir) if err != nil { return err } @@ -327,7 +326,7 @@ func GenerateModuleReferenceConfig(out string, moduleDirs ...string) error { var data []byte for _, f := range files { - data, err = ioutil.ReadFile(f) + data, err = os.ReadFile(f) if err != nil { if os.IsNotExist(err) { continue @@ -365,5 +364,5 @@ func GenerateModuleReferenceConfig(out string, moduleDirs ...string) error { "Modules": moduleConfigs, }) - return ioutil.WriteFile(createDir(out), []byte(config), 0644) + return os.WriteFile(createDir(out), []byte(config), 0644) } diff --git a/dev-tools/mage/crossbuild.go b/dev-tools/mage/crossbuild.go index 972531c25a8..d9de45cef09 100644 --- a/dev-tools/mage/crossbuild.go +++ b/dev-tools/mage/crossbuild.go @@ -21,7 +21,6 @@ import ( "errors" "fmt" "go/build" - "log" "os" "path/filepath" "runtime" @@ -57,11 +56,9 @@ func init() { if packageTypes := os.Getenv("PACKAGES"); len(packageTypes) > 0 { for _, pkgtype := range strings.Split(packageTypes, ",") { var p PackageType - err := p.UnmarshalText([]byte(pkgtype)) - if err != nil { - continue + if err := p.UnmarshalText([]byte(pkgtype)); err == nil { + SelectedPackageTypes = append(SelectedPackageTypes, p) } - SelectedPackageTypes = append(SelectedPackageTypes, p) } } } @@ -112,9 +109,8 @@ func ImageSelector(f ImageSelectorFunc) func(params *crossBuildParams) { // AddPlatforms sets dependencies on others platforms. func AddPlatforms(expressions ...string) func(params *crossBuildParams) { return func(params *crossBuildParams) { - var list BuildPlatformList for _, expr := range expressions { - list = NewPlatformList(expr) + list := NewPlatformList(expr) params.Platforms = params.Platforms.Merge(list) } } @@ -136,7 +132,7 @@ func CrossBuild(options ...CrossBuildOption) error { } if len(params.Platforms) == 0 { - log.Printf("Skipping cross-build of target=%v because platforms list is empty.", params.Target) + fmt.Printf("Skipping cross-build of target=%v because platforms list is empty.\n", params.Target) return nil } @@ -147,14 +143,13 @@ func CrossBuild(options ...CrossBuildOption) error { if platform.GOOS() == "aix" { if len(params.Platforms) != 1 { return errors.New("AIX cannot be crossbuilt with other platforms. Set PLATFORMS='aix/ppc64'") - } else { - // This is basically a short-out so we can attempt to build on AIX in a relatively generic way - log.Printf("Target is building for AIX, skipping normal crossbuild process") - args := DefaultBuildArgs() - args.OutputDir = filepath.Join("build", "golang-crossbuild") - args.Name += "-" + Platform.GOOS + "-" + Platform.Arch - return Build(args) } + // This is basically a short-out so we can attempt to build on AIX in a relatively generic way + fmt.Printf("Target is building for AIX, skipping normal crossbuild process\n") + args := DefaultBuildArgs() + args.OutputDir = filepath.Join("build", "golang-crossbuild") + args.Name += "-" + Platform.GOOS + "-" + Platform.Arch + return Build(args) } } // If we're here, something isn't set. @@ -163,7 +158,7 @@ func CrossBuild(options ...CrossBuildOption) error { // Docker is required for this target. if err := HaveDocker(); err != nil { - return err + return fmt.Errorf("docker is required for crossbuild: %w", err) } if CrossBuildMountModcache { @@ -175,7 +170,7 @@ func CrossBuild(options ...CrossBuildOption) error { // Build the magefile for Linux, so we can run it inside the container. mg.Deps(buildMage) - log.Println("crossBuild: Platform list =", params.Platforms) + fmt.Printf("crossBuild: Platform list: %v\n", params.Platforms) var deps []interface{} for _, buildPlatform := range params.Platforms { if !buildPlatform.Flags.CanCrossBuild() { @@ -207,13 +202,26 @@ func CrossBuildXPack(options ...CrossBuildOption) error { return CrossBuild(o...) } -// buildMage pre-compiles the magefile to a binary using the GOARCH parameter. -// It has the benefit of speeding up the build because the -// mage -compile is done only once rather than in each Docker container. +// buildMage pre-compiles the magefile to a binary using the current GOARCH. +// It speeds up the build process by compiling mage only once for each architecture. func buildMage() error { - arch := runtime.GOARCH - return sh.RunWith(map[string]string{"CGO_ENABLED": "0"}, "mage", "-f", "-goos=linux", "-goarch="+arch, - "-compile", CreateDir(filepath.Join("build", "mage-linux-"+arch))) + const arch = runtime.GOARCH + + args := []string{ + "-f", + "-goos=linux", + "-goarch=" + arch, + "-compile", + filepath.Join("build", "mage-linux-"+arch), + } + + env := map[string]string{"CGO_ENABLED": "0"} + err := sh.RunWith(env, "mage", args...) + if err != nil { + return fmt.Errorf("failed to compile mage: %w", err) + } + + return nil } func CrossBuildImage(platform string) (string, error) { @@ -246,10 +254,10 @@ func CrossBuildImage(platform string) (string, error) { goVersion, err := GoVersion() if err != nil { - return "", err + return "", fmt.Errorf("failed to get Go version: %w", err) } - return BeatsCrossBuildImage + ":" + goVersion + "-" + tagSuffix, nil + return fmt.Sprintf("%s:%s-%s", BeatsCrossBuildImage, goVersion, tagSuffix), nil } // GolangCrossBuilder executes the specified mage target inside of the @@ -272,27 +280,29 @@ func (b GolangCrossBuilder) Build() error { mountPoint := filepath.ToSlash(filepath.Join("/go", "src", repoInfo.CanonicalRootImportPath)) // use custom dir for build if given, subdir if not: - cwd := repoInfo.SubDir - if b.InDir != "" { - cwd = b.InDir + cwd := b.InDir + if cwd == "" { + cwd = repoInfo.SubDir } workDir := filepath.ToSlash(filepath.Join(mountPoint, cwd)) builderArch := runtime.GOARCH - buildCmd, err := filepath.Rel(workDir, filepath.Join(mountPoint, repoInfo.SubDir, "build/mage-linux-"+builderArch)) + buildCmd, err := filepath.Rel(workDir, filepath.Join(mountPoint, repoInfo.SubDir, "build", "mage-linux-"+builderArch)) if err != nil { - return fmt.Errorf("failed to determine mage-linux-"+builderArch+" relative path: %w", err) + return fmt.Errorf("failed to determine mage-linux-%s relative path: %w", builderArch, err) } dockerRun := sh.RunCmd("docker", "run") image, err := b.ImageSelector(b.Platform) if err != nil { - return fmt.Errorf("failed to determine golang-crossbuild image tag: %w", err) + return fmt.Errorf("failed to determine golang-crossbuild image tag for platform %s: %w", b.Platform, err) } + verbose := "" if mg.Verbose() { verbose = "true" } + var args []string // There's a bug on certain debian versions: // https://discuss.linuxcontainers.org/t/debian-jessie-containers-have-extremely-low-performance/1272 @@ -309,35 +319,65 @@ func (b GolangCrossBuilder) Build() error { "--env", "EXEC_GID="+strconv.Itoa(os.Getgid()), ) } + if versionQualified { args = append(args, "--env", "VERSION_QUALIFIER="+versionQualifier) } + if CrossBuildMountModcache { // Mount $GOPATH/pkg/mod into the container, read-only. hostDir := filepath.Join(build.Default.GOPATH, "pkg", "mod") args = append(args, "-v", hostDir+":/go/pkg/mod:ro") } - if b.Platform == "darwin/amd64" { + switch b.Platform { + case "darwin/amd64": fmt.Printf(">> %v: Forcing DEV=0 for %s: https://github.com/elastic/golang-crossbuild/issues/217\n", b.Target, b.Platform) args = append(args, "--env", "DEV=0") - } else { - args = append(args, "--env", fmt.Sprintf("DEV=%v", DevBuild)) + default: + args = append(args, "--env", "DEV="+strconv.FormatBool(DevBuild)) } + // To speed up cross-compilation, we need to persist the build cache so that subsequent builds + // for the same arch are faster (⚡). + // + // As we want to persist the build cache, we need to mount the cache directory to the Docker host. + // This is done by mounting the host directory to the container. + // + // Path of the cache directory on the host: + // /build/.go-build/ + // Example: /build/.go-build/linux/amd64 + // + // As per: https://docs.docker.com/engine/storage/bind-mounts/#differences-between--v-and---mount-behavior + // If the directory doesn't exist, Docker does not automatically create it for you, but generates an error. + // So, we need to create the directory before mounting it. + // + // Also, in the container, the cache directory is mounted to /root/.cache/go-build. + buildCacheHostDir := filepath.Join(repoInfo.RootDir, "build", ".go-build", b.Platform) + buildCacheContainerDir := "/root/.cache/go-build" + if err = os.MkdirAll(buildCacheHostDir, 0755); err != nil { + return fmt.Errorf("failed to create directory %s: %w", buildCacheHostDir, err) + } + + // Common arguments args = append(args, "--rm", "--env", "GOFLAGS=-mod=readonly -buildvcs=false", "--env", "MAGEFILE_VERBOSE="+verbose, "--env", "MAGEFILE_TIMEOUT="+EnvOr("MAGEFILE_TIMEOUT", ""), - "--env", fmt.Sprintf("SNAPSHOT=%v", Snapshot), + "--env", "SNAPSHOT="+strconv.FormatBool(Snapshot), + + // To persist the build cache, we need to mount the cache directory to the Docker host. + // With docker run, mount types are: bind, volume and tmpfs. For our use case, we have + // decide to use the bind mount type. + "--mount", fmt.Sprintf("type=bind,source=%s,target=%s", buildCacheHostDir, buildCacheContainerDir), "-v", repoInfo.RootDir+":"+mountPoint, "-w", workDir, ) + // Image and build command arguments args = append(args, image, - // Arguments for docker crossbuild entrypoint. For details see // https://github.com/elastic/golang-crossbuild/blob/main/go1.17/base/rootfs/entrypoint.go. "--build-cmd", buildCmd+" "+b.Target, @@ -354,9 +394,9 @@ func DockerChown(path string) { uid, _ := strconv.Atoi(EnvOr("EXEC_UID", "-1")) gid, _ := strconv.Atoi(EnvOr("EXEC_GID", "-1")) if uid > 0 && gid > 0 { - log.Printf(">>> Fixing file ownership issues from Docker at path=%v", path) + fmt.Printf(">>> Fixing file ownership issues from Docker at path=%v\n", path) if err := chownPaths(uid, gid, path); err != nil { - log.Println(err) + fmt.Println(err) } } } @@ -366,7 +406,7 @@ func chownPaths(uid, gid int, path string) error { start := time.Now() numFixed := 0 defer func() { - log.Printf("chown took: %v, changed %d files", time.Since(start), numFixed) + fmt.Printf("chown took: %v, changed %d files\n", time.Since(start), numFixed) }() return filepath.Walk(path, func(name string, info os.FileInfo, err error) error { diff --git a/dev-tools/mage/dockerbuilder.go b/dev-tools/mage/dockerbuilder.go index 2066670dc80..6f2c7ff20ed 100644 --- a/dev-tools/mage/dockerbuilder.go +++ b/dev-tools/mage/dockerbuilder.go @@ -43,7 +43,7 @@ type dockerBuilder struct { func newDockerBuilder(spec PackageSpec) (*dockerBuilder, error) { imageName, err := spec.ImageName() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get image name: %w", err) } buildDir := filepath.Join(spec.packageDir, "docker-build") @@ -63,7 +63,7 @@ func (b *dockerBuilder) Build() error { } if err := b.copyFiles(); err != nil { - return err + return fmt.Errorf("failed to copy files: %w", err) } if err := b.prepareBuild(); err != nil { @@ -71,13 +71,14 @@ func (b *dockerBuilder) Build() error { } tag, err := b.dockerBuild() - tries := 3 - for err != nil && tries != 0 { + + const maxRetries = 3 + const retryInterval = 10 * time.Second + + for retries := 0; err != nil && retries < maxRetries; retries++ { fmt.Println(">> Building docker images again (after 10 s)") - // This sleep is to avoid hitting the docker build issues when resources are not available. - time.Sleep(time.Second * 10) + time.Sleep(retryInterval) tag, err = b.dockerBuild() - tries -= 1 } if err != nil { return fmt.Errorf("failed to build docker: %w", err) @@ -123,7 +124,7 @@ func (b *dockerBuilder) copyFiles() error { func (b *dockerBuilder) prepareBuild() error { elasticBeatsDir, err := ElasticBeatsDir() if err != nil { - return err + return fmt.Errorf("failed to get ElasticBeatsDir: %w", err) } templatesDir := filepath.Join(elasticBeatsDir, "dev-tools/packaging/templates/docker") @@ -139,8 +140,7 @@ func (b *dockerBuilder) prepareBuild() error { ".tmpl", ) - err = b.ExpandFile(path, target, data) - if err != nil { + if err := b.ExpandFile(path, target, data); err != nil { return fmt.Errorf("expanding template '%s' to '%s': %w", path, target, err) } } @@ -148,15 +148,15 @@ func (b *dockerBuilder) prepareBuild() error { }) if err != nil { - return err + return fmt.Errorf("failed to walk templates directory: %w", err) } return b.expandDockerfile(templatesDir, data) } func isDockerFile(path string) bool { - path = filepath.Base(path) - return strings.HasPrefix(path, "Dockerfile") || strings.HasPrefix(path, "docker-entrypoint") + base := filepath.Base(path) + return strings.HasPrefix(base, "Dockerfile") || strings.HasPrefix(base, "docker-entrypoint") } func (b *dockerBuilder) expandDockerfile(templatesDir string, data map[string]interface{}) error { @@ -170,18 +170,21 @@ func (b *dockerBuilder) expandDockerfile(templatesDir string, data map[string]in entrypoint = e } - type fileExpansion struct { + files := []struct { source string target string + }{ + {dockerfile, "Dockerfile.tmpl"}, + {entrypoint, "docker-entrypoint.tmpl"}, } - for _, file := range []fileExpansion{{dockerfile, "Dockerfile.tmpl"}, {entrypoint, "docker-entrypoint.tmpl"}} { + + for _, file := range files { target := strings.TrimSuffix( filepath.Join(b.buildDir, file.target), ".tmpl", ) path := filepath.Join(templatesDir, file.source) - err := b.ExpandFile(path, target, data) - if err != nil { + if err := b.ExpandFile(path, target, data); err != nil { return fmt.Errorf("expanding template '%s' to '%s': %w", path, target, err) } } @@ -192,7 +195,7 @@ func (b *dockerBuilder) expandDockerfile(templatesDir string, data map[string]in func (b *dockerBuilder) dockerBuild() (string, error) { tag := fmt.Sprintf("%s:%s", b.imageName, b.Version) if b.Snapshot { - tag = tag + "-SNAPSHOT" + tag += "-SNAPSHOT" } if repository, _ := b.ExtraVars["repository"]; repository != "" { tag = fmt.Sprintf("%s/%s", repository, tag) @@ -201,12 +204,10 @@ func (b *dockerBuilder) dockerBuild() (string, error) { } func (b *dockerBuilder) dockerSave(tag string) error { - if _, err := os.Stat(distributionsDir); os.IsNotExist(err) { - err := os.MkdirAll(distributionsDir, 0750) - if err != nil { - return fmt.Errorf("cannot create folder for docker artifacts: %+v", err) - } + if err := os.MkdirAll(distributionsDir, 0750); err != nil { + return fmt.Errorf("cannot create folder for docker artifacts: %w", err) } + // Save the container as artifact outputFile := b.OutputFile if outputFile == "" { @@ -214,46 +215,46 @@ func (b *dockerBuilder) dockerSave(tag string) error { "Name": b.imageName, }) if err != nil { - return err + return fmt.Errorf("failed to expand output file name: %w", err) } outputFile = filepath.Join(distributionsDir, outputTar) } + var stderr bytes.Buffer cmd := exec.Command("docker", "save", tag) cmd.Stderr = &stderr stdout, err := cmd.StdoutPipe() if err != nil { - return err + return fmt.Errorf("failed to get stdout pipe: %w", err) } + if err = cmd.Start(); err != nil { - return err + return fmt.Errorf("failed to start docker save command: %w", err) } - err = func() error { + if err := func() error { f, err := os.Create(outputFile) if err != nil { - return err + return fmt.Errorf("failed to create output file: %w", err) } defer f.Close() w := gzip.NewWriter(f) defer w.Close() - _, err = io.Copy(w, stdout) - if err != nil { - return err + if _, err = io.Copy(w, stdout); err != nil { + return fmt.Errorf("failed to copy docker save output: %w", err) } return nil - }() - if err != nil { + }(); err != nil { return err } if err = cmd.Wait(); err != nil { if errmsg := strings.TrimSpace(stderr.String()); errmsg != "" { - err = fmt.Errorf(err.Error()+": %w", errors.New(errmsg)) + err = fmt.Errorf("%w: %s", err, errmsg) } - return err + return fmt.Errorf("docker save command failed: %w", err) } if err = CreateSHA512File(outputFile); err != nil { diff --git a/dev-tools/mage/platforms.go b/dev-tools/mage/platforms.go index f2e835f687c..c15cdcffb0a 100644 --- a/dev-tools/mage/platforms.go +++ b/dev-tools/mage/platforms.go @@ -327,7 +327,7 @@ func newPlatformExpression(expr string) (*platformExpression, error) { // // By default, the initial set include only the platforms designated as defaults. // To add additional platforms to list use an addition term that is designated -// with a plug sign (e.g. "+netbsd" or "+linux/armv7"). Or you may use "+all" +// with a plus sign (e.g. "+netbsd" or "+linux/armv7"). Or you may use "+all" // to change the initial set to include all possible platforms then filter // from there (e.g. "+all linux windows"). // @@ -446,27 +446,33 @@ func (list BuildPlatformList) Filter(expr string) BuildPlatformList { return out.deduplicate() } -// Merge creates a new list with the two list merged. +// Merge creates a new list with the two lists merged. func (list BuildPlatformList) Merge(with BuildPlatformList) BuildPlatformList { - out := append(list, with...) + out := make(BuildPlatformList, 0, len(list)+len(with)) + out = append(out, list...) out = append(out, with...) return out.deduplicate() } // deduplicate removes duplicate platforms and sorts the list. func (list BuildPlatformList) deduplicate() BuildPlatformList { - set := map[string]BuildPlatform{} - for _, item := range list { - set[item.Name] = item + if len(list) <= 1 { + return list } - var out BuildPlatformList - for _, v := range set { - out = append(out, v) + seen := make(map[string]struct{}, len(list)) + out := make(BuildPlatformList, 0, len(list)) + + for _, item := range list { + if _, exists := seen[item.Name]; !exists { + seen[item.Name] = struct{}{} + out = append(out, item) + } } sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name }) + return out } From 57eec7cbac9c7ab7a74ecf13599023486553acf9 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 01:58:23 +0530 Subject: [PATCH 02/20] make most lints happy --- dev-tools/mage/check.go | 9 ++++----- dev-tools/mage/common.go | 13 ++++++------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/dev-tools/mage/check.go b/dev-tools/mage/check.go index e01e98c16e1..6daf14d3e66 100644 --- a/dev-tools/mage/check.go +++ b/dev-tools/mage/check.go @@ -22,7 +22,6 @@ import ( "bytes" "encoding/json" "fmt" - "io/ioutil" "log" "os" "os/exec" @@ -59,7 +58,7 @@ func Check() error { if len(changes) > 0 { if mg.Verbose() { - GitDiff() + _ = GitDiff() } return fmt.Errorf("some files are not up-to-date. "+ @@ -229,7 +228,7 @@ func CheckDashboardsFormat() error { hasErrors := false for _, file := range dashboardFiles { - d, err := ioutil.ReadFile(file) + d, err := os.ReadFile(file) if err != nil { return fmt.Errorf("failed to read dashboard file %s: %w", file, err) } @@ -321,11 +320,11 @@ func (d *DashboardObject) CheckFormat(module string) error { return fmt.Errorf("empty description on dashboard '%s'", d.Attributes.Title) } if err := checkTitle(dashboardTitleRegexp, d.Attributes.Title, module); err != nil { - return fmt.Errorf("expected title with format '[%s Module] Some title', found '%s': %w", strings.Title(BeatName), d.Attributes.Title, err) + return fmt.Errorf("expected title with format '[%s Module] Some title', found '%s': %w", strings.Title(BeatName), d.Attributes.Title, err) // nolint:staticcheck // strings.Title is deprecated but we need it. } case "visualization": if err := checkTitle(visualizationTitleRegexp, d.Attributes.Title, module); err != nil { - return fmt.Errorf("expected title with format 'Some title [%s Module]', found '%s': %w", strings.Title(BeatName), d.Attributes.Title, err) + return fmt.Errorf("expected title with format 'Some title [%s Module]', found '%s': %w", strings.Title(BeatName), d.Attributes.Title, err) // nolint:staticcheck // strings.Title is deprecated but we need it. } } diff --git a/dev-tools/mage/common.go b/dev-tools/mage/common.go index 2fc2122547d..d9589d224b2 100644 --- a/dev-tools/mage/common.go +++ b/dev-tools/mage/common.go @@ -32,7 +32,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "log" "net/http" "os" @@ -125,7 +124,7 @@ func joinMaps(args ...map[string]interface{}) map[string]interface{} { } func expandFile(src, dst string, args ...map[string]interface{}) error { - tmplData, err := ioutil.ReadFile(src) + tmplData, err := os.ReadFile(src) if err != nil { return fmt.Errorf("failed reading from template %v: %w", src, err) } @@ -140,7 +139,7 @@ func expandFile(src, dst string, args ...map[string]interface{}) error { return err } - if err = ioutil.WriteFile(createDir(dst), []byte(output), 0644); err != nil { + if err = os.WriteFile(createDir(dst), []byte(output), 0644); err != nil { return fmt.Errorf("failed to write rendered template: %w", err) } @@ -262,13 +261,13 @@ func FindReplace(file string, re *regexp.Regexp, repl string) error { return err } - contents, err := ioutil.ReadFile(file) + contents, err := os.ReadFile(file) if err != nil { return err } out := re.ReplaceAllString(string(contents), repl) - return ioutil.WriteFile(file, []byte(out), info.Mode().Perm()) + return os.WriteFile(file, []byte(out), info.Mode().Perm()) } // MustFindReplace invokes FindReplace and panics if an error occurs. @@ -281,9 +280,9 @@ func MustFindReplace(file string, re *regexp.Regexp, repl string) { // DownloadFile downloads the given URL and writes the file to destinationDir. // The path to the file is returned. func DownloadFile(url, destinationDir string) (string, error) { - log.Println("Downloading", url) + fmt.Println("Downloading", url) - resp, err := http.Get(url) + resp, err := http.Get(url) //nolint:gosec // we trust the url if err != nil { return "", fmt.Errorf("http get failed: %w", err) } From b65f336281a2f5ad8e3619550030f22707203544 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 02:20:05 +0530 Subject: [PATCH 03/20] add statements to debug something --- dev-tools/mage/crossbuild.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dev-tools/mage/crossbuild.go b/dev-tools/mage/crossbuild.go index d9de45cef09..f1c9507752e 100644 --- a/dev-tools/mage/crossbuild.go +++ b/dev-tools/mage/crossbuild.go @@ -355,10 +355,19 @@ func (b GolangCrossBuilder) Build() error { // Also, in the container, the cache directory is mounted to /root/.cache/go-build. buildCacheHostDir := filepath.Join(repoInfo.RootDir, "build", ".go-build", b.Platform) buildCacheContainerDir := "/root/.cache/go-build" + + _, err = os.Stat(buildCacheHostDir) + if err != nil { + return fmt.Errorf("failed to stat directory %s: %w", buildCacheHostDir, err) + } if err = os.MkdirAll(buildCacheHostDir, 0755); err != nil { return fmt.Errorf("failed to create directory %s: %w", buildCacheHostDir, err) } + // Print the directory tree to ensure that the directory is mounted correctly. + fmt.Println("Displaying .go-build directory structure:") + sh.Run("tree", filepath.Join(repoInfo.RootDir, "build", ".go-build")) + // Common arguments args = append(args, "--rm", @@ -366,6 +375,7 @@ func (b GolangCrossBuilder) Build() error { "--env", "MAGEFILE_VERBOSE="+verbose, "--env", "MAGEFILE_TIMEOUT="+EnvOr("MAGEFILE_TIMEOUT", ""), "--env", "SNAPSHOT="+strconv.FormatBool(Snapshot), + "--env", "GOGC=off", // Disable GC during build. // To persist the build cache, we need to mount the cache directory to the Docker host. // With docker run, mount types are: bind, volume and tmpfs. For our use case, we have From fb2d80bd2eefd525929f2ae7566bbe0d7c4fa040 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 02:41:26 +0530 Subject: [PATCH 04/20] add statements to debug something --- dev-tools/mage/crossbuild.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dev-tools/mage/crossbuild.go b/dev-tools/mage/crossbuild.go index f1c9507752e..9b5a3ed3f19 100644 --- a/dev-tools/mage/crossbuild.go +++ b/dev-tools/mage/crossbuild.go @@ -353,12 +353,13 @@ func (b GolangCrossBuilder) Build() error { // So, we need to create the directory before mounting it. // // Also, in the container, the cache directory is mounted to /root/.cache/go-build. - buildCacheHostDir := filepath.Join(repoInfo.RootDir, "build", ".go-build", b.Platform) + // buildCacheHostDir := filepath.Join(repoInfo.RootDir, "build", ".go-build", b.Platform) + buildCacheHostDir := filepath.Join(os.TempDir(), "build", ".go-build", b.Platform) buildCacheContainerDir := "/root/.cache/go-build" _, err = os.Stat(buildCacheHostDir) if err != nil { - return fmt.Errorf("failed to stat directory %s: %w", buildCacheHostDir, err) + fmt.Printf("Failed to stat cache directory %s: %v", buildCacheHostDir, err) } if err = os.MkdirAll(buildCacheHostDir, 0755); err != nil { return fmt.Errorf("failed to create directory %s: %w", buildCacheHostDir, err) @@ -366,7 +367,9 @@ func (b GolangCrossBuilder) Build() error { // Print the directory tree to ensure that the directory is mounted correctly. fmt.Println("Displaying .go-build directory structure:") - sh.Run("tree", filepath.Join(repoInfo.RootDir, "build", ".go-build")) + if err = sh.Run("tree", filepath.Join(repoInfo.RootDir, "build", ".go-build")); err != nil { + fmt.Printf("Failed to execute tree command: %v", err) + } // Common arguments args = append(args, From 5a161ceaa54119bbdd28c86bc8fb130e9144573d Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 11:07:23 +0530 Subject: [PATCH 05/20] debug --- dev-tools/mage/crossbuild.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/dev-tools/mage/crossbuild.go b/dev-tools/mage/crossbuild.go index 9b5a3ed3f19..dbd56f4ebff 100644 --- a/dev-tools/mage/crossbuild.go +++ b/dev-tools/mage/crossbuild.go @@ -21,6 +21,8 @@ import ( "errors" "fmt" "go/build" + "io/fs" + "log" "os" "path/filepath" "runtime" @@ -367,8 +369,14 @@ func (b GolangCrossBuilder) Build() error { // Print the directory tree to ensure that the directory is mounted correctly. fmt.Println("Displaying .go-build directory structure:") - if err = sh.Run("tree", filepath.Join(repoInfo.RootDir, "build", ".go-build")); err != nil { - fmt.Printf("Failed to execute tree command: %v", err) + err = filepath.WalkDir(buildCacheHostDir, func(path string, d fs.DirEntry, err error) error { + if d.IsDir() { + fmt.Println(path, d.Name()) + } + return nil + }) + if err != nil { + log.Fatalf("impossible to walk directories: %s", err) } // Common arguments From 428d059bcece392c99df618f349ec301bd1340d1 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 11:34:26 +0530 Subject: [PATCH 06/20] debug 1 --- dev-tools/mage/crossbuild.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/dev-tools/mage/crossbuild.go b/dev-tools/mage/crossbuild.go index dbd56f4ebff..6ac72f970aa 100644 --- a/dev-tools/mage/crossbuild.go +++ b/dev-tools/mage/crossbuild.go @@ -21,8 +21,6 @@ import ( "errors" "fmt" "go/build" - "io/fs" - "log" "os" "path/filepath" "runtime" @@ -359,26 +357,10 @@ func (b GolangCrossBuilder) Build() error { buildCacheHostDir := filepath.Join(os.TempDir(), "build", ".go-build", b.Platform) buildCacheContainerDir := "/root/.cache/go-build" - _, err = os.Stat(buildCacheHostDir) - if err != nil { - fmt.Printf("Failed to stat cache directory %s: %v", buildCacheHostDir, err) - } if err = os.MkdirAll(buildCacheHostDir, 0755); err != nil { return fmt.Errorf("failed to create directory %s: %w", buildCacheHostDir, err) } - // Print the directory tree to ensure that the directory is mounted correctly. - fmt.Println("Displaying .go-build directory structure:") - err = filepath.WalkDir(buildCacheHostDir, func(path string, d fs.DirEntry, err error) error { - if d.IsDir() { - fmt.Println(path, d.Name()) - } - return nil - }) - if err != nil { - log.Fatalf("impossible to walk directories: %s", err) - } - // Common arguments args = append(args, "--rm", From 836b67ff17b490eb4b9c6206bbf15123f5c94672 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 14:44:47 +0530 Subject: [PATCH 07/20] make parallel better --- dev-tools/mage/common.go | 88 ++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/dev-tools/mage/common.go b/dev-tools/mage/common.go index d9589d224b2..93a9a36917f 100644 --- a/dev-tools/mage/common.go +++ b/dev-tools/mage/common.go @@ -33,6 +33,7 @@ import ( "fmt" "io" "log" + "math" "net/http" "os" "os/exec" @@ -524,40 +525,36 @@ func RunCmds(cmds ...[]string) error { return nil } -var ( - parallelJobsLock sync.Mutex - parallelJobsSemaphore chan int -) - -func parallelJobs() chan int { - parallelJobsLock.Lock() - defer parallelJobsLock.Unlock() +var parallelJobsSemaphore chan struct{} +// parallelJobs returns a semaphore channel to limit the number of parallel jobs. +func parallelJobs() chan struct{} { if parallelJobsSemaphore == nil { max := numParallel() - parallelJobsSemaphore = make(chan int, max) - log.Println("Max parallel jobs =", max) + parallelJobsSemaphore = make(chan struct{}, max) + fmt.Printf("Max parallel jobs: %d\n", max) } return parallelJobsSemaphore } +// numParallel determines the maximum number of parallel jobs to run. +// It considers the MAX_PARALLEL environment variable, the number of CPUs on the host, +// and the number of CPUs reported by Docker. func numParallel() int { - if maxParallel := os.Getenv("MAX_PARALLEL"); maxParallel != "" { - if num, err := strconv.Atoi(maxParallel); err == nil && num > 0 { - return num - } + if maxParallel, err := strconv.Atoi(os.Getenv("MAX_PARALLEL")); err == nil && maxParallel > 0 { + return maxParallel } - // To be conservative use the minimum of the number of CPUs between the host - // and the Docker host. - maxParallel := runtime.NumCPU() + // Calculate based on available CPUs + maxParallel := runtime.NumCPU() / 2 + // Adjust based on Docker-reported CPUs if available info, err := GetDockerInfo() // Check that info.NCPU != 0 since docker info doesn't return with an - // error status if communcation with the daemon failed. - if err == nil && info.NCPU != 0 && info.NCPU < maxParallel { - maxParallel = info.NCPU + // error status if communication with the daemon fails. + if err == nil && info.NCPU != 0 { + maxParallel = int(math.Min(float64(maxParallel), float64(info.NCPU))) } return maxParallel @@ -571,39 +568,49 @@ func ParallelCtx(ctx context.Context, fns ...interface{}) { for _, f := range fns { fnWrapper := funcTypeWrap(f) if fnWrapper == nil { - panic("attempted to add a dep that did not match required function type") + panic(fmt.Sprintf("unsupported function type: %T", f)) } fnWrappers = append(fnWrappers, fnWrapper) } - var mu sync.Mutex - var errs []error + errChan := make(chan error, len(fnWrappers)) var wg sync.WaitGroup for _, fw := range fnWrappers { wg.Add(1) go func(fw func(context.Context) error) { + defer wg.Done() defer func() { - if v := recover(); v != nil { - mu.Lock() - errs = append(errs, fmt.Errorf("%s", v)) - mu.Unlock() + if r := recover(); r != nil { + errChan <- fmt.Errorf("panic: %v", r) } - wg.Done() <-parallelJobs() }() + + select { + case parallelJobs() <- struct{}{}: + case <-ctx.Done(): + errChan <- ctx.Err() + return + } + waitStart := time.Now() - parallelJobs() <- 1 fmt.Printf("Parallel job waited %v before starting.\n", time.Since(waitStart)) + if err := fw(ctx); err != nil { - mu.Lock() - errs = append(errs, err) - mu.Unlock() + errChan <- err } }(fw) } wg.Wait() + close(errChan) + + var errs []error + for err := range errChan { + errs = append(errs, err) + } + if len(errs) > 0 { panic(errors.Join(errs...)) } @@ -619,23 +626,16 @@ func Parallel(fns ...interface{}) { func funcTypeWrap(fn interface{}) func(context.Context) error { switch f := fn.(type) { case func(): - return func(context.Context) error { - f() - return nil - } + return func(context.Context) error { f(); return nil } case func() error: - return func(context.Context) error { - return f() - } + return func(context.Context) error { return f() } case func(context.Context): - return func(ctx context.Context) error { - f(ctx) - return nil - } + return func(ctx context.Context) error { f(ctx); return nil } case func(context.Context) error: return f + default: + return nil } - return nil } // FindFiles return a list of file matching the given glob patterns. From dc868a89033e058545a5ff718ff0bbb30614de8a Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 15:05:41 +0530 Subject: [PATCH 08/20] parallelize better --- dev-tools/mage/common.go | 7 +++++-- dev-tools/mage/crossbuild.go | 11 +++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/dev-tools/mage/common.go b/dev-tools/mage/common.go index 93a9a36917f..2b2fe9c79bc 100644 --- a/dev-tools/mage/common.go +++ b/dev-tools/mage/common.go @@ -546,8 +546,7 @@ func numParallel() int { return maxParallel } - // Calculate based on available CPUs - maxParallel := runtime.NumCPU() / 2 + maxParallel := runtime.NumCPU() // Adjust based on Docker-reported CPUs if available info, err := GetDockerInfo() @@ -557,6 +556,10 @@ func numParallel() int { maxParallel = int(math.Min(float64(maxParallel), float64(info.NCPU))) } + // Parallelize conservatively to avoid overloading the host. + if maxParallel >= 2 { + return maxParallel / 2 + } return maxParallel } diff --git a/dev-tools/mage/crossbuild.go b/dev-tools/mage/crossbuild.go index 6ac72f970aa..d3579432971 100644 --- a/dev-tools/mage/crossbuild.go +++ b/dev-tools/mage/crossbuild.go @@ -345,15 +345,19 @@ func (b GolangCrossBuilder) Build() error { // This is done by mounting the host directory to the container. // // Path of the cache directory on the host: - // /build/.go-build/ - // Example: /build/.go-build/linux/amd64 + // /build/.go-build/ + // Example: /tmp/build/.go-build/linux/amd64 + // Reason for using and not as base because for + // builds happening on CI, the paths looks similar to: + // /opt/buildkite-agent/builds/bk-agent-prod-gcp-1727515099712207954/elastic/beats-xpack-agentbeat/ + // where bk-agent-prod-gcp-1727515099712207954 is the agent so it keeps changing. So even if we do cache the + // build, it will be useless as the cache directory will be different for every build. // // As per: https://docs.docker.com/engine/storage/bind-mounts/#differences-between--v-and---mount-behavior // If the directory doesn't exist, Docker does not automatically create it for you, but generates an error. // So, we need to create the directory before mounting it. // // Also, in the container, the cache directory is mounted to /root/.cache/go-build. - // buildCacheHostDir := filepath.Join(repoInfo.RootDir, "build", ".go-build", b.Platform) buildCacheHostDir := filepath.Join(os.TempDir(), "build", ".go-build", b.Platform) buildCacheContainerDir := "/root/.cache/go-build" @@ -368,7 +372,6 @@ func (b GolangCrossBuilder) Build() error { "--env", "MAGEFILE_VERBOSE="+verbose, "--env", "MAGEFILE_TIMEOUT="+EnvOr("MAGEFILE_TIMEOUT", ""), "--env", "SNAPSHOT="+strconv.FormatBool(Snapshot), - "--env", "GOGC=off", // Disable GC during build. // To persist the build cache, we need to mount the cache directory to the Docker host. // With docker run, mount types are: bind, volume and tmpfs. For our use case, we have From 933b63a10c5965d1b132707cb5feee40581884fe Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 16:27:11 +0530 Subject: [PATCH 09/20] play with buildkite --- .buildkite/x-pack/pipeline.xpack.agentbeat.yml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml index 70aa4362b86..97d13b6f696 100644 --- a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml +++ b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml @@ -34,7 +34,7 @@ steps: - label: ":linux: Agentbeat packaging Linux" key: "agentbeat-package-linux" env: - PLATFORMS: "+all linux/amd64 linux/arm64 windows/amd64 darwin/amd64 darwin/arm64" + PLATFORMS: "linux/amd64" SNAPSHOT: true command: | set -euo pipefail @@ -64,22 +64,15 @@ steps: - agentbeat-package-linux env: ASDF_NODEJS_VERSION: 18.17.1 - PLATFORMS: "+all linux/amd64 linux/arm64 windows/amd64 darwin/amd64 darwin/arm64" + PLATFORMS: "linux/amd64" SNAPSHOT: true command: | set -euo pipefail - echo "~~~ Downloading artifacts" - buildkite-agent artifact download x-pack/agentbeat/build/distributions/** . --step 'agentbeat-package-linux' - ls -lah x-pack/agentbeat/build/distributions/ echo "~~~ Installing @elastic/synthetics with npm" npm install -g @elastic/synthetics echo "~~~ Running tests" cd x-pack/agentbeat mage goIntegTest - artifact_paths: - - x-pack/agentbeat/build/distributions/**/* - - "x-pack/agentbeat/build/*.xml" - - "x-pack/agentbeat/build/*.json" retry: automatic: - limit: 1 From b846a497896a2ee439289970194886b11bb5edcf Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 17:30:44 +0530 Subject: [PATCH 10/20] play with buildkite 1 --- .buildkite/pull-requests.json | 2 +- .../x-pack/pipeline.xpack.agentbeat.yml | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.buildkite/pull-requests.json b/.buildkite/pull-requests.json index 3ee4a17a135..8e9ff8c4b19 100644 --- a/.buildkite/pull-requests.json +++ b/.buildkite/pull-requests.json @@ -15,6 +15,6 @@ "skip_target_branches": [ ], "skip_ci_on_only_changed": [ ], "always_require_ci_on_changed": [ ] - } + } ] } diff --git a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml index 97d13b6f696..b8ee597f102 100644 --- a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml +++ b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml @@ -31,6 +31,19 @@ steps: key: "agentbeat-mandatory-tests" steps: + - label: "Warm Go cache" + key: "warm-go-cache" + command: | + go mod download + go build ./... + echo "GOMODCACHE=$(go env GOMODCACHE)" >> $BUILDKITE_ENV_FILE + echo "GOCACHE=$(go env GOCACHE)" >> $BUILDKITE_ENV_FILE + artifact_paths: + - "${GOMODCACHE}/**/*" + - "${GOCACHE}/**/*" + + - wait + - label: ":linux: Agentbeat packaging Linux" key: "agentbeat-package-linux" env: @@ -39,7 +52,7 @@ steps: command: | set -euo pipefail cd x-pack/agentbeat - mage package + # mage package artifact_paths: - x-pack/agentbeat/build/distributions/**/* - "x-pack/agentbeat/build/*.xml" @@ -60,14 +73,14 @@ steps: - label: ":linux: Agentbeat/Integration tests Linux" key: "agentbeat-it-linux" - depends_on: - - agentbeat-package-linux env: ASDF_NODEJS_VERSION: 18.17.1 PLATFORMS: "linux/amd64" SNAPSHOT: true command: | set -euo pipefail + buildkite-agent artifact download "${GOMODCACHE}/**/*" . + buildkite-agent artifact download "${GOCACHE}/**/*" . echo "~~~ Installing @elastic/synthetics with npm" npm install -g @elastic/synthetics echo "~~~ Running tests" From 6ebf51daabc2a74522da9a9f68c936f488d72bd7 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 18:43:32 +0530 Subject: [PATCH 11/20] play with buildkite 2 --- .../x-pack/pipeline.xpack.agentbeat.yml | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml index b8ee597f102..37015888a4f 100644 --- a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml +++ b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml @@ -31,19 +31,6 @@ steps: key: "agentbeat-mandatory-tests" steps: - - label: "Warm Go cache" - key: "warm-go-cache" - command: | - go mod download - go build ./... - echo "GOMODCACHE=$(go env GOMODCACHE)" >> $BUILDKITE_ENV_FILE - echo "GOCACHE=$(go env GOCACHE)" >> $BUILDKITE_ENV_FILE - artifact_paths: - - "${GOMODCACHE}/**/*" - - "${GOCACHE}/**/*" - - - wait - - label: ":linux: Agentbeat packaging Linux" key: "agentbeat-package-linux" env: @@ -52,11 +39,17 @@ steps: command: | set -euo pipefail cd x-pack/agentbeat - # mage package + echo "GOMODCACHE=$(go env GOMODCACHE)" >> $BUILDKITE_ENV_FILE + echo "GOCACHE=$(go env GOCACHE)" >> $BUILDKITE_ENV_FILE + ls -ltr $GOMODCACHE + echo $BUILDKITE_ENV_FILE + mage package artifact_paths: - x-pack/agentbeat/build/distributions/**/* - "x-pack/agentbeat/build/*.xml" - "x-pack/agentbeat/build/*.json" + - "${GOMODCACHE}/**/*" + - "${GOCACHE}/**/*" retry: automatic: - limit: 2 @@ -79,8 +72,6 @@ steps: SNAPSHOT: true command: | set -euo pipefail - buildkite-agent artifact download "${GOMODCACHE}/**/*" . - buildkite-agent artifact download "${GOCACHE}/**/*" . echo "~~~ Installing @elastic/synthetics with npm" npm install -g @elastic/synthetics echo "~~~ Running tests" From 0f2cf7cccb4bf10aa15bc06f08245e764b169eb9 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 18:57:52 +0530 Subject: [PATCH 12/20] play with buildkite 3 --- .buildkite/x-pack/pipeline.xpack.agentbeat.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml index 37015888a4f..cdebd948cd6 100644 --- a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml +++ b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml @@ -39,17 +39,18 @@ steps: command: | set -euo pipefail cd x-pack/agentbeat + go env GOMODCACHE + go env GOCACHE echo "GOMODCACHE=$(go env GOMODCACHE)" >> $BUILDKITE_ENV_FILE echo "GOCACHE=$(go env GOCACHE)" >> $BUILDKITE_ENV_FILE - ls -ltr $GOMODCACHE - echo $BUILDKITE_ENV_FILE - mage package + echo $GOMODCACHE + echo $GOCACHE + cat $BUILDKITE_ENV_FILE + # mage package artifact_paths: - x-pack/agentbeat/build/distributions/**/* - "x-pack/agentbeat/build/*.xml" - "x-pack/agentbeat/build/*.json" - - "${GOMODCACHE}/**/*" - - "${GOCACHE}/**/*" retry: automatic: - limit: 2 @@ -76,7 +77,7 @@ steps: npm install -g @elastic/synthetics echo "~~~ Running tests" cd x-pack/agentbeat - mage goIntegTest + # mage goIntegTest retry: automatic: - limit: 1 From 6c81c5c8d4e03426f5cbce51951ec36e99442a05 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 19:05:22 +0530 Subject: [PATCH 13/20] play with buildkite 4 --- .buildkite/x-pack/pipeline.xpack.agentbeat.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml index cdebd948cd6..c2f4917dedb 100644 --- a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml +++ b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml @@ -2,7 +2,6 @@ env: ASDF_MAGE_VERSION: 1.15.0 GCP_HI_PERF_MACHINE_TYPE: "c2d-highcpu-16" IMAGE_UBUNTU_X86_64: "family/platform-ingest-beats-ubuntu-2204" - IMAGE_BEATS_WITH_HOOKS_LATEST: "docker.elastic.co/ci-agent-images/platform-ingest/buildkite-agent-beats-ci-with-hooks:latest" steps: @@ -41,10 +40,6 @@ steps: cd x-pack/agentbeat go env GOMODCACHE go env GOCACHE - echo "GOMODCACHE=$(go env GOMODCACHE)" >> $BUILDKITE_ENV_FILE - echo "GOCACHE=$(go env GOCACHE)" >> $BUILDKITE_ENV_FILE - echo $GOMODCACHE - echo $GOCACHE cat $BUILDKITE_ENV_FILE # mage package artifact_paths: @@ -72,6 +67,10 @@ steps: PLATFORMS: "linux/amd64" SNAPSHOT: true command: | + go env GOMODCACHE + go env GOCACHE + ls -ltr $(go env GOMODCACHE) + ls -ltr $(go env GOCACHE) set -euo pipefail echo "~~~ Installing @elastic/synthetics with npm" npm install -g @elastic/synthetics From e2dbfae7ff79783a55d2da6068202e9187edbe51 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 19:14:09 +0530 Subject: [PATCH 14/20] play with buildkite 5 --- .buildkite/x-pack/pipeline.xpack.agentbeat.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml index c2f4917dedb..3ed3ab01900 100644 --- a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml +++ b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml @@ -40,7 +40,8 @@ steps: cd x-pack/agentbeat go env GOMODCACHE go env GOCACHE - cat $BUILDKITE_ENV_FILE + ls -ltr $(go env GOMODCACHE) + ls -ltr $(go env GOCACHE) # mage package artifact_paths: - x-pack/agentbeat/build/distributions/**/* From fc303d1818770a2c3ab48a760f8856b12abdbf84 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 19:58:25 +0530 Subject: [PATCH 15/20] play with buildkite 6 --- .buildkite/x-pack/pipeline.xpack.agentbeat.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml index 3ed3ab01900..2b58d5161c9 100644 --- a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml +++ b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml @@ -38,11 +38,15 @@ steps: command: | set -euo pipefail cd x-pack/agentbeat + + go mod tidy + go env GOMODCACHE go env GOCACHE - ls -ltr $(go env GOMODCACHE) + ls -Rltr $(go env GOMODCACHE) ls -ltr $(go env GOCACHE) # mage package + artifact_paths: - x-pack/agentbeat/build/distributions/**/* - "x-pack/agentbeat/build/*.xml" @@ -70,7 +74,7 @@ steps: command: | go env GOMODCACHE go env GOCACHE - ls -ltr $(go env GOMODCACHE) + ls -Rltr $(go env GOMODCACHE) ls -ltr $(go env GOCACHE) set -euo pipefail echo "~~~ Installing @elastic/synthetics with npm" From 6838049c873fcd861cabdfd31163597bc5ea8221 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 20:10:55 +0530 Subject: [PATCH 16/20] play with buildkite 6 --- .buildkite/x-pack/pipeline.xpack.agentbeat.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml index 2b58d5161c9..e7c6a1a60bc 100644 --- a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml +++ b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml @@ -74,6 +74,9 @@ steps: command: | go env GOMODCACHE go env GOCACHE + + go mod tidy + ls -Rltr $(go env GOMODCACHE) ls -ltr $(go env GOCACHE) set -euo pipefail From 468eeb67564b2648436b98f2a04b14577ade43f7 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 21:16:43 +0530 Subject: [PATCH 17/20] play with buildkite 7 --- .buildkite/x-pack/pipeline.xpack.agentbeat.yml | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml index e7c6a1a60bc..655fdb6ac08 100644 --- a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml +++ b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml @@ -38,19 +38,19 @@ steps: command: | set -euo pipefail cd x-pack/agentbeat - go mod tidy - go env GOMODCACHE - go env GOCACHE - ls -Rltr $(go env GOMODCACHE) - ls -ltr $(go env GOCACHE) + buildkite-agent env set GOMODCACHE=$(go env GOMODCACHE) GOCACHE=$(go env GOCACHE) + + echo $GOMODCACHE + echo $GOCACHE # mage package artifact_paths: - x-pack/agentbeat/build/distributions/**/* - "x-pack/agentbeat/build/*.xml" - "x-pack/agentbeat/build/*.json" + - "$GOMODCACHE/**/*" retry: automatic: - limit: 2 @@ -72,13 +72,6 @@ steps: PLATFORMS: "linux/amd64" SNAPSHOT: true command: | - go env GOMODCACHE - go env GOCACHE - - go mod tidy - - ls -Rltr $(go env GOMODCACHE) - ls -ltr $(go env GOCACHE) set -euo pipefail echo "~~~ Installing @elastic/synthetics with npm" npm install -g @elastic/synthetics From 5628ab6084cc02a61699ff6467704610fa38c9d9 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 21:25:48 +0530 Subject: [PATCH 18/20] play with buildkite 8 --- .buildkite/x-pack/pipeline.xpack.agentbeat.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml index 655fdb6ac08..13cc27e2bd5 100644 --- a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml +++ b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml @@ -40,7 +40,11 @@ steps: cd x-pack/agentbeat go mod tidy - buildkite-agent env set GOMODCACHE=$(go env GOMODCACHE) GOCACHE=$(go env GOCACHE) + echo export GOMODCACHE=$(go env GOMODCACHE) > shared_vars.sh + echo export GOCACHE=$(go env GOCACHE) >> shared_vars.sh + + cat shared_vars.sh + source shared_vars.sh echo $GOMODCACHE echo $GOCACHE From 97795e12ed6c459923271ea1fc8ec6eacc7dca48 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 21:41:54 +0530 Subject: [PATCH 19/20] play with buildkite 9 --- .../x-pack/pipeline.xpack.agentbeat.yml | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml index 13cc27e2bd5..fd756b76d47 100644 --- a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml +++ b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml @@ -1,5 +1,6 @@ env: ASDF_MAGE_VERSION: 1.15.0 + GO_VERSION: 1.22.7 GCP_HI_PERF_MACHINE_TYPE: "c2d-highcpu-16" IMAGE_UBUNTU_X86_64: "family/platform-ingest-beats-ubuntu-2204" IMAGE_BEATS_WITH_HOOKS_LATEST: "docker.elastic.co/ci-agent-images/platform-ingest/buildkite-agent-beats-ci-with-hooks:latest" @@ -39,22 +40,14 @@ steps: set -euo pipefail cd x-pack/agentbeat go mod tidy - - echo export GOMODCACHE=$(go env GOMODCACHE) > shared_vars.sh - echo export GOCACHE=$(go env GOCACHE) >> shared_vars.sh - - cat shared_vars.sh - source shared_vars.sh - - echo $GOMODCACHE - echo $GOCACHE # mage package artifact_paths: - x-pack/agentbeat/build/distributions/**/* - "x-pack/agentbeat/build/*.xml" - "x-pack/agentbeat/build/*.json" - - "$GOMODCACHE/**/*" + - /opt/buildkite-agent/.asdf/installs/golang/$GO_VERSION/packages/pkg/mod/**/* + - /opt/buildkite-agent/.cache/go-build/**/* retry: automatic: - limit: 2 @@ -71,12 +64,23 @@ steps: - label: ":linux: Agentbeat/Integration tests Linux" key: "agentbeat-it-linux" + depends_on: + - agentbeat-package-linux env: ASDF_NODEJS_VERSION: 18.17.1 PLATFORMS: "linux/amd64" SNAPSHOT: true command: | set -euo pipefail + echo "~~~ Downloading cache artifacts" + buildkite-agent artifact download /opt/buildkite-agent/.asdf/installs/golang/$GO_VERSION/packages/pkg/mod/* /opt/buildkite-agent/.asdf/installs/golang/$GO_VERSION/packages/pkg/mod/ --step 'agentbeat-package-linux' + buildkite-agent artifact download /opt/buildkite-agent/.cache/go-build/* /opt/buildkite-agent/.cache/go-build/ --step 'agentbeat-package-linux' + + ls -Rltr /opt/buildkite-agent/.asdf/installs/golang/$GO_VERSION/packages/pkg/mod/ + ls -Rltr /opt/buildkite-agent/.cache/go-build/ + + go mod tidy + echo "~~~ Installing @elastic/synthetics with npm" npm install -g @elastic/synthetics echo "~~~ Running tests" From e21f531abc530aae0d38f5f494d11e04eda4bb09 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Sat, 28 Sep 2024 21:59:33 +0530 Subject: [PATCH 20/20] play with buildkite 10 --- .../x-pack/pipeline.xpack.agentbeat.yml | 23 ++++--------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml index fd756b76d47..0c59d5bef72 100644 --- a/.buildkite/x-pack/pipeline.xpack.agentbeat.yml +++ b/.buildkite/x-pack/pipeline.xpack.agentbeat.yml @@ -1,6 +1,5 @@ env: ASDF_MAGE_VERSION: 1.15.0 - GO_VERSION: 1.22.7 GCP_HI_PERF_MACHINE_TYPE: "c2d-highcpu-16" IMAGE_UBUNTU_X86_64: "family/platform-ingest-beats-ubuntu-2204" IMAGE_BEATS_WITH_HOOKS_LATEST: "docker.elastic.co/ci-agent-images/platform-ingest/buildkite-agent-beats-ci-with-hooks:latest" @@ -34,20 +33,17 @@ steps: - label: ":linux: Agentbeat packaging Linux" key: "agentbeat-package-linux" env: - PLATFORMS: "linux/amd64" + PLATFORMS: "+all linux/amd64 linux/arm64 windows/amd64 darwin/amd64 darwin/arm64" SNAPSHOT: true command: | set -euo pipefail cd x-pack/agentbeat - go mod tidy - # mage package + mage package artifact_paths: - x-pack/agentbeat/build/distributions/**/* - "x-pack/agentbeat/build/*.xml" - "x-pack/agentbeat/build/*.json" - - /opt/buildkite-agent/.asdf/installs/golang/$GO_VERSION/packages/pkg/mod/**/* - - /opt/buildkite-agent/.cache/go-build/**/* retry: automatic: - limit: 2 @@ -64,28 +60,17 @@ steps: - label: ":linux: Agentbeat/Integration tests Linux" key: "agentbeat-it-linux" - depends_on: - - agentbeat-package-linux env: ASDF_NODEJS_VERSION: 18.17.1 - PLATFORMS: "linux/amd64" + PLATFORMS: "+all linux/amd64 linux/arm64 windows/amd64 darwin/amd64 darwin/arm64" SNAPSHOT: true command: | set -euo pipefail - echo "~~~ Downloading cache artifacts" - buildkite-agent artifact download /opt/buildkite-agent/.asdf/installs/golang/$GO_VERSION/packages/pkg/mod/* /opt/buildkite-agent/.asdf/installs/golang/$GO_VERSION/packages/pkg/mod/ --step 'agentbeat-package-linux' - buildkite-agent artifact download /opt/buildkite-agent/.cache/go-build/* /opt/buildkite-agent/.cache/go-build/ --step 'agentbeat-package-linux' - - ls -Rltr /opt/buildkite-agent/.asdf/installs/golang/$GO_VERSION/packages/pkg/mod/ - ls -Rltr /opt/buildkite-agent/.cache/go-build/ - - go mod tidy - echo "~~~ Installing @elastic/synthetics with npm" npm install -g @elastic/synthetics echo "~~~ Running tests" cd x-pack/agentbeat - # mage goIntegTest + mage goIntegTest retry: automatic: - limit: 1