Skip to content

Commit

Permalink
Add go and alpine version overrides (#181)
Browse files Browse the repository at this point in the history
  • Loading branch information
agouin committed Oct 12, 2023
1 parent 5aed3f4 commit 3f3f185
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 86 deletions.
61 changes: 19 additions & 42 deletions builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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(
Expand Down Expand Up @@ -351,51 +340,39 @@ 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"
for i, imageTag := range imageTags {
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)
Expand All @@ -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,
Expand All @@ -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,
}
Expand Down
38 changes: 27 additions & 11 deletions builder/go_versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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}
}
18 changes: 13 additions & 5 deletions builder/go_versions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
2 changes: 2 additions & 0 deletions builder/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ type HeighlinerDockerBuildConfig struct {
Platform string
NoCache bool
NoBuildCache bool
GoVersion string
AlpineVersion string
}

type HeighlinerQueuedChainBuilds struct {
Expand Down
60 changes: 32 additions & 28 deletions cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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")
Expand Down

0 comments on commit 3f3f185

Please sign in to comment.