Feature 57 (config and provisioning): modules declare config and provisions, their files rendered from templates; synced with main (issues of feature 57, 874)

This commit is contained in:
2026-10-16 07:37:43 +00:00
parent 1a2c917abf
commit 9652b2d5ce
771 changed files with 52063 additions and 1774 deletions
+4 -4
View File
@@ -55,16 +55,16 @@ func app(name, exec, mime string) string {
// The desktop's folders as found on 2026-10-05, in the module's file with that machine's settings.
func desktopUserDirs(t *testing.T) string {
raw, err := os.ReadFile(filepath.Join("..", "..", "config", "user-dirs.dirs"))
raw, err := os.ReadFile(filepath.Join("..", "..", "files", "user-dirs.dirs"))
if err != nil {
t.Fatal(err)
}
r := strings.NewReplacer("${setting:desktop-dir}", "$HOME/", "${setting:publicshare-dir}", "$HOME/", "${setting:videos-dir}", "$HOME/")
r := strings.NewReplacer("${config:desktop-dir}", "$HOME/", "${config:publicshare-dir}", "$HOME/", "${config:videos-dir}", "$HOME/")
return r.Replace(string(raw))
}
func TestTheFoldersAreReadAsXdgUserDirResolvesThem(t *testing.T) {
conf, _ := os.ReadFile(filepath.Join("..", "..", "config", "user-dirs.conf"))
conf, _ := os.ReadFile(filepath.Join("..", "..", "files", "user-dirs.conf"))
m := fake(t, map[string]string{
home + "/.config/user-dirs.dirs": desktopUserDirs(t),
home + "/.config/user-dirs.conf": string(conf),
@@ -159,7 +159,7 @@ func TestADuplicateGroupOrKeyIsReportedNotMerged(t *testing.T) {
// A machine with the mesh's list, the person's list, and some applications.
func mimeMachine(t *testing.T, extra map[string]string) *Machine {
mesh, err := os.ReadFile(filepath.Join("..", "..", "config", "mimeapps.list"))
mesh, err := os.ReadFile(filepath.Join("..", "..", "files", "mimeapps.list"))
if err != nil {
t.Fatal(err)
}
+36 -7
View File
@@ -74,9 +74,10 @@ func TestItOwnsTheFilesItsSourcesHold(t *testing.T) {
continue
}
files++
src, _ := os.ReadFile(filepath.Join("..", "..", "config", w[2]))
if r["path"] != w[0] || r["mode"] != w[1] || r["content"] != string(src) || r["into"] != nil {
t.Errorf("%s is not config/%s, whole, at %s mode %s: %v", id, w[2], w[0], w[1], r["path"])
_, inline := r["content"]
if _, err := os.Stat(filepath.Join("..", "..", "files", w[2])); err != nil || inline ||
r["template"] != "files/"+w[2] || r["path"] != w[0] || r["mode"] != w[1] || r["into"] != nil {
t.Errorf("%s is not files/%s, whole, as its template, at %s mode %s: %v", id, w[2], w[0], w[1], r["path"])
}
home := strings.HasPrefix(w[0], "${machine:account-home}/")
if home != (r["owner"] == "${machine:account}") {
@@ -100,9 +101,9 @@ func TestItOwnsTheFilesItsSourcesHold(t *testing.T) {
}
func TestTheFoldersFileIsXdgUserDirsOwnFormatWithThreeSettings(t *testing.T) {
raw, _ := os.ReadFile(filepath.Join("..", "..", "config", "user-dirs.dirs"))
raw, _ := os.ReadFile(filepath.Join("..", "..", "files", "user-dirs.dirs"))
text := string(raw)
settings := regexp.MustCompile(`\$\{setting:([a-z0-9-]+)\}`).FindAllStringSubmatch(text, -1)
settings := regexp.MustCompile(`\$\{config:([a-z0-9-]+)\}`).FindAllStringSubmatch(text, -1)
var names []string
for _, s := range settings {
names = append(names, s[1])
@@ -128,14 +129,14 @@ func TestTheFoldersFileIsXdgUserDirsOwnFormatWithThreeSettings(t *testing.T) {
if !strings.Contains(firstLines(text, 3), meshMark) {
t.Error("the header xdg_check recognises the file by")
}
conf, _ := os.ReadFile(filepath.Join("..", "..", "config", "user-dirs.conf"))
conf, _ := os.ReadFile(filepath.Join("..", "..", "files", "user-dirs.conf"))
if !regexp.MustCompile(`(?m)^enabled=False$`).Match(conf) {
t.Error("xdg-user-dirs-update must be disabled, or it rewrites the mesh's file at login")
}
}
func TestTheMeshsDefaultsNameEachTypeOnceInOneGroupEach(t *testing.T) {
raw, _ := os.ReadFile(filepath.Join("..", "..", "config", "mimeapps.list"))
raw, _ := os.ReadFile(filepath.Join("..", "..", "files", "mimeapps.list"))
k := ParseKeyFile(string(raw))
if len(k.DupGroups)+len(k.DupKeys)+len(k.Unparsable) != 0 {
t.Fatalf("%+v", k)
@@ -212,3 +213,31 @@ func TestTheFoldersFileStaysTrustedUntilSettingsAreQuoted(t *testing.T) {
}
t.Fatal("no user-dirs resource")
}
// No file resource carries its text inline: each names its template in files/, and the build packs files/
// into the one archive the controller reads the templates back from (novox/hq ADR 0349 §2).
func TestEveryFileTakesItsTextFromATemplate(t *testing.T) {
m, _ := readManifest(t)
for _, r := range m.Resources {
if _, inline := r["content"]; inline {
t.Errorf("resource %v keeps its text inline: keep it in files/ and name it as the template", r["id"])
}
if name, ok := r["template"].(string); ok {
if _, err := os.Stat(filepath.Join("..", "..", name)); err != nil {
t.Errorf("resource %v names %s: %v", r["id"], name, err)
}
}
}
packs := 0
for _, a := range m.Build.Artifacts {
if a["kind"] == "archive" && a["from"] == "files" {
packs++
if a["name"] != "files" {
t.Errorf("the templates archive is named %v, not files", a["name"])
}
}
}
if packs != 1 {
t.Errorf("the build packs files/ into %d archives, not one", packs)
}
}