diff --git a/api/api/openapi.yaml b/api/api/openapi.yaml
index 426599bc..5160d157 100644
--- a/api/api/openapi.yaml
+++ b/api/api/openapi.yaml
@@ -2608,6 +2608,7 @@ components:
instances:
- backupSize: 0
lastBackup: 6
+ buildVersion: buildVersion
role: role
logLevel: logLevel
userCount: 1
@@ -2619,6 +2620,7 @@ components:
coreAddress: coreAddress
- backupSize: 0
lastBackup: 6
+ buildVersion: buildVersion
role: role
logLevel: logLevel
userCount: 1
@@ -3720,6 +3722,7 @@ components:
example:
backupSize: 0
lastBackup: 6
+ buildVersion: buildVersion
role: role
logLevel: logLevel
userCount: 1
@@ -3733,6 +3736,11 @@ components:
backupSize:
format: int64
type: integer
+ buildVersion:
+ description: |-
+ BuildVersion is the build version of the running server binary, sourced
+ from WEBLENS_BUILD_VERSION or the embedded VCS revision.
+ type: string
coreAddress:
description: |-
Address of the remote server, only if the instance is a core.
diff --git a/api/docs/TowerInfo.md b/api/docs/TowerInfo.md
index 10c069ec..f04376b3 100644
--- a/api/docs/TowerInfo.md
+++ b/api/docs/TowerInfo.md
@@ -5,6 +5,7 @@
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**BackupSize** | **int64** | |
+**BuildVersion** | Pointer to **string** | BuildVersion is the build version of the running server binary, sourced from WEBLENS_BUILD_VERSION or the embedded VCS revision. | [optional]
**CoreAddress** | **string** | Address of the remote server, only if the instance is a core. Not set for any remotes/backups on core server, as it IS the core |
**Id** | **string** | |
**LastBackup** | **int64** | |
@@ -55,6 +56,31 @@ and a boolean to check if the value has been set.
SetBackupSize sets BackupSize field to given value.
+### GetBuildVersion
+
+`func (o *TowerInfo) GetBuildVersion() string`
+
+GetBuildVersion returns the BuildVersion field if non-nil, zero value otherwise.
+
+### GetBuildVersionOk
+
+`func (o *TowerInfo) GetBuildVersionOk() (*string, bool)`
+
+GetBuildVersionOk returns a tuple with the BuildVersion field if it's non-nil, zero value otherwise
+and a boolean to check if the value has been set.
+
+### SetBuildVersion
+
+`func (o *TowerInfo) SetBuildVersion(v string)`
+
+SetBuildVersion sets BuildVersion field to given value.
+
+### HasBuildVersion
+
+`func (o *TowerInfo) HasBuildVersion() bool`
+
+HasBuildVersion returns a boolean if a field has been set.
+
### GetCoreAddress
`func (o *TowerInfo) GetCoreAddress() string`
diff --git a/api/model_tower_info.go b/api/model_tower_info.go
index b5e8319e..7cfafe85 100644
--- a/api/model_tower_info.go
+++ b/api/model_tower_info.go
@@ -22,6 +22,8 @@ var _ MappedNullable = &TowerInfo{}
// TowerInfo struct for TowerInfo
type TowerInfo struct {
BackupSize int64 `json:"backupSize"`
+ // BuildVersion is the build version of the running server binary, sourced from WEBLENS_BUILD_VERSION or the embedded VCS revision.
+ BuildVersion *string `json:"buildVersion,omitempty"`
// Address of the remote server, only if the instance is a core. Not set for any remotes/backups on core server, as it IS the core
CoreAddress string `json:"coreAddress"`
Id string `json:"id"`
@@ -90,6 +92,38 @@ func (o *TowerInfo) SetBackupSize(v int64) {
o.BackupSize = v
}
+// GetBuildVersion returns the BuildVersion field value if set, zero value otherwise.
+func (o *TowerInfo) GetBuildVersion() string {
+ if o == nil || IsNil(o.BuildVersion) {
+ var ret string
+ return ret
+ }
+ return *o.BuildVersion
+}
+
+// GetBuildVersionOk returns a tuple with the BuildVersion field value if set, nil otherwise
+// and a boolean to check if the value has been set.
+func (o *TowerInfo) GetBuildVersionOk() (*string, bool) {
+ if o == nil || IsNil(o.BuildVersion) {
+ return nil, false
+ }
+ return o.BuildVersion, true
+}
+
+// HasBuildVersion returns a boolean if a field has been set.
+func (o *TowerInfo) HasBuildVersion() bool {
+ if o != nil && !IsNil(o.BuildVersion) {
+ return true
+ }
+
+ return false
+}
+
+// SetBuildVersion gets a reference to the given string and assigns it to the BuildVersion field.
+func (o *TowerInfo) SetBuildVersion(v string) {
+ o.BuildVersion = &v
+}
+
// GetCoreAddress returns the CoreAddress field value
func (o *TowerInfo) GetCoreAddress() string {
if o == nil {
@@ -349,6 +383,9 @@ func (o TowerInfo) MarshalJSON() ([]byte, error) {
func (o TowerInfo) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
toSerialize["backupSize"] = o.BackupSize
+ if !IsNil(o.BuildVersion) {
+ toSerialize["buildVersion"] = o.BuildVersion
+ }
toSerialize["coreAddress"] = o.CoreAddress
toSerialize["id"] = o.Id
toSerialize["lastBackup"] = o.LastBackup
diff --git a/api/ts/dist/AllApi.d.ts b/api/ts/dist/AllApi.d.ts
index 5db3c4b8..5d2f1847 100644
--- a/api/ts/dist/AllApi.d.ts
+++ b/api/ts/dist/AllApi.d.ts
@@ -441,6 +441,10 @@ declare const TowerHealthStatusEnum: {
type TowerHealthStatusEnum = typeof TowerHealthStatusEnum[keyof typeof TowerHealthStatusEnum];
interface TowerInfo {
'backupSize': number;
+ /**
+ * BuildVersion is the build version of the running server binary, sourced from WEBLENS_BUILD_VERSION or the embedded VCS revision.
+ */
+ 'buildVersion'?: string;
/**
* Address of the remote server, only if the instance is a core. Not set for any remotes/backups on core server, as it IS the core
*/
diff --git a/api/ts/generated/api.ts b/api/ts/generated/api.ts
index 188559b4..1f92d4af 100644
--- a/api/ts/generated/api.ts
+++ b/api/ts/generated/api.ts
@@ -345,6 +345,10 @@ export type TowerHealthStatusEnum = typeof TowerHealthStatusEnum[keyof typeof To
export interface TowerInfo {
'backupSize': number;
+ /**
+ * BuildVersion is the build version of the running server binary, sourced from WEBLENS_BUILD_VERSION or the embedded VCS revision.
+ */
+ 'buildVersion'?: string;
/**
* Address of the remote server, only if the instance is a core. Not set for any remotes/backups on core server, as it IS the core
*/
diff --git a/api/ts/generated/docs/TowerInfo.md b/api/ts/generated/docs/TowerInfo.md
index 58cd2a44..5ccff6c0 100644
--- a/api/ts/generated/docs/TowerInfo.md
+++ b/api/ts/generated/docs/TowerInfo.md
@@ -6,6 +6,7 @@
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**backupSize** | **number** | | [default to undefined]
+**buildVersion** | **string** | BuildVersion is the build version of the running server binary, sourced from WEBLENS_BUILD_VERSION or the embedded VCS revision. | [optional] [default to undefined]
**coreAddress** | **string** | Address of the remote server, only if the instance is a core. Not set for any remotes/backups on core server, as it IS the core | [default to undefined]
**id** | **string** | | [default to undefined]
**lastBackup** | **number** | | [default to undefined]
@@ -24,6 +25,7 @@ import { TowerInfo } from './api';
const instance: TowerInfo = {
backupSize,
+ buildVersion,
coreAddress,
id,
lastBackup,
diff --git a/docs/docs.go b/docs/docs.go
index 8947a80b..5f3f690b 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -4387,6 +4387,10 @@ const docTemplate = `{
"type": "integer",
"format": "int64"
},
+ "buildVersion": {
+ "description": "BuildVersion is the build version of the running server binary, sourced\nfrom WEBLENS_BUILD_VERSION or the embedded VCS revision.",
+ "type": "string"
+ },
"coreAddress": {
"description": "Address of the remote server, only if the instance is a core.\nNot set for any remotes/backups on core server, as it IS the core",
"type": "string"
diff --git a/docs/swagger.json b/docs/swagger.json
index 13004e79..f1dcd9da 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -4385,6 +4385,10 @@
"type": "integer",
"format": "int64"
},
+ "buildVersion": {
+ "description": "BuildVersion is the build version of the running server binary, sourced\nfrom WEBLENS_BUILD_VERSION or the embedded VCS revision.",
+ "type": "string"
+ },
"coreAddress": {
"description": "Address of the remote server, only if the instance is a core.\nNot set for any remotes/backups on core server, as it IS the core",
"type": "string"
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index 4045c1a2..e44a324d 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -544,6 +544,11 @@ definitions:
backupSize:
format: int64
type: integer
+ buildVersion:
+ description: |-
+ BuildVersion is the build version of the running server binary, sourced
+ from WEBLENS_BUILD_VERSION or the embedded VCS revision.
+ type: string
coreAddress:
description: |-
Address of the remote server, only if the instance is a core.
diff --git a/modules/config/buildversion.go b/modules/config/buildversion.go
new file mode 100644
index 00000000..6a095a49
--- /dev/null
+++ b/modules/config/buildversion.go
@@ -0,0 +1,31 @@
+package config
+
+import (
+ "os"
+ "runtime/debug"
+)
+
+const unknownBuildVersion = "unknown"
+
+// BuildVersion returns the build version of the running binary. It checks the
+// WEBLENS_BUILD_VERSION environment variable first, falling back to the
+// embedded VCS revision from runtime/debug. Returns "unknown" if neither is
+// available.
+func BuildVersion() string {
+ if v := os.Getenv("WEBLENS_BUILD_VERSION"); v != "" {
+ return v
+ }
+
+ buildInfo, ok := debug.ReadBuildInfo()
+ if !ok {
+ return unknownBuildVersion
+ }
+
+ for _, s := range buildInfo.Settings {
+ if s.Key == "vcs.revision" {
+ return s.Value
+ }
+ }
+
+ return unknownBuildVersion
+}
diff --git a/modules/wlog/log.go b/modules/wlog/log.go
index 9f4ec5bf..636998b5 100644
--- a/modules/wlog/log.go
+++ b/modules/wlog/log.go
@@ -6,7 +6,6 @@ import (
"io"
"os"
"runtime"
- "runtime/debug"
"strings"
"sync"
@@ -105,31 +104,16 @@ func NewZeroLogger(opts ...CreateOpts) *zerolog.Logger {
}
}
- config := config.GetConfig()
+ wlVersion := config.BuildVersion()
+ cfg := config.GetConfig()
var logWriter io.Writer
- if config.LogFormat == "dev" {
+ if cfg.LogFormat == "dev" {
logWriter = newDevLogger(outputLocation)
} else {
logWriter = outputLocation
}
- wlVersion := os.Getenv("WEBLENS_BUILD_VERSION")
- if wlVersion == "" {
- wlVersion = "unknown"
-
- buildInfo, ok := debug.ReadBuildInfo()
- if ok {
- for _, v := range buildInfo.Settings {
- if v.Key == "vcs.revision" {
- wlVersion = v.Value
-
- break
- }
- }
- }
- }
-
level := zerolog.InfoLevel
if o.Level != zerolog.Disabled {
level = o.Level
@@ -140,7 +124,7 @@ func NewZeroLogger(opts ...CreateOpts) *zerolog.Logger {
// If no options are provided, set the global loggers
if o.Global {
- zerolog.SetGlobalLevel(config.LogLevel)
+ zerolog.SetGlobalLevel(cfg.LogLevel)
loggerMu.Lock()
@@ -152,9 +136,9 @@ func NewZeroLogger(opts ...CreateOpts) *zerolog.Logger {
loggerMu.Unlock()
- log.Info().CallerSkipFrame(2).Msgf("Weblens logger initialized [%s][%s]", log.GetLevel(), config.LogFormat)
+ log.Info().CallerSkipFrame(2).Msgf("Weblens logger initialized [%s][%s]", log.GetLevel(), cfg.LogFormat)
} else {
- log.Debug().CallerSkipFrame(1).Msgf("Created new Weblens logger [%s][%s]", log.GetLevel(), config.LogFormat)
+ log.Debug().CallerSkipFrame(1).Msgf("Created new Weblens logger [%s][%s]", log.GetLevel(), cfg.LogFormat)
}
return &log
diff --git a/modules/wlstructs/tower.go b/modules/wlstructs/tower.go
index b7720366..6e146b56 100644
--- a/modules/wlstructs/tower.go
+++ b/modules/wlstructs/tower.go
@@ -33,6 +33,10 @@ type TowerInfo struct {
Started bool `json:"started" validate:"required"`
LogLevel string `json:"logLevel,omitempty"`
+
+ // BuildVersion is the build version of the running server binary, sourced
+ // from WEBLENS_BUILD_VERSION or the embedded VCS revision.
+ BuildVersion string `json:"buildVersion,omitempty"`
} // @name TowerInfo
// TowerHealth represents the health status of the server instance.
diff --git a/services/reshape/tower.go b/services/reshape/tower.go
index 28b16463..7c8519c2 100644
--- a/services/reshape/tower.go
+++ b/services/reshape/tower.go
@@ -5,6 +5,7 @@ import (
openapi "github.com/ethanrous/weblens/api"
tower_model "github.com/ethanrous/weblens/models/tower"
+ "github.com/ethanrous/weblens/modules/config"
"github.com/ethanrous/weblens/modules/wlstructs"
context_service "github.com/ethanrous/weblens/services/ctxservice"
)
@@ -31,7 +32,7 @@ func TowerToTowerInfo(ctx context.Context, tower tower_model.Instance) wlstructs
}
}
- return wlstructs.TowerInfo{
+ info := wlstructs.TowerInfo{
ID: tower.TowerID,
Name: tower.Name,
Role: string(tower.Role),
@@ -45,6 +46,12 @@ func TowerToTowerInfo(ctx context.Context, tower tower_model.Instance) wlstructs
ReportedRole: string(tower.Role),
Online: online,
}
+
+ if tower.IsThisTower {
+ info.BuildVersion = config.BuildVersion()
+ }
+
+ return info
}
// TowerInfoToTower converts a TowerInfo from the API to a tower Instance.
diff --git a/services/reshape/tower_test.go b/services/reshape/tower_test.go
new file mode 100644
index 00000000..4f8ee689
--- /dev/null
+++ b/services/reshape/tower_test.go
@@ -0,0 +1,27 @@
+package reshape_test
+
+import (
+ "testing"
+
+ tower_model "github.com/ethanrous/weblens/models/tower"
+ "github.com/ethanrous/weblens/services/reshape"
+)
+
+func TestTowerToTowerInfo_LocalIncludesBuildVersion(t *testing.T) {
+ t.Setenv("WEBLENS_BUILD_VERSION", "test-version-1.2.3")
+
+ ctx := newTestAppContext(t)
+
+ tower := tower_model.Instance{
+ TowerID: "test-tower",
+ Name: "Test Tower",
+ Role: tower_model.RoleCore,
+ IsThisTower: true,
+ }
+
+ info := reshape.TowerToTowerInfo(ctx, tower)
+
+ if info.BuildVersion != "test-version-1.2.3" {
+ t.Fatalf("expected BuildVersion %q, got %q", "test-version-1.2.3", info.BuildVersion)
+ }
+}
diff --git a/weblens-vue/weblens-nuxt/pages/files.vue b/weblens-vue/weblens-nuxt/pages/files.vue
index 228928f0..9a1d9be8 100644
--- a/weblens-vue/weblens-nuxt/pages/files.vue
+++ b/weblens-vue/weblens-nuxt/pages/files.vue
@@ -68,10 +68,15 @@