release: 0.107.1 (improvement/gate-timing)

This commit is contained in:
2026-10-16 00:45:45 +02:00
8 changed files with 90 additions and 19 deletions
+6
View File
@@ -7,6 +7,12 @@ edit the release notes and re-run the generator.
Upgrading, pinning a version and rolling back: [docs/self-hosting.md](docs/self-hosting.md#upgrading).
## 0.107.1 — 2026-10-16
### Fixed
- Downloads: a failed download's explanation now says to press Retry, instead of pointing to a download list that no longer exists.
## 0.107.0 — 2026-10-15
### New
+1 -1
View File
@@ -1 +1 @@
0.107.0
0.107.1
@@ -1,4 +1,12 @@
[
{
"version": "0.107.1",
"date": "2026-10-16",
"new": [],
"fixed": [
"Downloads: a failed download's explanation now says to press Retry, instead of pointing to a download list that no longer exists."
]
},
{
"version": "0.107.0",
"date": "2026-10-15",
@@ -1,4 +1,12 @@
[
{
"version": "0.107.1",
"date": "2026-10-16",
"new": [],
"fixed": [
"Letöltés: egy sikertelen letöltés magyarázata most az Újra gombot mondja, nem egy már nem létező letöltési listát."
]
},
{
"version": "0.107.0",
"date": "2026-10-15",
+5 -5
View File
@@ -316,11 +316,11 @@
"facebook": {
"login_wall": {
"short": "Facebook sign-in required",
"body": "Facebook only shows this to signed-in users (e.g. 18+ content or a closed group). Add your Facebook cookies under Settings → Account → Download authentication, then retry the download from the list."
"body": "Facebook only shows this to signed-in users (e.g. 18+ content or a closed group). Add your Facebook cookies under Settings → Account → Download authentication, then press Retry."
},
"cookie_rejected": {
"short": "Facebook didn't accept the cookies",
"body": "The cookies have probably expired, or you signed out in that browser. Export them again, paste them in under Settings → Account → Download authentication, then retry the download from the list. If it still fails, the content has been removed or isn't visible to you."
"body": "The cookies have probably expired, or you signed out in that browser. Export them again, paste them in under Settings → Account → Download authentication, then press Retry. If it still fails, the content has been removed or isn't visible to you."
},
"group_post_video": {
"short": "No video found in this post",
@@ -330,15 +330,15 @@
"youtube": {
"bot_wall": {
"short": "YouTube sign-in required",
"body": "YouTube only serves this video to a signed-in viewer — it asks the downloader to confirm it isn't a bot. Other YouTube videos are usually unaffected. Add your YouTube cookies under Settings → Account → Download authentication, then retry the download from the list."
"body": "YouTube only serves this video to a signed-in viewer — it asks the downloader to confirm it isn't a bot. Other YouTube videos are usually unaffected. Add your YouTube cookies under Settings → Account → Download authentication, then press Retry."
},
"cookie_rejected": {
"short": "YouTube didn't accept the cookies",
"body": "YouTube rotates exported cookies as a security measure, so yours have probably expired. Export them again from a private browsing window, close that window without browsing on, paste them in under Settings → Account → Download authentication, then retry the download from the list."
"body": "YouTube rotates exported cookies as a security measure, so yours have probably expired. Export them again from a private browsing window, close that window without browsing on, paste them in under Settings → Account → Download authentication, then press Retry."
},
"media_forbidden": {
"short": "YouTube refused the video stream",
"body": "YouTube found the video but refused to send the file to a signed-out download. It comes and goes, so a retry from the list is worth one try — and adding your YouTube cookies under Settings → Account → Download authentication is what gets a stubborn one through."
"body": "YouTube found the video but refused to send the file to a signed-out download. It comes and goes, so pressing Retry once is worth it — and adding your YouTube cookies under Settings → Account → Download authentication is what gets a stubborn one through."
}
}
}
+5 -5
View File
@@ -316,11 +316,11 @@
"facebook": {
"login_wall": {
"short": "Facebook-bejelentkezés szükséges",
"body": "A Facebook ezt csak bejelentkezve mutatja (pl. 18+ tartalom vagy zárt csoport). Illeszd be a Facebook-cookie-kat a Beállítások → Fiók → Letöltés-hitelesítés alatt, majd a listában indítsd újra a letöltést."
"body": "A Facebook ezt csak bejelentkezve mutatja (pl. 18+ tartalom vagy zárt csoport). Illeszd be a Facebook-cookie-kat a Beállítások → Fiók → Letöltés-hitelesítés alatt, majd nyomd meg az Újra gombot."
},
"cookie_rejected": {
"short": "A Facebook nem fogadta el a cookie-kat",
"body": "A cookie-k valószínűleg lejártak, vagy kijelentkeztél abban a böngészőben. Exportáld újra őket, illeszd be a Beállítások → Fiók → Letöltés-hitelesítés alatt, majd a listában indítsd újra a letöltést. Ha így sem megy, a tartalmat törölték, vagy nem látható számodra."
"body": "A cookie-k valószínűleg lejártak, vagy kijelentkeztél abban a böngészőben. Exportáld újra őket, illeszd be a Beállítások → Fiók → Letöltés-hitelesítés alatt, majd nyomd meg az Újra gombot. Ha így sem megy, a tartalmat törölték, vagy nem látható számodra."
},
"group_post_video": {
"short": "Ebben a posztban nem található videó",
@@ -330,15 +330,15 @@
"youtube": {
"bot_wall": {
"short": "YouTube-bejelentkezés szükséges",
"body": "A YouTube ezt a videót csak bejelentkezett nézőnek adja ki — a letöltőprogramtól azt kéri, igazolja, hogy nem robot. A többi YouTube-videót ez általában nem érinti. Illeszd be a YouTube-cookie-kat a Beállítások → Fiók → Letöltés-hitelesítés alatt, majd a listában indítsd újra a letöltést."
"body": "A YouTube ezt a videót csak bejelentkezett nézőnek adja ki — a letöltőprogramtól azt kéri, igazolja, hogy nem robot. A többi YouTube-videót ez általában nem érinti. Illeszd be a YouTube-cookie-kat a Beállítások → Fiók → Letöltés-hitelesítés alatt, majd nyomd meg az Újra gombot."
},
"cookie_rejected": {
"short": "A YouTube nem fogadta el a cookie-kat",
"body": "A YouTube biztonsági okból lecseréli az exportált cookie-kat, ezért a tiéid valószínűleg lejártak. Exportáld őket újra egy privát böngészőablakból, majd zárd be azt az ablakot további böngészés nélkül, illeszd be a Beállítások → Fiók → Letöltés-hitelesítés alatt, majd a listában indítsd újra a letöltést."
"body": "A YouTube biztonsági okból lecseréli az exportált cookie-kat, ezért a tiéid valószínűleg lejártak. Exportáld őket újra egy privát böngészőablakból, majd zárd be azt az ablakot további böngészés nélkül, illeszd be a Beállítások → Fiók → Letöltés-hitelesítés alatt, majd nyomd meg az Újra gombot."
},
"media_forbidden": {
"short": "A YouTube nem adta ki a videófájlt",
"body": "A YouTube visszaadta a videó adatait, de a fájlt már nem adta ki bejelentkezés nélkül. Ez hol van, hol nincs, ezért érdemes újrapróbálni a listából — a makacs eseteken pedig a YouTube-cookie-k segítenek, a Beállítások → Fiók → Letöltés-hitelesítés alatt."
"body": "A YouTube visszaadta a videó adatait, de a fájlt már nem adta ki bejelentkezés nélkül. Ez hol van, hol nincs, ezért érdemes egyszer megnyomni az Újra gombot — a makacs eseteken pedig a YouTube-cookie-k segítenek, a Beállítások → Fiók → Letöltés-hitelesítés alatt."
}
}
}
+26 -4
View File
@@ -1307,21 +1307,39 @@
"export MSYS_NO_PATHCONV=1 # Git Bash: do not rewrite the in-container paths below",
"TESTCOMPOSE=backend/docker-compose.test.yml",
"failed=()",
"timings=()",
"ms() { date +%s%3N; }",
"secs() { awk -v t=\"$1\" 'BEGIN { printf \"%.1f\", t / 1000 }'; }",
"took=\"\"",
"timed() { # timed <name> <ok|red> <start-ms> — sets $took (no subshell: it must add to $timings)",
" took=\"$(secs $(($(ms) - $3)))\"",
" timings+=(\"$(printf '%8s s %s' \"$took\" \"$1\")$([ \"$2\" = red ] && echo ' (red)')\")",
" if [ -n \"${GATE_TIMES_FILE:-}\" ]; then",
" printf '%s\\t%s\\t%s\\t%s\\t%s\\t%s\\n' \"$(date -u +%FT%TZ)\" \"$mode\" \"$1\" \"$took\" \"$2\" \\",
" \"$(git rev-parse --short 'HEAD^{tree}' 2>/dev/null)\" >>\"$GATE_TIMES_FILE\"",
" fi",
" return 0",
"}",
"lane() { # lane <name> <command…> — run it, remember a failure, never stop",
" local name=\"$1\"",
" local name=\"$1\" t0 result=ok",
" shift",
" t0=\"$(ms)\"",
" if [ \"$brief\" = 0 ]; then",
" echo \">> $name…\"",
" \"$@\" || failed+=(\"$name\")",
" \"$@\" || { failed+=(\"$name\"); result=red; }",
" timed \"$name\" \"$result\" \"$t0\"",
" echo \"<< $name: $took s\"",
" return 0",
" fi",
" local out",
" out=\"$(mktemp)\"",
" if \"$@\" >\"$out\" 2>&1; then",
" echo \">> $name: ok\"",
" timed \"$name\" ok \"$t0\"",
" echo \">> $name: ok ($took s)\"",
" else",
" failed+=(\"$name\")",
" echo \">> $name: FAILED\"",
" timed \"$name\" red \"$t0\"",
" echo \">> $name: FAILED ($took s)\"",
" brief_excerpt \"$out\"",
" fi",
" rm -f \"$out\"",
@@ -1361,6 +1379,7 @@
" return 1",
"}",
"frontend() { (cd frontend && \"$@\"); }",
"gate_t0=\"$(ms)\"",
"lane \"ruff\" ruff_check",
"lane \"ruff format --check\" ruff_format",
"lane \"basedpyright (new errors only)\" basedpyright",
@@ -1387,6 +1406,9 @@
" lane \"pip-audit (backend lock)\" pip_audit",
" lane \"npm audit (production dependencies)\" frontend npm audit --omit=dev --audit-level=high",
"fi",
"echo \">> lane times:\"",
"printf '%s\\n' \"${timings[@]}\"",
"echo \"$(printf '%8s' \"$(secs $(($(ms) - gate_t0)))\") s total\"",
"if [ ${#failed[@]} -eq 0 ]; then",
" echo \">> gate ($mode): green ✓\"",
" exit 0",
+31 -4
View File
@@ -9,6 +9,8 @@
# bash scripts/check.sh lint the static lanes only: no tests, no build, no audits
# … --brief (either mode) a lane's output only when it fails, and only its first
# error lines — for an agent, whose context the full log would flood
# GATE_TIMES_FILE=<file> … also append each lane's time as a TSV row (UTC, mode, lane, seconds,
# ok|red, HEAD's tree) — to compare runs; every run prints the times anyway
#
# Each lane runs even when an earlier one failed, and the summary names every red one: a gate that
# stops at the first failure hides the second until the first is fixed. The backend lanes run in the
@@ -29,21 +31,42 @@ done
export MSYS_NO_PATHCONV=1 # Git Bash: do not rewrite the in-container paths below
TESTCOMPOSE=backend/docker-compose.test.yml
failed=()
timings=()
ms() { date +%s%3N; }
secs() { awk -v t="$1" 'BEGIN { printf "%.1f", t / 1000 }'; }
# How long each lane took: a line after the lane, a table at the end, and — when GATE_TIMES_FILE names a
# file — one tab-separated row per lane appended to it (UTC time, mode, lane, seconds, ok|red, tree), so
# runs can be compared. The script writes no file unless asked to.
took=""
timed() { # timed <name> <ok|red> <start-ms> — sets $took (no subshell: it must add to $timings)
took="$(secs $(($(ms) - $3)))"
timings+=("$(printf '%8s s %s' "$took" "$1")$([ "$2" = red ] && echo ' (red)')")
if [ -n "${GATE_TIMES_FILE:-}" ]; then
printf '%s\t%s\t%s\t%s\t%s\t%s\n' "$(date -u +%FT%TZ)" "$mode" "$1" "$took" "$2" \
"$(git rev-parse --short 'HEAD^{tree}' 2>/dev/null)" >>"$GATE_TIMES_FILE"
fi
return 0
}
lane() { # lane <name> <command…> — run it, remember a failure, never stop
local name="$1"
local name="$1" t0 result=ok
shift
t0="$(ms)"
if [ "$brief" = 0 ]; then
echo ">> $name…"
"$@" || failed+=("$name")
"$@" || { failed+=("$name"); result=red; }
timed "$name" "$result" "$t0"
echo "<< $name: $took s"
return 0
fi
local out
out="$(mktemp)"
if "$@" >"$out" 2>&1; then
echo ">> $name: ok"
timed "$name" ok "$t0"
echo ">> $name: ok ($took s)"
else
failed+=("$name")
echo ">> $name: FAILED"
timed "$name" red "$t0"
echo ">> $name: FAILED ($took s)"
brief_excerpt "$out"
fi
rm -f "$out"
@@ -102,6 +125,7 @@ basedpyright() {
frontend() { (cd frontend && "$@"); }
gate_t0="$(ms)"
lane "ruff" ruff_check
lane "ruff format --check" ruff_format
lane "basedpyright (new errors only)" basedpyright
@@ -139,6 +163,9 @@ if [ "$mode" = all ]; then
lane "npm audit (production dependencies)" frontend npm audit --omit=dev --audit-level=high
fi
echo ">> lane times:"
printf '%s\n' "${timings[@]}"
echo "$(printf '%8s' "$(secs $(($(ms) - gate_t0)))") s total"
if [ ${#failed[@]} -eq 0 ]; then
echo ">> gate ($mode): green ✓"
exit 0