diff --git a/README.dev.md b/README.dev.md index d0f2a4e..04f9cd2 100644 --- a/README.dev.md +++ b/README.dev.md @@ -593,6 +593,74 @@ Für Production mit echten Subdomains siehe: --- +## 🚀 Release Management + +### Automated Release (EMPFOHLEN) + +**Ein Befehl macht alles:** + +```bash +npm run release # Patch: 1.2.0 → 1.2.1 +npm run release:minor # Minor: 1.2.0 → 1.3.0 +npm run release:major # Major: 1.2.0 → 2.0.0 +``` + +**Was passiert automatisch:** +1. ✅ Version in allen package.json erhöht +2. ✅ Footer.js, OpenAPI-Spec, Docker-Images aktualisiert +3. ✅ **CHANGELOG.md automatisch generiert** aus Git-Commits +4. ✅ Git Commit erstellt +5. ✅ Git Tag erstellt +6. ✅ Preview anzeigen + Bestätigung + +Dann nur noch: +```bash +git push && git push --tags +``` + +### Beispiel-Workflow: + +```bash +# Features entwickeln mit Conventional Commits: +git commit -m "feat: Add user login" +git commit -m "fix: Fix button alignment" +git commit -m "refactor: Extract ConsentFilter component" + +# Release erstellen: +npm run release:minor + +# Preview wird angezeigt, dann [Y] drücken +# Push: +git push && git push --tags +``` + +### CHANGELOG wird automatisch generiert! + +Das Release-Script (`scripts/release.sh`) gruppiert deine Commits nach Typ: +- `feat:` → ✨ Features +- `fix:` → 🐛 Fixes +- `refactor:` → ♻️ Refactoring +- `chore:` → 🔧 Chores +- `docs:` → 📚 Documentation + +**Wichtig:** Verwende [Conventional Commits](https://www.conventionalcommits.org/)! + +### Manuelle Scripts (falls nötig) + +```bash +# Version nur synchronisieren (ohne Bump): +./scripts/sync-version.sh + +# Version manuell bumpen: +./scripts/bump-version.sh patch # oder minor/major +``` + +**Version-Synchronisation:** +- Single Source of Truth: `frontend/package.json` +- Wird synchronisiert zu: `backend/package.json`, `Footer.js`, `generate-openapi.js`, Docker Images + +--- + ## Nützliche Befehle ```bash diff --git a/backend/docs/openapi.json b/backend/docs/openapi.json index c9e095a..3a5d05e 100644 --- a/backend/docs/openapi.json +++ b/backend/docs/openapi.json @@ -2,7 +2,7 @@ "openapi": "3.0.0", "info": { "title": "Project Image Uploader API", - "version": "1.0.0", + "version": "1.2.0", "description": "Auto-generated OpenAPI spec with correct mount prefixes" }, "servers": [ diff --git a/backend/package.json b/backend/package.json index b487d4a..0c84eb0 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "backend", - "version": "1.0.0", + "version": "1.2.0", "description": "", "main": "src/index.js", "scripts": { diff --git a/backend/src/generate-openapi.js b/backend/src/generate-openapi.js index 4403362..2d29d6c 100644 --- a/backend/src/generate-openapi.js +++ b/backend/src/generate-openapi.js @@ -16,7 +16,7 @@ const endpointsFiles = routerMappings.map(r => path.join(routesDir, r.file)); const doc = { info: { title: 'Project Image Uploader API', - version: '1.0.0', + version: '1.2.0', description: 'Auto-generated OpenAPI spec with correct mount prefixes' }, host: 'localhost:5001', diff --git a/frontend/package.json b/frontend/package.json index 3b63dea..d0b5eb0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "frontend", - "version": "1.1.0", + "version": "1.2.0", "private": true, "dependencies": { "@dnd-kit/core": "^6.3.1", @@ -31,7 +31,8 @@ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "version": "cd .. && ./scripts/sync-version.sh && git add -A" }, "proxy": "http://backend-dev:5000", "eslintConfig": { diff --git a/package.json b/package.json new file mode 100644 index 0000000..76c2a14 --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "project-image-uploader", + "version": "1.2.0", + "private": true, + "scripts": { + "release": "./scripts/release.sh patch", + "release:patch": "./scripts/release.sh patch", + "release:minor": "./scripts/release.sh minor", + "release:major": "./scripts/release.sh major" + }, + "workspaces": [ + "frontend", + "backend" + ] +} diff --git a/scripts/README.md b/scripts/README.md index 65f56fb..22864c3 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,4 +1,120 @@ -# Scripts Overview +# Scripts + +## 🚀 Automated Release (EMPFOHLEN) + +### Ein Befehl macht alles: + +```bash +npm run release # Patch: 1.2.0 → 1.2.1 +npm run release:minor # Minor: 1.2.0 → 1.3.0 +npm run release:major # Major: 1.2.0 → 2.0.0 +``` + +**Was passiert automatisch:** +1. ✅ Version in allen package.json erhöht +2. ✅ Footer.js, OpenAPI-Spec, Docker-Images aktualisiert +3. ✅ **CHANGELOG.md automatisch generiert** aus Git-Commits +4. ✅ Git Commit erstellt +5. ✅ Git Tag erstellt +6. ✅ Preview anzeigen + Bestätigung + +Dann nur noch: +```bash +git push && git push --tags +``` + +### Beispiel-Workflow: + +```bash +# Features entwickeln mit Conventional Commits: +git commit -m "feat: Add user login" +git commit -m "fix: Fix button alignment" +git commit -m "refactor: Extract ConsentFilter component" + +# Release erstellen: +npm run release:minor + +# Preview wird angezeigt, dann [Y] drücken +# Push: +git push && git push --tags +``` + +### CHANGELOG wird automatisch aus Commits generiert! + +Das Script gruppiert deine Commits nach Typ: +- `feat:` → ✨ Features +- `fix:` → 🐛 Fixes +- `refactor:` → ♻️ Refactoring +- `chore:` → 🔧 Chores +- `docs:` → 📚 Documentation + +**Wichtig:** Verwende [Conventional Commits](https://www.conventionalcommits.org/)! + +--- + +## Manual Scripts + +Falls du manuell Kontrolle brauchst: + +### Version Management + +### Quick Start + +```bash +# Version erhöhen (patch: 1.2.0 → 1.2.1) +./scripts/bump-version.sh patch + +# Version erhöhen (minor: 1.2.0 → 1.3.0) +./scripts/bump-version.sh minor + +# Version erhöhen (major: 1.2.0 → 2.0.0) +./scripts/bump-version.sh major + +# Nur synchronisieren (ohne Bump) +./scripts/sync-version.sh +``` + +### Workflow + +1. **Version erhöhen:** + ```bash + ./scripts/bump-version.sh patch # oder minor/major + ``` + +2. **CHANGELOG.md manuell aktualisieren** + +3. **Commit & Tag:** + ```bash + git add -A + git commit -m "chore: bump version to v1.2.1" + git tag v1.2.1 + git push && git push --tags + ``` + +### Was wird synchronisiert? + +- ✅ `frontend/package.json` → **Single Source of Truth** +- ✅ `backend/package.json` +- ✅ `frontend/src/Components/ComponentUtils/Footer.js` (Fallback) +- ✅ `backend/src/generate-openapi.js` (API Version) +- ✅ Docker Images (falls vorhanden) +- ✅ OpenAPI Spec wird neu generiert + +### Scripts + +#### `bump-version.sh` +Erhöht die Version in `frontend/package.json` und ruft `sync-version.sh` auf. + +**Parameter:** `patch` | `minor` | `major` + +#### `sync-version.sh` +Synchronisiert die Version aus `frontend/package.json` zu allen anderen Dateien. + +Kann auch manuell aufgerufen werden, wenn du die Version direkt in `frontend/package.json` geändert hast. + +--- + +## Other Scripts Overview ## Admin-Benutzer anlegen (Shell) diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh new file mode 100755 index 0000000..58421a8 --- /dev/null +++ b/scripts/bump-version.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Bumpt die Version und synchronisiert alle Dateien + +set -e + +VERSION_TYPE=${1:-patch} # patch, minor, major + +if [[ ! "$VERSION_TYPE" =~ ^(patch|minor|major)$ ]]; then + echo "❌ Ungültiger Version-Typ: $VERSION_TYPE" + echo "Verwendung: ./scripts/bump-version.sh [patch|minor|major]" + exit 1 +fi + +GREEN='\033[0;32m' +BLUE='\033[0;34m' +YELLOW='\033[1;33m' +NC='\033[0m' + +echo -e "${BLUE}🚀 Version Bump: ${YELLOW}${VERSION_TYPE}${NC}" + +# 1. Frontend Version bumpen (als Single Source of Truth) +echo " ├─ Bumpe Frontend Version..." +cd frontend +npm version $VERSION_TYPE --no-git-tag-version +NEW_VERSION=$(node -p "require('./package.json').version") +cd .. + +echo -e "${GREEN} ✓ Neue Version: ${NEW_VERSION}${NC}" + +# 2. Alle anderen Stellen synchronisieren +./scripts/sync-version.sh + +echo "" +echo -e "${GREEN}✅ Version erfolgreich auf v${NEW_VERSION} erhöht!${NC}" +echo "" +echo "Vergiss nicht:" +echo " 1. CHANGELOG.md für v${NEW_VERSION} aktualisieren" +echo " 2. Commit & Tag erstellen" diff --git a/scripts/examples.sh b/scripts/examples.sh old mode 100644 new mode 100755 diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 0000000..3ecad2f --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,172 @@ +#!/bin/bash +# Automatisches Release-Script mit CHANGELOG-Generierung + +set -e + +VERSION_TYPE=${1:-patch} +CUSTOM_MESSAGE=${2:-""} + +if [[ ! "$VERSION_TYPE" =~ ^(patch|minor|major)$ ]]; then + echo "❌ Ungültiger Version-Typ: $VERSION_TYPE" + echo "Verwendung: ./scripts/release.sh [patch|minor|major] [optional: custom message]" + exit 1 +fi + +GREEN='\033[0;32m' +BLUE='\033[0;34m' +YELLOW='\033[1;33m' +NC='\033[0m' + +echo -e "${BLUE}🚀 Automated Release: ${YELLOW}${VERSION_TYPE}${NC}" +echo "" + +# 1. Hole aktuelle Version +CURRENT_VERSION=$(node -p "require('./frontend/package.json').version") +echo -e "📌 Aktuelle Version: ${CURRENT_VERSION}" + +# 2. Berechne neue Version +cd frontend +npm version $VERSION_TYPE --no-git-tag-version > /dev/null +NEW_VERSION=$(node -p "require('./package.json').version") +cd .. + +echo -e "📦 Neue Version: ${GREEN}${NEW_VERSION}${NC}" +echo "" + +# 3. Synchronisiere alle Dateien +echo "🔄 Synchronisiere Version überall..." +./scripts/sync-version.sh > /dev/null 2>&1 + +# 4. Sammle Commits seit letztem Tag +echo "📝 Generiere CHANGELOG-Eintrag..." + +LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") +if [ -z "$LAST_TAG" ]; then + echo -e "${YELLOW}⚠️ Kein vorheriger Tag gefunden. Alle Commits werden verwendet.${NC}" + echo " Tipp: Erstelle rückwirkend einen Tag für die letzte Version:" + echo " git tag -a v1.1.0 -m 'Release 1.1.0'" + echo "" + COMMITS=$(git log --oneline --no-merges) +else + echo "📋 Commits seit Tag $LAST_TAG werden verwendet" + COMMITS=$(git log ${LAST_TAG}..HEAD --online --no-merges) +fi + +# 5. Gruppiere Commits nach Typ +FEATURES=$(echo "$COMMITS" | grep "^[a-f0-9]* feat:" || true) +FIXES=$(echo "$COMMITS" | grep "^[a-f0-9]* fix:" || true) +REFACTOR=$(echo "$COMMITS" | grep "^[a-f0-9]* refactor:" || true) +CHORE=$(echo "$COMMITS" | grep "^[a-f0-9]* chore:" || true) +DOCS=$(echo "$COMMITS" | grep "^[a-f0-9]* docs:" || true) + +# 6. Erstelle CHANGELOG-Eintrag +DATE=$(date +%Y-%m-%d) +CHANGELOG_ENTRY="## [${NEW_VERSION}] - ${DATE}\n\n" + +if [ -n "$CUSTOM_MESSAGE" ]; then + CHANGELOG_ENTRY+="${CUSTOM_MESSAGE}\n\n" +fi + +if [ -n "$FEATURES" ]; then + CHANGELOG_ENTRY+="### ✨ Features\n" + while IFS= read -r line; do + MSG=$(echo "$line" | sed -E 's/^[a-f0-9]+ feat: //') + CHANGELOG_ENTRY+="- ${MSG}\n" + done <<< "$FEATURES" + CHANGELOG_ENTRY+="\n" +fi + +if [ -n "$FIXES" ]; then + CHANGELOG_ENTRY+="### 🐛 Fixes\n" + while IFS= read -r line; do + MSG=$(echo "$line" | sed -E 's/^[a-f0-9]+ fix: //') + CHANGELOG_ENTRY+="- ${MSG}\n" + done <<< "$FIXES" + CHANGELOG_ENTRY+="\n" +fi + +if [ -n "$REFACTOR" ]; then + CHANGELOG_ENTRY+="### ♻️ Refactoring\n" + while IFS= read -r line; do + MSG=$(echo "$line" | sed -E 's/^[a-f0-9]+ refactor: //') + CHANGELOG_ENTRY+="- ${MSG}\n" + done <<< "$REFACTOR" + CHANGELOG_ENTRY+="\n" +fi + +if [ -n "$CHORE" ]; then + CHANGELOG_ENTRY+="### 🔧 Chores\n" + while IFS= read -r line; do + MSG=$(echo "$line" | sed -E 's/^[a-f0-9]+ chore: //') + CHANGELOG_ENTRY+="- ${MSG}\n" + done <<< "$CHORE" + CHANGELOG_ENTRY+="\n" +fi + +# 7. Füge Eintrag in CHANGELOG.md ein (nach der Überschrift) +if [ -f "CHANGELOG.md" ]; then + # Temporäre Datei erstellen + TEMP_FILE=$(mktemp) + + # Erste Zeilen (bis erste ##) behalten + awk '/^## \[/ {exit} {print}' CHANGELOG.md > "$TEMP_FILE" + + # Neuen Eintrag hinzufügen + echo -e "$CHANGELOG_ENTRY" >> "$TEMP_FILE" + + # Rest des alten CHANGELOG anhängen + awk '/^## \[/ {found=1} found {print}' CHANGELOG.md >> "$TEMP_FILE" + + # Ersetzen + mv "$TEMP_FILE" CHANGELOG.md + + echo -e "${GREEN}✓ CHANGELOG.md aktualisiert${NC}" +else + # CHANGELOG erstellen + cat > CHANGELOG.md << EOF +# Changelog + +Alle wichtigen Änderungen an diesem Projekt werden in dieser Datei dokumentiert. + +Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.0.0/), +und dieses Projekt hält sich an [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +$CHANGELOG_ENTRY +EOF + echo -e "${GREEN}✓ CHANGELOG.md erstellt${NC}" +fi + +# 8. Preview anzeigen +echo "" +echo -e "${BLUE}📄 CHANGELOG Preview:${NC}" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo -e "$CHANGELOG_ENTRY" | head -20 +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" + +# 9. Frage nach Bestätigung +read -p "Sieht das gut aus? [Y/n] " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]] && [[ ! -z $REPLY ]]; then + echo "❌ Abgebrochen. Änderungen wurden NICHT committed." + exit 1 +fi + +# 10. Git Commit & Tag +echo "" +echo "📦 Erstelle Git Commit & Tag..." +git add -A +git commit -m "chore: release v${NEW_VERSION} + +🔖 Version ${NEW_VERSION} + +$(echo -e "$CHANGELOG_ENTRY" | sed 's/^## .*//' | sed 's/^$//' | head -30)" + +git tag -a "v${NEW_VERSION}" -m "Release v${NEW_VERSION}" + +echo -e "${GREEN}✓ Commit & Tag erstellt${NC}" +echo "" +echo -e "${BLUE}Nächste Schritte:${NC}" +echo " git push && git push --tags" +echo "" +echo -e "${GREEN}✅ Release v${NEW_VERSION} fertig!${NC}" diff --git a/scripts/sync-version.sh b/scripts/sync-version.sh new file mode 100755 index 0000000..502b919 --- /dev/null +++ b/scripts/sync-version.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# Synchronisiert Versionsnummer über das gesamte Projekt + +set -e + +# Farben für Output +GREEN='\033[0;32m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Hole Version aus frontend/package.json (als Single Source of Truth) +FRONTEND_VERSION=$(node -p "require('./frontend/package.json').version") + +echo -e "${BLUE}📦 Synchronisiere Version: ${GREEN}${FRONTEND_VERSION}${NC}" + +# 1. Backend package.json aktualisieren +echo " ├─ Backend package.json..." +cd backend +npm version $FRONTEND_VERSION --no-git-tag-version --allow-same-version +cd .. + +# 2. Footer.js Fallback aktualisieren +echo " ├─ Frontend Footer.js Fallback..." +sed -i "s/window\._env_\?\.APP_VERSION || '[0-9]\+\.[0-9]\+\.[0-9]\+'/window._env_?.APP_VERSION || '${FRONTEND_VERSION}'/" frontend/src/Components/ComponentUtils/Footer.js + +# 3. OpenAPI generate-openapi.js aktualisieren +echo " ├─ Backend OpenAPI Spec..." +sed -i "s/version: '[0-9]\+\.[0-9]\+\.[0-9]\+'/version: '${FRONTEND_VERSION}'/" backend/src/generate-openapi.js + +# 4. Docker Compose Files (optional, falls vorhanden) +if [ -f "docker/prod/docker-compose.yml" ]; then + echo " ├─ Docker Compose (prod)..." + sed -i "s/image: hobbyhimmel\/image-uploader-frontend:[0-9]\+\.[0-9]\+\.[0-9]\+/image: hobbyhimmel\/image-uploader-frontend:${FRONTEND_VERSION}/" docker/prod/docker-compose.yml || true + sed -i "s/image: hobbyhimmel\/image-uploader-backend:[0-9]\+\.[0-9]\+\.[0-9]\+/image: hobbyhimmel\/image-uploader-backend:${FRONTEND_VERSION}/" docker/prod/docker-compose.yml || true +fi + +# 5. OpenAPI Spec neu generieren +echo " ├─ Regeneriere OpenAPI Spec..." +cd backend +npm run generate-openapi > /dev/null 2>&1 +cd .. + +echo -e "${GREEN}✓ Alle Versionen auf ${FRONTEND_VERSION} synchronisiert!${NC}" +echo "" +echo "Nächste Schritte:" +echo " 1. CHANGELOG.md manuell aktualisieren" +echo " 2. Git commit: git add -A && git commit -m 'chore: bump version to v${FRONTEND_VERSION}'" +echo " 3. Git tag: git tag v${FRONTEND_VERSION}" +echo " 4. Push: git push && git push --tags"