docs(standards): zentrale Anleitung zur automatisierten Versionierung hinzugefügt

- beschreibt das Versionskonzept für package.json, package-lock.json und .env.*
- erklärt die Verwendung von bumpVersion.js und Husky-Hooks
- hilft neuen und bestehenden Entwicklern, konsistent zu arbeiten
- gilt als Standardrichtlinie für zukünftige Projekte
This commit is contained in:
ISA
2025-06-17 15:31:21 +02:00
parent 3be337f53d
commit 534b22f325
11 changed files with 142 additions and 78 deletions

View File

@@ -5,4 +5,6 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_TDR_START=true
NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false
NEXT_PUBLIC_EXPORT_STATIC=false NEXT_PUBLIC_EXPORT_STATIC=false
NEXT_PUBLIC_USE_CGI=false NEXT_PUBLIC_USE_CGI=false
# App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.6.408

View File

@@ -4,3 +4,5 @@ NEXT_PUBLIC_ENCRYPTION_IV=1
NEXT_PUBLIC_CPL_API_PATH=/CPL NEXT_PUBLIC_CPL_API_PATH=/CPL
NEXT_PUBLIC_EXPORT_STATIC=true NEXT_PUBLIC_EXPORT_STATIC=true
NEXT_PUBLIC_USE_CGI=true NEXT_PUBLIC_USE_CGI=true
# App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.6.408

View File

@@ -1,4 +1,12 @@
#!/bin/sh #!/bin/sh
. "$(dirname "$0")/_/husky.sh" . "$(dirname "$0")/_/husky.sh"
node incrementVersion.ts echo "🔄 Version wird automatisch erhöht (bumpVersion.ts)..."
# Version automatisch erhöhen
node /scripts/bumpVersion.ts
# Automatisch relevante Dateien zum Commit hinzufügen
git add package.json package-lock.json .env.development .env.production
# Fortsetzen mit dem Commit

View File

@@ -9,7 +9,7 @@ const VersionInfo: React.FC = () => {
useSelector((state: RootState) => state.systemSettingsSlice.appVersion) || useSelector((state: RootState) => state.systemSettingsSlice.appVersion) ||
"Unbekannt"; "Unbekannt";
const webVersion = useSelector( const webVersion = useSelector(
(state: RootState) => state.webVersionSlice.version (state: RootState) => state.webVersionSlice.appVersion
); // Webversion aus Redux holen ); // Webversion aus Redux holen
return ( return (

View File

@@ -1,10 +0,0 @@
// config/webVersion.ts
/*
1: Hauptversion (komplettes Redesign oder neue Hauptfeatures).
0: Nebenversion (kleinere, aber bedeutende neue Features).
6: Build-Nummer (interne Entwicklungsiteration).
2: Patch oder Hotfix (Bugfixes oder kleine Änderungen).
*/
const webVersion = "1.6.407";
export default webVersion;

View File

@@ -0,0 +1,66 @@
# 📦 Versionierung im Projekt
## 🎯 Ziel
Dieses Projekt verwendet eine automatisierte und konsistente Versionsverwaltung, um Klarheit über
die aktuelle App-Version zu gewährleisten und manuelle Fehler zu vermeiden.
---
## 🗂️ Wo wird die Version gespeichert?
Die App-Version ist in **vier Dateien synchron enthalten**:
| Datei | Zweck |
| ------------------- | ----------------------------------------- |
| `package.json` | Hauptquelle für Version (npm, Git) |
| `package-lock.json` | Technischer Zustand des Builds |
| `.env.development` | Anzeige in der UI zur Entwicklungszeit |
| `.env.production` | Anzeige in der UI auf Produktionssystemen |
Beispiel-Eintrag in `.env.*`:
```env
NEXT_PUBLIC_APP_VERSION=1.1.265
```
---
## ⚙️ Wie wird die Version erhöht?
Die Version wird automatisch durch folgendes Skript erhöht:
```bash
node scripts/bumpVersion.js
```
### Dieses Skript erledigt:
- Erhöhung der Patch-Version (z.B. `1.1.265``1.1.266`)
- Aktualisierung von `package.json`
- Erstellung eines synchronen `package-lock.json`
- Aktualisierung der `.env.development` und `.env.production` mit neuer Version
Das Skript wird zusätzlich automatisch beim Git-Commit über Husky (`.husky/pre-commit`) ausgeführt.
---
## 🧠 Warum ist das hilfreich?
- Die UI zeigt **immer die aktuelle App-Version**, über `process.env.NEXT_PUBLIC_APP_VERSION`
- Git-History, Deployments und ZIP-Versionen sind nachvollziehbar
- Keine Inkonsistenzen durch manuelle Pflege
- Reproduzierbare Builds dank `package-lock.json`
---
## 🧑‍💻 Hinweis für neue Entwickler
- ❌ Niemals die Versionsnummer manuell in nur einer Datei ändern!
- ✅ Immer das Skript nutzen oder den Commit-Hook wirken lassen.
- 🔁 Nach Konflikten: Stelle sicher, dass `package-lock.json` und `.env.*` konsistent sind.
---
📘 Pfad diese Datei:
[`/docs/standards/versioning.md`](/docs/standards/versioning.md)

View File

@@ -1,52 +0,0 @@
// /incrementVersion.ts
const fs = require("fs");
const path = require("path");
const versionFilePath = path.join(process.cwd(), "config/webVersion.ts");
// Falls die Datei nicht existiert, erstelle eine Standardversion
if (!fs.existsSync(versionFilePath)) {
fs.writeFileSync(
versionFilePath,
`export const WEB_VERSION = "1.0.0.0";\n`,
"utf8"
);
}
const versionFile = fs.readFileSync(versionFilePath, "utf8");
// Regex, um Versionsnummer zu finden (vX.Y.Z oder vX.Y.Z.N)
const versionRegex = /(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?/;
const match = versionFile.match(versionRegex);
if (match) {
let [major, minor, patch, build] = match
.slice(1)
.map((num) => (num !== undefined ? Number(num) : 0));
const isHotfix = process.env.HOTFIX_MODE === "true"; // Umgebungsvariable für Hotfixes
if (isHotfix) {
build++; // Falls ein Hotfix gemacht wird, nur `N` erhöhen (vX.Y.Z.N)
console.log(
`🔧 Hotfix-Modus aktiv Erhöhe Patch-Fix auf: ${major}.${minor}.${patch}.${build}`
);
} else {
patch++; // Normale Builds erhöhen `Z`
build = 0; // Falls es kein Hotfix ist, beginnt `N` wieder bei 0
console.log(
`📦 Normale Build-Erhöhung Neue Version: ${major}.${minor}.${patch}`
);
}
const newVersion = isHotfix
? `${major}.${minor}.${patch}.${build}`
: `${major}.${minor}.${patch}`;
const updatedFile = versionFile.replace(versionRegex, newVersion);
fs.writeFileSync(versionFilePath, updatedFile, "utf8");
console.log(`✅ Webversion aktualisiert auf: ${newVersion}`);
} else {
console.error("❌ Konnte die Version nicht finden!");
process.exit(1);
}

8
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "23.09.2024-cpl-v4", "name": "cpl-v4",
"version": "0.1.0", "version": "1.6.408",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "23.09.2024-cpl-v4", "name": "cpl-v4",
"version": "0.1.0", "version": "1.6.408",
"dependencies": { "dependencies": {
"@fontsource/roboto": "^5.1.0", "@fontsource/roboto": "^5.1.0",
"@iconify-icons/ri": "^1.2.10", "@iconify-icons/ri": "^1.2.10",

View File

@@ -1,6 +1,6 @@
{ {
"name": "23.09.2024-cpl-v4", "name": "cpl-v4",
"version": "0.1.0", "version": "1.6.408",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
@@ -10,7 +10,8 @@
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "next lint",
"test": "jest", "test": "jest",
"prepare": "husky install" "prepare": "husky install",
"bump-version": "node ./scripts/bumpVersion.js"
}, },
"dependencies": { "dependencies": {
"@fontsource/roboto": "^5.1.0", "@fontsource/roboto": "^5.1.0",

View File

@@ -1,13 +1,12 @@
// redux/slices/webVersionSlice.ts // redux/slices/webVersionSlice.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import webVersion from "../../config/webVersion";
interface WebVersionState { interface WebVersionState {
version: string; appVersion: string;
} }
const initialState: WebVersionState = { const initialState: WebVersionState = {
version: webVersion, appVersion: process.env.NEXT_PUBLIC_APP_VERSION ?? "",
}; };
const webVersionSlice = createSlice({ const webVersionSlice = createSlice({
@@ -15,14 +14,14 @@ const webVersionSlice = createSlice({
initialState, initialState,
reducers: { reducers: {
setWebVersion(state, action: PayloadAction<string>) { setWebVersion(state, action: PayloadAction<string>) {
state.version = action.payload; state.appVersion = action.payload;
}, },
incrementBuild(state) { incrementBuild(state) {
// Versionsnummer zerlegen und Build hochzählen // Versionsnummer zerlegen und Build hochzählen
const parts = state.version.split("."); const parts = state.appVersion.split(".");
if (parts.length === 3) { if (parts.length === 3) {
parts[2] = (parseInt(parts[2]) + 1).toString(); // Build hochzählen parts[2] = (parseInt(parts[2]) + 1).toString(); // Build hochzählen
state.version = parts.join("."); state.appVersion = parts.join(".");
} }
}, },
}, },

48
scripts/bumpVersion.ts Normal file
View File

@@ -0,0 +1,48 @@
// /bumpVersion.ts
const fs = require("fs");
const path = require("path");
const { execSync } = require("child_process");
const envPaths = [
path.join(__dirname, "../.env.development"),
path.join(__dirname, "../.env.production"),
];
const pkgPath = path.join(__dirname, "../package.json");
// 🟢 Versionsnummer aus package.json holen
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
const [major, minor, patch] = pkg.version.split(".").map(Number);
const newVersion = `${major}.${minor}.${patch + 1}`;
// 🟢 package.json aktualisieren
pkg.version = newVersion;
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2), "utf8");
// 🟢 .env Dateien aktualisieren
envPaths.forEach((envFile) => {
if (!fs.existsSync(envFile)) return;
let content = fs.readFileSync(envFile, "utf8");
const versionRegex = /^NEXT_PUBLIC_APP_VERSION=.*$/m;
if (versionRegex.test(content)) {
content = content.replace(
versionRegex,
`NEXT_PUBLIC_APP_VERSION=${newVersion}`
);
} else {
content += `\nNEXT_PUBLIC_APP_VERSION=${newVersion}`;
}
fs.writeFileSync(envFile, content, "utf8");
});
// 🟢 package-lock.json aktualisieren
try {
execSync("npm install --package-lock-only", { stdio: "inherit" });
} catch (error) {
console.error("❌ Fehler beim Aktualisieren der package-lock.json:", error);
process.exit(1);
}
console.log(`✅ Version erhöht auf ${newVersion}`);