feat: Versionierung mit Changelog, Version 1.0.0
Bis jetzt stand nirgends, welcher Stand laeuft. Beim Aktualisieren auf einem Server ist das die erste Frage. CHANGELOG.md nach Keep a Changelog, Versionsnummern nach SemVer. Der Changelog sagt, was sich beim Arbeiten aendert - nicht, welche Datei angefasst wurde. Dazu eine Tabelle, was Major, Minor und Patch fuer den Betreiber praktisch bedeuten, und der Hinweis, dass sich eine Datenbank-Migration nicht zurueckrollen laesst. Die Version steht bewusst an zwei Stellen: package.json und src/lib/version.ts. Ein Import der package.json waere im Standalone-Build eine andere Datei als die des Projekts - die Zahl haenge dann an der Laufzeit. Ein Test haelt beide zusammen, und "npm run version" setzt sie gemeinsam samt Changelog-Abschnitt. Committet und getaggt wird nicht automatisch. Ein Changelog-Eintrag, den niemand gegengelesen hat, ist keinen Deut besser als keiner. Sichtbar wird die Version unten in der Seitenleiste und unter /api/gesundheit - dort mit Git-Stand, den der Docker-Build hineinreicht. Auf der Anmeldeseite steht sie nicht: wer nicht angemeldet ist, muss nicht wissen, welche Fassung hier laeuft. Etappe: 8 Phase: Haertung
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
#!/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 --------------------------------------------------------
|
||||
|
||||
const heute = new Date().toISOString().slice(0, 10)
|
||||
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
|
||||
`)
|
||||
Reference in New Issue
Block a user