From a59443c852295f6356bb0fac6e18dc9abee197e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 24 Oct 2025 14:24:53 +0200 Subject: [PATCH 1/4] Allow to override the Golang version from the config files --- config/backstage-plugins.yaml | 1 + config/client.yaml | 1 + config/eventing-istio.yaml | 1 + config/eventing-kafka-broker.yaml | 1 + config/eventing.yaml | 1 + config/kn-plugin-event.yaml | 1 + config/kn-plugin-func.yaml | 1 + config/serverless-operator.yaml | 1 + config/serving-net-istio.yaml | 1 + config/serving-net-kourier.yaml | 1 + config/serving.yaml | 1 + pkg/dockerfilegen/generator.go | 41 ++++++++++++++++++++++++++----- pkg/dockerfilegen/params.go | 9 +++++++ pkg/prowgen/prowgen_config.go | 1 + 14 files changed, 56 insertions(+), 6 deletions(-) diff --git a/config/backstage-plugins.yaml b/config/backstage-plugins.yaml index 98ea01090..cb5d4fe55 100644 --- a/config/backstage-plugins.yaml +++ b/config/backstage-plugins.yaml @@ -1,6 +1,7 @@ config: branches: release-v1.15: + golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/client.yaml b/config/client.yaml index ca53dedca..c6b5e2621 100644 --- a/config/client.yaml +++ b/config/client.yaml @@ -1,6 +1,7 @@ config: branches: release-v1.15: + golangVersion: "1.24" konflux: enabled: true imageOverrides: diff --git a/config/eventing-istio.yaml b/config/eventing-istio.yaml index 89b288d1c..41b163175 100644 --- a/config/eventing-istio.yaml +++ b/config/eventing-istio.yaml @@ -8,6 +8,7 @@ config: version: "4.14" promotion: {} release-v1.15: + golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/eventing-kafka-broker.yaml b/config/eventing-kafka-broker.yaml index dc2882bf0..cda7530d2 100644 --- a/config/eventing-kafka-broker.yaml +++ b/config/eventing-kafka-broker.yaml @@ -14,6 +14,7 @@ config: skipDockerFilesMatches: - .*hermetic.* release-v1.15: + golangVersion: "1.24" konflux: enabled: true javaImages: diff --git a/config/eventing.yaml b/config/eventing.yaml index b6a5c966f..17278fdea 100644 --- a/config/eventing.yaml +++ b/config/eventing.yaml @@ -12,6 +12,7 @@ config: version: "4.14" promotion: {} release-v1.15: + golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/kn-plugin-event.yaml b/config/kn-plugin-event.yaml index 61e1c17fc..f73190d9c 100644 --- a/config/kn-plugin-event.yaml +++ b/config/kn-plugin-event.yaml @@ -1,6 +1,7 @@ config: branches: release-1.15: + golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/kn-plugin-func.yaml b/config/kn-plugin-func.yaml index 01c1d32fd..3924bda1e 100644 --- a/config/kn-plugin-func.yaml +++ b/config/kn-plugin-func.yaml @@ -7,6 +7,7 @@ config: version: "4.19" promotion: {} release-v1.15: + golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/serverless-operator.yaml b/config/serverless-operator.yaml index b4b286d05..8b4578701 100644 --- a/config/serverless-operator.yaml +++ b/config/serverless-operator.yaml @@ -38,6 +38,7 @@ config: version: "4.14" promotion: {} release-1.35: + golangVersion: "1.24" konflux: enabled: true excludes: diff --git a/config/serving-net-istio.yaml b/config/serving-net-istio.yaml index b585ddd0a..bfe2436da 100644 --- a/config/serving-net-istio.yaml +++ b/config/serving-net-istio.yaml @@ -1,6 +1,7 @@ config: branches: release-v1.15: + golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/serving-net-kourier.yaml b/config/serving-net-kourier.yaml index 39075f682..ac92fa8fb 100644 --- a/config/serving-net-kourier.yaml +++ b/config/serving-net-kourier.yaml @@ -1,6 +1,7 @@ config: branches: release-v1.15: + golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/serving.yaml b/config/serving.yaml index 844bde05c..11c62a0c6 100644 --- a/config/serving.yaml +++ b/config/serving.yaml @@ -13,6 +13,7 @@ config: - perf-tests$ - .*e2e-tls$ release-v1.15: + golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/pkg/dockerfilegen/generator.go b/pkg/dockerfilegen/generator.go index 97b790896..f8e6a55a5 100644 --- a/pkg/dockerfilegen/generator.go +++ b/pkg/dockerfilegen/generator.go @@ -17,6 +17,7 @@ import ( "strings" "text/template" + "github.com/openshift-knative/hack/config" "github.com/openshift-knative/hack/pkg/soversion" "github.com/coreos/go-semver/semver" @@ -150,12 +151,6 @@ func generateDockerfile(params Params, mainPackagesPaths sets.Set[string]) error if err != nil { return err } - goVersion := goMod.Go.Version - - // The builder images are distinguished by golang major.minor, so we ignore the rest of the goVersion - if strings.Count(goVersion, ".") > 1 { - goVersion = strings.Join(strings.Split(goVersion, ".")[0:2], ".") - } metadata, err := project.ReadMetadataFile(params.ProjectFilePath) if err != nil { @@ -167,6 +162,11 @@ func generateDockerfile(params Params, mainPackagesPaths sets.Set[string]) error metadata = project.DefaultMetadata() } + var goVersion string + if goVersion, err = resolveGolangVersion(params, goMod, metadata); err != nil { + return err + } + rhelVersion := RHEL9 templateFilePattern := "dockerfile-templates/rhel-9/*.tmpl" var soVersion string @@ -400,6 +400,35 @@ func generateDockerfile(params Params, mainPackagesPaths sets.Set[string]) error return nil } +func resolveGolangVersion(params Params, goMod *modfile.File, metadata *project.Metadata) (string, error) { + goVersion := goMod.Go.Version + + // The builder images are distinguished by golang major.minor, so we ignore the rest of the goVersion + if strings.Count(goVersion, ".") > 1 { + goVersion = strings.Join(strings.Split(goVersion, ".")[0:2], ".") + } + + log.Println("Golang version (from go.mod): ", goVersion) + + cfgYaml, err := config.Configs.ReadFile(fmt.Sprint(params.GetRepoName(goMod), ".yaml")) + if err != nil { + return "", err + } + prowcfg, perr := prowgen.UnmarshalConfig(cfgYaml) + if perr != nil { + return "", perr + } + + release := metadata.Project.Tag + branch := prowcfg.Config.Branches[release] + if branch.GolangVersion != "" { + goVersion = branch.GolangVersion + log.Println("Golang version (overridden for ", release, "): ", goVersion) + } + + return goVersion, nil +} + func hasVendorFolder(dir string) (bool, error) { info, err := os.Stat(path.Join(dir, "vendor")) if err == nil { diff --git a/pkg/dockerfilegen/params.go b/pkg/dockerfilegen/params.go index 5a3e1119c..d214dad0e 100644 --- a/pkg/dockerfilegen/params.go +++ b/pkg/dockerfilegen/params.go @@ -7,6 +7,7 @@ import ( "github.com/octago/sflags" "github.com/octago/sflags/gen/gpflag" "github.com/spf13/pflag" + "golang.org/x/mod/modfile" ) type Params struct { @@ -20,6 +21,7 @@ type Params struct { DockerfilesBuildDir string `json:"dockerfiles-build-dir" desc:"Dockerfiles output directory for build image relative to output flag"` DockerfilesSourceDir string `json:"dockerfiles-source-dir" desc:"Dockerfiles output directory for source image relative to output flag"` ProjectFilePath string `json:"project-file" desc:"Project metadata file path"` + RepoName string `json:"repo-name" desc:"Repository name (implied from go.mod by default)"` DockerfileImageBuilderFmt string `json:"dockerfile-image-builder-fmt" desc:"Dockerfile image builder format"` AppFileFmt string `json:"app-file-fmt" desc:"Target application binary path format"` RegistryImageFmt string `json:"registry-image-fmt" desc:"Container registry image format"` @@ -40,6 +42,13 @@ func (p *Params) ConfigureFlags() (*pflag.FlagSet, error) { return fs, nil } +func (p *Params) GetRepoName(goMod *modfile.File) string { + if p.RepoName != "" { + return p.RepoName + } + return path.Base(goMod.Module.Mod.Path) +} + func DefaultParams(wd string) Params { return Params{ RootDir: wd, diff --git a/pkg/prowgen/prowgen_config.go b/pkg/prowgen/prowgen_config.go index 5350c89ea..612410b58 100644 --- a/pkg/prowgen/prowgen_config.go +++ b/pkg/prowgen/prowgen_config.go @@ -91,6 +91,7 @@ type Branch struct { SkipE2EMatches []string `json:"skipE2EMatches,omitempty" yaml:"skipE2EMatches,omitempty"` SkipDockerFilesMatches []string `json:"skipDockerFilesMatches,omitempty" yaml:"skipDockerFilesMatches,omitempty"` Konflux *Konflux `json:"konflux,omitempty" yaml:"konflux,omitempty"` + GolangVersion string `json:"golangVersion,omitempty" yaml:"golangVersion,omitempty"` // DependabotEnabled enabled if `nil`. DependabotEnabled *bool `json:"dependabotEnabled,omitempty" yaml:"dependabotEnabled,omitempty"` From 1258681174a8bd62171f86558bafd1af71ba7f51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 24 Oct 2025 15:32:00 +0200 Subject: [PATCH 2/4] Replace Knative tag to match the release --- .gitignore | 1 + pkg/dockerfilegen/generator.go | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index f168ab3a7..459447af1 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ /openshift /openshift-knative /konflux-gen/out +_output/ # TODO: Remove rpms.lock.yaml diff --git a/pkg/dockerfilegen/generator.go b/pkg/dockerfilegen/generator.go index f8e6a55a5..44736a51b 100644 --- a/pkg/dockerfilegen/generator.go +++ b/pkg/dockerfilegen/generator.go @@ -408,7 +408,7 @@ func resolveGolangVersion(params Params, goMod *modfile.File, metadata *project. goVersion = strings.Join(strings.Split(goVersion, ".")[0:2], ".") } - log.Println("Golang version (from go.mod): ", goVersion) + log.Println("Golang version (from go.mod):", goVersion) cfgYaml, err := config.Configs.ReadFile(fmt.Sprint(params.GetRepoName(goMod), ".yaml")) if err != nil { @@ -420,10 +420,11 @@ func resolveGolangVersion(params Params, goMod *modfile.File, metadata *project. } release := metadata.Project.Tag + release = strings.Replace(release, "knative-", "release-", 1) branch := prowcfg.Config.Branches[release] if branch.GolangVersion != "" { goVersion = branch.GolangVersion - log.Println("Golang version (overridden for ", release, "): ", goVersion) + log.Println("Golang version (overridden for", release, "):", goVersion) } return goVersion, nil From d80d5c691eba673344b635f0c09438b95a7012ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 24 Oct 2025 16:01:42 +0200 Subject: [PATCH 3/4] Fall back to go.mod version if repo config is missing Previously, the `resolveGolangVersion` function would error out if it could not find a repository-specific `.yaml` configuration file. This made the config file a mandatory requirement for generating a Dockerfile for a Go project. --- pkg/dockerfilegen/generator.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/dockerfilegen/generator.go b/pkg/dockerfilegen/generator.go index 44736a51b..8e5784e4b 100644 --- a/pkg/dockerfilegen/generator.go +++ b/pkg/dockerfilegen/generator.go @@ -410,9 +410,11 @@ func resolveGolangVersion(params Params, goMod *modfile.File, metadata *project. log.Println("Golang version (from go.mod):", goVersion) - cfgYaml, err := config.Configs.ReadFile(fmt.Sprint(params.GetRepoName(goMod), ".yaml")) + reponame := params.GetRepoName(goMod) + cfgYaml, err := config.Configs.ReadFile(fmt.Sprint(reponame, ".yaml")) if err != nil { - return "", err + log.Println("Can't find config file:", err) + return goVersion, nil } prowcfg, perr := prowgen.UnmarshalConfig(cfgYaml) if perr != nil { From 8d05fb391166cdffdac87e1cbe0b19d105d92b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Tue, 4 Nov 2025 14:06:30 +0100 Subject: [PATCH 4/4] Centralize Go version resolution Remove the duplicated `golangVersion` key from all component configuration files for the `release-v1.15` branch. The Go version resolution logic in the dockerfile generator has been refactored to be more intelligent and reduce configuration duplication. Previously, the Go version for a specific release had to be defined in every single component's config file. The new logic introduces a fallback mechanism: 1. It first checks for a `golangVersion` in the component's specific configuration for the given branch (preserving override capability). 2. If not found, it calculates the corresponding Serverless Operator release branch from the upstream Knative release (e.g., `release-v1.15` -> `release-1.36`). 3. It then looks for the `golangVersion` in the `serverless-operator.yaml` configuration for that calculated branch. This allows us to define the Go version for an entire release train in a single location (`serverless-operator.yaml`), simplifying future updates. As part of this change, the `soversion` package was also improved to return errors from version parsing instead of panicking, increasing the robustness of the tooling. --- config/backstage-plugins.yaml | 1 - config/client.yaml | 1 - config/eventing-istio.yaml | 1 - config/eventing-kafka-broker.yaml | 1 - config/eventing.yaml | 1 - config/kn-plugin-event.yaml | 1 - config/kn-plugin-func.yaml | 1 - config/serving-net-istio.yaml | 1 - config/serving-net-kourier.yaml | 1 - config/serving.yaml | 1 - pkg/dockerfilegen/generator.go | 66 ++++++++++++++++++++++++++----- pkg/soversion/version.go | 16 +++++++- 12 files changed, 70 insertions(+), 22 deletions(-) diff --git a/config/backstage-plugins.yaml b/config/backstage-plugins.yaml index cb5d4fe55..98ea01090 100644 --- a/config/backstage-plugins.yaml +++ b/config/backstage-plugins.yaml @@ -1,7 +1,6 @@ config: branches: release-v1.15: - golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/client.yaml b/config/client.yaml index c6b5e2621..ca53dedca 100644 --- a/config/client.yaml +++ b/config/client.yaml @@ -1,7 +1,6 @@ config: branches: release-v1.15: - golangVersion: "1.24" konflux: enabled: true imageOverrides: diff --git a/config/eventing-istio.yaml b/config/eventing-istio.yaml index 41b163175..89b288d1c 100644 --- a/config/eventing-istio.yaml +++ b/config/eventing-istio.yaml @@ -8,7 +8,6 @@ config: version: "4.14" promotion: {} release-v1.15: - golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/eventing-kafka-broker.yaml b/config/eventing-kafka-broker.yaml index cda7530d2..dc2882bf0 100644 --- a/config/eventing-kafka-broker.yaml +++ b/config/eventing-kafka-broker.yaml @@ -14,7 +14,6 @@ config: skipDockerFilesMatches: - .*hermetic.* release-v1.15: - golangVersion: "1.24" konflux: enabled: true javaImages: diff --git a/config/eventing.yaml b/config/eventing.yaml index 17278fdea..b6a5c966f 100644 --- a/config/eventing.yaml +++ b/config/eventing.yaml @@ -12,7 +12,6 @@ config: version: "4.14" promotion: {} release-v1.15: - golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/kn-plugin-event.yaml b/config/kn-plugin-event.yaml index f73190d9c..61e1c17fc 100644 --- a/config/kn-plugin-event.yaml +++ b/config/kn-plugin-event.yaml @@ -1,7 +1,6 @@ config: branches: release-1.15: - golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/kn-plugin-func.yaml b/config/kn-plugin-func.yaml index 3924bda1e..01c1d32fd 100644 --- a/config/kn-plugin-func.yaml +++ b/config/kn-plugin-func.yaml @@ -7,7 +7,6 @@ config: version: "4.19" promotion: {} release-v1.15: - golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/serving-net-istio.yaml b/config/serving-net-istio.yaml index bfe2436da..b585ddd0a 100644 --- a/config/serving-net-istio.yaml +++ b/config/serving-net-istio.yaml @@ -1,7 +1,6 @@ config: branches: release-v1.15: - golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/serving-net-kourier.yaml b/config/serving-net-kourier.yaml index ac92fa8fb..39075f682 100644 --- a/config/serving-net-kourier.yaml +++ b/config/serving-net-kourier.yaml @@ -1,7 +1,6 @@ config: branches: release-v1.15: - golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/config/serving.yaml b/config/serving.yaml index 11c62a0c6..844bde05c 100644 --- a/config/serving.yaml +++ b/config/serving.yaml @@ -13,7 +13,6 @@ config: - perf-tests$ - .*e2e-tls$ release-v1.15: - golangVersion: "1.24" konflux: enabled: true openShiftVersions: diff --git a/pkg/dockerfilegen/generator.go b/pkg/dockerfilegen/generator.go index 8e5784e4b..bfc5d36a1 100644 --- a/pkg/dockerfilegen/generator.go +++ b/pkg/dockerfilegen/generator.go @@ -410,26 +410,72 @@ func resolveGolangVersion(params Params, goMod *modfile.File, metadata *project. log.Println("Golang version (from go.mod):", goVersion) + branch := strings.Replace(metadata.Project.Tag, "knative-", "release-", 1) + nvBranch := strings.Replace(branch, "release-v", "release-", 1) + soVer, err := soversion.SoFromUpstreamVersion(nvBranch) reponame := params.GetRepoName(goMod) + + resolver := golangResolver{ + defaultVersion: goVersion, + params: []golangResolverParams{ + {reponame, branch}, + {reponame, nvBranch}, + }, + } + + if err == nil { + soRelease := soversion.BranchName(soVer) + resolver.params = append(resolver.params, golangResolverParams{ + "serverless-operator", soRelease, + }) + } + + return resolver.perform() +} + +type golangResolverParams struct { + reponame, branch string +} + +type golangResolver struct { + defaultVersion string + params []golangResolverParams +} + +func (r golangResolver) perform() (string, error) { + goVersion := r.defaultVersion + for _, check := range r.params { + configGoVersion, err := resolveGolangVersionForRepo(check.reponame, check.branch) + if err != nil && !errors.Is(err, ErrCantFindConfig) { + return "", err + } + if configGoVersion != "" { + goVersion = configGoVersion + log.Println("Golang version (overridden for", check.reponame, "@", check.branch, "):", goVersion) + break + } + } + return goVersion, nil +} + +var ErrCantFindConfig = errors.New("can't find config file") + +func resolveGolangVersionForRepo(reponame string, branchName string) (string, error) { cfgYaml, err := config.Configs.ReadFile(fmt.Sprint(reponame, ".yaml")) if err != nil { - log.Println("Can't find config file:", err) - return goVersion, nil + return "", fmt.Errorf("%w: %w", ErrCantFindConfig, err) } prowcfg, perr := prowgen.UnmarshalConfig(cfgYaml) if perr != nil { - return "", perr + return "", errors.WithStack(perr) } - release := metadata.Project.Tag - release = strings.Replace(release, "knative-", "release-", 1) - branch := prowcfg.Config.Branches[release] + branch := prowcfg.Config.Branches[branchName] if branch.GolangVersion != "" { - goVersion = branch.GolangVersion - log.Println("Golang version (overridden for", release, "):", goVersion) + goVersion := branch.GolangVersion + return goVersion, nil } - - return goVersion, nil + return "", nil } func hasVendorFolder(dir string) (bool, error) { diff --git a/pkg/soversion/version.go b/pkg/soversion/version.go index 094b18882..5260e8064 100644 --- a/pkg/soversion/version.go +++ b/pkg/soversion/version.go @@ -5,9 +5,18 @@ import ( "strings" "github.com/coreos/go-semver/semver" + "github.com/pkg/errors" ) func FromUpstreamVersion(upstream string) *semver.Version { + ver, err := SoFromUpstreamVersion(upstream) + if err != nil { + panic(fmt.Sprintf("%+v", err)) + } + return ver +} + +func SoFromUpstreamVersion(upstream string) (*semver.Version, error) { upstream = strings.Replace(upstream, "release-v", "", 1) upstream = strings.Replace(upstream, "release-", "", 1) upstream = strings.Replace(upstream, "v", "", 1) @@ -16,7 +25,10 @@ func FromUpstreamVersion(upstream string) *semver.Version { if len(dotParts) == 2 { upstream = upstream + ".0" } - soVersion := semver.New(upstream) + soVersion, err := semver.NewVersion(upstream) + if err != nil { + return nil, errors.WithStack(err) + } for i := 0; i < 21; i++ { // Example 1.11 -> 1.32 soVersion.BumpMinor() } @@ -29,7 +41,7 @@ func FromUpstreamVersion(upstream string) *semver.Version { soVersion.Minor -= 1 } - return soVersion + return soVersion, nil } func ToUpstreamVersion(soversion string) *semver.Version {