From 9cc3fc58e9b8d5c04bc8a5485b1f175b5667b3a2 Mon Sep 17 00:00:00 2001 From: Robin Hahling Date: Wed, 29 Oct 2025 10:27:42 +0100 Subject: [PATCH 1/5] treewide: enable new linters Update golangci-lint to v2.5.0 and enable new linters. While here, disable linters that are not useful here (SQL related). Temporarily disable the sloglint linter and address reported findings in the next commit. Signed-off-by: Robin Hahling --- .github/workflows/build.yaml | 2 +- .golangci.yml | 75 ++++++++++++++++++++++++- cmd/certgen.go | 7 ++- internal/generate/generate.go | 40 +++++++------ internal/logging/logfields/logfields.go | 2 +- internal/logging/logging.go | 16 +++--- internal/option/config.go | 6 +- 7 files changed, 113 insertions(+), 35 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5abaa162..bde3c6aa 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -27,7 +27,7 @@ jobs: - name: Run static checks uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 with: - version: v2.1.6 + version: v2.5.0 # use our .golangci.yml args: --config=.golangci.yml --verbose skip-cache: true diff --git a/.golangci.yml b/.golangci.yml index 3153e02c..a989a1a5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -9,45 +9,62 @@ linters: - asciicheck - bidichk - bodyclose + - containedctx - contextcheck - copyloopvar - decorder + - dogsled + - dupl - dupword - durationcheck - err113 - errchkjson - errname + - errorlint + - exhaustive - exptostd + - forbidigo + - forcetypeassert - gocheckcompilerdirectives + - goconst - gocritic + - godoclint + - godot - goheader + - gomodguard - goprintffuncname - gosec - govet + - grouper - importas - ineffassign - interfacebloat - intrange + - iotamixing + - ireturn - makezero - mirror - misspell - musttag - nakedret + - nestif - nilerr + - nilnil - noctx - nosprintfhostport - perfsprint + - prealloc - predeclared - promlinter - protogetter - reassign - revive - - rowserrcheck - - sloglint - - sqlclosecheck + #- sloglint - staticcheck - tagalign - testifylint + - thelper + - tparallel - unconvert - unparam - unused @@ -59,9 +76,42 @@ linters: disabled-checks: - exitAfterDefer - singleCaseSwitch + godoclint: + default: all + disable: + - require-pkg-doc + options: + require-doc: + # Ignore unexported (private) symbols when applying the `require-doc` rule. + ignore-unexported: true goheader: template-path: ./HEADER + gomodguard: + blocked: + modules: + - github.com/goccy/go-yaml: + recommendations: + - go.yaml.in/yaml/v3 + reason: "Let's consolidate on a single YAML library that is also used by most of our dependencies" + - gopkg.in/yaml.v2: + recommendations: + - go.yaml.in/yaml/v3 + reason: "gopkg.in/yaml.v2 is unmaintained" + - gopkg.in/yaml.v3: + recommendations: + - go.yaml.in/yaml/v3 + reason: "gopkg.in/yaml.v3 is unmaintained" + - go.uber.org/multierr: + recommendations: + - errors + reason: "Go 1.20+ has support for combining multiple errors, see https://go.dev/doc/go1.20#errors" + - go.yaml.in/yaml/v2: + recommendations: + - go.yaml.in/yaml/v3 + reason: "We are using v3" gosec: + # available rules: https://github.com/securego/gosec#available-rules + includes: [] # include all available rules excludes: - G104 # Audit errors not checked - G307 # Deferring a method which returns an error @@ -88,7 +138,15 @@ linters: - name: package-comments disabled: true sloglint: + no-mixed-args: true + no-global: all static-msg: true + key-naming-case: kebab # be consistent with key names + forbidden-keys: # let's no use reserved log keys + - level + - msg + - source + - time exclusions: rules: - linters: @@ -100,3 +158,14 @@ formatters: enable: - gofmt - goimports + settings: + goimports: + local-prefixes: + - github.com/cilium/certgen/ +issues: + # Maximum issues count per one linter. + # Set to 0 to disable (default is 50) + max-issues-per-linter: 0 + # Maximum count of issues with the same text. + # Set to 0 to disable (default is 3) + max-same-issues: 0 diff --git a/cmd/certgen.go b/cmd/certgen.go index db03f965..8d4d43c1 100644 --- a/cmd/certgen.go +++ b/cmd/certgen.go @@ -135,7 +135,7 @@ func parseCertificateConfigs(cfg, cfgfile string) (certConfigs option.Certificat return certConfigs, nil } -// generateCertificates runs the main code to generate and store certificate +// generateCertificates runs the main code to generate and store certificate. func generateCertificates() error { k8sClient, err := k8sConfig(option.Config.K8sKubeConfigPath) if err != nil { @@ -152,7 +152,8 @@ func generateCertificates() error { ca := generate.NewCA(option.Config.CASecretName, option.Config.CASecretNamespace) - if option.Config.CAGenerate { + switch { + case option.Config.CAGenerate: err = ca.Generate(option.Config.CACommonName, option.Config.CAValidityDuration) if err != nil { return fmt.Errorf("failed to generate CA: %w", err) @@ -170,7 +171,7 @@ func generateCertificates() error { } else { count++ } - } else if option.Config.CACertFile != "" && option.Config.CAKeyFile != "" { + case option.Config.CACertFile != "" && option.Config.CAKeyFile != "": log.Info("Loading CA from file") err = ca.LoadFromFile(option.Config.CACertFile, option.Config.CAKeyFile) if err != nil { diff --git a/internal/generate/generate.go b/internal/generate/generate.go index e702f25d..1fb3c193 100644 --- a/internal/generate/generate.go +++ b/internal/generate/generate.go @@ -47,7 +47,7 @@ type Cert struct { KeyBytes []byte } -// NewCert creates a new certificate blueprint +// NewCert creates a new certificate blueprint. func NewCert( commonName string, validityDuration time.Duration, @@ -65,13 +65,14 @@ func NewCert( } } -// WithHosts modifies to use the given hosts instead of the default (CommonName) +// WithHosts modifies to use the given hosts instead of the default +// (CommonName). func (c *Cert) WithHosts(hosts []string) *Cert { c.Hosts = hosts return c } -// Generate the certificate and keyfile and populate c.CertBytes and c.CertKey +// Generate the certificate and keyfile and populate c.CertBytes and c.CertKey. func (c *Cert) Generate(ca *CA) error { log.Info("Creating CSR for certificate", logfields.CertCommonName, c.CommonName, @@ -123,7 +124,7 @@ func (c *Cert) Generate(ca *CA) error { return nil } -// StoreAsSecret creates or updates the certificate and keyfile in a K8s secret +// StoreAsSecret creates or updates the certificate and keyfile in a K8s secret. func (c *Cert) StoreAsSecret(ctx context.Context, k8sClient *kubernetes.Clientset) error { if c.CertBytes == nil || c.KeyBytes == nil { return fmt.Errorf("cannot create secret %s/%s from empty certificate", @@ -158,7 +159,7 @@ func (c *Cert) StoreAsSecret(ctx context.Context, k8sClient *kubernetes.Clientse return err } -// CA contains the data and metadata of the certificate authority +// CA contains the data and metadata of the certificate authority. type CA struct { SecretName string SecretNamespace string @@ -172,7 +173,7 @@ type CA struct { loadedFromSecret bool } -// NewCA creates a new root CA blueprint +// NewCA creates a new root CA blueprint. func NewCA(secretName, secretNamespace string) *CA { return &CA{ SecretName: secretName, @@ -180,7 +181,7 @@ func NewCA(secretName, secretNamespace string) *CA { } } -// loadKeyPair populates c.CACert/c.CAKey from c.CACertBytes/c.CAKeyBytes +// loadKeyPair populates c.CACert/c.CAKey from c.CACertBytes/c.CAKeyBytes. func (c *CA) loadKeyPair() error { caCert, err := helpers.ParseCertificatePEM(c.CACertBytes) if err != nil { @@ -197,24 +198,26 @@ func (c *CA) loadKeyPair() error { return nil } -// LoadedFromSecret returns true if this CA was loaded from a K8s secret +// LoadedFromSecret returns true if this CA was loaded from a K8s secret. func (c *CA) LoadedFromSecret() bool { return c.loadedFromSecret } -// IsEmpty returns true if this CA is empty +// IsEmpty returns true if this CA is empty. func (c *CA) IsEmpty() bool { return c.CAKey == nil && c.CACert == nil } -// Reset resets ca key and ca cert values, this is useful for reload or regeneration. +// Reset resets ca key and ca cert values, this is useful for reload or +// regeneration. func (c *CA) Reset() { c.CAKey = nil c.CACert = nil c.loadedFromSecret = false } -// Generate the root certificate and keyfile. Populates c.CACertBytes and c.CAKeyBytes +// Generate the root certificate and keyfile. Populates c.CACertBytes and +// c.CAKeyBytes. func (c *CA) Generate(commonName string, validityDuration time.Duration) error { log.Info("Creating CSR for certificate authority", logfields.CertCommonName, commonName, @@ -239,7 +242,8 @@ func (c *CA) Generate(commonName string, validityDuration time.Duration) error { return c.loadKeyPair() } -// LoadFromFile populates c.CACertBytes and c.CAKeyBytes by reading them from file. +// LoadFromFile populates c.CACertBytes and c.CAKeyBytes by reading them from +// file. func (c *CA) LoadFromFile(caCertFile, caKeyFile string) error { if caCertFile == "" || caKeyFile == "" { return errors.New("path for CA key and cert file must both be provided if CA is not generated") @@ -261,10 +265,11 @@ func (c *CA) LoadFromFile(caCertFile, caKeyFile string) error { return c.loadKeyPair() } -// StoreAsSecret creates or updates the CA certificate in a K8s secret -// - If force is true, the existing secret with same name in same namespace (if available) will be overwritten. -// - If force is false and there is existing secret with same name in same namespace, just -// throws IsAlreadyExists error to caller +// StoreAsSecret creates or updates the CA certificate in a K8s secret. +// - If force is true, the existing secret with same name in same namespace +// (if available) will be overwritten. +// - If force is false and there is existing secret with same name in same +// namespace, just throws IsAlreadyExists error to caller. func (c *CA) StoreAsSecret(ctx context.Context, k8sClient *kubernetes.Clientset, force bool) error { if c.CACertBytes == nil || c.CAKeyBytes == nil { return fmt.Errorf("cannot create secret %s/%s from empty certificate", @@ -302,7 +307,8 @@ func (c *CA) StoreAsSecret(ctx context.Context, k8sClient *kubernetes.Clientset, return err } -// LoadFromSecret populates c.CACertBytes and c.CAKeyBytes by reading them from a secret +// LoadFromSecret populates c.CACertBytes and c.CAKeyBytes by reading them from +// a secret. func (c *CA) LoadFromSecret(ctx context.Context, k8sClient *kubernetes.Clientset) error { k8sSecrets := k8sClient.CoreV1().Secrets(c.SecretNamespace) secret, err := k8sSecrets.Get(ctx, c.SecretName, meta_v1.GetOptions{}) diff --git a/internal/logging/logfields/logfields.go b/internal/logging/logfields/logfields.go index e8f213e4..ebcecc8f 100644 --- a/internal/logging/logfields/logfields.go +++ b/internal/logging/logfields/logfields.go @@ -13,7 +13,7 @@ const ( // CertCommonName is the field denoting a x509 certificate's CN. CertCommonName = "certCommonName" // CertValidityDuration is the field denoting a x509 certificate's validity - // durationg + // duration. CertValidityDuration = "certValidityDuration" // CertUsage is the field denoting a x509 certificate's key usages. CertUsage = "certUsage" diff --git a/internal/logging/logging.go b/internal/logging/logging.go index a8ab4d5e..dd4130c4 100644 --- a/internal/logging/logging.go +++ b/internal/logging/logging.go @@ -12,7 +12,7 @@ import ( cfsslLog "github.com/cloudflare/cfssl/log" ) -// DefaultLoggerLvl is a runtime-configurable log level used by DefaultLogger. +// Level is a runtime-configurable log level used by DefaultLogger. var Level = new(slog.LevelVar) // DefaultLogger is the log/slog logger instance used through the certgen @@ -29,37 +29,37 @@ func init() { }) } -// sysLogger wraps slog to implement the cfsslLog.SyslogWriter +// sysLogger wraps slog to implement the cfsslLog.SyslogWriter. type sysLogger struct { l *slog.Logger } -// Debug implements cfsslLog.SyslogWriter +// Debug implements cfsslLog.SyslogWriter. func (s *sysLogger) Debug(msg string) { s.l.Debug(msg, logfields.LogSyslog, "debug") //nolint:sloglint } -// Info implements cfsslLog.SyslogWriter +// Info implements cfsslLog.SyslogWriter. func (s *sysLogger) Info(msg string) { s.l.Info(msg, logfields.LogSyslog, "info") //nolint:sloglint } -// Warning implements cfsslLog.SyslogWriter +// Warning implements cfsslLog.SyslogWriter. func (s *sysLogger) Warning(msg string) { s.l.Warn(msg, logfields.LogSyslog, "warning") //nolint:sloglint } -// Error implements cfsslLog.SyslogWriter +// Err implements cfsslLog.SyslogWriter. func (s *sysLogger) Err(msg string) { s.l.Error(msg, logfields.LogSyslog, "err") //nolint:sloglint } -// Crit implements cfsslLog.SyslogWriter +// Crit implements cfsslLog.SyslogWriter. func (s *sysLogger) Crit(msg string) { s.l.Error(msg, logfields.LogSyslog, "crit") //nolint:sloglint } -// Emerg implements cfsslLog.SyslogWriter +// Emerg implements cfsslLog.SyslogWriter. func (s *sysLogger) Emerg(msg string) { s.l.Error(msg, logfields.LogSyslog, "emerg") //nolint:sloglint } diff --git a/internal/option/config.go b/internal/option/config.go index 6fd50f63..bba35d39 100644 --- a/internal/option/config.go +++ b/internal/option/config.go @@ -57,7 +57,7 @@ const ( CertsConfigFile = "config-file" ) -// CertGenConfig contains the main configuration options +// CertGenConfig contains the main configuration options. type CertGenConfig struct { // Debug enables debug messages. Debug bool @@ -101,10 +101,12 @@ type CertGenConfig struct { CertsConfigFile string } +// CertificateConfigs contains configuration of individual certificates. type CertificateConfigs struct { Certs []CertificateConfig `yaml:"certs"` } +// CertificateConfig contains the configuration of a certificate. type CertificateConfig struct { Name string `yaml:"name"` Namespace string `yaml:"namespace"` @@ -114,7 +116,7 @@ type CertificateConfig struct { Validity time.Duration `yaml:"validity"` } -// PopulateFrom populates the config struct with the values provided by vp +// PopulateFrom populates the config struct with the values provided by vp. func (c *CertGenConfig) PopulateFrom(vp *viper.Viper) { c.Debug = vp.GetBool(Debug) c.K8sKubeConfigPath = vp.GetString(K8sKubeConfigPath) From 3c75365a728639b0533b8d1897d29c0b8dbb8c09 Mon Sep 17 00:00:00 2001 From: Robin Hahling Date: Wed, 29 Oct 2025 11:13:25 +0100 Subject: [PATCH 2/5] treewide: avoid using a global logger And re-enable the sloglint linter. Signed-off-by: Robin Hahling --- .golangci.yml | 2 +- cmd/certgen.go | 15 +++++++-------- internal/generate/generate.go | 13 ++++--------- internal/logging/logging.go | 9 ++++----- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a989a1a5..e416f0e6 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -59,7 +59,7 @@ linters: - protogetter - reassign - revive - #- sloglint + - sloglint - staticcheck - tagalign - testifylint diff --git a/cmd/certgen.go b/cmd/certgen.go index 8d4d43c1..ea085cbc 100644 --- a/cmd/certgen.go +++ b/cmd/certgen.go @@ -29,10 +29,9 @@ import ( const binaryName = "cilium-certgen" -var log = logging.DefaultLogger.With(slog.String(logfields.LogSubsys, binaryName)) - // New creates and returns a certgen command. func New() (*cobra.Command, error) { + log := logging.Logger.With(slog.String(logfields.LogSubsys, binaryName)) vp := viper.New() rootCmd := &cobra.Command{ Use: binaryName + " [flags]", @@ -51,7 +50,7 @@ func New() (*cobra.Command, error) { "version", version.Version, ) - if err := generateCertificates(); err != nil { + if err := generateCertificates(log); err != nil { log.Error("failed to generate certificates", "error", err) } }, @@ -136,7 +135,7 @@ func parseCertificateConfigs(cfg, cfgfile string) (certConfigs option.Certificat } // generateCertificates runs the main code to generate and store certificate. -func generateCertificates() error { +func generateCertificates(log *slog.Logger) error { k8sClient, err := k8sConfig(option.Config.K8sKubeConfigPath) if err != nil { return fmt.Errorf("failed initialize kubernetes client: %w", err) @@ -154,14 +153,14 @@ func generateCertificates() error { switch { case option.Config.CAGenerate: - err = ca.Generate(option.Config.CACommonName, option.Config.CAValidityDuration) + err = ca.Generate(log, option.Config.CACommonName, option.Config.CAValidityDuration) if err != nil { return fmt.Errorf("failed to generate CA: %w", err) } ctx, cancel := context.WithTimeout(context.Background(), option.Config.K8sRequestTimeout) defer cancel() - err = ca.StoreAsSecret(ctx, k8sClient, !option.Config.CAReuseSecret) + err = ca.StoreAsSecret(ctx, log, k8sClient, !option.Config.CAReuseSecret) if err != nil { if !k8sErrors.IsAlreadyExists(err) || !option.Config.CAReuseSecret { return fmt.Errorf("failed to create secret for CA: %w", err) @@ -205,7 +204,7 @@ func generateCertificates() error { cfg.Namespace, ).WithHosts(cfg.Hosts) - err := certs[i].Generate(ca) + err := certs[i].Generate(log, ca) if err != nil { return fmt.Errorf("failed to generate cert: %w", err) } @@ -220,7 +219,7 @@ func generateCertificates() error { ctx, cancel := context.WithTimeout(context.Background(), option.Config.K8sRequestTimeout) defer cancel() - if err := cert.StoreAsSecret(ctx, k8sClient); err != nil { + if err := cert.StoreAsSecret(ctx, log, k8sClient); err != nil { return fmt.Errorf("failed to create secret: %w", err) } diff --git a/internal/generate/generate.go b/internal/generate/generate.go index 1fb3c193..46d8d43f 100644 --- a/internal/generate/generate.go +++ b/internal/generate/generate.go @@ -25,14 +25,9 @@ import ( meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" - "github.com/cilium/certgen/internal/logging" "github.com/cilium/certgen/internal/logging/logfields" ) -var ( - log = logging.DefaultLogger.With(logfields.LogSubsys, "generate") -) - // Cert contains the data and metadata of the certificate and keyfile. type Cert struct { CommonName string @@ -73,7 +68,7 @@ func (c *Cert) WithHosts(hosts []string) *Cert { } // Generate the certificate and keyfile and populate c.CertBytes and c.CertKey. -func (c *Cert) Generate(ca *CA) error { +func (c *Cert) Generate(log *slog.Logger, ca *CA) error { log.Info("Creating CSR for certificate", logfields.CertCommonName, c.CommonName, logfields.CertValidityDuration, c.ValidityDuration.String(), @@ -125,7 +120,7 @@ func (c *Cert) Generate(ca *CA) error { } // StoreAsSecret creates or updates the certificate and keyfile in a K8s secret. -func (c *Cert) StoreAsSecret(ctx context.Context, k8sClient *kubernetes.Clientset) error { +func (c *Cert) StoreAsSecret(ctx context.Context, log *slog.Logger, k8sClient *kubernetes.Clientset) error { if c.CertBytes == nil || c.KeyBytes == nil { return fmt.Errorf("cannot create secret %s/%s from empty certificate", c.Namespace, c.Name) @@ -218,7 +213,7 @@ func (c *CA) Reset() { // Generate the root certificate and keyfile. Populates c.CACertBytes and // c.CAKeyBytes. -func (c *CA) Generate(commonName string, validityDuration time.Duration) error { +func (c *CA) Generate(log *slog.Logger, commonName string, validityDuration time.Duration) error { log.Info("Creating CSR for certificate authority", logfields.CertCommonName, commonName, logfields.CertValidityDuration, validityDuration.String(), @@ -270,7 +265,7 @@ func (c *CA) LoadFromFile(caCertFile, caKeyFile string) error { // (if available) will be overwritten. // - If force is false and there is existing secret with same name in same // namespace, just throws IsAlreadyExists error to caller. -func (c *CA) StoreAsSecret(ctx context.Context, k8sClient *kubernetes.Clientset, force bool) error { +func (c *CA) StoreAsSecret(ctx context.Context, log *slog.Logger, k8sClient *kubernetes.Clientset, force bool) error { if c.CACertBytes == nil || c.CAKeyBytes == nil { return fmt.Errorf("cannot create secret %s/%s from empty certificate", c.SecretNamespace, c.SecretName) diff --git a/internal/logging/logging.go b/internal/logging/logging.go index dd4130c4..c3a2ce22 100644 --- a/internal/logging/logging.go +++ b/internal/logging/logging.go @@ -12,12 +12,11 @@ import ( cfsslLog "github.com/cloudflare/cfssl/log" ) -// Level is a runtime-configurable log level used by DefaultLogger. +// Level is a runtime-configurable log level used by Logger. var Level = new(slog.LevelVar) -// DefaultLogger is the log/slog logger instance used through the certgen -// packages. -var DefaultLogger = slog.New( +// Logger is the log/slog logger instance used through the certgen packages. +var Logger = slog.New( slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{ Level: Level, }), @@ -25,7 +24,7 @@ var DefaultLogger = slog.New( func init() { cfsslLog.SetLogger(&sysLogger{ - l: DefaultLogger.With(logfields.LogSubsys, "cfssl"), + l: Logger.With(logfields.LogSubsys, "cfssl"), //nolint:sloglint }) } From 4382da2e9785a0c853dbc50f389e085e99ea40f0 Mon Sep 17 00:00:00 2001 From: Robin Hahling Date: Wed, 29 Oct 2025 11:48:05 +0100 Subject: [PATCH 3/5] ci: enable the slowg linter Ref: https://github.com/cilium/linters?tab=readme-ov-file#slowg Signed-off-by: Robin Hahling --- .github/workflows/build.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index bde3c6aa..90a3f491 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -31,6 +31,10 @@ jobs: # use our .golangci.yml args: --config=.golangci.yml --verbose skip-cache: true + - name: Run the slowg linter + run: | + go install github.com/cilium/linters@latest + linters -slowg ./... - name: govulncheck uses: golang/govulncheck-action@b625fbe08f3bccbe446d94fbf87fcc875a4f50ee with: From 9c0741a4caf2c8329d7065b01dc479d6a2ab5910 Mon Sep 17 00:00:00 2001 From: Robin Hahling Date: Wed, 29 Oct 2025 14:01:16 +0100 Subject: [PATCH 4/5] bump Go to v1.25.3 Signed-off-by: Robin Hahling --- Dockerfile | 4 ++-- go.mod | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index b3aa5c14..854b2378 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ # (first line comment needed for DOCKER_BUILDKIT use) # # use skopeo inspect to get the multiarch manifest list digest -# skopeo inspect --override-os linux docker://golang:1.24.5-alpine3.22 | jq -r '.Digest' -ARG GOLANG_IMAGE=docker.io/library/golang:1.24.5-alpine3.22@sha256:daae04ebad0c21149979cd8e9db38f565ecefd8547cf4a591240dc1972cf1399 +# skopeo inspect --override-os linux docker://golang:1.25.3-alpine3.22 | jq -r '.Digest' +ARG GOLANG_IMAGE=docker.io/library/golang:1.25.3-alpine3.22@sha256:aee43c3ccbf24fdffb7295693b6e33b21e01baec1b2a55acc351fde345e9ec34 ARG BASE_IMAGE=scratch diff --git a/go.mod b/go.mod index 1a3d09f4..9140f6be 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/cilium/certgen -go 1.24.5 +go 1.25.3 require ( github.com/cloudflare/cfssl v1.6.5 From cb966f87cd51a02bf18394d949f75d54bedaf414 Mon Sep 17 00:00:00 2001 From: Robin Hahling Date: Wed, 29 Oct 2025 14:05:34 +0100 Subject: [PATCH 5/5] version: prepare for v0.3.0 release Signed-off-by: Robin Hahling --- internal/version/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/version/version.go b/internal/version/version.go index 9eb9bfdc..e1497d4a 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -4,4 +4,4 @@ package version // Version is the certgen version string. -var Version = "0.2.4" +var Version = "0.3.0"