1.0.0-1 Licence

This commit is contained in:
2026-07-02 08:32:25 +02:00
parent e754f1f7c3
commit 428cf951b2
13 changed files with 626 additions and 13 deletions
+551
View File
@@ -0,0 +1,551 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
set -euo pipefail
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "$script_dir/.." && pwd)"
cd "$repo_root"
require_command() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "Fehlender Befehl: $1"
exit 1
fi
}
PARSED_MAJOR=""
PARSED_MINOR=""
PARSED_PATCH=""
PARSED_BUILD=""
PARSED_SUFFIX=""
friendly_remote_name() {
local remote_name="$1"
local remote_url="$2"
if [[ "$remote_url" == *github.com* ]]; then
printf 'GitHub (%s)' "$remote_name"
return
fi
if [[ "$remote_url" == *git.d-razz.de* ]] || [[ "$remote_name" == "gitea" ]]; then
printf 'Gitea (%s)' "$remote_name"
return
fi
printf '%s' "$remote_name"
}
parse_version() {
local version="$1"
if [[ ! "$version" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)(-([0-9]+|alpha|beta|rc([.]?[0-9]+)?))?$ ]]; then
echo "Aktuelle Version hat kein unterstuetztes Format: $version"
exit 1
fi
PARSED_MAJOR="${BASH_REMATCH[1]}"
PARSED_MINOR="${BASH_REMATCH[2]}"
PARSED_PATCH="${BASH_REMATCH[3]}"
PARSED_SUFFIX="${BASH_REMATCH[5]:-}"
if [[ "$PARSED_SUFFIX" =~ ^[0-9]+$ ]]; then
PARSED_BUILD="$PARSED_SUFFIX"
else
PARSED_BUILD=""
fi
}
bump_version() {
local version="$1"
local bump_type="$2"
parse_version "$version"
local major="$PARSED_MAJOR"
local minor="$PARSED_MINOR"
local patch="$PARSED_PATCH"
case "$bump_type" in
major)
major=$((major + 1))
minor=0
patch=0
;;
minor)
minor=$((minor + 1))
patch=0
;;
patch)
patch=$((patch + 1))
;;
esac
printf '%s.%s.%s' "$major" "$minor" "$patch"
}
increment_build_version() {
local version="$1"
parse_version "$version"
local build_number=1
if [[ "$PARSED_SUFFIX" =~ ^[0-9]+$ ]]; then
build_number=$((PARSED_SUFFIX + 1))
elif [[ -n "$PARSED_SUFFIX" ]]; then
echo "Build-Bump nicht moeglich fuer Suffix '$PARSED_SUFFIX'."
echo "Unterstuetzt: keine Suffixe oder eine numerische Buildnummer."
exit 1
fi
printf '%s.%s.%s-%s' "$PARSED_MAJOR" "$PARSED_MINOR" "$PARSED_PATCH" "$build_number"
}
can_increment_build_version() {
local version="$1"
parse_version "$version"
[[ -z "$PARSED_SUFFIX" || "$PARSED_SUFFIX" =~ ^[0-9]+$ ]]
}
increment_rc_version() {
local version="$1"
parse_version "$version"
local rc_number=1
if [[ "$PARSED_SUFFIX" =~ ^rc([.]?([0-9]+))?$ ]]; then
if [[ -n "${BASH_REMATCH[2]:-}" ]]; then
rc_number=$((BASH_REMATCH[2] + 1))
fi
elif [[ -n "$PARSED_SUFFIX" ]]; then
echo "RC-Bump nicht moeglich fuer Suffix '$PARSED_SUFFIX'."
echo "Unterstuetzt: keine Suffixe oder -rc<nummer>."
exit 1
fi
printf '%s.%s.%s-rc%s' "$PARSED_MAJOR" "$PARSED_MINOR" "$PARSED_PATCH" "$rc_number"
}
can_increment_rc_version() {
local version="$1"
parse_version "$version"
[[ -z "$PARSED_SUFFIX" || "$PARSED_SUFFIX" =~ ^rc([.]?[0-9]+)?$ ]]
}
remove_rc_suffix() {
local version="$1"
parse_version "$version"
if [[ ! "$PARSED_SUFFIX" =~ ^rc([.]?[0-9]+)?$ ]]; then
echo "RC-Suffix kann nur von Versionen mit -rc entfernt werden."
echo "Aktuelle Version: $version"
exit 1
fi
printf '%s.%s.%s' "$PARSED_MAJOR" "$PARSED_MINOR" "$PARSED_PATCH"
}
select_release_variant() {
local base_version="$1"
local choice=""
local rc_number=""
echo "Release-Typ waehlen:"
echo " 1) Final -> $base_version"
echo " 2) Release Candidate -> ${base_version}-rc<nummer>"
echo " 3) Beta -> ${base_version}-beta"
echo " 4) Alpha -> ${base_version}-alpha"
read -r -p "Auswahl [1]: " choice
choice="${choice:-1}"
case "$choice" in
1)
SELECTED_RELEASE_VERSION="$base_version"
SELECTED_RELEASE_LABEL="Final"
;;
2)
while true; do
read -r -p "RC-Nummer eingeben (z.B. 1): " rc_number
if [[ "$rc_number" =~ ^[0-9]+$ ]]; then
break
fi
echo "Bitte eine gueltige Zahl eingeben."
done
SELECTED_RELEASE_VERSION="${base_version}-rc$rc_number"
SELECTED_RELEASE_LABEL="Release Candidate"
;;
3)
SELECTED_RELEASE_VERSION="${base_version}-beta"
SELECTED_RELEASE_LABEL="Beta"
;;
4)
SELECTED_RELEASE_VERSION="${base_version}-alpha"
SELECTED_RELEASE_LABEL="Alpha"
;;
*)
echo "Ungueltige Release-Typ-Auswahl."
exit 1
;;
esac
}
confirm_or_exit() {
local prompt="$1"
local response
read -r -p "$prompt" response
response="${response:-y}"
if [[ ! "$response" =~ ^[YyJj]$ ]]; then
echo "Abgebrochen."
exit 0
fi
}
require_command git
require_command node
require_command npm
find_deploy_script() {
local candidate=""
for candidate in \
"$repo_root/scripts/deploy-ripster.sh" \
"$repo_root/deploy-ripster.sh"
do
if [[ -f "$candidate" ]]; then
printf '%s' "$candidate"
return 0
fi
done
return 1
}
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "Dieses Skript muss in einem Git-Repository ausgefuehrt werden."
exit 1
fi
current_branch="$(git branch --show-current)"
github_release_mode="snapshot"
github_source_branch=""
github_source_ref=""
mapfile -t remotes < <(git remote)
default_remote_index=1
for i in "${!remotes[@]}"; do
if [[ "${remotes[$i]}" == "gitea" ]]; then
default_remote_index=$((i + 1))
break
fi
done
echo "Verfuegbare Remotes:"
for i in "${!remotes[@]}"; do
remote_name="${remotes[$i]}"
remote_url="$(git remote get-url "$remote_name")"
remote_label="$(friendly_remote_name "$remote_name" "$remote_url")"
echo " $((i + 1))) $remote_label -> $remote_url"
done
read -r -p "Remote waehlen [$default_remote_index]: " remote_choice
remote_choice="${remote_choice:-$default_remote_index}"
selected_remote="${remotes[$((remote_choice - 1))]}"
selected_remote_url="$(git remote get-url "$selected_remote")"
selected_is_github=false
if [[ "$selected_remote_url" == *github.com* ]]; then
selected_is_github=true
fi
echo "Lokaler Branch: $current_branch"
if [[ "$selected_is_github" == true ]]; then
echo
echo "GitHub-Modus waehlen:"
echo " 1) Snapshot-Release auf Ziel-Branch (bisheriger Ablauf)"
echo " 2) Branch-Merge/Veroeffentlichung dev -> main (force, main uebernimmt dev komplett)"
default_github_mode="1"
if [[ "$current_branch" == "dev" ]]; then
default_github_mode="2"
fi
read -r -p "Auswahl [$default_github_mode]: " github_mode_choice
github_mode_choice="${github_mode_choice:-$default_github_mode}"
case "$github_mode_choice" in
1)
github_release_mode="snapshot"
;;
2)
github_release_mode="branch-force-merge"
;;
*)
echo "Ungueltige GitHub-Modus-Auswahl."
exit 1
;;
esac
fi
if [[ "$selected_is_github" == true && "$github_release_mode" == "branch-force-merge" ]]; then
echo
read -r -p "Quell-Branch fuer GitHub-Veroeffentlichung [dev]: " github_source_branch
github_source_branch="${github_source_branch:-dev}"
if ! git check-ref-format --branch "$github_source_branch" >/dev/null 2>&1; then
echo "Ungueltiger Quell-Branch: $github_source_branch"
exit 1
fi
if git show-ref --verify --quiet "refs/heads/$github_source_branch"; then
github_source_ref="refs/heads/$github_source_branch"
elif git ls-remote --exit-code --heads "$selected_remote" "$github_source_branch" >/dev/null 2>&1; then
github_source_ref="refs/remotes/$selected_remote/$github_source_branch"
git fetch "$selected_remote" "$github_source_branch"
else
echo "Quell-Branch '$github_source_branch' wurde weder lokal noch auf $selected_remote gefunden."
exit 1
fi
read -r -p "Ziel-Branch auf $selected_remote [main]: " target_branch
target_branch="${target_branch:-main}"
else
read -r -p "Ziel-Branch auf $selected_remote [$current_branch]: " target_branch
target_branch="${target_branch:-$current_branch}"
fi
if ! git check-ref-format --branch "$target_branch" >/dev/null 2>&1; then
echo "Ungueltiger Branch-Name: $target_branch"
exit 1
fi
selected_push_ref="refs/heads/$target_branch"
root_version="$(node -p "require('./package.json').version")"
frontend_version="$(node -p "require('./frontend/package.json').version")"
backend_version="$(node -p "require('./backend/package.json').version")"
if [[ "$root_version" != "$frontend_version" ]] || [[ "$root_version" != "$backend_version" ]]; then
echo "Hinweis: Die Versionen sind aktuell nicht synchron."
echo " Root: $root_version"
echo " Frontend: $frontend_version"
echo " Backend: $backend_version"
echo "Das Skript synchronisiert sie gleich auf eine gemeinsame Zielversion."
echo
fi
next_patch="$(bump_version "$root_version" patch)"
next_minor="$(bump_version "$root_version" minor)"
next_major="$(bump_version "$root_version" major)"
next_build=""
if can_increment_build_version "$root_version"; then
next_build="$(increment_build_version "$root_version")"
fi
next_rc=""
if can_increment_rc_version "$root_version"; then
next_rc="$(increment_rc_version "$root_version")"
fi
current_final=""
if parse_version "$root_version" >/dev/null 2>&1 && [[ "$PARSED_SUFFIX" =~ ^rc([.]?[0-9]+)?$ ]]; then
current_final="$(remove_rc_suffix "$root_version")"
fi
apply_version_change=false
echo "Aktuelle Version: $root_version"
if [[ "$selected_is_github" == true ]]; then
target_version="$root_version"
release_mode="GitHub-Sync ohne Versionsaenderung"
echo "GitHub-Remote erkannt: Versions- und Build-Prozess wird uebersprungen."
else
read -r -p "Versionsnummer hochsetzen? [Y/n]: " should_bump_version
should_bump_version="${should_bump_version:-y}"
case "$should_bump_version" in
[YyJj])
echo "Version waehlen:"
echo " 1) Patch -> $next_patch"
echo " 2) Minor -> $next_minor"
echo " 3) Major -> $next_major"
if [[ -n "$next_build" ]]; then
echo " 4) Build -> $next_build"
fi
read -r -p "Auswahl [1]: " version_choice
version_choice="${version_choice:-1}"
case "$version_choice" in
1)
target_version="$next_patch"
release_mode="Patch"
apply_version_change=true
;;
2)
select_release_variant "$next_minor"
target_version="$SELECTED_RELEASE_VERSION"
release_mode="Minor ($SELECTED_RELEASE_LABEL)"
apply_version_change=true
;;
3)
select_release_variant "$next_major"
target_version="$SELECTED_RELEASE_VERSION"
release_mode="Major ($SELECTED_RELEASE_LABEL)"
apply_version_change=true
;;
4)
if [[ -z "$next_build" ]]; then
echo "Build-Bump ist fuer die aktuelle Version nicht verfuegbar."
exit 1
fi
target_version="$next_build"
release_mode="Build"
apply_version_change=true
;;
*)
echo "Ungueltige Versions-Auswahl."
exit 1
;;
esac
;;
[Nn])
echo "Option ohne Basisversionssprung waehlen:"
echo " 1) Ohne Versionsaenderung -> $root_version"
if [[ -n "$next_rc" ]]; then
echo " 2) Nur RC-Nummer hochsetzen -> $next_rc"
fi
if [[ -n "$current_final" ]]; then
echo " 3) RC entfernen -> $current_final"
fi
read -r -p "Auswahl [1]: " no_bump_choice
no_bump_choice="${no_bump_choice:-1}"
case "$no_bump_choice" in
1)
target_version="$root_version"
release_mode="Ohne Versionsaenderung"
;;
2)
if [[ -z "$next_rc" ]]; then
echo "RC-Bump ist fuer die aktuelle Version nicht verfuegbar."
exit 1
fi
target_version="$next_rc"
release_mode="RC"
apply_version_change=true
;;
3)
if [[ -z "$current_final" ]]; then
echo "RC entfernen ist nur moeglich, wenn die aktuelle Version ein -rc Suffix hat."
exit 1
fi
target_version="$current_final"
release_mode="RC entfernt"
apply_version_change=true
;;
*)
echo "Ungueltige Auswahl."
exit 1
;;
esac
;;
*)
echo "Bitte nur Y oder N eingeben."
exit 1
;;
esac
fi
echo
echo "Zusammenfassung:"
echo " Branch: $current_branch -> $selected_remote/$target_branch"
echo " Ziel-Ref: $selected_push_ref"
echo " Modus: $release_mode"
echo " Version: $root_version -> $target_version"
if [[ "$selected_is_github" == true ]]; then
echo " GitHub: $github_release_mode"
if [[ "$github_release_mode" == "branch-force-merge" ]]; then
echo " Quelle: $github_source_branch -> $target_branch (force)"
fi
fi
confirm_or_exit "Fortfahren? [Y/n]: "
echo
if [[ "$apply_version_change" == true ]]; then
echo "Setze Version auf $target_version ..."
npm version "$target_version" --no-git-tag-version
npm version "$target_version" --no-git-tag-version --prefix frontend
npm version "$target_version" --no-git-tag-version --prefix backend
else
echo "Version bleibt bei $target_version."
fi
git add -A
echo
echo "Gestagte Aenderungen:"
git status --short
if git diff --cached --quiet; then
echo "Keine neuen Aenderungen zum Committen. Verwende aktuellen Commit fuer den Push."
else
echo
commit_message=""
while [[ -z "$commit_message" ]]; do
read -r -p "Commit-Nachricht: " commit_message
if [[ -z "$commit_message" ]]; then
echo "Commit-Nachricht darf nicht leer sein."
fi
done
git commit -m "$target_version $commit_message"
fi
echo
echo "Push vorbereiten..."
if [[ "$selected_is_github" == true ]]; then
if [[ "$github_release_mode" == "branch-force-merge" ]]; then
echo "GitHub erkannt: $github_source_branch wird mit Force nach $target_branch uebernommen."
git push "$selected_remote" "$github_source_ref:$selected_push_ref" --force
else
echo "GitHub erkannt: Squash-Commit wird erzeugt."
temp_branch="github-publish-$target_branch"
git checkout -B "$temp_branch"
first_commit="$(git rev-list --max-parents=0 HEAD)"
git reset --soft "$first_commit"
git commit -m "$target_version release snapshot"
git push "$selected_remote" "$temp_branch:$selected_push_ref" --force
git checkout "$current_branch"
git branch -D "$temp_branch"
fi
else
git push "$selected_remote" "HEAD:$selected_push_ref"
fi
deploy_script=""
if deploy_script="$(find_deploy_script)"; then
echo
echo "Starte Deploy..."
bash "$deploy_script"
echo "Deploy abgeschlossen."
fi
echo
echo "Release abgeschlossen: $target_version -> $selected_remote/$target_branch"