Merge #37: Update brach ohne Meldung ab
Abgeschnittene Leitungen unter pipefail beendeten update.sh stumm und haetten die Selbstpruefung der Sicherung falsch negativ gemacht. Behoben, mit ERR-Falle und Test gegen das Muster.
This commit was merged in pull request #37.
This commit is contained in:
+47
-1
@@ -26,6 +26,51 @@ Wiederherstellung*.
|
|||||||
|
|
||||||
_Noch nichts._
|
_Noch nichts._
|
||||||
|
|
||||||
|
## [1.10.2] – 2026-08-24
|
||||||
|
|
||||||
|
### Behoben
|
||||||
|
|
||||||
|
- **Das Update brach ohne Meldung ab.** Beim Sprung von 1.5.0 auf 1.10.1
|
||||||
|
endete `scripts/update.sh` mitten in der Ausgabe — kein Fehler, keine
|
||||||
|
Zeile, einfach zurück zur Eingabeaufforderung. Ursache war eine
|
||||||
|
abgeschnittene Leitung:
|
||||||
|
|
||||||
|
```
|
||||||
|
git log --oneline "HEAD..$ZIEL" | head -15 | sed ...
|
||||||
|
```
|
||||||
|
|
||||||
|
`head` schließt die Leitung nach 15 Zeilen, `git log` schreibt weiter
|
||||||
|
und bekommt SIGPIPE. Weil das Skript mit `set -o pipefail` und
|
||||||
|
`set -e` läuft, gilt die ganze Kette als gescheitert und das Skript
|
||||||
|
beendet sich — stumm.
|
||||||
|
|
||||||
|
Das ist zeitabhängig und deshalb monatelang nicht aufgefallen: Solange
|
||||||
|
`git log` fertig war, bevor `head` zumachte, ging alles gut. Genau bei
|
||||||
|
1.10.0 lagen zum ersten Mal **mehr als 15 Commits** dazwischen.
|
||||||
|
|
||||||
|
- **Dieselbe Falle in der Selbstprüfung der Sicherung.** `sicherung.sh`
|
||||||
|
prüfte mit `openssl … | head -c 5 | grep -q "PGDMP"`, ob sich die
|
||||||
|
frische Sicherung wieder entschlüsseln lässt. Bei kleiner Datenbank
|
||||||
|
ging das gut, weil alles im Puffer stand. Mit wachsender Datenbank
|
||||||
|
hätte es gekippt — und dann hätte das Skript eine **völlig intakte
|
||||||
|
Sicherung als kaputt gemeldet** und das Update verweigert.
|
||||||
|
|
||||||
|
### Geändert
|
||||||
|
|
||||||
|
- **Ein stummer Abbruch ist nicht mehr möglich.** `update.sh` meldet
|
||||||
|
jetzt bei jedem unerwarteten Ende die Zeilennummer und den Exitcode,
|
||||||
|
und erklärt bei 141 ausdrücklich, dass es sich um SIGPIPE handelt und
|
||||||
|
um einen Fehler im Skript, nicht um einen Bedienfehler.
|
||||||
|
- Stehen mehr als 15 Commits an, steht jetzt „… und N weitere" darunter,
|
||||||
|
statt sie wortlos wegzulassen.
|
||||||
|
|
||||||
|
### Geprüft
|
||||||
|
|
||||||
|
- Ein Test verbietet das Muster künftig in allen Betriebsskripten:
|
||||||
|
Wer wieder `| head` in eine Leitung schreibt, bekommt die Zeilennummer
|
||||||
|
genannt. Gegenprobe gemacht — der Test schlägt an.
|
||||||
|
- Der Ablauf von 1.5.0 auf 1.10.1 einmal nachgestellt: läuft durch.
|
||||||
|
|
||||||
## [1.10.1] – 2026-08-23
|
## [1.10.1] – 2026-08-23
|
||||||
|
|
||||||
### Geändert
|
### Geändert
|
||||||
@@ -1126,7 +1171,8 @@ Was davon wann angegangen wird, steht in [`docs/ROADMAP.md`](docs/ROADMAP.md).
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[Unveröffentlicht]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.10.1...HEAD
|
[Unveröffentlicht]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.10.2...HEAD
|
||||||
|
[1.10.2]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.10.1...v1.10.2
|
||||||
[1.10.1]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.10.0...v1.10.1
|
[1.10.1]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.10.0...v1.10.1
|
||||||
[1.10.0]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.9.0...v1.10.0
|
[1.10.0]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.9.0...v1.10.0
|
||||||
[1.9.0]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.8.0...v1.9.0
|
[1.9.0]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.8.0...v1.9.0
|
||||||
|
|||||||
@@ -131,14 +131,14 @@ cd /opt/betreuungs-cockpit
|
|||||||
|
|
||||||
# Auf die letzte veröffentlichte Fassung wechseln,
|
# Auf die letzte veröffentlichte Fassung wechseln,
|
||||||
# nicht auf den laufenden Entwicklungsstand
|
# nicht auf den laufenden Entwicklungsstand
|
||||||
git checkout v1.10.1
|
git checkout v1.10.2
|
||||||
```
|
```
|
||||||
|
|
||||||
### Kontrolle
|
### Kontrolle
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ls docker-compose.yml Dockerfile .env.example # alle drei da
|
ls docker-compose.yml Dockerfile .env.example # alle drei da
|
||||||
git describe --tags # v1.10.1
|
git describe --tags # v1.10.2
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -299,7 +299,7 @@ betreuungs-cockpit-sicherung-1 Up
|
|||||||
```bash
|
```bash
|
||||||
# Antwortet die Anwendung? (Port anpassen, falls du APP_PORT gesetzt hast)
|
# Antwortet die Anwendung? (Port anpassen, falls du APP_PORT gesetzt hast)
|
||||||
curl -s http://127.0.0.1:3000/api/gesundheit
|
curl -s http://127.0.0.1:3000/api/gesundheit
|
||||||
# {"status":"bereit","version":"1.10.1","commit":"..."}
|
# {"status":"bereit","version":"1.10.2","commit":"..."}
|
||||||
```
|
```
|
||||||
|
|
||||||
Kommt hier nichts, sieh in die Logs:
|
Kommt hier nichts, sieh in die Logs:
|
||||||
@@ -649,7 +649,7 @@ Erst **vom Proxy-Server aus** — kommt er überhaupt an?
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s http://10.0.0.5:3000/api/gesundheit
|
curl -s http://10.0.0.5:3000/api/gesundheit
|
||||||
# {"status":"bereit","version":"1.10.1",...}
|
# {"status":"bereit","version":"1.10.2",...}
|
||||||
```
|
```
|
||||||
|
|
||||||
Kommt hier nichts, liegt es an 7a: falsche `APP_BIND`, Firewall, oder der
|
Kommt hier nichts, liegt es an 7a: falsche `APP_BIND`, Firewall, oder der
|
||||||
@@ -700,7 +700,7 @@ Zum Schluss: **Fristen → Pflichtfristen ableiten**.
|
|||||||
- Du kommst mit E-Mail, Passwort und dem Code aus der App herein.
|
- Du kommst mit E-Mail, Passwort und dem Code aus der App herein.
|
||||||
- Unter **Fristen** stehen Einträge mit Paragraphenbezug.
|
- Unter **Fristen** stehen Einträge mit Paragraphenbezug.
|
||||||
- Unter **Protokoll** siehst du deine eigene Anmeldung.
|
- Unter **Protokoll** siehst du deine eigene Anmeldung.
|
||||||
- Unten links in der Seitenleiste steht `Version 1.10.1 · <commit>`.
|
- Unten links in der Seitenleiste steht `Version 1.10.2 · <commit>`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -875,7 +875,7 @@ alles so vor wie zuvor.
|
|||||||
| Aufruf | Wirkung |
|
| Aufruf | Wirkung |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `./scripts/update.sh` | auf die neueste veröffentlichte Fassung |
|
| `./scripts/update.sh` | auf die neueste veröffentlichte Fassung |
|
||||||
| `./scripts/update.sh v1.10.1` | auf eine bestimmte Fassung |
|
| `./scripts/update.sh v1.10.2` | auf eine bestimmte Fassung |
|
||||||
| `./scripts/update.sh --pruefen` | nur nachsehen, nichts ändern |
|
| `./scripts/update.sh --pruefen` | nur nachsehen, nichts ändern |
|
||||||
| `./scripts/update.sh --ja` | ohne Rückfrage (für cron) |
|
| `./scripts/update.sh --ja` | ohne Rückfrage (für cron) |
|
||||||
| `./scripts/update.sh --verwerfen` | eigene Änderungen wegwerfen statt beiseitelegen |
|
| `./scripts/update.sh --verwerfen` | eigene Änderungen wegwerfen statt beiseitelegen |
|
||||||
@@ -913,7 +913,7 @@ git fetch --tags
|
|||||||
git log --oneline HEAD..origin/main
|
git log --oneline HEAD..origin/main
|
||||||
|
|
||||||
# 3. Umschalten
|
# 3. Umschalten
|
||||||
git checkout v1.10.1
|
git checkout v1.10.2
|
||||||
|
|
||||||
# 4. Neu bauen und starten
|
# 4. Neu bauen und starten
|
||||||
GIT_COMMIT=$(git rev-parse --short HEAD) BUILD_ZEIT=$(date -Iseconds) docker compose up -d --build
|
GIT_COMMIT=$(git rev-parse --short HEAD) BUILD_ZEIT=$(date -Iseconds) docker compose up -d --build
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ Zeit spart. Er steht weit unten, wenn er nur schön wäre.
|
|||||||
Diese Datei ist eine Absichtserklärung, kein Vertrag. Was sich im Betrieb
|
Diese Datei ist eine Absichtserklärung, kein Vertrag. Was sich im Betrieb
|
||||||
als wichtiger herausstellt, rutscht nach oben.
|
als wichtiger herausstellt, rutscht nach oben.
|
||||||
|
|
||||||
Stand: 23.08.2026 · Aktuelle Fassung: **1.10.1** ([CHANGELOG](../CHANGELOG.md))
|
Stand: 23.08.2026 · Aktuelle Fassung: **1.10.2** ([CHANGELOG](../CHANGELOG.md))
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "betreuungs-cockpit",
|
"name": "betreuungs-cockpit",
|
||||||
"version": "1.10.1",
|
"version": "1.10.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Arbeits- und Dokumentationswerkzeug fuer die ehrenamtliche rechtliche Betreuung",
|
"description": "Arbeits- und Dokumentationswerkzeug fuer die ehrenamtliche rechtliche Betreuung",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
+13
-3
@@ -75,9 +75,19 @@ done
|
|||||||
# --- Selbstpruefung ----------------------------------------------------------
|
# --- Selbstpruefung ----------------------------------------------------------
|
||||||
# Ein Backup, das sich nicht entschluesseln laesst, ist kein Backup.
|
# Ein Backup, das sich nicht entschluesseln laesst, ist kein Backup.
|
||||||
# Deshalb wird sofort geprueft, ob die Datei wieder lesbar ist.
|
# Deshalb wird sofort geprueft, ob die Datei wieder lesbar ist.
|
||||||
if openssl enc -d -aes-256-cbc -pbkdf2 -iter 200000 \
|
# Kein "| head -c 5 | grep -q": Beide schliessen die Leitung, sobald sie
|
||||||
-pass env:SICHERUNG_PASSWORT -in "$DATEI" 2>/dev/null \
|
# genug haben. openssl schreibt dann in ein geschlossenes Rohr, bekommt
|
||||||
| head -c 5 | grep -q "PGDMP"; then
|
# SIGPIPE - und mit "set -o pipefail" gilt die ganze Kette als
|
||||||
|
# gescheitert. Bei einer kleinen Datenbank faellt das nicht auf, weil
|
||||||
|
# alles schon im Puffer steht; mit wachsender Datenbank kippt es, und
|
||||||
|
# dann meldet die Selbstpruefung eine INTAKTE Sicherung als kaputt.
|
||||||
|
#
|
||||||
|
# "dd" liest eine feste Menge und beendet sich regulaer.
|
||||||
|
KOPF="$(openssl enc -d -aes-256-cbc -pbkdf2 -iter 200000 \
|
||||||
|
-pass env:SICHERUNG_PASSWORT -in "$DATEI" 2>/dev/null \
|
||||||
|
| dd bs=1 count=5 2>/dev/null || true)"
|
||||||
|
|
||||||
|
if [ "$KOPF" = "PGDMP" ]; then
|
||||||
echo "$(date -Iseconds) Selbstpruefung bestanden."
|
echo "$(date -Iseconds) Selbstpruefung bestanden."
|
||||||
else
|
else
|
||||||
echo "$(date -Iseconds) FEHLER: Die Sicherung laesst sich nicht entschluesseln!" >&2
|
echo "$(date -Iseconds) FEHLER: Die Sicherung laesst sich nicht entschluesseln!" >&2
|
||||||
|
|||||||
+45
-5
@@ -52,6 +52,32 @@ gut() { printf ' %s%s%s\n' "$GRUEN" "$1" "$AUS"; }
|
|||||||
warnung() { printf ' %s%s%s\n' "$GELB" "$1" "$AUS"; }
|
warnung() { printf ' %s%s%s\n' "$GELB" "$1" "$AUS"; }
|
||||||
abbruch() { printf '\n%sAbbruch: %s%s\n\n' "$ROT" "$1" "$AUS" >&2; exit 1; }
|
abbruch() { printf '\n%sAbbruch: %s%s\n\n' "$ROT" "$1" "$AUS" >&2; exit 1; }
|
||||||
|
|
||||||
|
# --- Unerwarteter Abbruch ----------------------------------------------------
|
||||||
|
#
|
||||||
|
# "set -e" beendet das Skript bei jedem Befehl, der nicht 0 zurueckgibt -
|
||||||
|
# stumm. Auf dem Bildschirm bricht die Ausgabe dann einfach ab, und man
|
||||||
|
# sucht an der falschen Stelle.
|
||||||
|
#
|
||||||
|
# Genau das ist beim Sprung von v1.5.0 auf v1.10.1 passiert: Eine Leitung
|
||||||
|
# der Form "git log ... | head -15" hat den Erzeuger mit SIGPIPE beendet,
|
||||||
|
# "pipefail" hat das an die Kette weitergereicht, und das Skript war weg.
|
||||||
|
#
|
||||||
|
# Diese Falle sagt jetzt wenigstens, WO es passiert ist. Exitcode 141
|
||||||
|
# heisst SIGPIPE - dann wurde irgendwo wieder eine Leitung zu frueh
|
||||||
|
# geschlossen.
|
||||||
|
unerwartet() {
|
||||||
|
code=$1
|
||||||
|
zeile=$2
|
||||||
|
printf '%sAbbruch in Zeile %s (Exitcode %s).%s\n' "$ROT" "$zeile" "$code" "$AUS" >&2
|
||||||
|
if [ "$code" = "141" ]; then
|
||||||
|
printf '%sExitcode 141 ist SIGPIPE: eine Leitung wurde zu frueh geschlossen,%s\n' "$ROT" "$AUS" >&2
|
||||||
|
printf '%setwa durch "| head". Das ist ein Fehler im Skript, nicht bei dir.%s\n' "$ROT" "$AUS" >&2
|
||||||
|
fi
|
||||||
|
printf '%sKam der Abbruch vor Schritt 5, wurde nichts veraendert.%s\n' "$ROT" "$AUS" >&2
|
||||||
|
}
|
||||||
|
trap 'unerwartet $? $LINENO' ERR
|
||||||
|
|
||||||
|
|
||||||
# --- Aufrufparameter ---------------------------------------------------------
|
# --- Aufrufparameter ---------------------------------------------------------
|
||||||
|
|
||||||
ZIEL=""
|
ZIEL=""
|
||||||
@@ -113,7 +139,11 @@ if ! git fetch --tags --quiet origin; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
JETZT="$(git describe --tags --exact-match 2>/dev/null || git rev-parse --short HEAD)"
|
JETZT="$(git describe --tags --exact-match 2>/dev/null || git rev-parse --short HEAD)"
|
||||||
NEUESTE="$(git tag --list 'v*' --sort=-v:refname | head -1)"
|
# Kein "| head -1": Siehe den Hinweis zu SIGPIPE weiter unten. Die erste
|
||||||
|
# Zeile holt die Shell selbst.
|
||||||
|
ALLE_TAGS="$(git tag --list 'v*' --sort=-v:refname)"
|
||||||
|
NEUESTE="${ALLE_TAGS%%$'
|
||||||
|
'*}"
|
||||||
|
|
||||||
[ -n "$NEUESTE" ] || abbruch "Es gibt keine veroeffentlichte Fassung (kein Tag)."
|
[ -n "$NEUESTE" ] || abbruch "Es gibt keine veroeffentlichte Fassung (kein Tag)."
|
||||||
|
|
||||||
@@ -123,7 +153,8 @@ fi
|
|||||||
|
|
||||||
git rev-parse --verify --quiet "$ZIEL^{commit}" >/dev/null \
|
git rev-parse --verify --quiet "$ZIEL^{commit}" >/dev/null \
|
||||||
|| abbruch "Die Fassung '$ZIEL' gibt es nicht. Vorhanden:
|
|| abbruch "Die Fassung '$ZIEL' gibt es nicht. Vorhanden:
|
||||||
$(git tag --list 'v*' --sort=-v:refname | head -5 | sed 's/^/ /')"
|
$(printf '%s
|
||||||
|
' "$ALLE_TAGS" | sed -n '1,5p' | sed 's/^/ /')"
|
||||||
|
|
||||||
printf ' Jetzt: %s\n' "$JETZT"
|
printf ' Jetzt: %s\n' "$JETZT"
|
||||||
printf ' Ziel: %s%s%s\n' "$FETT" "$ZIEL" "$AUS"
|
printf ' Ziel: %s%s%s\n' "$FETT" "$ZIEL" "$AUS"
|
||||||
@@ -152,14 +183,23 @@ if [ -n "$CHANGELOG" ]; then
|
|||||||
if (nummer == jetzt) exit
|
if (nummer == jetzt) exit
|
||||||
drucken = (nummer != "Unveröffentlicht")
|
drucken = (nummer != "Unveröffentlicht")
|
||||||
}
|
}
|
||||||
drucken { print " " $0 }
|
drucken && zeilen < 60 { print " " $0; zeilen++ }
|
||||||
' | head -60
|
'
|
||||||
else
|
else
|
||||||
warnung "Kein CHANGELOG.md in $ZIEL gefunden."
|
warnung "Kein CHANGELOG.md in $ZIEL gefunden."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf '\n'
|
printf '\n'
|
||||||
git log --oneline --no-decorate "HEAD..$ZIEL" | head -15 | sed 's/^/ /'
|
# "-15" statt "| head -15": Bei mehr Commits als der Grenze schliesst head
|
||||||
|
# die Leitung, git bekommt SIGPIPE, und mit "set -o pipefail" gilt die ganze
|
||||||
|
# Kette als gescheitert - "set -e" beendet das Skript dann OHNE Meldung.
|
||||||
|
# Genau das ist beim Sprung von v1.5.0 auf v1.10.1 passiert.
|
||||||
|
ANZAHL="$(git rev-list --count "HEAD..$ZIEL")"
|
||||||
|
git log --oneline --no-decorate -15 "HEAD..$ZIEL" | sed 's/^/ /'
|
||||||
|
if [ "$ANZAHL" -gt 15 ]; then
|
||||||
|
printf ' ... und %s weitere
|
||||||
|
' "$((ANZAHL - 15))"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$NUR_PRUEFEN" = "1" ]; then
|
if [ "$NUR_PRUEFEN" = "1" ]; then
|
||||||
printf '\n'
|
printf '\n'
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/** Muss zur "version" in der package.json passen. */
|
/** Muss zur "version" in der package.json passen. */
|
||||||
export const VERSION = '1.10.1'
|
export const VERSION = '1.10.2'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kurzer Git-Stand, beim Bauen hineingereicht:
|
* Kurzer Git-Stand, beim Bauen hineingereicht:
|
||||||
|
|||||||
@@ -85,3 +85,50 @@ describe.skipIf(!mitGit)('Betriebsskripte', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abschneidende Leitungen in Skripten mit "pipefail".
|
||||||
|
*
|
||||||
|
* Anlass ist ein Abbruch im Betrieb: Beim Sprung von v1.5.0 auf v1.10.1
|
||||||
|
* endete update.sh mitten in der Ausgabe, ohne jede Meldung. Ursache war
|
||||||
|
*
|
||||||
|
* git log --oneline "HEAD..$ZIEL" | head -15 | sed ...
|
||||||
|
*
|
||||||
|
* "head" schliesst die Leitung nach 15 Zeilen, "git log" schreibt weiter
|
||||||
|
* und bekommt SIGPIPE (Exitcode 141). Mit "set -o pipefail" gilt die
|
||||||
|
* ganze Kette als gescheitert, "set -e" beendet das Skript - stumm.
|
||||||
|
*
|
||||||
|
* Es ist zeitabhaengig: Solange der Erzeuger fertig wird, bevor "head"
|
||||||
|
* zumacht, faellt nichts auf. Deshalb lief es monatelang gut und riss
|
||||||
|
* genau dann, als zum ersten Mal mehr als 15 Commits dazwischenlagen.
|
||||||
|
*
|
||||||
|
* Dieselbe Falle steckte in der Selbstpruefung der Sicherung, wo sie
|
||||||
|
* eine intakte Sicherung als kaputt gemeldet haette, sobald die
|
||||||
|
* Datenbank gross genug ist.
|
||||||
|
*
|
||||||
|
* Der Test verbietet das Muster deshalb ganz. Wer eine Ausgabe kuerzen
|
||||||
|
* will, nimmt "git log -15", "sed -n '1,15p'" oder einen Zaehler in awk -
|
||||||
|
* alles drei liest bis zum Ende und schliesst nichts zu frueh.
|
||||||
|
*/
|
||||||
|
describe('Skripte mit pipefail', () => {
|
||||||
|
const skripte = ['scripts/update.sh', 'scripts/sicherung.sh', 'scripts/wiederherstellung.sh']
|
||||||
|
|
||||||
|
it.each(skripte)('%s schneidet keine Leitung mit head ab', (pfad) => {
|
||||||
|
const inhalt = readFileSync(pfad, 'utf8')
|
||||||
|
if (!/set -[a-z]*o pipefail|set -o pipefail/.test(inhalt)) return
|
||||||
|
|
||||||
|
const treffer = inhalt
|
||||||
|
.split('\n')
|
||||||
|
.map((zeile, nummer) => ({ zeile, nummer: nummer + 1 }))
|
||||||
|
// Kommentarzeilen erklaeren das Muster gerade - sie sind erlaubt.
|
||||||
|
.filter(({ zeile }) => !zeile.trim().startsWith('#'))
|
||||||
|
.filter(({ zeile }) => !zeile.includes('printf'))
|
||||||
|
.filter(({ zeile }) => /\|\s*head\b/.test(zeile))
|
||||||
|
|
||||||
|
expect(
|
||||||
|
treffer.map((t) => `Zeile ${t.nummer}: ${t.zeile.trim()}`),
|
||||||
|
'Abschneidende Leitung: der Erzeuger bekommt SIGPIPE, pipefail reicht ' +
|
||||||
|
'es weiter, set -e beendet das Skript stumm.',
|
||||||
|
).toEqual([])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user