diff --git a/.make/go.mk b/.make/go.mk index 90ed1b5c7..a0945177d 100644 --- a/.make/go.mk +++ b/.make/go.mk @@ -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" diff --git a/.woodpecker.star b/.woodpecker.star index 7fadb097e..bc673ca50 100644 --- a/.woodpecker.star +++ b/.woodpecker.star @@ -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", }, diff --git a/opencloud/docker/Dockerfile.multiarch b/opencloud/docker/Dockerfile.multiarch index cebe07b98..0d859da15 100644 --- a/opencloud/docker/Dockerfile.multiarch +++ b/opencloud/docker/Dockerfile.multiarch @@ -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 diff --git a/pkg/version/export_test.go b/pkg/version/export_test.go new file mode 100644 index 000000000..d74fe6811 --- /dev/null +++ b/pkg/version/export_test.go @@ -0,0 +1,4 @@ +package version + +// InitEdition exports the private edition initialization func for testing +var InitEdition = initEdition diff --git a/pkg/version/version.go b/pkg/version/version.go index 4943af61c..d7aed0934 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -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) diff --git a/pkg/version/version_test.go b/pkg/version/version_test.go new file mode 100644 index 000000000..217a5099b --- /dev/null +++ b/pkg/version/version_test.go @@ -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) + } + }) + } +} diff --git a/services/frontend/pkg/config/config.go b/services/frontend/pkg/config/config.go index 14f2fa1ab..57495d3e5 100644 --- a/services/frontend/pkg/config/config.go +++ b/services/frontend/pkg/config/config.go @@ -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"` diff --git a/services/frontend/pkg/config/defaults/defaultconfig.go b/services/frontend/pkg/config/defaults/defaultconfig.go index 709cca972..a6891ad87 100644 --- a/services/frontend/pkg/config/defaults/defaultconfig.go +++ b/services/frontend/pkg/config/defaults/defaultconfig.go @@ -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"}, diff --git a/services/frontend/pkg/revaconfig/config.go b/services/frontend/pkg/revaconfig/config.go index 31d0e89a0..9ba5a2ce7 100644 --- a/services/frontend/pkg/revaconfig/config.go +++ b/services/frontend/pkg/revaconfig/config.go @@ -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(), diff --git a/services/ocdav/pkg/config/config.go b/services/ocdav/pkg/config/config.go index 45a46c992..8c4dd43ff 100644 --- a/services/ocdav/pkg/config/config.go +++ b/services/ocdav/pkg/config/config.go @@ -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"` } diff --git a/services/ocdav/pkg/config/defaults/defaultconfig.go b/services/ocdav/pkg/config/defaults/defaultconfig.go index e6a4130d9..b87b9b394 100644 --- a/services/ocdav/pkg/config/defaults/defaultconfig.go +++ b/services/ocdav/pkg/config/defaults/defaultconfig.go @@ -92,7 +92,7 @@ func DefaultConfig() *config.Config { ProductVersion: version.GetString(), Product: "OpenCloud", ProductName: "OpenCloud", - Edition: "", + Edition: version.Edition, }, } } diff --git a/tests/acceptance/features/coreApiCapabilities/capabilities.feature b/tests/acceptance/features/coreApiCapabilities/capabilities.feature index f4731872b..7b1b885a1 100644 --- a/tests/acceptance/features/coreApiCapabilities/capabilities.feature +++ b/tests/acceptance/features/coreApiCapabilities/capabilities.feature @@ -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", diff --git a/tests/acceptance/features/coreApiCapabilities/capabilitiesWithNormalUser.feature b/tests/acceptance/features/coreApiCapabilities/capabilitiesWithNormalUser.feature index 56db3e44a..c56997200 100644 --- a/tests/acceptance/features/coreApiCapabilities/capabilitiesWithNormalUser.feature +++ b/tests/acceptance/features/coreApiCapabilities/capabilitiesWithNormalUser.feature @@ -58,7 +58,7 @@ Feature: default capabilities for normal user "const": "%versionstring%" }, "edition": { - "const": "%edition%" + "const": "dev" }, "productname": { "const": "%productname%"