diff --git a/builder/builder.go b/builder/builder.go index 2d70e57..53e809d 100644 --- a/builder/builder.go +++ b/builder/builder.go @@ -147,15 +147,6 @@ func rawDockerfile( } } -// baseImageForGoVersion will determine the go version in go.mod and return the base image -func baseImageForGoVersion(modFile *modfile.File) GoVersion { - goVersion := modFile.Go.Version - baseImageVersion := GetImageAndVersionForGoVersion(goVersion) - fmt.Printf("Go version from go.mod: %s, will build with version: %s image: %s\n", goVersion, baseImageVersion.Version, baseImageVersion.Image) - - return baseImageVersion -} - func getModFile( repoHost string, organization string, @@ -220,12 +211,11 @@ func getModFile( return goMod, nil } - // getWasmvmVersion will get the wasmvm version from the mod file func getWasmvmVersion(modFile *modfile.File) string { wasmvmRepo := "github.com/CosmWasm/wasmvm" wasmvmVersion := "" - + // First check all the "requires" for _, item := range modFile.Require { // Must have 2 tokens, repo & version @@ -241,13 +231,12 @@ func getWasmvmVersion(modFile *modfile.File) string { wasmvmVersion = item.Syntax.Token[len(item.Syntax.Token)-1] } } - + fmt.Println("WasmVM version from go.mod: ", wasmvmVersion) return wasmvmVersion } - // buildChainNodeDockerImage builds the requested chain node docker image // based on the input configuration. func (h *HeighlinerBuilder) buildChainNodeDockerImage( @@ -351,32 +340,30 @@ func (h *HeighlinerBuilder) buildChainNodeDockerImage( buildTimestamp = strconv.FormatInt(time.Now().Unix(), 10) } - var baseVersion string - var baseVer GoVersion + var gv GoVersion var wasmvmVersion string race := "" + modFile, err := getModFile( + repoHost, chainConfig.Build.GithubOrganization, chainConfig.Build.GithubRepo, + chainConfig.Ref, chainConfig.Build.BuildDir, h.local, + ) + + goVersion := buildCfg.GoVersion + if goVersion == "" && err == nil { + goVersion = modFile.Go.Version + } + if goVersion != "" { + gv = GetImageAndVersionForGoVersion(goVersion, buildCfg.AlpineVersion) + } + if dockerfile == DockerfileTypeCosmos || dockerfile == DockerfileTypeAvalanche { - modFile, err := getModFile( - repoHost, chainConfig.Build.GithubOrganization, chainConfig.Build.GithubRepo, - chainConfig.Ref, chainConfig.Build.BuildDir, h.local, - ) if err != nil { return fmt.Errorf("error getting mod file: %w", err) } - baseVer = baseImageForGoVersion(modFile) wasmvmVersion = getWasmvmVersion(modFile) - baseVersion = GoDefaultImage // default, and fallback if go.mod parse fails - - // In error case, fallback to default image - if err != nil { - fmt.Println(err) - } else { - baseVersion = baseVer.Image - } - if h.race { race = "true" buildEnv += " GOFLAGS=-race" @@ -384,18 +371,8 @@ func (h *HeighlinerBuilder) buildChainNodeDockerImage( imageTags[i] = imageTag + "-race" } } - } else { - // Try to get mod file for non-cosmos/non-avax dockerfile types. - // If no error, get go version, if error, continue on without go version. - // Agoric looks to be the only chain needing this. - modFile, err := getModFile( - repoHost, chainConfig.Build.GithubOrganization, chainConfig.Build.GithubRepo, - chainConfig.Ref, chainConfig.Build.BuildDir, h.local, - ) - if err == nil { - baseVer = baseImageForGoVersion(modFile) - } + fmt.Printf("Go version from go.mod: %s, will build with version: %s image: %s\n", modFile.Go.Version, gv.Version, gv.Image) } fmt.Printf("Building image from %s, resulting docker image tags: +%v\n", buildFrom, imageTags) @@ -407,7 +384,7 @@ func (h *HeighlinerBuilder) buildChainNodeDockerImage( buildArgs := map[string]string{ "VERSION": chainConfig.Ref, - "BASE_VERSION": baseVersion, + "BASE_VERSION": gv.Image, "NAME": chainConfig.Build.Name, "BASE_IMAGE": chainConfig.Build.BaseImage, "REPO_HOST": repoHost, @@ -424,7 +401,7 @@ func (h *HeighlinerBuilder) buildChainNodeDockerImage( "BUILD_TAGS": buildTagsEnvVar, "BUILD_DIR": chainConfig.Build.BuildDir, "BUILD_TIMESTAMP": buildTimestamp, - "GO_VERSION": baseVer.Version, + "GO_VERSION": gv.Version, "WASMVM_VERSION": wasmvmVersion, "RACE": race, } diff --git a/builder/go_versions.go b/builder/go_versions.go index 395ea6d..e059a00 100644 --- a/builder/go_versions.go +++ b/builder/go_versions.go @@ -2,35 +2,41 @@ package builder import ( "sort" + "strings" "golang.org/x/mod/semver" ) // To add a new go version, add to `ADD NEW GO VERSION` [1], [2], [3], and [4] - const ( Go118Version = "1.18.10" - Go119Version = "1.19.12" - Go120Version = "1.20.7" - Go121Version = "1.21.0" + Go119Version = "1.19.13" + Go120Version = "1.20.10" + Go121Version = "1.21.3" // ADD NEW GO VERSION [1] - latest patch release for each major/minor // When updating alpine image, ensure all golang build image combinations below exist - AlpineImageVersion = "3.17" + LatestAlpineImageVersion = "3.18" +) +var ( + // ADD NEW GO VERSION [2] // golang official dockerhub images to use for cosmos builds // Find from https://hub.docker.com/_/golang - Go118Image = Go118Version + "-alpine" + AlpineImageVersion - Go119Image = Go119Version + "-alpine" + AlpineImageVersion - Go120Image = Go120Version + "-alpine" + AlpineImageVersion - Go121Image = Go121Version + "-alpine" + AlpineImageVersion - // ADD NEW GO VERSION [2] + Go118Image = GolangAlpineImage(Go118Version, "3.17") // Go 1.18 is now deprecated, pinning to 3.17 + Go119Image = GolangAlpineImage(Go119Version, LatestAlpineImageVersion) + Go120Image = GolangAlpineImage(Go120Version, LatestAlpineImageVersion) + Go121Image = GolangAlpineImage(Go121Version, LatestAlpineImageVersion) // ADD NEW GO VERSION [3] - update GoDefaultVersion and GoDefaultImage to latest GoDefaultVersion = Go121Version GoDefaultImage = Go121Image // default image for cosmos go builds if go.mod parse fails ) +func GolangAlpineImage(goVersion, alpineVersion string) string { + return goVersion + "-alpine" + alpineVersion +} + type GoVersion struct { Version string Image string @@ -60,11 +66,21 @@ func goVersionsDesc() []string { } // GetImageForGoVersion will return the build docker image for the provided go version -func GetImageAndVersionForGoVersion(goVersion string) GoVersion { +func GetImageAndVersionForGoVersion(goVersion string, alpineVersion string) GoVersion { + // If alpine version is provided, use that image explicitly + if alpineVersion != "" { + return GoVersion{Version: goVersion, Image: GolangAlpineImage(goVersion, alpineVersion)} + } + // If alpine version is not provided, but go version is provided to the patch version, use the latest alpine version with that go version. + if len(strings.Split(goVersion, ".")) == 3 { + return GoVersion{Version: goVersion, Image: GolangAlpineImage(goVersion, LatestAlpineImageVersion)} + } + // If alpine version is not provided, and go version is not provided to the patch version, use the latest alpine version with the latest go patch version. for _, goVer := range goVersionsDesc() { if semver.Compare("v"+goVersion, "v"+goVer) >= 0 { return GoImageForVersion[goVer] } } + // If unable to find go version in mapping, return default return GoVersion{Version: GoDefaultVersion, Image: GoDefaultImage} } diff --git a/builder/go_versions_test.go b/builder/go_versions_test.go index effd56c..7e0238b 100644 --- a/builder/go_versions_test.go +++ b/builder/go_versions_test.go @@ -8,23 +8,31 @@ import ( ) func TestGoVersions(t *testing.T) { - goVer := builder.GetImageAndVersionForGoVersion("1.18") + goVer := builder.GetImageAndVersionForGoVersion("1.18", "") require.Equal(t, builder.Go118Image, goVer.Image) require.Equal(t, builder.Go118Version, goVer.Version) - goVer = builder.GetImageAndVersionForGoVersion("1.19") + goVer = builder.GetImageAndVersionForGoVersion("1.19", "") require.Equal(t, builder.Go119Image, goVer.Image) require.Equal(t, builder.Go119Version, goVer.Version) - goVer = builder.GetImageAndVersionForGoVersion("1.20") + goVer = builder.GetImageAndVersionForGoVersion("1.20", "") require.Equal(t, builder.Go120Image, goVer.Image) require.Equal(t, builder.Go120Version, goVer.Version) - goVer = builder.GetImageAndVersionForGoVersion("1.21") + goVer = builder.GetImageAndVersionForGoVersion("1.21", "") require.Equal(t, builder.Go121Image, goVer.Image) require.Equal(t, builder.Go121Version, goVer.Version) - goVer = builder.GetImageAndVersionForGoVersion("unknown") + goVer = builder.GetImageAndVersionForGoVersion("unknown", "") require.Equal(t, builder.GoDefaultImage, goVer.Image) require.Equal(t, builder.GoDefaultVersion, goVer.Version) + + goVer = builder.GetImageAndVersionForGoVersion("1.19.7", "3.17") + require.Equal(t, "1.19.7-alpine3.17", goVer.Image) + require.Equal(t, "1.19.7", goVer.Version) + + goVer = builder.GetImageAndVersionForGoVersion("1.19.10", "") + require.Equal(t, "1.19.10-alpine"+builder.LatestAlpineImageVersion, goVer.Image) + require.Equal(t, "1.19.10", goVer.Version) } diff --git a/builder/types.go b/builder/types.go index 7f6fdb1..fc3aed5 100644 --- a/builder/types.go +++ b/builder/types.go @@ -55,6 +55,8 @@ type HeighlinerDockerBuildConfig struct { Platform string NoCache bool NoBuildCache bool + GoVersion string + AlpineVersion string } type HeighlinerQueuedChainBuilds struct { diff --git a/cmd/build.go b/cmd/build.go index 7c8c3f9..247f5b1 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -35,34 +35,36 @@ type chainConfigFlags struct { } const ( - flagFile = "file" - flagRegistry = "registry" - flagChain = "chain" - flagOrg = "org" - flagRepo = "repo" - flagRepoHost = "repo-host" - flagGitRef = "git-ref" - flagDockerfile = "dockerfile" - flagBuildDir = "build-dir" - flagPreBuild = "pre-build" - flagBuildTarget = "build-target" - flagBuildEnv = "build-env" - flagBinaries = "binaries" - flagLibraries = "libraries" - flagTag = "tag" - flagVersion = "version" // DEPRECATED - flagNumber = "number" - flagParallel = "parallel" - flagSkip = "skip" - flagTarExport = "tar-export-path" - flagLatest = "latest" - flagLocal = "local" - flagUseBuildkit = "use-buildkit" - flagBuildkitAddr = "buildkit-addr" - flagPlatform = "platform" - flagNoCache = "no-cache" - flagNoBuildCache = "no-build-cache" - flagRace = "race" + flagFile = "file" + flagRegistry = "registry" + flagChain = "chain" + flagOrg = "org" + flagRepo = "repo" + flagRepoHost = "repo-host" + flagGitRef = "git-ref" + flagDockerfile = "dockerfile" + flagBuildDir = "build-dir" + flagPreBuild = "pre-build" + flagBuildTarget = "build-target" + flagBuildEnv = "build-env" + flagBinaries = "binaries" + flagLibraries = "libraries" + flagTag = "tag" + flagVersion = "version" // DEPRECATED + flagNumber = "number" + flagParallel = "parallel" + flagSkip = "skip" + flagTarExport = "tar-export-path" + flagLatest = "latest" + flagLocal = "local" + flagUseBuildkit = "use-buildkit" + flagBuildkitAddr = "buildkit-addr" + flagPlatform = "platform" + flagNoCache = "no-cache" + flagNoBuildCache = "no-build-cache" + flagRace = "race" + flagGoVersion = "go-version" + flagAlpineVersion = "alpine-version" ) func loadChainsYaml(configFile string) error { @@ -165,6 +167,8 @@ An optional flag --tag/-t is now available to override the resulting docker imag buildCmd.PersistentFlags().StringVarP(&buildConfig.Platform, flagPlatform, "p", docker.DefaultPlatforms, "Platforms to build (only applies to buildkit builds with -b)") buildCmd.PersistentFlags().BoolVar(&buildConfig.NoCache, flagNoCache, false, "Don't use docker cache for building") buildCmd.PersistentFlags().BoolVar(&buildConfig.NoBuildCache, flagNoBuildCache, false, "Invalidate caches for clone and build.") + buildCmd.PersistentFlags().StringVar(&buildConfig.GoVersion, flagGoVersion, "", "Go version override to use for building (go builds only)") + buildCmd.PersistentFlags().StringVar(&buildConfig.AlpineVersion, flagAlpineVersion, "", "Alpine version override to use for building (go builds only)") // DEPRECATED buildCmd.PersistentFlags().StringP(flagVersion, "v", "", "DEPRECATED, use --git-ref/-g instead")