diff --git a/README.md b/README.md index 8d36457..3ddb9ee 100644 --- a/README.md +++ b/README.md @@ -202,10 +202,15 @@ Konfiguration, nicht am Code. ## Bauen und schieben ```bash -./build.sh # → gitea.honeyy.duckdns.org/docker/honeyos:latest -./build.sh 0.2 # mit Tag +./build.sh # Tag kommt aus `const Version` in main.go, dazu :latest +./build.sh 1.0-test # abweichender Tag, falls nötig ``` +**Die Version steht an genau einer Stelle:** `const Version` in `main.go`. +`build.sh` liest sie von dort, die Oberfläche holt sie über `/api/public`. Vorher +stand sie zusätzlich in `os.js` — dann hiess das Image 0.4 und der Schreibtisch +zeigte 0.2. + ## Grenzen, die man kennen sollte - **Die Lampe an der Kachel ist kein Health-Check.** Bei einer fremden Domain darf der diff --git a/auth_test.go b/auth_test.go index 9c947e9..a206509 100644 --- a/auth_test.go +++ b/auth_test.go @@ -570,3 +570,28 @@ func TestAppListeBringtDasAussehenMit(t *testing.T) { t.Errorf("Aussehen fehlt: %+v", got.Settings) } } + +// Die angezeigte Version muss vom Server kommen. Vorher stand sie zusätzlich in +// os.js und blieb bei 0.2 stehen, während die Images schon 0.4 hiessen. +func TestVersionKommtVomServer(t *testing.T) { + h := proxyServer(t, Config{ProxyAuth: true}).routes() + + for _, pfad := range []string{"/api/public", "/api/me"} { + rec := httptest.NewRecorder() + h.ServeHTTP(rec, httptest.NewRequest("GET", pfad, nil)) + var got struct{ Version string } + _ = json.Unmarshal(rec.Body.Bytes(), &got) + if got.Version != Version { + t.Errorf("%s nennt Version %q, erwartet %q", pfad, got.Version, Version) + } + } + + // Und in der Oberfläche darf keine zweite fest eingetragen sein. + raw, err := webFS.ReadFile("web/os.js") + if err != nil { + t.Fatal(err) + } + if strings.Contains(string(raw), `const VERSION = "`) { + t.Error("os.js trägt wieder eine eigene Version — die läuft mit den Image-Tags auseinander") + } +} diff --git a/build.sh b/build.sh index f3d7d3c..2161498 100755 --- a/build.sh +++ b/build.sh @@ -3,9 +3,13 @@ set -e REGISTRY="gitea.honeyy.duckdns.org" OWNER="${GITEA_OWNER:-docker}" -TAG="${1:-latest}" +# Die Version steht in main.go. Von dort kommt der Tag, damit das Image nicht +# 0.4 heisst und die Oberflaeche 0.2 anzeigt — genau das war schon passiert. +VERSION="$(grep -oP 'const Version = "\K[^"]+' main.go)" +TAG="${1:-$VERSION}" IMAGE="${REGISTRY}/${OWNER}/honeyos:${TAG}" +LATEST="${REGISTRY}/${OWNER}/honeyos:latest" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo " HoneyOS — Build & Push to Gitea" @@ -19,11 +23,12 @@ docker login "${REGISTRY}" echo "" echo "→ Building..." -docker build -t "${IMAGE}" . +docker build -t "${IMAGE}" -t "${LATEST}" . echo "" echo "→ Pushing..." docker push "${IMAGE}" +docker push "${LATEST}" echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" diff --git a/main.go b/main.go index dbaabbe..5eb4060 100644 --- a/main.go +++ b/main.go @@ -24,6 +24,11 @@ var webFS embed.FS // localSub ist die Kennung im offenen Betrieb — dann gibt es genau einen Nutzer. const localSub = "local" +// Version ist die einzige Stelle, an der sie steht. build.sh liest sie hier aus +// und vergibt denselben Docker-Tag; die Oberfläche holt sie über /api/public. +// Vorher stand sie zusätzlich in os.js und lief mit den Image-Tags auseinander. +const Version = "0.5" + type Config struct { Addr string PublicURL string @@ -131,8 +136,8 @@ func main() { ReadHeaderTimeout: 10 * time.Second, IdleTimeout: 60 * time.Second, } - log.Printf("HoneyOS lauscht auf %s (Daten: %s, Anmeldung: %s)", - cfg.Addr, dataPath(cfg.DataDir), map[bool]string{true: cfg.OIDCIssuer, false: "aus"}[s.auth.Enabled()]) + log.Printf("HoneyOS %s lauscht auf %s (Daten: %s, Anmeldung: %s)", + Version, cfg.Addr, dataPath(cfg.DataDir), map[bool]string{true: cfg.OIDCIssuer, false: "aus"}[s.auth.Enabled()]) log.Fatal(srv.ListenAndServe()) } @@ -285,6 +290,7 @@ func (s *Server) handlePublic(w http.ResponseWriter, r *http.Request) { "oidc": s.auth.Enabled(), "buttonLabel": s.cfg.ButtonLabel, "signedIn": signedIn, + "version": Version, }) } @@ -301,6 +307,7 @@ func (s *Server) handleMe(w http.ResponseWriter, r *http.Request, sub string) { "picture": u.Picture, "settings": u.Settings, "oidc": s.auth.Enabled(), + "version": Version, }) } diff --git a/web/os.js b/web/os.js index 7c2f898..b659069 100644 --- a/web/os.js +++ b/web/os.js @@ -18,7 +18,6 @@ const LS_SETTINGS = "honeyos.settings"; const SS_BOOTED = "honeyos.booted"; -const VERSION = "0.2"; const DEFAULT_SETTINGS = { mode: "terminal", // terminal | desktop @@ -30,7 +29,7 @@ const DEFAULT_SETTINGS = { }; const state = { - cfg: { user: "", hostname: "honeyos", version: VERSION, apps: [] }, + cfg: { user: "", hostname: "honeyos", version: "…", apps: [] }, me: null, // {sub, name, picture} sobald angemeldet oidc: false, settings: { ...DEFAULT_SETTINGS }, @@ -217,6 +216,7 @@ function cookie(name) { async function loadFromServer() { const me = await api("/api/me"); state.me = { sub: me.sub, name: me.name, picture: me.picture }; + if (me.version) state.cfg.version = me.version; state.oidc = !!me.oidc; state.cfg.user = me.name || ""; @@ -1132,7 +1132,7 @@ function showLogin(pub) { const fehler = new URLSearchParams(location.search).get("fehler"); const lines = [ - `HoneyOS ${VERSION} — ${state.cfg.hostname}`, + `HoneyOS ${state.cfg.version} — ${state.cfg.hostname}`, "", "prüfe sitzung".padEnd(28, ".") + " keine", "anmeldung erforderlich", @@ -1181,6 +1181,7 @@ async function main() { let pub = { oidc: false, buttonLabel: "Anmelden" }; try { pub = await api("/api/public"); + if (pub.version) state.cfg.version = pub.version; } catch { /* Server nicht erreichbar — der Anmeldeschirm sagt es gleich selbst */ }