chore: Improve release script with tag-based commit detection

- Add helpful warning when no previous tag exists
- Show which tag is being used for commit range
- Provide tip for creating retroactive tags
- Fix typo in git log command (--online -> --oneline)
This commit is contained in:
Matthias Lotz 2025-11-29 16:52:19 +01:00
parent e4712f9e7e
commit 40aa546498
11 changed files with 465 additions and 6 deletions

View File

@ -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 ## Nützliche Befehle
```bash ```bash

View File

@ -2,7 +2,7 @@
"openapi": "3.0.0", "openapi": "3.0.0",
"info": { "info": {
"title": "Project Image Uploader API", "title": "Project Image Uploader API",
"version": "1.0.0", "version": "1.2.0",
"description": "Auto-generated OpenAPI spec with correct mount prefixes" "description": "Auto-generated OpenAPI spec with correct mount prefixes"
}, },
"servers": [ "servers": [

View File

@ -1,6 +1,6 @@
{ {
"name": "backend", "name": "backend",
"version": "1.0.0", "version": "1.2.0",
"description": "", "description": "",
"main": "src/index.js", "main": "src/index.js",
"scripts": { "scripts": {

View File

@ -16,7 +16,7 @@ const endpointsFiles = routerMappings.map(r => path.join(routesDir, r.file));
const doc = { const doc = {
info: { info: {
title: 'Project Image Uploader API', title: 'Project Image Uploader API',
version: '1.0.0', version: '1.2.0',
description: 'Auto-generated OpenAPI spec with correct mount prefixes' description: 'Auto-generated OpenAPI spec with correct mount prefixes'
}, },
host: 'localhost:5001', host: 'localhost:5001',

View File

@ -1,6 +1,6 @@
{ {
"name": "frontend", "name": "frontend",
"version": "1.1.0", "version": "1.2.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@dnd-kit/core": "^6.3.1", "@dnd-kit/core": "^6.3.1",
@ -31,7 +31,8 @@
"start": "react-scripts start", "start": "react-scripts start",
"build": "react-scripts build", "build": "react-scripts build",
"test": "react-scripts test", "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", "proxy": "http://backend-dev:5000",
"eslintConfig": { "eslintConfig": {

15
package.json Normal file
View File

@ -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"
]
}

View File

@ -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) ## Admin-Benutzer anlegen (Shell)

38
scripts/bump-version.sh Executable file
View File

@ -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"

0
scripts/examples.sh Normal file → Executable file
View File

172
scripts/release.sh Executable file
View File

@ -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 <commit-hash> -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}"

49
scripts/sync-version.sh Executable file
View File

@ -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"