v0.8.13-beta - updates voor beta en releases herstellen
All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 7m43s
All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 7m43s
This commit is contained in:
parent
331475415a
commit
6cc078e7b9
15 changed files with 268 additions and 63 deletions
|
|
@ -23,6 +23,10 @@ PORT=5000
|
||||||
# hand aanpassen kan om terug te rollen naar een eerdere versie.
|
# hand aanpassen kan om terug te rollen naar een eerdere versie.
|
||||||
#SU_TAG=0.5.40-beta
|
#SU_TAG=0.5.40-beta
|
||||||
|
|
||||||
|
# De versie die bij die image-tag hoort. De deploy-workflow en updatehelper
|
||||||
|
# houden SU_TAG en SU_VERSION samen bij; normaal hoef je dit niet zelf te zetten.
|
||||||
|
#SU_VERSION=0.5.40-beta
|
||||||
|
|
||||||
# Registry-image, zónder tag. Staat dit ingevuld, dan draait deze server vanaf
|
# Registry-image, zónder tag. Staat dit ingevuld, dan draait deze server vanaf
|
||||||
# een registry en werkt de knop "Nu bijwerken" in de interface. Laat het leeg
|
# een registry en werkt de knop "Nu bijwerken" in de interface. Laat het leeg
|
||||||
# als de server zelf bouwt na een push naar Git — dan is Git de update-route.
|
# als de server zelf bouwt na een push naar Git — dan is Git de update-route.
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ jobs:
|
||||||
if [ -z "$VERSION" ]; then
|
if [ -z "$VERSION" ]; then
|
||||||
VERSION="$(tr -d '[:space:]' < VERSION)"
|
VERSION="$(tr -d '[:space:]' < VERSION)"
|
||||||
fi
|
fi
|
||||||
|
VERSION="${VERSION#v}"
|
||||||
IMAGE="${{ vars.REGISTRY }}/${{ vars.OWNER }}/server-up"
|
IMAGE="${{ vars.REGISTRY }}/${{ vars.OWNER }}/server-up"
|
||||||
echo "VERSION=${VERSION}" >> "$GITHUB_ENV"
|
echo "VERSION=${VERSION}" >> "$GITHUB_ENV"
|
||||||
echo "IMAGE=${IMAGE}" >> "$GITHUB_ENV"
|
echo "IMAGE=${IMAGE}" >> "$GITHUB_ENV"
|
||||||
|
|
@ -131,6 +132,7 @@ jobs:
|
||||||
--pull \
|
--pull \
|
||||||
--build-arg "SU_VERSION=${VERSION}" \
|
--build-arg "SU_VERSION=${VERSION}" \
|
||||||
-t "${IMAGE}:${VERSION}" \
|
-t "${IMAGE}:${VERSION}" \
|
||||||
|
-t "${IMAGE}:v${VERSION}" \
|
||||||
-t "${IMAGE}:${EXTRA_TAG}" \
|
-t "${IMAGE}:${EXTRA_TAG}" \
|
||||||
.
|
.
|
||||||
|
|
||||||
|
|
@ -138,8 +140,11 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
docker push "${IMAGE}:${VERSION}"
|
docker push "${IMAGE}:${VERSION}"
|
||||||
|
# Compatibiliteit met Server Up <= 0.8.12: die vroeg ten onrechte
|
||||||
|
# om de Forgejo-tag mét v. Nieuwe versies gebruiken de kale tag.
|
||||||
|
docker push "${IMAGE}:v${VERSION}"
|
||||||
docker push "${IMAGE}:${EXTRA_TAG}"
|
docker push "${IMAGE}:${EXTRA_TAG}"
|
||||||
echo "Gepusht: ${IMAGE}:${VERSION} en ${IMAGE}:${EXTRA_TAG}"
|
echo "Gepusht: ${IMAGE}:${VERSION}, :v${VERSION} en :${EXTRA_TAG}"
|
||||||
|
|
||||||
- name: Uitloggen
|
- name: Uitloggen
|
||||||
if: always()
|
if: always()
|
||||||
|
|
|
||||||
|
|
@ -146,8 +146,8 @@ jobs:
|
||||||
|
|
||||||
if [ -w .env ] || { [ ! -e .env ] && [ -w . ]; }; then
|
if [ -w .env ] || { [ ! -e .env ] && [ -w . ]; }; then
|
||||||
touch .env
|
touch .env
|
||||||
sed -i '/^SU_TAG=/d' .env
|
sed -i '/^SU_TAG=/d; /^SU_VERSION=/d' .env
|
||||||
echo "SU_TAG=${VERSION}" >> .env
|
printf 'SU_TAG=%s\nSU_VERSION=%s\n' "${VERSION}" "${VERSION}" >> .env
|
||||||
echo "Inhoud van $(pwd)/.env:"
|
echo "Inhoud van $(pwd)/.env:"
|
||||||
grep -vE '^\s*(#|$)' .env | sed 's/^/ /'
|
grep -vE '^\s*(#|$)' .env | sed 's/^/ /'
|
||||||
else
|
else
|
||||||
|
|
@ -172,6 +172,11 @@ jobs:
|
||||||
| docker login "${{ vars.REGISTRY }}" -u "${{ vars.OWNER }}" --password-stdin
|
| docker login "${{ vars.REGISTRY }}" -u "${{ vars.OWNER }}" --password-stdin
|
||||||
docker tag "${SU_IMAGE}:${VERSION}" "${SU_IMAGE}:${CHANNEL}" || true
|
docker tag "${SU_IMAGE}:${VERSION}" "${SU_IMAGE}:${CHANNEL}" || true
|
||||||
docker push "${SU_IMAGE}:${VERSION}"
|
docker push "${SU_IMAGE}:${VERSION}"
|
||||||
|
# Compatibiliteit met Server Up <= 0.8.12: de oude updater vroeg
|
||||||
|
# om de Forgejo-tag mét v. Hiermee kan die zichzelf één keer naar
|
||||||
|
# de gerepareerde updater brengen; nieuwe versies gebruiken de kale tag.
|
||||||
|
docker tag "${SU_IMAGE}:${VERSION}" "${SU_IMAGE}:v${VERSION}"
|
||||||
|
docker push "${SU_IMAGE}:v${VERSION}"
|
||||||
# Pre-releases krijgen geen 'latest': dat hoort bij stable.
|
# Pre-releases krijgen geen 'latest': dat hoort bij stable.
|
||||||
case "$VERSION" in
|
case "$VERSION" in
|
||||||
*-*) docker tag "${SU_IMAGE}:${VERSION}" "${SU_IMAGE}:beta"
|
*-*) docker tag "${SU_IMAGE}:${VERSION}" "${SU_IMAGE}:beta"
|
||||||
|
|
|
||||||
|
|
@ -149,8 +149,8 @@ jobs:
|
||||||
|
|
||||||
if [ -w .env ] || { [ ! -e .env ] && [ -w . ]; }; then
|
if [ -w .env ] || { [ ! -e .env ] && [ -w . ]; }; then
|
||||||
touch .env
|
touch .env
|
||||||
sed -i '/^SU_TAG=/d' .env
|
sed -i '/^SU_TAG=/d; /^SU_VERSION=/d' .env
|
||||||
echo "SU_TAG=${VERSION}" >> .env
|
printf 'SU_TAG=%s\nSU_VERSION=%s\n' "${VERSION}" "${VERSION}" >> .env
|
||||||
echo "Inhoud van $(pwd)/.env:"
|
echo "Inhoud van $(pwd)/.env:"
|
||||||
grep -vE '^\s*(#|$)' .env | sed 's/^/ /'
|
grep -vE '^\s*(#|$)' .env | sed 's/^/ /'
|
||||||
else
|
else
|
||||||
|
|
|
||||||
23
CHANGELOG.md
23
CHANGELOG.md
|
|
@ -1,3 +1,26 @@
|
||||||
|
# v0.8.13-beta — De update haalt nu de juiste release op
|
||||||
|
|
||||||
|
**Bijwerken vanuit de interface vroeg Docker om een image dat niet bestond.**
|
||||||
|
Forgejo noemt een release `v0.8.13`, terwijl de workflows bewust image
|
||||||
|
`:0.8.13` publiceren. De interface stuurde de Git-tag mét `v` door en dus
|
||||||
|
mislukte iedere beta- en stable/main-update bij `docker pull`.
|
||||||
|
|
||||||
|
- **Eén expliciete registry-tag.** De updatecheck geeft naast de Git-tag nu
|
||||||
|
`image_tag` terug. Frontend, endpoint en pull-laag normaliseren allemaal de
|
||||||
|
ene voorloop-`v`. De workflows publiceren ook `:v<versie>` als tijdelijke
|
||||||
|
compatibiliteitstag, zodat de al geïnstalleerde defecte updater zichzelf naar
|
||||||
|
deze reparatie kan brengen.
|
||||||
|
- **De herstart gebruikt exact het bestaande Compose-project.** Projectnaam,
|
||||||
|
projectmap en alle configuratiebestanden komen uit de containerlabels.
|
||||||
|
`--no-build --pull never` voorkomt dat Compose tijdens de update oude
|
||||||
|
broncode bouwt of onverwacht een andere tag ophaalt.
|
||||||
|
- **Tag en versie blijven bij elkaar.** De helper en beide deploy-workflows
|
||||||
|
schrijven `SU_TAG` en `SU_VERSION` samen. Ook na een handmatige Compose-
|
||||||
|
herstart toont en draait Server Up daardoor dezelfde beta- of releaseversie.
|
||||||
|
- **Terugrollen blijft naar een echte versie wijzen.** Als de container via de
|
||||||
|
beweeglijke alias `beta` of `latest` draaide, wordt voortaan het ingebakken
|
||||||
|
OCI-versielabel als terugrolpunt onthouden.
|
||||||
|
|
||||||
# v0.8.12-beta — De image-controle van twaalf minuten naar seconden
|
# v0.8.12-beta — De image-controle van twaalf minuten naar seconden
|
||||||
|
|
||||||
De controle of elk image nog bestaat kostte elf à twaalf minuten, bij élke push,
|
De controle of elk image nog bestaat kostte elf à twaalf minuten, bij élke push,
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
0.8.12-beta
|
0.8.13-beta
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ services:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
args:
|
args:
|
||||||
# Bakt de versie in het image. De deploy-workflow zet SU_VERSION
|
# Bakt de versie in het image. De deploy-workflow zet SU_VERSION uit
|
||||||
# (git-tag of main-<sha>); zonder waarde valt het terug op 'dev'.
|
# VERSION of de release-tag; zonder waarde valt het terug op 'dev'.
|
||||||
SU_VERSION: ${SU_VERSION:-dev}
|
SU_VERSION: ${SU_VERSION:-dev}
|
||||||
# Image + tag staan los, zodat bijwerken vanuit de interface werkt: die
|
# Image + tag staan los, zodat bijwerken vanuit de interface werkt: die
|
||||||
# schrijft SU_TAG in .env en laat compose de container hercreëren.
|
# schrijft SU_TAG in .env en laat compose de container hercreëren.
|
||||||
|
|
|
||||||
|
|
@ -56,15 +56,17 @@ aangeboden.
|
||||||
### Wat er gebeurt als je op "Nu bijwerken" klikt
|
### Wat er gebeurt als je op "Nu bijwerken" klikt
|
||||||
|
|
||||||
```
|
```
|
||||||
1. docker pull git.example.com/bes-r/server-up:0.5.10
|
1. Forgejo-tag `v0.5.10` vertalen naar registry-tag `0.5.10`
|
||||||
2. SU_TAG=0.5.10 wegschrijven in het .env van de deploy-map
|
2. docker pull git.example.com/bes-r/server-up:0.5.10
|
||||||
3. helper-container starten: sleep 5 && docker compose up -d server-up
|
3. SU_TAG=0.5.10 en SU_VERSION=0.5.10 in de deploy-.env vastleggen
|
||||||
4. Server Up wordt vervangen; de browser pollt /healthz tot de nieuwe versie leeft
|
4. helper starten met exact dezelfde Compose-projectnaam en configuratiebestanden
|
||||||
|
5. Server Up vervangen; de browser pollt /healthz tot de nieuwe versie leeft
|
||||||
```
|
```
|
||||||
|
|
||||||
Stap 3 is nodig omdat een container zichzelf niet kan hercreëren: het commando
|
Stap 4 is nodig omdat een container zichzelf niet kan hercreëren: het commando
|
||||||
zou halverwege zijn eigen proces afbreken. De helper draait op het zojuist
|
zou halverwege zijn eigen proces afbreken. De helper draait op het zojuist
|
||||||
gehaalde image — dat bevat de docker- en compose-CLI al — en ruimt zichzelf op.
|
gehaalde image — dat bevat de docker- en compose-CLI al — en ruimt zichzelf op.
|
||||||
|
Met `--no-build --pull never` gebruikt Compose gegarandeerd precies dat image.
|
||||||
|
|
||||||
De deploy-map wordt niet geraden maar uitgelezen uit de compose-labels op de
|
De deploy-map wordt niet geraden maar uitgelezen uit de compose-labels op de
|
||||||
eigen container (`com.docker.compose.project.working_dir`). Draait Server Up niet
|
eigen container (`com.docker.compose.project.working_dir`). Draait Server Up niet
|
||||||
|
|
@ -170,6 +172,7 @@ Op de server waar Server Up draait, in de deploy-map (`/opt/server-up`):
|
||||||
# .env
|
# .env
|
||||||
SU_IMAGE=10.0.20.22:3000/bes-r/server-up
|
SU_IMAGE=10.0.20.22:3000/bes-r/server-up
|
||||||
SU_TAG=0.5.10
|
SU_TAG=0.5.10
|
||||||
|
SU_VERSION=0.5.10
|
||||||
BIND=127.0.0.1
|
BIND=127.0.0.1
|
||||||
PORT=5000
|
PORT=5000
|
||||||
```
|
```
|
||||||
|
|
@ -178,10 +181,16 @@ PORT=5000
|
||||||
registry en werkt de updateknop. Staat het er niet, dan bouwt de server lokaal
|
registry en werkt de updateknop. Staat het er niet, dan bouwt de server lokaal
|
||||||
zoals voorheen en meldt de interface netjes waarom bijwerken niet kan.
|
zoals voorheen en meldt de interface netjes waarom bijwerken niet kan.
|
||||||
|
|
||||||
> Server Up schrijft `SU_TAG` niet zelf in je `.env`, en dat is met opzet: de
|
De Git-release heet bijvoorbeeld `v0.5.10`, maar de canonieke image-tag heet
|
||||||
> installatiemap is nergens in de container gemount. De helper-container die de
|
`:0.5.10`. Server Up verwijdert die ene voorloop-`v` automatisch voor zowel
|
||||||
> hercreatie doet, mount hem wél en zet de tag daar. Tot v0.7.95 probeerde
|
stable/main- als beta-releases. De build publiceert daarnaast `:v0.5.10` als
|
||||||
> Server Up het zelf, en faalde dat dus altijd.
|
compatibiliteitstag, zodat installaties met de oude updater één keer zonder
|
||||||
|
handmatige ingreep naar de gerepareerde versie kunnen overstappen.
|
||||||
|
|
||||||
|
> De draaiende Server Up-container schrijft niet rechtstreeks in je deploy-
|
||||||
|
> `.env`: de installatiemap is daar niet gemount. De updatehelper mount die map
|
||||||
|
> wel en werkt `SU_TAG` en `SU_VERSION` samen bij. Zo blijft ook een latere
|
||||||
|
> handmatige `docker compose up -d` op dezelfde versie.
|
||||||
|
|
||||||
Eerste keer overstappen van lokaal bouwen naar de registry:
|
Eerste keer overstappen van lokaal bouwen naar de registry:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -407,10 +407,11 @@ def api_update_apply():
|
||||||
Kort na afloop verdwijnt deze container; de front-end pollt daarna /healthz.
|
Kort na afloop verdwijnt deze container; de front-end pollt daarna /healthz.
|
||||||
"""
|
"""
|
||||||
d = request.json or {}
|
d = request.json or {}
|
||||||
tag = (d.get("tag") or "").strip()
|
tag = updater.image_tag(d.get("tag") or "")
|
||||||
if not tag:
|
if not tag:
|
||||||
info = updater.check(VERSION)
|
info = updater.check(VERSION)
|
||||||
tag = info.get("latest_tag") or ""
|
tag = (info.get("image_tag")
|
||||||
|
or updater.image_tag(info.get("latest_tag") or ""))
|
||||||
if not tag:
|
if not tag:
|
||||||
return jsonify(ok=False, msg="Geen versie opgegeven en geen release gevonden"), 400
|
return jsonify(ok=False, msg="Geen versie opgegeven en geen release gevonden"), 400
|
||||||
st = selfupdate.status()
|
st = selfupdate.status()
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ Up alleen het voorwerk (image ophalen, tag wegschrijven) en laat het de
|
||||||
daadwerkelijke hercreatie over aan een korte **helper-container**:
|
daadwerkelijke hercreatie over aan een korte **helper-container**:
|
||||||
|
|
||||||
1. `docker pull <registry>/<repo>:<tag>` ← nieuw image binnenhalen
|
1. `docker pull <registry>/<repo>:<tag>` ← nieuw image binnenhalen
|
||||||
2. `SU_TAG=<tag>` in het .env van de deploy-map schrijven
|
2. `SU_TAG=<tag>` en `SU_VERSION=<tag>` in de deploy-.env schrijven
|
||||||
3. helper starten: sleep 5 && docker compose up -d server-up
|
3. helper starten met exact hetzelfde Compose-project en -configuratie
|
||||||
4. helper stopt zichzelf (`--rm`)
|
4. helper stopt zichzelf (`--rm`)
|
||||||
|
|
||||||
De helper draait op het zojuist gepulde image: dat bevat de docker- en
|
De helper draait op het zojuist gepulde image: dat bevat de docker- en
|
||||||
|
|
@ -27,7 +27,7 @@ import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import core as cfg
|
import core as cfg
|
||||||
from core import docker
|
from core import docker, updater
|
||||||
|
|
||||||
# Labels die `docker compose` op elke container zet.
|
# Labels die `docker compose` op elke container zet.
|
||||||
_LBL_PROJECT = "com.docker.compose.project"
|
_LBL_PROJECT = "com.docker.compose.project"
|
||||||
|
|
@ -70,6 +70,7 @@ def inspect_self() -> dict:
|
||||||
"working_dir": labels.get(_LBL_WORKDIR, ""),
|
"working_dir": labels.get(_LBL_WORKDIR, ""),
|
||||||
"config_files": labels.get(_LBL_CONFIGS, ""),
|
"config_files": labels.get(_LBL_CONFIGS, ""),
|
||||||
"service": labels.get(_LBL_SERVICE, "") or "server-up",
|
"service": labels.get(_LBL_SERVICE, "") or "server-up",
|
||||||
|
"version": labels.get("org.opencontainers.image.version", ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -159,6 +160,10 @@ def _login(log_fn=None) -> tuple[bool, str]:
|
||||||
|
|
||||||
def pull(tag: str, log_fn=None) -> tuple[bool, str]:
|
def pull(tag: str, log_fn=None) -> tuple[bool, str]:
|
||||||
"""Haal `<repo>:<tag>` binnen. Retourneert (ok, image of foutmelding)."""
|
"""Haal `<repo>:<tag>` binnen. Retourneert (ok, image of foutmelding)."""
|
||||||
|
# Forgejo noemt de Git-tag v0.8.13, maar de workflows pushen :0.8.13.
|
||||||
|
# Normaliseer hier óók, zodat oude clients die nog latest_tag versturen
|
||||||
|
# nooit een niet-bestaande :v0.8.13 proberen op te halen.
|
||||||
|
tag = updater.image_tag(tag)
|
||||||
if not _TAG_RE.match(tag or ""):
|
if not _TAG_RE.match(tag or ""):
|
||||||
return False, f"Ongeldige tag: {tag!r}"
|
return False, f"Ongeldige tag: {tag!r}"
|
||||||
repo = image_repo()
|
repo = image_repo()
|
||||||
|
|
@ -180,22 +185,19 @@ def pull(tag: str, log_fn=None) -> tuple[bool, str]:
|
||||||
# ── Toepassen ────────────────────────────────────────────────────────────────
|
# ── Toepassen ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
def _tag_script(tag: str) -> str:
|
def _tag_script(tag: str) -> str:
|
||||||
"""Sh-regels die SU_TAG in het .env van de werkmap zetten.
|
"""Sh-regels die de image-tag én versie in de deploy-.env vastleggen.
|
||||||
|
|
||||||
Dit gebeurt in de helper-container en niet hier, en dat is geen detail: de
|
Dit gebeurt in de helper-container: de installatiemap is niet in de
|
||||||
installatiemap (`/opt/server-up`) is nérgens in deze container gemount. Er
|
draaiende Server Up-container gemount, maar wordt wel expliciet aan de
|
||||||
zijn maar drie mounts — de docker-socket, het `su-data`-volume en `BASE_DIR`
|
helper gekoppeld. SU_VERSION is nodig voor oudere compose-bestanden die de
|
||||||
— en de installatiemap zit daar niet bij. Zelf schrijven belandde dus in de
|
ingebakken imageversie met een runtimewaarde overschrijven.
|
||||||
overlay van de container of, waarschijnlijker, mislukte omdat de map hier
|
|
||||||
niet bestaat. Bijwerken vanuit de interface kon daardoor nooit werken.
|
|
||||||
|
|
||||||
De helper mount `working_dir` wél, op hetzelfde pad, en draait als root.
|
|
||||||
"""
|
"""
|
||||||
q = shlex.quote(f"SU_TAG={tag}")
|
tag_regel = shlex.quote(f"SU_TAG={tag}")
|
||||||
|
versie_regel = shlex.quote(f"SU_VERSION={tag}")
|
||||||
return (
|
return (
|
||||||
"touch .env; "
|
"touch .env; "
|
||||||
"sed -i '/^SU_TAG=/d' .env; "
|
"sed -i '/^SU_TAG=/d; /^SU_VERSION=/d' .env; "
|
||||||
f"printf '%s\\n' {q} >> .env; "
|
f"printf '%s\\n' {tag_regel} {versie_regel} >> .env; "
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -216,6 +218,7 @@ def apply(tag: str, log_fn=None) -> tuple[bool, str]:
|
||||||
Bij succes keert deze functie terug terwijl de helper al gestart is; enkele
|
Bij succes keert deze functie terug terwijl de helper al gestart is; enkele
|
||||||
seconden later verdwijnt dit proces omdat de container hercreëerd wordt.
|
seconden later verdwijnt dit proces omdat de container hercreëerd wordt.
|
||||||
"""
|
"""
|
||||||
|
tag = updater.image_tag(tag)
|
||||||
st = status()
|
st = status()
|
||||||
if not st["can_apply"]:
|
if not st["can_apply"]:
|
||||||
return False, st["reason"]
|
return False, st["reason"]
|
||||||
|
|
@ -229,39 +232,66 @@ def apply(tag: str, log_fn=None) -> tuple[bool, str]:
|
||||||
return False, image_of_fout
|
return False, image_of_fout
|
||||||
image = image_of_fout
|
image = image_of_fout
|
||||||
|
|
||||||
# Onthoud waar we vandaan komen, zodat terugrollen mogelijk blijft als het
|
# Een alias als latest of beta verschuift bij iedere release en is dus geen
|
||||||
# nieuwe image niet start.
|
# bruikbaar terugrolpunt. Het OCI-versielabel verwijst naar de echte,
|
||||||
|
# onveranderlijke versietag; val terug op de gebruikte imagetag voor oude
|
||||||
|
# images zonder label.
|
||||||
|
versie = updater.image_tag(info.get("version", ""))
|
||||||
huidig = info.get("image", "")
|
huidig = info.get("image", "")
|
||||||
|
if _TAG_RE.match(versie or "") and versie != "dev":
|
||||||
|
vorige_tag = versie
|
||||||
|
else:
|
||||||
vorige_tag = huidig.rsplit(":", 1)[-1] if _has_tag(huidig) else "latest"
|
vorige_tag = huidig.rsplit(":", 1)[-1] if _has_tag(huidig) else "latest"
|
||||||
|
|
||||||
cfg.patch({"UPDATE_PREVIOUS_TAG": vorige_tag,
|
cfg.patch({"UPDATE_PREVIOUS_TAG": vorige_tag,
|
||||||
"UPDATE_LAST_APPLIED": {"tag": tag, "ts": time.time(),
|
"UPDATE_LAST_APPLIED": {"tag": tag, "ts": time.time(),
|
||||||
"from": vorige_tag}})
|
"from": vorige_tag}})
|
||||||
|
|
||||||
if log_fn:
|
if log_fn:
|
||||||
log_fn(f"Vorige versie: {vorige_tag} (terugrollen kan vanuit Instellingen)")
|
log_fn(f"Vorige versie: {vorige_tag} (terugrollen kan vanuit Instellingen)")
|
||||||
log_fn(f"SU_TAG={tag} wordt door de helper in {werkmap}/.env gezet")
|
log_fn(f"SU_TAG en SU_VERSION worden in {werkmap}/.env bijgewerkt")
|
||||||
log_fn("Helper starten die de container hercreëert…")
|
log_fn("Helper starten die de container hercreëert…")
|
||||||
|
|
||||||
ok, melding = _spawn_helper(image, werkmap, service, tag, log_fn)
|
ok, melding = _spawn_helper(
|
||||||
|
image, werkmap, service, tag,
|
||||||
|
project=info.get("project", ""),
|
||||||
|
config_files=info.get("config_files", ""),
|
||||||
|
log_fn=log_fn,
|
||||||
|
)
|
||||||
if not ok:
|
if not ok:
|
||||||
return False, melding
|
return False, melding
|
||||||
return True, (f"Bijwerken naar {tag} gestart. Server Up herstart nu; "
|
return True, (f"Bijwerken naar {tag} gestart. Server Up herstart nu; "
|
||||||
"de interface komt over enkele seconden terug.")
|
"de interface komt over enkele seconden terug.")
|
||||||
|
|
||||||
|
|
||||||
|
def _compose_up(working_dir: str, project: str, config_files: str,
|
||||||
|
service: str) -> str:
|
||||||
|
"""Bouw het commando voor exact het huidige Compose-project."""
|
||||||
|
cmd = ["docker", "compose", "--project-directory", working_dir]
|
||||||
|
if project:
|
||||||
|
cmd.extend(["--project-name", project])
|
||||||
|
for config in (p.strip() for p in (config_files or "").split(",")):
|
||||||
|
if config:
|
||||||
|
cmd.extend(["--file", config])
|
||||||
|
# Het doelimage is vlak hiervoor expliciet gepulld. Bouw nooit stilletjes
|
||||||
|
# oude broncode uit de deploy-map en haal tijdens de herstart niets anders.
|
||||||
|
cmd.extend(["up", "-d", "--remove-orphans", "--no-build", "--pull", "never",
|
||||||
|
service])
|
||||||
|
return shlex.join(cmd)
|
||||||
|
|
||||||
|
|
||||||
def _spawn_helper(image: str, working_dir: str, service: str, tag: str,
|
def _spawn_helper(image: str, working_dir: str, service: str, tag: str,
|
||||||
|
project: str = "", config_files: str = "",
|
||||||
log_fn=None) -> tuple[bool, str]:
|
log_fn=None) -> tuple[bool, str]:
|
||||||
"""Start een korte container die `docker compose up -d <service>` uitvoert.
|
"""Start een helper die het bestaande Compose-project exact hercreëert.
|
||||||
|
|
||||||
Draait op hetzelfde (nieuwe) image, dat de docker- en compose-CLI al bevat.
|
Projectnaam en configuratiebestanden komen uit de labels van de huidige
|
||||||
`sleep` geeft dit proces de tijd om zijn HTTP-antwoord af te maken voordat
|
container. Daardoor werkt dit ook bij `docker compose -p ... -f ...`, en
|
||||||
het onder zijn eigen voeten wordt weggehaald.
|
wordt niet per ongeluk een tweede project gestart. `--no-build` garandeert
|
||||||
|
dat Compose het zojuist gepullde release-image gebruikt.
|
||||||
De helper zet ook SU_TAG: hij mount de werkmap, deze container niet.
|
|
||||||
"""
|
"""
|
||||||
script = (f"sleep 5; "
|
compose_up = _compose_up(working_dir, project, config_files, service)
|
||||||
f"{_tag_script(tag)}"
|
script = f"sleep 5; {_tag_script(tag)}{compose_up}"
|
||||||
f"docker compose up -d --remove-orphans {shlex.quote(service)}")
|
|
||||||
cmd = [docker._bin(), "run", "--rm", "--detach",
|
cmd = [docker._bin(), "run", "--rm", "--detach",
|
||||||
"--name", "server-up-updater",
|
"--name", "server-up-updater",
|
||||||
"-v", "/var/run/docker.sock:/var/run/docker.sock",
|
"-v", "/var/run/docker.sock:/var/run/docker.sock",
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,17 @@ def is_prerelease(version: str) -> bool:
|
||||||
return bool(t and t[3] == 0)
|
return bool(t and t[3] == 0)
|
||||||
|
|
||||||
|
|
||||||
|
def image_tag(release_tag: str) -> str:
|
||||||
|
"""Vertaal een Forgejo-release-tag naar de tag uit onze registry.
|
||||||
|
|
||||||
|
Git-tags heten volgens afspraak `v0.8.13`; de build-workflows verwijderen
|
||||||
|
die voorloop-v en pushen `:0.8.13`. Alleen een geldige semver wordt
|
||||||
|
aangepast, zodat een handmatige registry-tag zoals `beta` intact blijft.
|
||||||
|
"""
|
||||||
|
tag = (release_tag or "").strip()
|
||||||
|
return tag[1:] if tag.startswith("v") and _parse(tag) else tag
|
||||||
|
|
||||||
|
|
||||||
def _releases(url: str) -> list[dict]:
|
def _releases(url: str) -> list[dict]:
|
||||||
req = urllib.request.Request(
|
req = urllib.request.Request(
|
||||||
url, headers={"Accept": "application/json", "User-Agent": "server-up"})
|
url, headers={"Accept": "application/json", "User-Agent": "server-up"})
|
||||||
|
|
@ -91,7 +102,8 @@ def check(current: str, force: bool = False) -> dict:
|
||||||
ch = channel()
|
ch = channel()
|
||||||
res = {"enabled": bool(url), "current": current, "channel": ch,
|
res = {"enabled": bool(url), "current": current, "channel": ch,
|
||||||
"current_is_prerelease": is_prerelease(current),
|
"current_is_prerelease": is_prerelease(current),
|
||||||
"latest": None, "latest_tag": "", "update_available": False,
|
"latest": None, "latest_tag": "", "image_tag": "",
|
||||||
|
"update_available": False,
|
||||||
"url": "", "notes": "", "prerelease": False, "error": "",
|
"url": "", "notes": "", "prerelease": False, "error": "",
|
||||||
"checked_at": time.time()}
|
"checked_at": time.time()}
|
||||||
if not url:
|
if not url:
|
||||||
|
|
@ -121,7 +133,8 @@ def check(current: str, force: bool = False) -> dict:
|
||||||
|
|
||||||
tag = (best.get("tag_name") or best.get("name") or "")
|
tag = (best.get("tag_name") or best.get("name") or "")
|
||||||
res["latest_tag"] = tag
|
res["latest_tag"] = tag
|
||||||
res["latest"] = tag.lstrip("v")
|
res["image_tag"] = image_tag(tag)
|
||||||
|
res["latest"] = res["image_tag"]
|
||||||
res["url"] = best.get("html_url") or best.get("url") or ""
|
res["url"] = best.get("html_url") or best.get("url") or ""
|
||||||
res["notes"] = best.get("body") or ""
|
res["notes"] = best.get("body") or ""
|
||||||
res["prerelease"] = bool(best.get("prerelease"))
|
res["prerelease"] = bool(best.get("prerelease"))
|
||||||
|
|
|
||||||
|
|
@ -4078,7 +4078,7 @@ function app() {
|
||||||
// Bijwerken: de container vervangt zichzelf, dus na het startsein is deze
|
// Bijwerken: de container vervangt zichzelf, dus na het startsein is deze
|
||||||
// pagina zijn server kwijt. We pollen /healthz tot de nieuwe versie leeft.
|
// pagina zijn server kwijt. We pollen /healthz tot de nieuwe versie leeft.
|
||||||
async applyUpdate() {
|
async applyUpdate() {
|
||||||
const naar = this.update.latest_tag || this.update.latest;
|
const naar = this.update.image_tag || this.update.latest || this.update.latest_tag;
|
||||||
if (!confirm(this.t('update_confirm', {tag: naar}))) return;
|
if (!confirm(this.t('update_confirm', {tag: naar}))) return;
|
||||||
this.updating = true;
|
this.updating = true;
|
||||||
const d = await this.rpc('/api/update/apply', { tag: naar });
|
const d = await this.rpc('/api/update/apply', { tag: naar });
|
||||||
|
|
|
||||||
|
|
@ -349,6 +349,18 @@ check('balk staat halverwege', c.job.progress.pct === 50);
|
||||||
// De poortcontrole praat met de backend, dus die checks zijn asynchroon.
|
// De poortcontrole praat met de backend, dus die checks zijn asynchroon.
|
||||||
// Top-level await kan niet in een CommonJS-script; vandaar deze afsluiting.
|
// Top-level await kan niet in een CommonJS-script; vandaar deze afsluiting.
|
||||||
(async () => {
|
(async () => {
|
||||||
|
// Forgejo noemt de release v0.8.13-beta, maar de registry-workflow pusht de
|
||||||
|
// image-tag zonder v. De updateknop moet de expliciete image-tag gebruiken.
|
||||||
|
let updateBody = null;
|
||||||
|
global.confirm = () => true;
|
||||||
|
c.update = { current: '0.8.12-beta', latest: '0.8.13-beta',
|
||||||
|
latest_tag: 'v0.8.13-beta', image_tag: '0.8.13-beta' };
|
||||||
|
c.rpc = async (url, body) => { updateBody = body; return { job_id: 'upd1' }; };
|
||||||
|
c.pollJob = () => {};
|
||||||
|
await c.applyUpdate();
|
||||||
|
check('update gebruikt registry-tag zonder v',
|
||||||
|
updateBody && updateBody.tag === '0.8.13-beta');
|
||||||
|
|
||||||
// ── De hoofdmap ───────────────────────────────────────────────────────────
|
// ── De hoofdmap ───────────────────────────────────────────────────────────
|
||||||
let gevraagdPad = null;
|
let gevraagdPad = null;
|
||||||
c.rpc = async (url) => {
|
c.rpc = async (url) => {
|
||||||
|
|
|
||||||
|
|
@ -106,11 +106,25 @@ def test_pull_weigert_ongeldige_tag(su, monkeypatch, tag):
|
||||||
assert "Ongeldige tag" in msg
|
assert "Ongeldige tag" in msg
|
||||||
|
|
||||||
|
|
||||||
|
def test_pull_stript_de_v_van_een_forgejo_release(su, monkeypatch):
|
||||||
|
"""De workflow pusht :0.8.13-beta, niet :v0.8.13-beta."""
|
||||||
|
_fake_inspect(su, monkeypatch)
|
||||||
|
getrokken = []
|
||||||
|
monkeypatch.setattr(su, "_login", lambda log_fn=None: (True, ""))
|
||||||
|
monkeypatch.setattr(
|
||||||
|
su.docker, "_stream",
|
||||||
|
lambda cmd, **kw: getrokken.append(cmd[-1]) or 0,
|
||||||
|
)
|
||||||
|
ok, image = su.pull("v0.8.13-beta")
|
||||||
|
assert ok is True
|
||||||
|
assert image == "git.example.com/bes-r/server-up:0.8.13-beta"
|
||||||
|
assert getrokken == [image]
|
||||||
|
|
||||||
|
|
||||||
# ── SU_TAG wegschrijven ──────────────────────────────────────────────────────
|
# ── SU_TAG wegschrijven ──────────────────────────────────────────────────────
|
||||||
# Dit gebeurde eerder in Python, hier in de container. Maar de installatiemap is
|
# De draaiende container kan de deploy-.env niet schrijven: de installatiemap
|
||||||
# hier nergens gemount — er zijn maar drie mounts: de docker-socket, su-data en
|
# is daar niet gemount. De helper mount de werkmap wel en houdt tag en versie
|
||||||
# BASE_DIR. Bijwerken vanuit de interface kon daardoor nooit werken. Het gebeurt
|
# bij elkaar, dus toetsen we het shellfragment rechtstreeks.
|
||||||
# nu in de helper, die de werkmap wél mount, dus toetsen we het shellfragment.
|
|
||||||
|
|
||||||
def _draai_tagscript(su, map_: Path, tag: str):
|
def _draai_tagscript(su, map_: Path, tag: str):
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
@ -121,14 +135,19 @@ def _draai_tagscript(su, map_: Path, tag: str):
|
||||||
|
|
||||||
|
|
||||||
def test_tagscript_maakt_env_aan(su, tmp_path):
|
def test_tagscript_maakt_env_aan(su, tmp_path):
|
||||||
assert _draai_tagscript(su, tmp_path, "0.5.10").strip() == "SU_TAG=0.5.10"
|
assert _draai_tagscript(su, tmp_path, "0.5.10").splitlines() == [
|
||||||
|
"SU_TAG=0.5.10", "SU_VERSION=0.5.10",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_tagscript_vervangt_bestaande_regel(su, tmp_path):
|
def test_tagscript_vervangt_bestaande_regel(su, tmp_path):
|
||||||
(tmp_path / ".env").write_text("BIND=0.0.0.0\nSU_TAG=0.5.00\nPORT=5000\n")
|
(tmp_path / ".env").write_text(
|
||||||
|
"BIND=0.0.0.0\nSU_TAG=0.5.00\nSU_VERSION=0.5.00\nPORT=5000\n")
|
||||||
regels = _draai_tagscript(su, tmp_path, "0.5.10").splitlines()
|
regels = _draai_tagscript(su, tmp_path, "0.5.10").splitlines()
|
||||||
assert regels == ["BIND=0.0.0.0", "PORT=5000", "SU_TAG=0.5.10"]
|
assert regels == ["BIND=0.0.0.0", "PORT=5000", "SU_TAG=0.5.10",
|
||||||
|
"SU_VERSION=0.5.10"]
|
||||||
assert sum(1 for r in regels if r.startswith("SU_TAG=")) == 1
|
assert sum(1 for r in regels if r.startswith("SU_TAG=")) == 1
|
||||||
|
assert sum(1 for r in regels if r.startswith("SU_VERSION=")) == 1
|
||||||
|
|
||||||
|
|
||||||
def test_tagscript_behoudt_andere_instellingen(su, tmp_path):
|
def test_tagscript_behoudt_andere_instellingen(su, tmp_path):
|
||||||
|
|
@ -136,6 +155,7 @@ def test_tagscript_behoudt_andere_instellingen(su, tmp_path):
|
||||||
inhoud = _draai_tagscript(su, tmp_path, "0.5.10")
|
inhoud = _draai_tagscript(su, tmp_path, "0.5.10")
|
||||||
assert "SU_IMAGE=git.example.com/bes-r/server-up" in inhoud
|
assert "SU_IMAGE=git.example.com/bes-r/server-up" in inhoud
|
||||||
assert "SU_TAG=0.5.10" in inhoud
|
assert "SU_TAG=0.5.10" in inhoud
|
||||||
|
assert "SU_VERSION=0.5.10" in inhoud
|
||||||
|
|
||||||
|
|
||||||
def test_tagscript_laat_zich_niet_uitbreiden(su, tmp_path):
|
def test_tagscript_laat_zich_niet_uitbreiden(su, tmp_path):
|
||||||
|
|
@ -144,11 +164,11 @@ def test_tagscript_laat_zich_niet_uitbreiden(su, tmp_path):
|
||||||
inhoud = _draai_tagscript(su, tmp_path, "1.0.0'; touch /tmp/su-inbraak; echo '")
|
inhoud = _draai_tagscript(su, tmp_path, "1.0.0'; touch /tmp/su-inbraak; echo '")
|
||||||
assert not Path("/tmp/su-inbraak").exists(), "de tag brak uit het commando"
|
assert not Path("/tmp/su-inbraak").exists(), "de tag brak uit het commando"
|
||||||
assert inhoud.count("SU_TAG=") == 1
|
assert inhoud.count("SU_TAG=") == 1
|
||||||
|
assert inhoud.count("SU_VERSION=") == 1
|
||||||
|
|
||||||
|
|
||||||
def test_de_helper_zet_de_tag_en_mount_de_werkmap(su, monkeypatch):
|
def test_de_helper_zet_de_tag_en_mount_de_werkmap(su, monkeypatch):
|
||||||
"""Zonder de mount schrijft de helper in zijn eigen overlay, en zonder het
|
"""De helper gebruikt dezelfde projectnaam en bestanden als de container."""
|
||||||
tag-fragment start compose gewoon het oude image opnieuw."""
|
|
||||||
aanroepen = []
|
aanroepen = []
|
||||||
|
|
||||||
def nep_run(cmd, **kw):
|
def nep_run(cmd, **kw):
|
||||||
|
|
@ -156,14 +176,82 @@ def test_de_helper_zet_de_tag_en_mount_de_werkmap(su, monkeypatch):
|
||||||
return type("R", (), {"returncode": 0, "stdout": "", "stderr": ""})()
|
return type("R", (), {"returncode": 0, "stdout": "", "stderr": ""})()
|
||||||
|
|
||||||
monkeypatch.setattr(su.docker, "_run", nep_run)
|
monkeypatch.setattr(su.docker, "_run", nep_run)
|
||||||
su._spawn_helper("git.example.com/bes-r/server-up:0.5.10",
|
su._spawn_helper(
|
||||||
"/opt/server-up", "server-up", "0.5.10")
|
"git.example.com/bes-r/server-up:0.5.10",
|
||||||
|
"/opt/server-up", "server-up", "0.5.10",
|
||||||
|
project="eigen-project",
|
||||||
|
config_files="/opt/server-up/compose.yml,/opt/server-up/extra.yml",
|
||||||
|
)
|
||||||
# De eerste aanroep ruimt een blijven hangen helper op; de tweede is de start.
|
# De eerste aanroep ruimt een blijven hangen helper op; de tweede is de start.
|
||||||
cmd = next(c for c in aanroepen if "run" in c)
|
cmd = next(c for c in aanroepen if "run" in c)
|
||||||
assert "-v" in cmd and "/opt/server-up:/opt/server-up" in cmd
|
assert "-v" in cmd and "/opt/server-up:/opt/server-up" in cmd
|
||||||
script = cmd[-1]
|
script = cmd[-1]
|
||||||
assert "SU_TAG=0.5.10" in script, "de helper zet de tag niet"
|
assert "SU_TAG=0.5.10" in script, "de helper zet de tag niet"
|
||||||
assert "docker compose up -d" in script
|
assert "SU_VERSION=0.5.10" in script, "de helper zet de versie niet"
|
||||||
|
assert "--project-directory /opt/server-up" in script
|
||||||
|
assert "--project-name eigen-project" in script
|
||||||
|
assert "--file /opt/server-up/compose.yml" in script
|
||||||
|
assert "--file /opt/server-up/extra.yml" in script
|
||||||
|
assert "up -d --remove-orphans --no-build --pull never server-up" in script
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_endpoint_normaliseert_release_tag(client, monkeypatch):
|
||||||
|
"""Ook een oudere UI mag :v0.8.13 nooit aan Docker doorgeven."""
|
||||||
|
from core import jobs, selfupdate
|
||||||
|
csrf = login(client)
|
||||||
|
gezien = []
|
||||||
|
monkeypatch.setattr(selfupdate, "status", lambda: {
|
||||||
|
"can_apply": True, "reason": "", "previous_tag": "",
|
||||||
|
})
|
||||||
|
monkeypatch.setattr(
|
||||||
|
selfupdate, "apply",
|
||||||
|
lambda tag, log_fn=None: (gezien.append(tag) or True, "gestart"),
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(jobs, "run", lambda fn, *args: fn(*args))
|
||||||
|
|
||||||
|
r = client.post("/api/update/apply", json={"tag": "v0.8.13-beta"},
|
||||||
|
headers={"X-CSRF-Token": csrf})
|
||||||
|
assert r.status_code == 200
|
||||||
|
assert r.get_json()["tag"] == "0.8.13-beta"
|
||||||
|
assert gezien == ["0.8.13-beta"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_onthoudt_versie_in_plaats_van_beweeglijke_alias(
|
||||||
|
su, env, monkeypatch):
|
||||||
|
_fake_inspect(su, monkeypatch, image="git.example.com/bes-r/server-up:beta",
|
||||||
|
version="0.8.12-beta")
|
||||||
|
monkeypatch.setattr(
|
||||||
|
su, "pull",
|
||||||
|
lambda tag, log_fn=None: (
|
||||||
|
True, "git.example.com/bes-r/server-up:0.8.13-beta"),
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(su, "_spawn_helper", lambda *args, **kw: (True, "ok"))
|
||||||
|
|
||||||
|
ok, _ = su.apply("v0.8.13-beta")
|
||||||
|
assert ok is True
|
||||||
|
opgeslagen = env["core"].load()
|
||||||
|
assert opgeslagen["UPDATE_PREVIOUS_TAG"] == "0.8.12-beta"
|
||||||
|
assert opgeslagen["UPDATE_LAST_APPLIED"]["tag"] == "0.8.13-beta"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("workflow", [
|
||||||
|
".forgejo/workflows/deploy.yml",
|
||||||
|
".forgejo/workflows/deploy-prod.yml",
|
||||||
|
])
|
||||||
|
def test_deploy_schrijft_tag_en_versie_samen(workflow):
|
||||||
|
tekst = (Path(__file__).resolve().parent.parent / workflow).read_text()
|
||||||
|
assert "'/^SU_TAG=/d; /^SU_VERSION=/d'" in tekst
|
||||||
|
assert "SU_TAG=%s\\nSU_VERSION=%s\\n" in tekst
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("workflow,pushregel", [
|
||||||
|
(".forgejo/workflows/build.yml", 'docker push "${IMAGE}:v${VERSION}"'),
|
||||||
|
(".forgejo/workflows/deploy-prod.yml",
|
||||||
|
'docker push "${SU_IMAGE}:v${VERSION}"'),
|
||||||
|
])
|
||||||
|
def test_release_publiceert_tag_voor_oude_updater(workflow, pushregel):
|
||||||
|
tekst = (Path(__file__).resolve().parent.parent / workflow).read_text()
|
||||||
|
assert pushregel in tekst
|
||||||
|
|
||||||
|
|
||||||
def test_rollback_zonder_vorige_versie(su):
|
def test_rollback_zonder_vorige_versie(su):
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ def test_stable_negeert_prereleases(upd):
|
||||||
res = upd.check("0.4.60", force=True)
|
res = upd.check("0.4.60", force=True)
|
||||||
assert res["channel"] == "stable"
|
assert res["channel"] == "stable"
|
||||||
assert res["latest"] == "0.5.00"
|
assert res["latest"] == "0.5.00"
|
||||||
|
assert res["latest_tag"] == "v0.5.00"
|
||||||
|
assert res["image_tag"] == "0.5.00"
|
||||||
assert res["update_available"] is True
|
assert res["update_available"] is True
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -35,6 +37,7 @@ def test_beta_ziet_de_prerelease(upd, env):
|
||||||
res = upd.check("0.5.00", force=True)
|
res = upd.check("0.5.00", force=True)
|
||||||
assert res["channel"] == "beta"
|
assert res["channel"] == "beta"
|
||||||
assert res["latest"] == "0.5.10-beta1"
|
assert res["latest"] == "0.5.10-beta1"
|
||||||
|
assert res["image_tag"] == "0.5.10-beta1"
|
||||||
assert res["update_available"] is True
|
assert res["update_available"] is True
|
||||||
assert res["prerelease"] is True
|
assert res["prerelease"] is True
|
||||||
|
|
||||||
|
|
@ -107,6 +110,18 @@ def test_is_prerelease():
|
||||||
assert updater.is_prerelease("0.5.00") is False
|
assert updater.is_prerelease("0.5.00") is False
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("release_tag,image_tag", [
|
||||||
|
("v0.8.13", "0.8.13"),
|
||||||
|
("v0.8.13-beta", "0.8.13-beta"),
|
||||||
|
("0.8.13", "0.8.13"),
|
||||||
|
("beta", "beta"),
|
||||||
|
])
|
||||||
|
def test_registry_tag_past_bij_de_workflow(release_tag, image_tag):
|
||||||
|
"""Forgejo-tags beginnen met v; de registry-workflow stript die v."""
|
||||||
|
from core import updater
|
||||||
|
assert updater.image_tag(release_tag) == image_tag
|
||||||
|
|
||||||
|
|
||||||
def test_ongeldig_kanaal_wordt_geweigerd(client):
|
def test_ongeldig_kanaal_wordt_geweigerd(client):
|
||||||
from conftest import login
|
from conftest import login
|
||||||
csrf = login(client)
|
csrf = login(client)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue