enhancement: introduce build time edition channels

be careful, the env:OC_EDITION, env:FRONTEND_EDITION, and conf:edition got removed as part of this commit, no deprecation because the flag is build time only!
This commit is contained in:
Florian Schade
2025-12-09 12:46:50 +01:00
parent 4c5d5fb218
commit 40d8aacea4
13 changed files with 154 additions and 13 deletions

View File

@@ -36,8 +36,18 @@ ifndef DATE
DATE := $(shell date -u '+%Y%m%d')
endif
LDFLAGS += -X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn -s -w -X "$(OC_REPO)/pkg/version.String=$(STRING)" -X "$(OC_REPO)/pkg/version.Tag=$(VERSION)" -X "$(OC_REPO)/pkg/version.Date=$(DATE)"
DEBUG_LDFLAGS += -X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn -X "$(OC_REPO)/pkg/version.String=$(STRING)" -X "$(OC_REPO)/pkg/version.Tag=$(VERSION)" -X "$(OC_REPO)/pkg/version.Date=$(DATE)"
LDFLAGS += -X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn -s -w \
-X "$(OC_REPO)/pkg/version.Edition=$(EDITION)" \
-X "$(OC_REPO)/pkg/version.String=$(STRING)" \
-X "$(OC_REPO)/pkg/version.Tag=$(VERSION)" \
-X "$(OC_REPO)/pkg/version.Date=$(DATE)"
DEBUG_LDFLAGS += -X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn \
-X "$(OC_REPO)/pkg/version.Edition=$(EDITION)" \
-X "$(OC_REPO)/pkg/version.String=$(STRING)" \
-X "$(OC_REPO)/pkg/version.Tag=$(VERSION)" \
-X "$(OC_REPO)/pkg/version.Date=$(DATE)"
DOCKER_LDFLAGS += -X "$(OC_REPO)/pkg/config/defaults.BaseDataPathType=path" -X "$(OC_REPO)/pkg/config/defaults.BaseDataPathValue=/var/lib/opencloud"
DOCKER_LDFLAGS += -X "$(OC_REPO)/pkg/config/defaults.BaseConfigPathType=path" -X "$(OC_REPO)/pkg/config/defaults.BaseConfigPathValue=/etc/opencloud"

View File

@@ -1628,6 +1628,7 @@ def dockerReleases(ctx):
if is_production:
docker_releases.append("production")
# a new production realease is also a rolling release
# unless skip_rolling is set in the config, i.e. for patch-releases on stable-branch
if not skip_rolling:
@@ -1636,7 +1637,7 @@ def dockerReleases(ctx):
else:
docker_releases.append("rolling")
# on non tag events, do daily build
# on non tag events, do daily build
else:
docker_releases.append("daily")
@@ -1662,6 +1663,7 @@ def dockerRelease(ctx, repo, build_type):
build_args = {
"REVISION": "%s" % ctx.build.commit,
"VERSION": "%s" % (ctx.build.ref.replace("refs/tags/", "") if ctx.build.event == "tag" else "daily"),
"EDITION": "stable" if build_type == "production" else "rolling",
}
# if no additional tag is given, the build-plugin adds latest
@@ -1825,6 +1827,7 @@ def binaryRelease(ctx, arch, depends_on = []):
"image": OC_CI_GOLANG,
"environment": {
"VERSION": (ctx.build.ref.replace("refs/tags/", "") if ctx.build.event == "tag" else "daily"),
"EDITION": "rolling",
"HTTP_PROXY": {
"from_secret": "ci_http_proxy",
},

View File

@@ -3,6 +3,7 @@ ARG TARGETOS
ARG TARGETARCH
ARG VERSION
ARG STRING
ARG EDITION
RUN apk add bash make git curl gcc musl-dev libc-dev binutils-gold inotify-tools vips-dev

View File

@@ -0,0 +1,4 @@
package version
// InitEdition exports the private edition initialization func for testing
var InitEdition = initEdition

View File

@@ -1,9 +1,27 @@
package version
import (
"fmt"
"slices"
"strings"
"time"
"github.com/Masterminds/semver"
"github.com/opencloud-eu/reva/v2/pkg/logger"
)
const (
// Dev is used as a placeholder.
Dev = "dev"
// EditionDev indicates the development build channel was used to build the binary.
EditionDev = Dev
// EditionRolling indicates the rolling release build channel was used to build the binary.
EditionRolling = "rolling"
// EditionStable indicates the stable release build channel was used to build the binary.
EditionStable = "stable"
// EditionLTS indicates the lts release build channel was used to build the binary.
EditionLTS = "lts"
)
var (
@@ -21,17 +39,56 @@ var (
// Date indicates the build date.
// This has been removed, it looks like you can only replace static strings with recent go versions
//Date = time.Now().Format("20060102")
Date = "dev"
Date = Dev
// Legacy defines the old long 4 number OpenCloud version needed for some clients
Legacy = "0.1.0.0"
// LegacyString defines the old OpenCloud version needed for some clients
LegacyString = "0.1.0"
// Edition describes the build channel (stable, rolling, nightly, daily, dev)
Edition = Dev // default for self-compiled builds
)
func init() { //nolint:gochecknoinits
if err := initEdition(); err != nil {
logger.New().Error().Err(err).Msg("falling back to dev")
}
}
func initEdition() error {
regularEditions := []string{EditionDev, EditionRolling, EditionStable}
versionedEditions := []string{EditionLTS}
if !slices.ContainsFunc(slices.Concat(regularEditions, versionedEditions), func(s string) bool {
isRegularEdition := slices.Contains(regularEditions, Edition)
if isRegularEdition && s == Edition {
return true
}
// handle editions with a version
editionParts := strings.Split(Edition, "-")
if len(editionParts) != 2 { // a versioned edition channel must consist of exactly 2 parts.
return false
}
isVersionedEdition := slices.Contains(versionedEditions, editionParts[0])
if !isVersionedEdition { // not all channels can contain version information
return false
}
_, err := semver.NewVersion(editionParts[1])
return err == nil
}) {
Edition = Dev
return fmt.Errorf(`unknown edition channel "%s"`, Edition)
}
return nil
}
// Compiled returns the compile time of this service.
func Compiled() time.Time {
if Date == "dev" {
if Date == Dev {
return time.Now()
}
t, _ := time.Parse("20060102", Date)

View File

@@ -0,0 +1,65 @@
package version_test
import (
"fmt"
"testing"
"github.com/opencloud-eu/opencloud/pkg/version"
)
func TestChannel(t *testing.T) {
tests := map[string]struct {
got string
valid bool
}{
"no channel, defaults to dev": {
got: "",
valid: false,
},
"dev channel": {
got: version.EditionDev,
valid: true,
},
"rolling channel": {
got: version.EditionRolling,
valid: true,
},
"stable channel": {
got: version.EditionStable,
valid: true,
},
"lts channel without version": {
got: version.EditionLTS,
valid: false,
},
"lts-1.0.0 channel": {
got: fmt.Sprintf("%s-1", version.EditionLTS),
valid: true,
},
"lts-one invalid version": {
got: fmt.Sprintf("%s-one", version.EditionLTS),
valid: false,
},
"known channel with version": {
got: fmt.Sprintf("%s-1", version.EditionStable),
valid: false,
},
"unknown channel": {
got: "foo",
valid: false,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
version.Edition = test.got
switch err := version.InitEdition(); {
case err != nil && !test.valid && version.Edition != version.Dev: // if a given edition is unknown, the value is always dev
fallthrough
case test.valid != (err == nil):
t.Fatalf("invalid edition: %s", version.Edition)
}
})
}
}

View File

@@ -33,7 +33,7 @@ type Config struct {
EnableFederatedSharingIncoming bool `yaml:"enable_federated_sharing_incoming" env:"OC_ENABLE_OCM;FRONTEND_ENABLE_FEDERATED_SHARING_INCOMING" desc:"Changing this value is NOT supported. Enables support for incoming federated sharing for clients. The backend behaviour is not changed." introductionVersion:"1.0.0"`
EnableFederatedSharingOutgoing bool `yaml:"enable_federated_sharing_outgoing" env:"OC_ENABLE_OCM;FRONTEND_ENABLE_FEDERATED_SHARING_OUTGOING" desc:"Changing this value is NOT supported. Enables support for outgoing federated sharing for clients. The backend behaviour is not changed." introductionVersion:"1.0.0"`
SearchMinLength int `yaml:"search_min_length" env:"FRONTEND_SEARCH_MIN_LENGTH" desc:"Minimum number of characters to enter before a client should start a search for Share receivers. This setting can be used to customize the user experience if e.g too many results are displayed." introductionVersion:"1.0.0"`
Edition string `yaml:"edition" env:"OC_EDITION;FRONTEND_EDITION" desc:"Edition of OpenCloud. Used for branding purposes." introductionVersion:"1.0.0"`
Edition string `desc:"Edition of OpenCloud. Used for branding purposes." introductionVersion:"1.0.0"`
DisableSSE bool `yaml:"disable_sse" env:"OC_DISABLE_SSE;FRONTEND_DISABLE_SSE" desc:"When set to true, clients are informed that the Server-Sent Events endpoint is not accessible." introductionVersion:"1.0.0"`
DisableRadicale bool `yaml:"disable_radicale" env:"FRONTEND_DISABLE_RADICALE" desc:"When set to true, clients are informed that the Radicale (CalDAV/CardDAV) is not accessible." introductionVersion:"4.0.0"`
DefaultLinkPermissions int `yaml:"default_link_permissions" env:"FRONTEND_DEFAULT_LINK_PERMISSIONS" desc:"Defines the default permissions a link is being created with. Possible values are 0 (= internal link, for instance members only) and 1 (= public link with viewer permissions). Defaults to 1." introductionVersion:"1.0.0"`

View File

@@ -5,6 +5,7 @@ import (
"github.com/opencloud-eu/opencloud/pkg/shared"
"github.com/opencloud-eu/opencloud/pkg/structs"
"github.com/opencloud-eu/opencloud/pkg/version"
"github.com/opencloud-eu/opencloud/services/frontend/pkg/config"
)
@@ -87,7 +88,7 @@ func DefaultConfig() *config.Config {
DefaultUploadProtocol: "tus",
DefaultLinkPermissions: 1,
SearchMinLength: 3,
Edition: "",
Edition: version.Edition,
CheckForUpdates: true,
Checksums: config.Checksums{
SupportedTypes: []string{"sha1", "md5", "adler32"},

View File

@@ -346,7 +346,7 @@ func FrontendConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string
},
"version": map[string]interface{}{
"product": "OpenCloud",
"edition": "",
"edition": version.Edition,
"major": version.ParsedLegacy().Major(),
"minor": version.ParsedLegacy().Minor(),
"micro": version.ParsedLegacy().Patch(),

View File

@@ -80,5 +80,5 @@ type Status struct {
Product string
ProductName string
ProductVersion string
Edition string `yaml:"edition" env:"OC_EDITION;OCDAV_EDITION" desc:"Edition of OpenCloud. Used for branding purposes." introductionVersion:"1.0.0"`
Edition string `desc:"Edition of OpenCloud. Used for branding purposes." introductionVersion:"1.0.0"`
}

View File

@@ -92,7 +92,7 @@ func DefaultConfig() *config.Config {
ProductVersion: version.GetString(),
Product: "OpenCloud",
ProductName: "OpenCloud",
Edition: "",
Edition: version.Edition,
},
}
}

View File

@@ -202,7 +202,7 @@ Feature: capabilities
"properties": {
"edition": {
"type": "string",
"enum": ["%edition%"]
"enum": ["dev"]
},
"product": {
"type": "string",
@@ -240,7 +240,7 @@ Feature: capabilities
},
"edition": {
"type": "string",
"enum": ["%edition%"]
"enum": ["dev"]
},
"product": {
"type": "string",

View File

@@ -58,7 +58,7 @@ Feature: default capabilities for normal user
"const": "%versionstring%"
},
"edition": {
"const": "%edition%"
"const": "dev"
},
"productname": {
"const": "%productname%"