Die Anleitung sagt "./scripts/update.sh" - auf Linux kam dort "Permission denied". Die drei .sh-Dateien lagen mit Modus 644 statt 755 im Index. Ursache ist der Entwicklungsrechner: Unter Windows steht core.filemode=false, git nimmt ein fehlendes Ausfuehrungsrecht dort gar nicht wahr. Gemeldet hat es der Betrieb, nicht der Bau. Wer von 1.1.0 oder aelter kommt, braucht einmalig "bash scripts/update.sh" - das alte Skript ist ja noch das nicht ausfuehrbare. Steht jetzt in README und Installationsanleitung. Zusaetzlich setzt update.sh nach dem Umschalten selbst ein chmod +x auf scripts/*.sh. Das faengt den Fall ab, dass jemand Dateien von Hand kopiert und das Recht dabei verliert - genau so kam man bisher an dieses Skript, bevor es in der laufenden Fassung existierte. Neu: tests/skripte.test.ts prueft nicht Verhalten, sondern Verpackung - Ausfuehrungsrecht im Index, Shebang, scripts/ im Docker-Abbild, die Sicherungsskripte in der Compose-Datei. Es ist der zweite Fehler dieser Art (vorher fehlte scripts/ ganz im Abbild, 1.0.1); beide Male war der Code richtig und kein Test sah hin, wie die Dateien beim Server ankommen. Gegenprobe gemacht: mit zurueckgesetztem Recht schlaegt er fehl und nennt die Datei. Nebenbei aufgefallen: scripts/version.mjs datierte in UTC. Diese Fassung waere um 00:08 deutscher Zeit auf den Vortag datiert worden. Rechnet jetzt in Europe/Berlin.
143 lines
4.3 KiB
JavaScript
143 lines
4.3 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* Version anheben.
|
||
*
|
||
* npm run version -- patch 1.0.0 -> 1.0.1
|
||
* npm run version -- minor 1.0.0 -> 1.1.0
|
||
* npm run version -- major 1.0.0 -> 2.0.0
|
||
* npm run version -- 1.2.3 genau diese Version
|
||
*
|
||
* Was passiert:
|
||
* 1. package.json und src/lib/version.ts werden gesetzt - beide, damit
|
||
* sie nicht auseinanderlaufen.
|
||
* 2. Im CHANGELOG wird aus "## [Unveroeffentlicht]" ein Abschnitt mit
|
||
* Versionsnummer und heutigem Datum, darueber ein neuer leerer
|
||
* Abschnitt.
|
||
* 3. Der Vergleichslink am Dateiende wird nachgezogen.
|
||
*
|
||
* Was NICHT passiert: committen und taggen. Das machst du selbst, nachdem
|
||
* du den Changelog-Eintrag gegengelesen hast. Ein automatisch erzeugter
|
||
* Changelog, den niemand liest, ist keinen Deut besser als keiner.
|
||
*
|
||
* Danach:
|
||
* git add -A && git commit -m "chore: Version 1.0.1"
|
||
* git tag -a v1.0.1 -m "..." && git push --follow-tags
|
||
*/
|
||
import { readFileSync, writeFileSync } from 'node:fs'
|
||
|
||
const WURZEL = new URL('..', import.meta.url)
|
||
const pfad = (name) => new URL(name, WURZEL)
|
||
|
||
function lesen(name) {
|
||
return readFileSync(pfad(name), 'utf8')
|
||
}
|
||
|
||
function schreiben(name, inhalt) {
|
||
writeFileSync(pfad(name), inhalt, 'utf8')
|
||
console.log(` ${name}`)
|
||
}
|
||
|
||
// --- Ziel bestimmen ---------------------------------------------------------
|
||
|
||
const argument = process.argv[2]
|
||
if (!argument) {
|
||
console.error('Aufruf: npm run version -- <patch|minor|major|x.y.z>')
|
||
process.exit(1)
|
||
}
|
||
|
||
const paket = JSON.parse(lesen('package.json'))
|
||
const alt = paket.version
|
||
|
||
function naechste(aktuell, art) {
|
||
const treffer = aktuell.match(/^(\d+)\.(\d+)\.(\d+)$/)
|
||
if (!treffer) throw new Error(`Version "${aktuell}" ist kein x.y.z`)
|
||
const [haupt, neben, fehler] = treffer.slice(1).map(Number)
|
||
|
||
switch (art) {
|
||
case 'major':
|
||
return `${haupt + 1}.0.0`
|
||
case 'minor':
|
||
return `${haupt}.${neben + 1}.0`
|
||
case 'patch':
|
||
return `${haupt}.${neben}.${fehler + 1}`
|
||
default:
|
||
if (!/^\d+\.\d+\.\d+$/.test(art)) {
|
||
throw new Error(`"${art}" ist weder patch/minor/major noch x.y.z`)
|
||
}
|
||
return art
|
||
}
|
||
}
|
||
|
||
const neu = naechste(alt, argument)
|
||
if (neu === alt) {
|
||
console.error(`Version ist bereits ${alt}.`)
|
||
process.exit(1)
|
||
}
|
||
|
||
console.log(`\n${alt} -> ${neu}\n`)
|
||
console.log('Geaendert:')
|
||
|
||
// --- 1. package.json --------------------------------------------------------
|
||
|
||
paket.version = neu
|
||
schreiben('package.json', `${JSON.stringify(paket, null, 2)}\n`)
|
||
|
||
// --- 2. src/lib/version.ts --------------------------------------------------
|
||
|
||
const versionsdatei = lesen('src/lib/version.ts')
|
||
const ersetzt = versionsdatei.replace(
|
||
/export const VERSION = '[^']+'/,
|
||
`export const VERSION = '${neu}'`,
|
||
)
|
||
if (ersetzt === versionsdatei) {
|
||
console.error('FEHLER: VERSION in src/lib/version.ts nicht gefunden.')
|
||
process.exit(1)
|
||
}
|
||
schreiben('src/lib/version.ts', ersetzt)
|
||
|
||
// --- 3. CHANGELOG.md --------------------------------------------------------
|
||
|
||
// Deutsche Zeit, nicht UTC. Sonst bekommt eine Veroeffentlichung nach
|
||
// 22 Uhr (Sommerzeit) das Datum des Vortages - dieselbe Zeitzonenfalle,
|
||
// derentwegen die Fristen im Schema @db.Date sind.
|
||
const heute = new Intl.DateTimeFormat('sv-SE', {
|
||
timeZone: 'Europe/Berlin',
|
||
}).format(new Date())
|
||
let changelog = lesen('CHANGELOG.md')
|
||
|
||
const UNVEROEFFENTLICHT = '## [Unveröffentlicht]'
|
||
if (!changelog.includes(UNVEROEFFENTLICHT)) {
|
||
console.error(`FEHLER: "${UNVEROEFFENTLICHT}" steht nicht im CHANGELOG.`)
|
||
process.exit(1)
|
||
}
|
||
|
||
const leererAbschnitt = [
|
||
UNVEROEFFENTLICHT,
|
||
'',
|
||
'_Noch nichts._',
|
||
'',
|
||
`## [${neu}] – ${heute}`,
|
||
].join('\n')
|
||
|
||
changelog = changelog.replace(UNVEROEFFENTLICHT, leererAbschnitt)
|
||
|
||
// Vergleichslinks am Dateiende nachziehen.
|
||
const basis = 'https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare'
|
||
changelog = changelog.replace(
|
||
/^\[Unveröffentlicht\]:.*$/m,
|
||
`[Unveröffentlicht]: ${basis}/v${neu}...HEAD\n[${neu}]: ${basis}/v${alt}...v${neu}`,
|
||
)
|
||
|
||
schreiben('CHANGELOG.md', changelog)
|
||
|
||
// --- Hinweis ----------------------------------------------------------------
|
||
|
||
console.log(`
|
||
Jetzt:
|
||
1. CHANGELOG.md gegenlesen - steht dort, was sich fuer den Nutzer
|
||
tatsaechlich aendert? Nicht, welche Datei angefasst wurde.
|
||
2. git add -A && git commit -m "chore: Version ${neu}"
|
||
3. git tag -a v${neu} -m "Version ${neu}"
|
||
4. git push --follow-tags
|
||
`)
|