feat: add motd-assist TUI for managing dynamic MOTDs

Initial Go project built with Bubble Tea and Lip Gloss:
- Live preview and management of /etc/update-motd.d scripts
- Embedded presets (ubuntu-default, minimal, server-dashboard)
- Bundled POSIX sh style scripts (brand header, sysinfo panel, footer)
- Snapshot/restore safety around applying changes
- CLI subcommands preview, apply, restore, list-presets
- Unit tests for detect, sanitize, and apply logic
This commit is contained in:
Tronax 2026-08-24 14:19:28 +02:00
commit d56659e21a
Signed by: Tronax
SSH key fingerprint: SHA256:2pKKXDZucWvaF/GzXNz0FY53EAO1YDLN80bqS+TTz/o
34 changed files with 3260 additions and 0 deletions

View file

@ -0,0 +1,59 @@
package preset
import (
"testing"
)
func TestBuiltinPresetsLoad(t *testing.T) {
t.Setenv("XDG_CONFIG_HOME", t.TempDir())
presets, err := LoadAll()
if err != nil {
t.Fatal(err)
}
if len(presets) < 3 {
t.Errorf("Built-in-Presets fehlen: %d geladen", len(presets))
}
for _, p := range presets {
if p.Source != "builtin" {
t.Errorf("Preset %s: Source = %s", p.Name, p.Source)
}
if len(p.Scripts) == 0 {
t.Errorf("Preset %s hat keine Scripte", p.Name)
}
}
}
func TestSaveAndUserOverride(t *testing.T) {
t.Setenv("XDG_CONFIG_HOME", t.TempDir())
p := Preset{
Name: "minimal",
Description: "eigene Variante",
Scripts: []Entry{{Name: "00-header", Enabled: true}},
}
if _, err := SaveUser(p); err != nil {
t.Fatal(err)
}
presets, err := LoadAll()
if err != nil {
t.Fatal(err)
}
for _, got := range presets {
if got.Name == "minimal" {
if got.Source != "user" || got.Description != "eigene Variante" {
t.Errorf("User-Override greift nicht: %+v", got)
}
return
}
}
t.Fatal("minimal nicht gefunden")
}
func TestDeleteUserRejectsUnknown(t *testing.T) {
t.Setenv("XDG_CONFIG_HOME", t.TempDir())
if err := DeleteUser("gibt-es-nicht"); err == nil {
t.Error("Löschen eines fehlenden Presets sollte fehlschlagen")
}
}