2 Commits
Author SHA1 Message Date
clawbot ebafb385c1 Keep the Applications list's table inside its card (closes #262)
Check / check (pull_request) Skipped
Table cells never wrap, so a long repository URL made the table wider
than its card, which hides what does not fit and so cut off the Actions
column and the Deploy buttons. The repository URL now wraps within its
column, and the card scrolls sideways when the table still does not
fit. A handler test checks both. Every class used was already in the
committed static/css/tailwind.css.

Model: opus-5-5
2026-10-02 01:28:54 +00:00
clawbot 5168db69d9 Read the architecture at run time instead of a Buildarch ldflag (closes #259)
Check / check (pull_request) Successful in 5m19s
The Makefile no longer passes the architecture to the linker. The
Buildarch variable in main and the field and setter in globals are
gone; the startup log line reports runtime.GOARCH as `arch`.
CONVENTIONS.md drops Buildarch from its main, globals, logger and
Makefile examples, as the sneak/prompts conventions do.

Model: opus-5-5
2026-10-02 03:21:51 +02:00
9 changed files with 64 additions and 48 deletions
+12 -20
View File
@@ -115,15 +115,13 @@ import (
)
var (
Appname string = "CHANGEME"
Version string
Buildarch string
Appname string = "CHANGEME"
Version string
)
func main() {
globals.Appname = Appname
globals.Version = Version
globals.Buildarch = Buildarch
fx.New(
fx.Provide(
@@ -823,7 +821,7 @@ func (l *Logger) Identify() {
l.log.Info("starting",
"appname", l.params.Globals.Appname,
"version", l.params.Globals.Version,
"buildarch", l.params.Globals.Buildarch,
"arch", runtime.GOARCH,
)
}
```
@@ -943,23 +941,20 @@ import "go.uber.org/fx"
// Package-level variables (set from main)
var (
Appname string
Version string
Buildarch string
Appname string
Version string
)
// Struct for DI
type Globals struct {
Appname string
Version string
Buildarch string
Appname string
Version string
}
func New(lc fx.Lifecycle) (*Globals, error) {
n := &Globals{
Appname: Appname,
Buildarch: Buildarch,
Version: Version,
Appname: Appname,
Version: Version,
}
return n, nil
}
@@ -970,15 +965,13 @@ func New(lc fx.Lifecycle) (*Globals, error) {
```go
// cmd/httpd/main.go
var (
Appname string = "CHANGEME" // Default, overridden by build
Version string // Set at build time
Buildarch string // Set at build time
Appname string = "CHANGEME" // Default, overridden by build
Version string // Set at build time
)
func main() {
globals.Appname = Appname
globals.Version = Version
globals.Buildarch = Buildarch
// ...
}
```
@@ -989,10 +982,9 @@ Use ldflags to inject version information at build time:
```makefile
VERSION := $(shell git describe --tags --always)
BUILDARCH := $(shell go env GOARCH)
build:
go build -ldflags "-X main.Version=$(VERSION) -X main.Buildarch=$(BUILDARCH)" ./cmd/httpd
go build -ldflags "-X main.Version=$(VERSION)" ./cmd/httpd
```
---
+1 -2
View File
@@ -2,8 +2,7 @@
BINARY := upaasd
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
BUILDARCH := $(shell go env GOARCH)
LDFLAGS := -X main.Version=$(VERSION) -X main.Buildarch=$(BUILDARCH)
LDFLAGS := -X main.Version=$(VERSION)
all: check build
+5
View File
@@ -25,6 +25,11 @@ regress.
Actions column and the Deploy buttons. In a window too narrow for the table,
the card scrolls sideways instead of cutting the table off (#262).
- 2026-10-02: The build no longer passes the CPU architecture in: upaas reads it
from Go's `runtime.GOARCH` when it runs, and the startup log line reports it
as `arch`. `CONVENTIONS.md` follows the updated conventions in `sneak/prompts`
(#259).
- 2026-10-01: Built images are tagged `upaas-<app>:<short hash>`, git's short
form of the commit built, instead of the deployment number. A redeploy of a
commit gives its tag to the new image; the old one is kept while the app runs
+2 -4
View File
@@ -25,15 +25,13 @@ import (
// Build-time variables injected by linker flags (-ldflags).
// These must be exported package-level variables for the build system.
var (
Appname = "upaas" //nolint:gochecknoglobals // build-time variable
Version string //nolint:gochecknoglobals // build-time variable
Buildarch string //nolint:gochecknoglobals // build-time variable
Appname = "upaas" //nolint:gochecknoglobals // build-time variable
Version string //nolint:gochecknoglobals // build-time variable
)
func main() {
globals.SetAppname(Appname)
globals.SetVersion(Version)
globals.SetBuildarch(Buildarch)
fx.New(
fx.Provide(
+7 -18
View File
@@ -12,17 +12,15 @@ import (
//
//nolint:gochecknoglobals // Required for ldflags injection at build time
var (
mu sync.RWMutex
appname string
version string
buildarch string
mu sync.RWMutex
appname string
version string
)
// Globals holds build-time variables for dependency injection.
type Globals struct {
Appname string
Version string
Buildarch string
Appname string
Version string
}
// New creates a new Globals instance from package-level variables.
@@ -31,9 +29,8 @@ func New(_ fx.Lifecycle) (*Globals, error) {
defer mu.RUnlock()
return &Globals{
Appname: appname,
Version: version,
Buildarch: buildarch,
Appname: appname,
Version: version,
}, nil
}
@@ -52,11 +49,3 @@ func SetVersion(ver string) {
version = ver
}
// SetBuildarch sets the build architecture (used for testing and main init).
func SetBuildarch(arch string) {
mu.Lock()
defer mu.Unlock()
buildarch = arch
}
@@ -51,6 +51,4 @@ func TestDashboardTableFitsCard(t *testing.T) {
cellTag := beforeURL[strings.LastIndex(beforeURL, "<td"):]
assert.Contains(t, cellTag, "whitespace-normal")
assert.Contains(t, cellTag, "break-all")
assert.Contains(t, cellTag, "min-w-[8rem]",
"without a minimum width the URL is one character wide in a narrow window")
}
+2 -1
View File
@@ -4,6 +4,7 @@ package logger
import (
"log/slog"
"os"
"runtime"
"go.uber.org/fx"
@@ -81,6 +82,6 @@ func (l *Logger) Identify() {
l.log.Info("starting",
"appname", l.params.Globals.Appname,
"version", l.params.Globals.Version,
"buildarch", l.params.Globals.Buildarch,
"arch", runtime.GOARCH,
)
}
+34
View File
@@ -0,0 +1,34 @@
package logger //nolint:testpackage // sets the unexported log and params fields
import (
"bytes"
"encoding/json"
"log/slog"
"runtime"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sneak.berlin/go/upaas/internal/globals"
)
func TestIdentifyLogsArchitectureFromRuntime(t *testing.T) {
t.Parallel()
var buf bytes.Buffer
l := &Logger{
log: slog.New(slog.NewJSONHandler(&buf, nil)),
params: Params{
Globals: &globals.Globals{Appname: "upaas-test", Version: "test"},
},
}
l.Identify()
var line map[string]any
require.NoError(t, json.Unmarshal(buf.Bytes(), &line))
assert.Equal(t, runtime.GOARCH, line["arch"])
}
+1 -1
View File
@@ -41,7 +41,7 @@
{{.App.Name}}
</a>
</td>
<td class="text-gray-500 font-mono text-xs whitespace-normal break-all min-w-[8rem]">{{.App.RepoURL}}</td>
<td class="text-gray-500 font-mono text-xs whitespace-normal break-all">{{.App.RepoURL}}</td>
<td class="text-gray-500">{{.App.Branch}}</td>
<td>
{{if eq .App.Status "running"}}