v0.3.01 — boilerplate fixes + git-driven versioning
Some checks failed
Deploy server-up / deploy (push) Has been cancelled
Some checks failed
Deploy server-up / deploy (push) Has been cancelled
This commit is contained in:
parent
e34c5ebff6
commit
0b8e3dffb8
4 changed files with 123 additions and 5 deletions
43
CHANGELOG.md
43
CHANGELOG.md
|
|
@ -1,3 +1,46 @@
|
|||
# v0.3.01 — Boilerplates fixes + git-driven versioning
|
||||
|
||||
## Fixes bovenop v0.3.0
|
||||
|
||||
### 🔁 Auto-migratie van default-repos voor upgraders
|
||||
Bestaande installaties (vanaf v0.2.x) hadden de Boilerplates-repo niet zichtbaar
|
||||
in de App Store omdat hun `config.json` in de `su-data` volume al bestond en de
|
||||
nieuwe `DEFAULTS["APP_REPOS"]` daardoor werd overschreven.
|
||||
|
||||
`core/__init__.py` `load()` doet nu een eenmalige migratie: ontbrekende
|
||||
default-repos worden bij opstart aangevuld op basis van id, en gemarkeerd in
|
||||
`MIGRATIONS_DONE: ["v0.3.0_default_repos"]`. Wordt direct gepersisteerd.
|
||||
Verwijdert een gebruiker de Boilerplates-repo expliciet, dan komt-ie niet
|
||||
automatisch terug.
|
||||
|
||||
### 🧹 YAML-poetsstap na boilerplate-render
|
||||
Bij stacks waar de meeste optionele groepen uit staan (Authentik, Nextcloud,
|
||||
etc.) liet de Jinja-render verlaten mapping-sleutels achter (`volumes:`,
|
||||
`networks:`, etc. zonder kinderen). Docker-compose faalt daarop met *"block
|
||||
sequence entries are not allowed in this context"*.
|
||||
|
||||
`core/boilerplates.py` `_tidy()` heeft nu een `_drop_empty_mappings()` substep
|
||||
die in meerdere passes mapping-sleutels verwijdert die alleen worden gevolgd
|
||||
door whitespace/commentaar of een sibling op gelijke/lagere indent. Werkt in
|
||||
cascade.
|
||||
|
||||
### 🏷️ Versie komt nu uit git
|
||||
`Dockerfile` accepteert `ARG SU_VERSION=dev` en bakt die in `ENV SU_VERSION` +
|
||||
OCI image-label. Met `docker build --build-arg SU_VERSION=$(git describe ...)`
|
||||
weet het image zijn eigen versie. De Server Up UI toont automatisch de juiste
|
||||
waarde, ongeacht wat de productie-compose meegeeft.
|
||||
|
||||
Forgejo Actions kan een tag-push automatisch verwerken — zie
|
||||
`server-up-deploy/README.md`.
|
||||
|
||||
## Migratie vanaf v0.3.0
|
||||
```bash
|
||||
docker compose build --no-cache
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# v0.3.0 — UI rebuild + Boilerplates support
|
||||
|
||||
## Hoogtepunten
|
||||
|
|
|
|||
14
Dockerfile
14
Dockerfile
|
|
@ -1,10 +1,16 @@
|
|||
FROM python:3.12-slim AS build
|
||||
WORKDIR /app
|
||||
COPY app/requirements.txt .
|
||||
COPY server-up/requirements.txt .
|
||||
RUN pip install --no-cache-dir --prefix=/inst -r requirements.txt
|
||||
|
||||
FROM python:3.12-slim
|
||||
LABEL org.opencontainers.image.title="Server Up" org.opencontainers.image.version="0.3.0"
|
||||
# Build-arg: zet bij build naar de git-tag, zodat de image z'n eigen versie kent.
|
||||
# docker build --build-arg SU_VERSION=$(git describe --tags --always) ...
|
||||
# Forgejo Actions doet dit automatisch (zie server-up-deploy/README.md).
|
||||
ARG SU_VERSION=dev
|
||||
LABEL org.opencontainers.image.title="Server Up" \
|
||||
org.opencontainers.image.version="${SU_VERSION}" \
|
||||
org.opencontainers.image.source="https://git.example.com/bes-r/server-up"
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
git openssh-client curl tar gzip ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
|
@ -29,7 +35,7 @@ RUN DPKG_ARCH=$(dpkg --print-architecture) \
|
|||
|
||||
COPY --from=build /inst /usr/local
|
||||
WORKDIR /app
|
||||
COPY app/ ./
|
||||
COPY server-up/ ./
|
||||
COPY modules/ ./modules-bundled/
|
||||
RUN mkdir -p static/fonts \
|
||||
&& curl -fsSL "https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css" -o static/fonts/mdi.min.css \
|
||||
|
|
@ -41,7 +47,7 @@ RUN mkdir -p /data/stacks /data/appdata /data/backups /data/git modules /root \
|
|||
&& printf '[safe]\n\tdirectory = *\n' > /root/.gitconfig
|
||||
|
||||
ENV PYTHONUNBUFFERED=1 PORT=5000 HOME=/root \
|
||||
SU_VERSION=0.3.0 \
|
||||
SU_VERSION=${SU_VERSION} \
|
||||
SU_CONFIG=/data/config.json SU_AUDIT=/data/audit.db SU_GIT_CACHE=/data/git \
|
||||
GIT_SSH_COMMAND="ssh -F /dev/null -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
|
||||
EXPOSE 5000
|
||||
|
|
|
|||
|
|
@ -70,6 +70,29 @@ def load() -> dict:
|
|||
for key in ("APP_REPOS", "MODULE_REPOS"):
|
||||
if not cfg.get(key) and DEFAULTS.get(key):
|
||||
cfg[key] = list(DEFAULTS[key])
|
||||
# Migratie: vul ontbrekende default-repos eenmalig aan (bij upgrade van oudere
|
||||
# versie). Markeer welke migraties al gedraaid zijn — zo komt een door de
|
||||
# gebruiker verwijderde repo niet automatisch terug.
|
||||
done = set(cfg.get("MIGRATIONS_DONE") or [])
|
||||
migrated = False
|
||||
if "v0.3.0_default_repos" not in done:
|
||||
for key in ("APP_REPOS", "MODULE_REPOS"):
|
||||
existing = {r.get("id") for r in (cfg.get(key) or []) if isinstance(r, dict)}
|
||||
for d in DEFAULTS.get(key, []) or []:
|
||||
if d.get("id") and d["id"] not in existing:
|
||||
cfg[key].append(dict(d))
|
||||
migrated = True
|
||||
done.add("v0.3.0_default_repos")
|
||||
cfg["MIGRATIONS_DONE"] = sorted(done)
|
||||
if migrated and _path.exists():
|
||||
try:
|
||||
with _lock:
|
||||
fd, tmp = tempfile.mkstemp(dir=str(_path.parent), suffix=".json")
|
||||
with os.fdopen(fd, "w") as f:
|
||||
json.dump(cfg, f, indent=2)
|
||||
Path(tmp).replace(_path)
|
||||
except Exception:
|
||||
pass
|
||||
# Fix foute URLs
|
||||
for key in ("APP_REPOS", "MODULE_REPOS"):
|
||||
if cfg.get(key):
|
||||
|
|
|
|||
|
|
@ -233,10 +233,56 @@ def _looks_textual(p: Path) -> bool:
|
|||
|
||||
|
||||
def _tidy(text: str) -> str:
|
||||
# Collapse 3+ blank lines into 2 — block conditionals leave gaps behind.
|
||||
"""Repareer artefacten die conditional-blocks achterlaten in YAML output:
|
||||
|
||||
1. Verwijder mapping-sleutels die geen inhoud hebben (bv. `volumes:` met alleen
|
||||
een whitespace-blok eronder dat door een uitgeschakelde `<%- if %>` ontstond).
|
||||
Een sleutel `key:` is "verlaten" als de eerstvolgende regel met content óf
|
||||
op gelijk-of-minder indent staat (volgende sibling) óf het einde is.
|
||||
2. Vouw 3+ lege regels in tot 2.
|
||||
"""
|
||||
text = _drop_empty_mappings(text)
|
||||
return re.sub(r"\n{3,}", "\n\n", text)
|
||||
|
||||
|
||||
_KEY_RE = re.compile(r"^(\s*)([A-Za-z_][\w\-]*)\s*:\s*$")
|
||||
|
||||
|
||||
def _drop_empty_mappings(text: str) -> str:
|
||||
"""Verwijder ´keys´ die op een lege regel of een gelijk/minder-indent sibling
|
||||
worden gevolgd — meerdere passes voor cascade-effect (parent kan leeg worden
|
||||
nadat een child is opgeruimd)."""
|
||||
for _ in range(5):
|
||||
lines = text.splitlines()
|
||||
keep = [True] * len(lines)
|
||||
for i, line in enumerate(lines):
|
||||
m = _KEY_RE.match(line)
|
||||
if not m:
|
||||
continue
|
||||
indent = len(m.group(1))
|
||||
# Zoek de eerste niet-lege, niet-commentaar regel hierna
|
||||
j = i + 1
|
||||
while j < len(lines) and (lines[j].strip() == "" or lines[j].lstrip().startswith("#")):
|
||||
j += 1
|
||||
if j >= len(lines):
|
||||
# Sleutel aan het einde van het bestand zonder inhoud
|
||||
keep[i] = False
|
||||
continue
|
||||
next_line = lines[j]
|
||||
stripped = next_line.lstrip()
|
||||
next_indent = len(next_line) - len(stripped)
|
||||
# Geen kinderen → meer indent zou dat zijn. Sibling/uncle = leeg.
|
||||
if next_indent <= indent:
|
||||
keep[i] = False
|
||||
new_text = "\n".join(l for l, k in zip(lines, keep) if k)
|
||||
if new_text == text:
|
||||
break
|
||||
text = new_text
|
||||
if not text.endswith("\n"):
|
||||
text += "\n"
|
||||
return text
|
||||
|
||||
|
||||
def _normalize_compose_name(dest: Path):
|
||||
"""Ensure there's a docker-compose.yml at root; rename compose.yaml if not."""
|
||||
if (dest / "docker-compose.yml").exists() or (dest / "compose.yml").exists():
|
||||
|
|
|
|||
Loading…
Reference in a new issue