From af4a9280fc9dec3a1ce975ba11232b6f5a852303 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Fri, 7 Aug 2026 11:10:31 +0200 Subject: [PATCH 01/14] modify available versions and add update self fallback --- runs/update_available_versions.sh | 151 +++++++++++++++++++----------- runs/update_self.sh | 64 ++++++++++++- 2 files changed, 158 insertions(+), 57 deletions(-) diff --git a/runs/update_available_versions.sh b/runs/update_available_versions.sh index 0f48995fa4..4a50412715 100755 --- a/runs/update_available_versions.sh +++ b/runs/update_available_versions.sh @@ -3,41 +3,54 @@ OPENWBBASEDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) LOGFILE="${OPENWBBASEDIR}/ramdisk/versions.log" GITREMOTE="origin" YOURCHARGEPREFIX="yc/" +DRY_RUN=0 if [ "$(id -u -n)" != "openwb" ]; then echo "this script has to be run as user openwb" exit 1 fi -validateTag() { - branch=$1 - tag=$2 +buildTagJson() { + includeHead=$1 + shift + local -a inputTags=("$@") - case $branch in - "release" | "Release") - if [[ $tag =~ ([Rr][Cc])|([Bb]eta)|([Aa]lpha) ]] || [[ $tag =~ 1.99 ]]; then - return 1 - fi - ;; - "beta" | "Beta") - if [[ $tag =~ [Aa]lpha ]] || [[ $tag =~ 1.99 ]]; then - return 1 + { + for tagLine in "${inputTags[@]}"; do + if [[ -z $tagLine ]]; then + continue + fi + echo "${tagLine%%: *}" + echo "$tagLine" + done + if [[ $includeHead == "true" ]]; then + echo "*HEAD*" + echo "Aktuellster Stand" fi - ;; - *) - return 0 - ;; - esac + } | + jq -n -R -c 'reduce inputs as $key ({}; . + { ($key): (input) })' +} + +mqttPublish() { + if [[ $DRY_RUN -eq 0 ]]; then + mosquitto_pub -p 1886 -t "$1" -r -m "$2" + fi } -{ +writeFile() { + if [[ $DRY_RUN -eq 0 ]]; then + echo "$2" >"$1" + fi +} + +runUpdate() { echo "#### updating available version info ####" # update our local version currentCommit=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1) echo "current commit: $currentCommit" - mosquitto_pub -p 1886 -t "openWB/system/current_commit" -r -m "\"$currentCommit\"" - echo "$currentCommit" >"$OPENWBBASEDIR/web/lastcommit" + mqttPublish "openWB/system/current_commit" "\"$currentCommit\"" + writeFile "$OPENWBBASEDIR/web/lastcommit" "$currentCommit" # fetch data from git echo "fetching latest data from '$GITREMOTE'..." @@ -61,33 +74,52 @@ validateTag() { echo -n "checking commit for '$GITREMOTE/${branches[$index]}'..." availableBranches[${branches[$index]}]=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1 "$GITREMOTE/${branches[$index]}") echo "${availableBranches[${branches[$index]}]}" - echo "tags in branch:" - read -r -d '' -a tags < <(git -C "$OPENWBBASEDIR" tag -n --format "%(refname:short): %(subject)" --merged "$GITREMOTE/${branches[$index]}") - echo "${tags[*]}" - tagsJson[${branches[$index]}]=$( - for key in "${!tags[@]}"; do - if validateTag "${branches[$index]}" "${tags[${key}]//: */}"; then - echo "${tags[${key}]//: */}" - echo "${tags[${key}]}" - else - # invalid tag for this branch, skip - continue - fi - # special handling for last element in $tags - if (( key == ${#tags[@]}-1 )); then - # add tag *HEAD* if branch is not "Beta" or "Release" - if [[ ${branches[$index]} != "Beta" ]] && [[ ${branches[$index]} != "Release" ]]; then - echo "*HEAD*" - echo "Aktuellster Stand" - fi - fi - done | - jq -n -R -c 'reduce inputs as $key ({}; . + { ($key): (input) })' - ) + if [[ ${branches[$index]} == "master" ]]; then + echo "tags in branch:" + read -r -d '' -a tags < <(git -C "$OPENWBBASEDIR" tag -n --format "%(refname:short): %(subject)" --merged "$GITREMOTE/${branches[$index]}" && printf '\0') + echo "${tags[*]}" + tagsJson[${branches[$index]}]=$(buildTagJson true "${tags[@]}") + else + tagsJson[${branches[$index]}]='{"*HEAD*":"Aktuellster Stand"}' + fi echo "${branches[$index]}: ${tagsJson[${branches[$index]}]}" fi fi done + + # Build virtual Release/Beta entries from repository tags + read -r -d '' -a allTags < <(git -C "$OPENWBBASEDIR" tag -n --format "%(refname:short): %(subject)" && printf '\0') + declare -a releaseTags + declare -a betaTags + for tagLine in "${allTags[@]}"; do + tagName="${tagLine%%: *}" + if [[ $tagName =~ ^[2-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$ ]]; then + releaseTags+=("$tagLine") + betaTags+=("$tagLine") + + elif [[ $tagName =~ ^[2-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$ ]]; then + betaTags+=("$tagLine") + fi + done + + tagsJson["Release"]=$(buildTagJson false "${releaseTags[@]}") + tagsJson["Beta"]=$(buildTagJson false "${betaTags[@]}") + + latestReleaseTag=$(git -C "$OPENWBBASEDIR" tag --sort=-version:refname | grep -E -m1 '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$') + if [[ -n $latestReleaseTag ]]; then + availableBranches["Release"]=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1 "$latestReleaseTag") + else + availableBranches["Release"]=${availableBranches["master"]} + fi + + latestBetaTag=$(git -C "$OPENWBBASEDIR" tag --sort=-version:refname | grep -E -m1 '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$') + if [[ -n $latestBetaTag ]]; then + availableBranches["Beta"]=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1 "$latestBetaTag") + else + availableBranches["Beta"]=${availableBranches["master"]} + fi + echo "Release: ${tagsJson["Release"]}" + echo "Beta: ${tagsJson["Beta"]}" branchJson=$( for key in "${!availableBranches[@]}"; do echo "$key" @@ -97,23 +129,32 @@ validateTag() { jq -n -R 'reduce inputs as $key ({}; . + { ($key): { commit: (input), tags: (input|fromjson) } })' ) echo "$branchJson" - mosquitto_pub -p 1886 -t "openWB/system/available_branches" -r -m "$branchJson" + mqttPublish "openWB/system/available_branches" "$branchJson" # update current branch currentBranch=$(git -C "$OPENWBBASEDIR" branch --no-color --show-current) echo "currently selected branch: $currentBranch" - mosquitto_pub -p 1886 -t "openWB/system/current_branch" -r -m "\"$currentBranch\"" + mqttPublish "openWB/system/current_branch" "\"$currentBranch\"" - # update $currentBranch commit - currentBranchCommit=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1 "$GITREMOTE/$currentBranch") - echo "last commit in '$currentBranch' branch: $currentBranchCommit" - mosquitto_pub -p 1886 -t "openWB/system/current_branch_commit" -r -m "\"$currentBranchCommit\"" - - # list missing commits + # update $currentBranch commit and list missing commits + remoteCurrentBranch="$GITREMOTE/$currentBranch" echo "changes:" - IFS=$'\n' - read -r -d '' -a commitDiff < <(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h] - %s' "$currentBranch..$GITREMOTE/$currentBranch") + if [[ -n $currentBranch ]] && git -C "$OPENWBBASEDIR" show-ref --verify --quiet "refs/remotes/$remoteCurrentBranch"; then + currentBranchCommit=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1 "$remoteCurrentBranch") + echo "last commit in '$currentBranch' branch: $currentBranchCommit" + mqttPublish "openWB/system/current_branch_commit" "\"$currentBranchCommit\"" + IFS=$'\n' + read -r -d '' -a commitDiff < <(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h] - %s' "$currentBranch..$remoteCurrentBranch" && printf '\0') + else + currentBranchCommit=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1) + echo "no remote branch '$remoteCurrentBranch' found, using local HEAD commit" + echo "last commit in '$currentBranch' branch: $currentBranchCommit" + mqttPublish "openWB/system/current_branch_commit" "\"$currentBranchCommit\"" + commitDiff=() + fi printf "* %s\n" "${commitDiff[@]}" commitDiffMessage=$(jq --compact-output --null-input '$ARGS.positional' --args -- "${commitDiff[@]}") - mosquitto_pub -p 1886 -t "openWB/system/current_missing_commits" -r -m "$commitDiffMessage" -} >"$LOGFILE" 2>&1 + mqttPublish "openWB/system/current_missing_commits" "$commitDiffMessage" +} + +runUpdate >"$LOGFILE" 2>&1 diff --git a/runs/update_self.sh b/runs/update_self.sh index 00b4145214..7a4dbecfaa 100755 --- a/runs/update_self.sh +++ b/runs/update_self.sh @@ -6,6 +6,48 @@ SELECTEDBRANCH="$1" DEFAULTTAG="*HEAD*" SELECTEDTAG=$2 +latestTagByPattern() { + local pattern=$1 + git -C "$OPENWBBASEDIR" tag --sort=-version:refname | grep -E -m1 "$pattern" +} + +extractBaseVersion() { + local tag=$1 + echo "$tag" | sed -E 's/-Patch\.[0-9]+$//; s/-Beta\.[0-9]+$//; s/-[Rr][Cc]\.[0-9]+$//' +} + +highestBaseByPattern() { + local pattern=$1 + local tag + tag=$(latestTagByPattern "$pattern") || return 1 + extractBaseVersion "$tag" +} + +selectFallbackTag() { + local baseVersion + local basePattern + + case "$SELECTEDBRANCH" in + "Release") + baseVersion=$(highestBaseByPattern '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$') || return 1 + basePattern=${baseVersion//./\\.} + latestTagByPattern "^${basePattern}-Patch\\.[0-9]+$" || + latestTagByPattern "^${basePattern}$" + ;; + "Beta") + baseVersion=$(highestBaseByPattern '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$') || return 1 + basePattern=${baseVersion//./\\.} + latestTagByPattern "^${basePattern}-Patch\\.[0-9]+$" || + latestTagByPattern "^${basePattern}$" || + latestTagByPattern "^${basePattern}-[Rr][Cc]\\.[0-9]+$" || + latestTagByPattern "^${basePattern}-Beta\\.[0-9]+$" + ;; + *) + return 1 + ;; + esac +} + echo "#### running update ####" >"$LOGFILE" { @@ -13,9 +55,22 @@ echo "#### running update ####" >"$LOGFILE" echo "#### 1. fetching latest data from '$GITREMOTE' ####" git -C "$OPENWBBASEDIR" fetch -v "$GITREMOTE" && echo "#### done" + if [[ -z $SELECTEDTAG ]] || [[ $SELECTEDTAG == "$DEFAULTTAG" ]]; then + fallbackTag=$(selectFallbackTag) + if [[ -n $fallbackTag ]]; then + echo "#### using fallback tag '$fallbackTag' for branch '$SELECTEDBRANCH' ####" + SELECTEDTAG="$fallbackTag" + fi + fi + # checkout selected branch echo "#### 2. checkout selected branch '$SELECTEDBRANCH'" - git -C "$OPENWBBASEDIR" checkout --force "$SELECTEDBRANCH" && echo "#### done" + if git -C "$OPENWBBASEDIR" show-ref --verify --quiet "refs/heads/$SELECTEDBRANCH"; then + git -C "$OPENWBBASEDIR" checkout --force "$SELECTEDBRANCH" && echo "#### done" + else + echo "#### ERROR: local branch '$SELECTEDBRANCH' not found, aborting update ####" + exit 1 + fi # reset to latest revision or selected tag echo "#### 3. reset working dir ###" @@ -25,7 +80,12 @@ echo "#### running update ####" >"$LOGFILE" echo "#### selected tag: '$SELECTEDTAG'" resetTarget="$SELECTEDTAG" else - echo "#### no tag or default selected, resetting to latest revision" + if git -C "$OPENWBBASEDIR" show-ref --verify --quiet "refs/remotes/$GITREMOTE/$SELECTEDBRANCH"; then + echo "#### no tag or default selected, resetting to latest revision" + else + echo "#### no remote branch '$GITREMOTE/$SELECTEDBRANCH', keeping current checkout ####" + resetTarget="HEAD" + fi fi git -C "$OPENWBBASEDIR" reset --hard "$resetTarget" && echo "#### done" From 7c04b84714188c9d8b2698f62febefe76e41e2fb Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 10 Aug 2026 09:54:26 +0200 Subject: [PATCH 02/14] rewrite update_self.sh --- runs/update_available_versions.sh | 56 +++++----- runs/update_self.sh | 164 +++++++++++++++++++++++------- 2 files changed, 153 insertions(+), 67 deletions(-) diff --git a/runs/update_available_versions.sh b/runs/update_available_versions.sh index 4a50412715..c448aa6720 100755 --- a/runs/update_available_versions.sh +++ b/runs/update_available_versions.sh @@ -1,9 +1,9 @@ #!/bin/bash -OPENWBBASEDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) -LOGFILE="${OPENWBBASEDIR}/ramdisk/versions.log" -GITREMOTE="origin" -YOURCHARGEPREFIX="yc/" -DRY_RUN=0 +OPENWB_BASE_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +LOG_FILE="${OPENWB_BASE_DIR}/ramdisk/versions.log" +GIT_REMOTE="origin" +YOUR_CHARGE_PREFIX="yc/" +DRY_RUN=0 # set to 1 for testing without writing to files or publishing to MQTT if [ "$(id -u -n)" != "openwb" ]; then echo "this script has to be run as user openwb" @@ -47,36 +47,36 @@ runUpdate() { echo "#### updating available version info ####" # update our local version - currentCommit=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1) + currentCommit=$(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h]' -n1) echo "current commit: $currentCommit" mqttPublish "openWB/system/current_commit" "\"$currentCommit\"" - writeFile "$OPENWBBASEDIR/web/lastcommit" "$currentCommit" + writeFile "$OPENWB_BASE_DIR/web/lastcommit" "$currentCommit" # fetch data from git - echo "fetching latest data from '$GITREMOTE'..." - git -C "$OPENWBBASEDIR" fetch --verbose --prune --tags --prune-tags --force "$GITREMOTE" && echo "done" + echo "fetching latest data from '$GIT_REMOTE'..." + git -C "$OPENWB_BASE_DIR" fetch --verbose --prune --tags --prune-tags --force "$GIT_REMOTE" && echo "done" - # update branches from $GITREMOTE + # update branches from $GIT_REMOTE echo "branches:" IFS=$'\n' - read -r -d '' -a branches < <(git -C "$OPENWBBASEDIR" branch -r --list "$GITREMOTE/*") + read -r -d '' -a branches < <(git -C "$OPENWB_BASE_DIR" branch -r --list "$GIT_REMOTE/*") declare -A availableBranches declare -A tagsJson for index in "${!branches[@]}"; do if [[ ${branches[$index]} == *"HEAD"* ]]; then unset 'branches[$index]' else - branches[index]="${branches[$index]//*$GITREMOTE\//}" # remove leading whitespace and $GITREMOTE/ - if [[ ${branches[$index]} == *"$YOURCHARGEPREFIX"* ]]; then + branches[index]="${branches[$index]//*$GIT_REMOTE\//}" # remove leading whitespace and $GIT_REMOTE/ + if [[ ${branches[$index]} == *"$YOUR_CHARGE_PREFIX"* ]]; then echo "skipping branch '${branches[$index]}'" unset 'branches[$index]' else - echo -n "checking commit for '$GITREMOTE/${branches[$index]}'..." - availableBranches[${branches[$index]}]=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1 "$GITREMOTE/${branches[$index]}") + echo -n "checking commit for '$GIT_REMOTE/${branches[$index]}'..." + availableBranches[${branches[$index]}]=$(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h]' -n1 "$GIT_REMOTE/${branches[$index]}") echo "${availableBranches[${branches[$index]}]}" if [[ ${branches[$index]} == "master" ]]; then echo "tags in branch:" - read -r -d '' -a tags < <(git -C "$OPENWBBASEDIR" tag -n --format "%(refname:short): %(subject)" --merged "$GITREMOTE/${branches[$index]}" && printf '\0') + read -r -d '' -a tags < <(git -C "$OPENWB_BASE_DIR" tag -n --format "%(refname:short): %(subject)" --merged "$GIT_REMOTE/${branches[$index]}" && printf '\0') echo "${tags[*]}" tagsJson[${branches[$index]}]=$(buildTagJson true "${tags[@]}") else @@ -88,7 +88,7 @@ runUpdate() { done # Build virtual Release/Beta entries from repository tags - read -r -d '' -a allTags < <(git -C "$OPENWBBASEDIR" tag -n --format "%(refname:short): %(subject)" && printf '\0') + read -r -d '' -a allTags < <(git -C "$OPENWB_BASE_DIR" tag -n --format "%(refname:short): %(subject)" && printf '\0') declare -a releaseTags declare -a betaTags for tagLine in "${allTags[@]}"; do @@ -105,16 +105,16 @@ runUpdate() { tagsJson["Release"]=$(buildTagJson false "${releaseTags[@]}") tagsJson["Beta"]=$(buildTagJson false "${betaTags[@]}") - latestReleaseTag=$(git -C "$OPENWBBASEDIR" tag --sort=-version:refname | grep -E -m1 '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$') + latestReleaseTag=$(git -C "$OPENWB_BASE_DIR" tag --sort=-version:refname | grep -E -m1 '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$') if [[ -n $latestReleaseTag ]]; then - availableBranches["Release"]=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1 "$latestReleaseTag") + availableBranches["Release"]=$(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h]' -n1 "$latestReleaseTag") else availableBranches["Release"]=${availableBranches["master"]} fi - latestBetaTag=$(git -C "$OPENWBBASEDIR" tag --sort=-version:refname | grep -E -m1 '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$') + latestBetaTag=$(git -C "$OPENWB_BASE_DIR" tag --sort=-version:refname | grep -E -m1 '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$') if [[ -n $latestBetaTag ]]; then - availableBranches["Beta"]=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1 "$latestBetaTag") + availableBranches["Beta"]=$(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h]' -n1 "$latestBetaTag") else availableBranches["Beta"]=${availableBranches["master"]} fi @@ -132,21 +132,21 @@ runUpdate() { mqttPublish "openWB/system/available_branches" "$branchJson" # update current branch - currentBranch=$(git -C "$OPENWBBASEDIR" branch --no-color --show-current) + currentBranch=$(git -C "$OPENWB_BASE_DIR" branch --no-color --show-current) echo "currently selected branch: $currentBranch" mqttPublish "openWB/system/current_branch" "\"$currentBranch\"" # update $currentBranch commit and list missing commits - remoteCurrentBranch="$GITREMOTE/$currentBranch" + remoteCurrentBranch="$GIT_REMOTE/$currentBranch" echo "changes:" - if [[ -n $currentBranch ]] && git -C "$OPENWBBASEDIR" show-ref --verify --quiet "refs/remotes/$remoteCurrentBranch"; then - currentBranchCommit=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1 "$remoteCurrentBranch") + if [[ -n $currentBranch ]] && git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/remotes/$remoteCurrentBranch"; then + currentBranchCommit=$(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h]' -n1 "$remoteCurrentBranch") echo "last commit in '$currentBranch' branch: $currentBranchCommit" mqttPublish "openWB/system/current_branch_commit" "\"$currentBranchCommit\"" IFS=$'\n' - read -r -d '' -a commitDiff < <(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h] - %s' "$currentBranch..$remoteCurrentBranch" && printf '\0') + read -r -d '' -a commitDiff < <(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h] - %s' "$currentBranch..$remoteCurrentBranch" && printf '\0') else - currentBranchCommit=$(git -C "$OPENWBBASEDIR" log --pretty='format:%ci [%h]' -n1) + currentBranchCommit=$(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h]' -n1) echo "no remote branch '$remoteCurrentBranch' found, using local HEAD commit" echo "last commit in '$currentBranch' branch: $currentBranchCommit" mqttPublish "openWB/system/current_branch_commit" "\"$currentBranchCommit\"" @@ -157,4 +157,4 @@ runUpdate() { mqttPublish "openWB/system/current_missing_commits" "$commitDiffMessage" } -runUpdate >"$LOGFILE" 2>&1 +runUpdate >"$LOG_FILE" 2>&1 diff --git a/runs/update_self.sh b/runs/update_self.sh index 7a4dbecfaa..75ce2bc24d 100755 --- a/runs/update_self.sh +++ b/runs/update_self.sh @@ -1,14 +1,15 @@ #!/bin/bash -OPENWBBASEDIR=$(cd "$(dirname "$0")/../" && pwd) -LOGFILE="${OPENWBBASEDIR}/data/log/update.log" -GITREMOTE="origin" -SELECTEDBRANCH="$1" -DEFAULTTAG="*HEAD*" -SELECTEDTAG=$2 +OPENWB_BASE_DIR=$(cd "$(dirname "$0")/../" && pwd) +LOG_FILE="${OPENWB_BASE_DIR}/data/log/update.log" +GIT_REMOTE="origin" +SELECTED_BRANCH="$1" +DEFAULT_TAG="*HEAD*" +SELECTED_TAG="${2:-$DEFAULT_TAG}" +DRY_RUN=1 # set to 1 for testing without writing to files or publishing to MQTT latestTagByPattern() { local pattern=$1 - git -C "$OPENWBBASEDIR" tag --sort=-version:refname | grep -E -m1 "$pattern" + git -C "$OPENWB_BASE_DIR" tag --sort=-version:refname | grep -E -m1 "$pattern" } extractBaseVersion() { @@ -27,7 +28,7 @@ selectFallbackTag() { local baseVersion local basePattern - case "$SELECTEDBRANCH" in + case "$SELECTED_BRANCH" in "Release") baseVersion=$(highestBaseByPattern '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$') || return 1 basePattern=${baseVersion//./\\.} @@ -48,58 +49,143 @@ selectFallbackTag() { esac } -echo "#### running update ####" >"$LOGFILE" +validateTag() { + local tag=$1 + if ! git -C "$OPENWB_BASE_DIR" rev-parse --verify --quiet "$tag" >/dev/null; then + echo "#### ERROR: tag '$tag' does not exist ####" + return 1 + fi + return 0 +} + +checkoutTag() { + local tag=$1 + if [[ -n $tag ]]; then + validateTag "$tag" || return 1 + echo "#### checking out tag '$tag' ####" + if [[ $DRY_RUN -eq 0 ]]; then + git -C "$OPENWB_BASE_DIR" checkout --force "$tag" && echo "#### done" + else + echo "DRY RUN: would checkout tag '$tag'" + fi + fi +} + +validateBranch() { + local branch=$1 + if ! git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/heads/$branch"; then + echo "#### ERROR: local branch '$branch' does not exist ####" + return 1 + fi + return 0 +} + +checkoutBranch() { + local branch=$1 + if [[ -n $branch ]]; then + echo "#### checking out branch '$branch' ####" + if [[ $DRY_RUN -eq 0 ]]; then + git -C "$OPENWB_BASE_DIR" checkout --force "$branch" && echo "#### done" + else + echo "DRY RUN: would checkout branch '$branch'" + fi + fi +} + +echo "#### running update ####" >"$LOG_FILE" { + if [[ -z $SELECTED_BRANCH ]]; then + echo "#### ERROR: no branch selected, aborting update ####" + exit 1 + fi + # fetch new release from GitHub - echo "#### 1. fetching latest data from '$GITREMOTE' ####" - git -C "$OPENWBBASEDIR" fetch -v "$GITREMOTE" && echo "#### done" + echo "#### 1. fetching latest data from '$GIT_REMOTE' ####" + git -C "$OPENWB_BASE_DIR" fetch -v "$GIT_REMOTE" && echo "#### done" - if [[ -z $SELECTEDTAG ]] || [[ $SELECTEDTAG == "$DEFAULTTAG" ]]; then + if [[ -z $SELECTED_TAG ]] || [[ $SELECTED_TAG == "$DEFAULT_TAG" ]]; then fallbackTag=$(selectFallbackTag) if [[ -n $fallbackTag ]]; then - echo "#### using fallback tag '$fallbackTag' for branch '$SELECTEDBRANCH' ####" - SELECTEDTAG="$fallbackTag" + echo "#### using fallback tag '$fallbackTag' for branch '$SELECTED_BRANCH' ####" + SELECTED_TAG="$fallbackTag" fi fi - # checkout selected branch - echo "#### 2. checkout selected branch '$SELECTEDBRANCH'" - if git -C "$OPENWBBASEDIR" show-ref --verify --quiet "refs/heads/$SELECTEDBRANCH"; then - git -C "$OPENWBBASEDIR" checkout --force "$SELECTEDBRANCH" && echo "#### done" - else - echo "#### ERROR: local branch '$SELECTEDBRANCH' not found, aborting update ####" - exit 1 + # check if selected tag exists + if [[ -n $SELECTED_TAG ]] && [[ $SELECTED_TAG != "$DEFAULT_TAG" ]]; then + if ! validateTag "$SELECTED_TAG"; then + echo "#### ERROR: selected tag '$SELECTED_TAG' does not exist, aborting update ####" + exit 1 + fi fi - # reset to latest revision or selected tag - echo "#### 3. reset working dir ###" - resetTarget="$GITREMOTE/$SELECTEDBRANCH" - echo "SELECTEDTAG: $SELECTEDTAG" - if [[ -n $SELECTEDTAG ]] && [[ $SELECTEDTAG != "$DEFAULTTAG" ]]; then - echo "#### selected tag: '$SELECTEDTAG'" - resetTarget="$SELECTEDTAG" + # checkout tag if selected and branch is "Release" or "Beta", as tags are not part of any branch + if [[ $SELECTED_BRANCH == "Release" || $SELECTED_BRANCH == "Beta" ]]; then + if [[ -n $SELECTED_TAG ]] && [[ $SELECTED_TAG != "$DEFAULT_TAG" ]]; then + echo "#### 2. checkout selected tag '$SELECTED_TAG' for virtual branch '$SELECTED_BRANCH' ####" + checkoutTag "$SELECTED_TAG" + fi else - if git -C "$OPENWBBASEDIR" show-ref --verify --quiet "refs/remotes/$GITREMOTE/$SELECTEDBRANCH"; then - echo "#### no tag or default selected, resetting to latest revision" + # checkout selected branch + echo "#### 2. checkout selected branch ####" + if ! validateBranch "$SELECTED_BRANCH"; then + echo "#### ERROR: selected branch '$SELECTED_BRANCH' does not exist, aborting update ####" + exit 1 + fi + checkoutBranch "$SELECTED_BRANCH" + # set Selected_Tag to default if branch is not "master" + if [[ $SELECTED_BRANCH != "master" ]]; then + echo "#### branch '$SELECTED_BRANCH' is not 'master', ignoring selected tag and using default tag '$DEFAULT_TAG' ####" + SELECTED_TAG="$DEFAULT_TAG" + fi + # reset to latest revision or selected tag + echo "#### 3. reset working dir ###" + resetTarget="$GIT_REMOTE/$SELECTED_BRANCH" + echo "#### SELECTED_TAG: $SELECTED_TAG ####" + if [[ -n $SELECTED_TAG ]] && [[ $SELECTED_TAG != "$DEFAULT_TAG" ]]; then + echo "#### resetting working dir to selected tag '$SELECTED_TAG' ####" + resetTarget="$SELECTED_TAG" else - echo "#### no remote branch '$GITREMOTE/$SELECTEDBRANCH', keeping current checkout ####" - resetTarget="HEAD" + if git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/remotes/$GIT_REMOTE/$SELECTED_BRANCH"; then + echo "#### no tag or default selected, resetting to latest revision" + else + echo "#### no remote branch '$GIT_REMOTE/$SELECTED_BRANCH', keeping current checkout ####" + resetTarget="HEAD" + fi + fi + + if [[ $DRY_RUN -eq 0 ]]; then + echo "#### resetting working dir to '$resetTarget' ####" + git -C "$OPENWB_BASE_DIR" reset --hard "$resetTarget" && echo "#### done" + else + echo "DRY RUN: would reset working dir to '$resetTarget'" fi fi - git -C "$OPENWBBASEDIR" reset --hard "$resetTarget" && echo "#### done" # clean mosquitto configuration directory to remove possibly outdated files - echo "#### 4. clean mosquitto configuration, will be recreated on next boot" - sudo rm -v -f /etc/mosquitto/conf.d/openwb-*.conf + echo "#### 4. clean mosquitto configuration, will be recreated on next boot ####" + if [[ $DRY_RUN -eq 0 ]]; then + sudo rm -v -f /etc/mosquitto/conf.d/openwb-*.conf + else + echo "DRY RUN: would remove /etc/mosquitto/conf.d/openwb-*.conf" + fi # notify system # set boot_done first to prevent flickering in gui - mosquitto_pub -p 1886 -t "openWB/system/boot_done" -r -m 'false' - mosquitto_pub -p 1886 -t "openWB/system/update_in_progress" -r -m 'false' + if [[ $DRY_RUN -eq 0 ]]; then + mosquitto_pub -p 1886 -t "openWB/system/boot_done" -r -m 'false' + mosquitto_pub -p 1886 -t "openWB/system/update_in_progress" -r -m 'false' + else + echo "DRY RUN: would publish to MQTT topics 'openWB/system/boot_done' and 'openWB/system/update_in_progress'" + fi sleep 1 # now reboot system echo "#### 5. rebooting system ####" - sudo reboot now & -} >>"$LOGFILE" 2>&1 + if [[ $DRY_RUN -eq 0 ]]; then + sudo reboot now & + else + echo "DRY RUN: would reboot system now" + fi +} >>"$LOG_FILE" 2>&1 From a0325007f1408636377ded1d4e65ed76a2fbdfaa Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Fri, 9 Oct 2026 10:20:07 +0200 Subject: [PATCH 03/14] review fixes and improvements --- runs/update_available_versions.sh | 46 ++++++++++++++- runs/update_self.sh | 93 +++++++++++-------------------- runs/update_version_helpers.sh | 44 +++++++++++++++ 3 files changed, 119 insertions(+), 64 deletions(-) create mode 100644 runs/update_version_helpers.sh diff --git a/runs/update_available_versions.sh b/runs/update_available_versions.sh index c448aa6720..c11dec99ed 100755 --- a/runs/update_available_versions.sh +++ b/runs/update_available_versions.sh @@ -5,6 +5,8 @@ GIT_REMOTE="origin" YOUR_CHARGE_PREFIX="yc/" DRY_RUN=0 # set to 1 for testing without writing to files or publishing to MQTT +source "$OPENWB_BASE_DIR/runs/update_version_helpers.sh" + if [ "$(id -u -n)" != "openwb" ]; then echo "this script has to be run as user openwb" exit 1 @@ -105,14 +107,14 @@ runUpdate() { tagsJson["Release"]=$(buildTagJson false "${releaseTags[@]}") tagsJson["Beta"]=$(buildTagJson false "${betaTags[@]}") - latestReleaseTag=$(git -C "$OPENWB_BASE_DIR" tag --sort=-version:refname | grep -E -m1 '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$') + latestReleaseTag=$(selectLatestTrainTag "Release") if [[ -n $latestReleaseTag ]]; then availableBranches["Release"]=$(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h]' -n1 "$latestReleaseTag") else availableBranches["Release"]=${availableBranches["master"]} fi - latestBetaTag=$(git -C "$OPENWB_BASE_DIR" tag --sort=-version:refname | grep -E -m1 '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$') + latestBetaTag=$(selectLatestTrainTag "Beta") if [[ -n $latestBetaTag ]]; then availableBranches["Beta"]=$(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h]' -n1 "$latestBetaTag") else @@ -133,13 +135,51 @@ runUpdate() { # update current branch currentBranch=$(git -C "$OPENWB_BASE_DIR" branch --no-color --show-current) + if [[ -z $currentBranch ]]; then + logicalBranch=$(git -C "$OPENWB_BASE_DIR" config --local --get openwb.updateBranch) + if [[ -z $logicalBranch ]]; then + local -a headTags + local train headTag + read -r -d '' -a headTags < <(git -C "$OPENWB_BASE_DIR" tag --points-at HEAD && printf '\0') + for train in Release Beta; do + for headTag in "${headTags[@]}"; do + if jq -e --arg tag "$headTag" 'has($tag)' <<<"${tagsJson[$train]}" >/dev/null; then + logicalBranch="$train" + break 2 + fi + done + done + if [[ -n $logicalBranch ]]; then + echo "inferred update branch '$logicalBranch' from tags at HEAD" + if [[ $DRY_RUN -eq 0 ]]; then + git -C "$OPENWB_BASE_DIR" config --local openwb.updateBranch "$logicalBranch" || return 1 + else + echo "DRY RUN: would persist update branch '$logicalBranch'" + fi + fi + fi + if [[ $logicalBranch == "Release" || $logicalBranch == "Beta" ]]; then + currentBranch="$logicalBranch" + fi + fi echo "currently selected branch: $currentBranch" mqttPublish "openWB/system/current_branch" "\"$currentBranch\"" # update $currentBranch commit and list missing commits remoteCurrentBranch="$GIT_REMOTE/$currentBranch" echo "changes:" - if [[ -n $currentBranch ]] && git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/remotes/$remoteCurrentBranch"; then + latestTrainTag="" + case "$currentBranch" in + "Release") latestTrainTag="$latestReleaseTag" ;; + "Beta") latestTrainTag="$latestBetaTag" ;; + esac + if [[ -n $latestTrainTag ]]; then + currentBranchCommit=$(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h]' -n1 "refs/tags/$latestTrainTag") + echo "last commit in '$currentBranch' train: $currentBranchCommit" + mqttPublish "openWB/system/current_branch_commit" "\"$currentBranchCommit\"" + IFS=$'\n' + read -r -d '' -a commitDiff < <(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h] - %s' "HEAD..refs/tags/$latestTrainTag" && printf '\0') + elif [[ -n $currentBranch ]] && git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/remotes/$remoteCurrentBranch"; then currentBranchCommit=$(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h]' -n1 "$remoteCurrentBranch") echo "last commit in '$currentBranch' branch: $currentBranchCommit" mqttPublish "openWB/system/current_branch_commit" "\"$currentBranchCommit\"" diff --git a/runs/update_self.sh b/runs/update_self.sh index 75ce2bc24d..9159fcf017 100755 --- a/runs/update_self.sh +++ b/runs/update_self.sh @@ -7,54 +7,18 @@ DEFAULT_TAG="*HEAD*" SELECTED_TAG="${2:-$DEFAULT_TAG}" DRY_RUN=1 # set to 1 for testing without writing to files or publishing to MQTT -latestTagByPattern() { - local pattern=$1 - git -C "$OPENWB_BASE_DIR" tag --sort=-version:refname | grep -E -m1 "$pattern" -} - -extractBaseVersion() { - local tag=$1 - echo "$tag" | sed -E 's/-Patch\.[0-9]+$//; s/-Beta\.[0-9]+$//; s/-[Rr][Cc]\.[0-9]+$//' -} - -highestBaseByPattern() { - local pattern=$1 - local tag - tag=$(latestTagByPattern "$pattern") || return 1 - extractBaseVersion "$tag" -} - -selectFallbackTag() { - local baseVersion - local basePattern - - case "$SELECTED_BRANCH" in - "Release") - baseVersion=$(highestBaseByPattern '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$') || return 1 - basePattern=${baseVersion//./\\.} - latestTagByPattern "^${basePattern}-Patch\\.[0-9]+$" || - latestTagByPattern "^${basePattern}$" - ;; - "Beta") - baseVersion=$(highestBaseByPattern '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$') || return 1 - basePattern=${baseVersion//./\\.} - latestTagByPattern "^${basePattern}-Patch\\.[0-9]+$" || - latestTagByPattern "^${basePattern}$" || - latestTagByPattern "^${basePattern}-[Rr][Cc]\\.[0-9]+$" || - latestTagByPattern "^${basePattern}-Beta\\.[0-9]+$" - ;; - *) - return 1 - ;; - esac -} +source "$OPENWB_BASE_DIR/runs/update_version_helpers.sh" validateTag() { local tag=$1 - if ! git -C "$OPENWB_BASE_DIR" rev-parse --verify --quiet "$tag" >/dev/null; then + if ! git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/tags/$tag"; then echo "#### ERROR: tag '$tag' does not exist ####" return 1 fi + if ! git -C "$OPENWB_BASE_DIR" rev-parse --verify --quiet "refs/tags/$tag^{commit}" >/dev/null; then + echo "#### ERROR: tag '$tag' does not resolve to a commit ####" + return 1 + fi return 0 } @@ -64,7 +28,9 @@ checkoutTag() { validateTag "$tag" || return 1 echo "#### checking out tag '$tag' ####" if [[ $DRY_RUN -eq 0 ]]; then - git -C "$OPENWB_BASE_DIR" checkout --force "$tag" && echo "#### done" + git -C "$OPENWB_BASE_DIR" checkout --detach --force "refs/tags/$tag" || return 1 + git -C "$OPENWB_BASE_DIR" config --local openwb.updateBranch "$SELECTED_BRANCH" || return 1 + echo "#### done" else echo "DRY RUN: would checkout tag '$tag'" fi @@ -73,8 +39,8 @@ checkoutTag() { validateBranch() { local branch=$1 - if ! git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/heads/$branch"; then - echo "#### ERROR: local branch '$branch' does not exist ####" + if ! git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/remotes/$GIT_REMOTE/$branch"; then + echo "#### ERROR: remote branch '$GIT_REMOTE/$branch' does not exist ####" return 1 fi return 0 @@ -85,9 +51,15 @@ checkoutBranch() { if [[ -n $branch ]]; then echo "#### checking out branch '$branch' ####" if [[ $DRY_RUN -eq 0 ]]; then - git -C "$OPENWB_BASE_DIR" checkout --force "$branch" && echo "#### done" + git -C "$OPENWB_BASE_DIR" checkout --force -B "$branch" --track "refs/remotes/$GIT_REMOTE/$branch" || return 1 + git -C "$OPENWB_BASE_DIR" config --local --unset-all openwb.updateBranch + local configStatus=$? + if [[ $configStatus -ne 0 && $configStatus -ne 5 ]]; then + return "$configStatus" + fi + echo "#### done" else - echo "DRY RUN: would checkout branch '$branch'" + echo "DRY RUN: would checkout branch '$branch' from '$GIT_REMOTE/$branch'" fi fi } @@ -102,10 +74,11 @@ echo "#### running update ####" >"$LOG_FILE" # fetch new release from GitHub echo "#### 1. fetching latest data from '$GIT_REMOTE' ####" - git -C "$OPENWB_BASE_DIR" fetch -v "$GIT_REMOTE" && echo "#### done" + git -C "$OPENWB_BASE_DIR" fetch -v --prune "$GIT_REMOTE" || exit 1 + echo "#### done" if [[ -z $SELECTED_TAG ]] || [[ $SELECTED_TAG == "$DEFAULT_TAG" ]]; then - fallbackTag=$(selectFallbackTag) + fallbackTag=$(selectLatestTrainTag "$SELECTED_BRANCH") if [[ -n $fallbackTag ]]; then echo "#### using fallback tag '$fallbackTag' for branch '$SELECTED_BRANCH' ####" SELECTED_TAG="$fallbackTag" @@ -115,7 +88,7 @@ echo "#### running update ####" >"$LOG_FILE" # check if selected tag exists if [[ -n $SELECTED_TAG ]] && [[ $SELECTED_TAG != "$DEFAULT_TAG" ]]; then if ! validateTag "$SELECTED_TAG"; then - echo "#### ERROR: selected tag '$SELECTED_TAG' does not exist, aborting update ####" + echo "#### ERROR: selected tag '$SELECTED_TAG' is invalid, aborting update ####" exit 1 fi fi @@ -124,16 +97,19 @@ echo "#### running update ####" >"$LOG_FILE" if [[ $SELECTED_BRANCH == "Release" || $SELECTED_BRANCH == "Beta" ]]; then if [[ -n $SELECTED_TAG ]] && [[ $SELECTED_TAG != "$DEFAULT_TAG" ]]; then echo "#### 2. checkout selected tag '$SELECTED_TAG' for virtual branch '$SELECTED_BRANCH' ####" - checkoutTag "$SELECTED_TAG" + checkoutTag "$SELECTED_TAG" || exit 1 + else + echo "#### ERROR: no tag available for virtual branch '$SELECTED_BRANCH', aborting update ####" + exit 1 fi else # checkout selected branch echo "#### 2. checkout selected branch ####" if ! validateBranch "$SELECTED_BRANCH"; then - echo "#### ERROR: selected branch '$SELECTED_BRANCH' does not exist, aborting update ####" + echo "#### ERROR: selected remote branch '$GIT_REMOTE/$SELECTED_BRANCH' does not exist, aborting update ####" exit 1 fi - checkoutBranch "$SELECTED_BRANCH" + checkoutBranch "$SELECTED_BRANCH" || exit 1 # set Selected_Tag to default if branch is not "master" if [[ $SELECTED_BRANCH != "master" ]]; then echo "#### branch '$SELECTED_BRANCH' is not 'master', ignoring selected tag and using default tag '$DEFAULT_TAG' ####" @@ -141,18 +117,13 @@ echo "#### running update ####" >"$LOG_FILE" fi # reset to latest revision or selected tag echo "#### 3. reset working dir ###" - resetTarget="$GIT_REMOTE/$SELECTED_BRANCH" + resetTarget="refs/remotes/$GIT_REMOTE/$SELECTED_BRANCH" echo "#### SELECTED_TAG: $SELECTED_TAG ####" if [[ -n $SELECTED_TAG ]] && [[ $SELECTED_TAG != "$DEFAULT_TAG" ]]; then echo "#### resetting working dir to selected tag '$SELECTED_TAG' ####" - resetTarget="$SELECTED_TAG" + resetTarget="refs/tags/$SELECTED_TAG" else - if git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/remotes/$GIT_REMOTE/$SELECTED_BRANCH"; then - echo "#### no tag or default selected, resetting to latest revision" - else - echo "#### no remote branch '$GIT_REMOTE/$SELECTED_BRANCH', keeping current checkout ####" - resetTarget="HEAD" - fi + echo "#### no tag or default selected, resetting to latest remote revision" fi if [[ $DRY_RUN -eq 0 ]]; then diff --git a/runs/update_version_helpers.sh b/runs/update_version_helpers.sh new file mode 100644 index 0000000000..afc46c1198 --- /dev/null +++ b/runs/update_version_helpers.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +latestTagByPattern() { + local pattern=$1 + git -C "$OPENWB_BASE_DIR" tag --sort=-version:refname | grep -E -m1 "$pattern" +} + +extractBaseVersion() { + local tag=$1 + echo "$tag" | sed -E 's/-Patch\.[0-9]+$//; s/-Beta\.[0-9]+$//; s/-[Rr][Cc]\.[0-9]+$//' +} + +highestBaseByPattern() { + local pattern=$1 + local tag + tag=$(latestTagByPattern "$pattern") || return 1 + extractBaseVersion "$tag" +} + +selectLatestTrainTag() { + local branch=$1 + local baseVersion + local basePattern + + case "$branch" in + "Release") + baseVersion=$(highestBaseByPattern '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$') || return 1 + basePattern=${baseVersion//./\\.} + latestTagByPattern "^${basePattern}-Patch\\.[0-9]+$" || + latestTagByPattern "^${basePattern}$" + ;; + "Beta") + baseVersion=$(highestBaseByPattern '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$') || return 1 + basePattern=${baseVersion//./\\.} + latestTagByPattern "^${basePattern}-Patch\\.[0-9]+$" || + latestTagByPattern "^${basePattern}$" || + latestTagByPattern "^${basePattern}-[Rr][Cc]\\.[0-9]+$" || + latestTagByPattern "^${basePattern}-Beta\\.[0-9]+$" + ;; + *) + return 1 + ;; + esac +} \ No newline at end of file From d825e91695e71eb652304f09968c513b627551fc Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Fri, 9 Oct 2026 10:38:05 +0200 Subject: [PATCH 04/14] fetch tags in update_self.sh --- runs/update_self.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runs/update_self.sh b/runs/update_self.sh index 9159fcf017..4816f94f0c 100755 --- a/runs/update_self.sh +++ b/runs/update_self.sh @@ -74,7 +74,7 @@ echo "#### running update ####" >"$LOG_FILE" # fetch new release from GitHub echo "#### 1. fetching latest data from '$GIT_REMOTE' ####" - git -C "$OPENWB_BASE_DIR" fetch -v --prune "$GIT_REMOTE" || exit 1 + git -C "$OPENWB_BASE_DIR" fetch -v --prune --tags --prune-tags --force "$GIT_REMOTE" || exit 1 echo "#### done" if [[ -z $SELECTED_TAG ]] || [[ $SELECTED_TAG == "$DEFAULT_TAG" ]]; then From 07761a6c2b33fdd4c0618c6b81688c7b693f295f Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Fri, 9 Oct 2026 10:38:33 +0200 Subject: [PATCH 05/14] allow major versions with more than one digit --- runs/update_available_versions.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runs/update_available_versions.sh b/runs/update_available_versions.sh index c11dec99ed..5ed42065e6 100755 --- a/runs/update_available_versions.sh +++ b/runs/update_available_versions.sh @@ -95,11 +95,11 @@ runUpdate() { declare -a betaTags for tagLine in "${allTags[@]}"; do tagName="${tagLine%%: *}" - if [[ $tagName =~ ^[2-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$ ]]; then + if [[ $tagName =~ ^([2-9]|[1-9][0-9]+)\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$ ]]; then releaseTags+=("$tagLine") betaTags+=("$tagLine") - elif [[ $tagName =~ ^[2-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$ ]]; then + elif [[ $tagName =~ ^([2-9]|[1-9][0-9]+)\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$ ]]; then betaTags+=("$tagLine") fi done From 534d847918c05c7d462557e1076018f0da34a7a2 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Fri, 9 Oct 2026 10:53:44 +0200 Subject: [PATCH 06/14] extend tag validation --- runs/update_available_versions.sh | 4 ++-- runs/update_self.sh | 6 ++++++ runs/update_version_helpers.sh | 33 ++++++++++++++++++++++++++----- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/runs/update_available_versions.sh b/runs/update_available_versions.sh index 5ed42065e6..cefa5a2e59 100755 --- a/runs/update_available_versions.sh +++ b/runs/update_available_versions.sh @@ -95,11 +95,11 @@ runUpdate() { declare -a betaTags for tagLine in "${allTags[@]}"; do tagName="${tagLine%%: *}" - if [[ $tagName =~ ^([2-9]|[1-9][0-9]+)\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$ ]]; then + if tagMatchesTrain "Release" "$tagName"; then releaseTags+=("$tagLine") betaTags+=("$tagLine") - elif [[ $tagName =~ ^([2-9]|[1-9][0-9]+)\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$ ]]; then + elif tagMatchesTrain "Beta" "$tagName"; then betaTags+=("$tagLine") fi done diff --git a/runs/update_self.sh b/runs/update_self.sh index 4816f94f0c..80703c3022 100755 --- a/runs/update_self.sh +++ b/runs/update_self.sh @@ -19,6 +19,12 @@ validateTag() { echo "#### ERROR: tag '$tag' does not resolve to a commit ####" return 1 fi + if [[ $SELECTED_BRANCH == "Release" || $SELECTED_BRANCH == "Beta" ]]; then + if ! tagMatchesTrain "$SELECTED_BRANCH" "$tag"; then + echo "#### ERROR: tag '$tag' does not belong to train '$SELECTED_BRANCH' ####" + return 1 + fi + fi return 0 } diff --git a/runs/update_version_helpers.sh b/runs/update_version_helpers.sh index afc46c1198..ddf80197b7 100644 --- a/runs/update_version_helpers.sh +++ b/runs/update_version_helpers.sh @@ -1,5 +1,28 @@ #!/bin/bash +getTrainTagPattern() { + local branch=$1 + case "$branch" in + "Release") + echo '^([2-9]|[1-9][0-9]+)\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$' + ;; + "Beta") + echo '^([2-9]|[1-9][0-9]+)\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$' + ;; + *) + return 1 + ;; + esac +} + +tagMatchesTrain() { + local branch=$1 + local tag=$2 + local pattern + pattern=$(getTrainTagPattern "$branch") || return 1 + [[ $tag =~ $pattern ]] +} + latestTagByPattern() { local pattern=$1 git -C "$OPENWB_BASE_DIR" tag --sort=-version:refname | grep -E -m1 "$pattern" @@ -21,17 +44,17 @@ selectLatestTrainTag() { local branch=$1 local baseVersion local basePattern + local trainPattern + trainPattern=$(getTrainTagPattern "$branch") || return 1 + baseVersion=$(highestBaseByPattern "$trainPattern") || return 1 + basePattern=${baseVersion//./\\.} case "$branch" in "Release") - baseVersion=$(highestBaseByPattern '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+)?$') || return 1 - basePattern=${baseVersion//./\\.} latestTagByPattern "^${basePattern}-Patch\\.[0-9]+$" || latestTagByPattern "^${basePattern}$" ;; "Beta") - baseVersion=$(highestBaseByPattern '^[0-9]+\.[0-9]+\.[0-9]+(-Patch\.[0-9]+|-Beta\.[0-9]+|-[Rr][Cc]\.[0-9]+)?$') || return 1 - basePattern=${baseVersion//./\\.} latestTagByPattern "^${basePattern}-Patch\\.[0-9]+$" || latestTagByPattern "^${basePattern}$" || latestTagByPattern "^${basePattern}-[Rr][Cc]\\.[0-9]+$" || @@ -41,4 +64,4 @@ selectLatestTrainTag() { return 1 ;; esac -} \ No newline at end of file +} From be009de6fcf9c60c6103d4cff8d6113632f329a6 Mon Sep 17 00:00:00 2001 From: benderl Date: Fri, 9 Oct 2026 15:41:34 +0200 Subject: [PATCH 07/14] Potential fix for pull request finding 'Clear update_in_progress flag on update script failures' Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- runs/update_self.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/runs/update_self.sh b/runs/update_self.sh index 80703c3022..9dac13d203 100755 --- a/runs/update_self.sh +++ b/runs/update_self.sh @@ -70,6 +70,14 @@ checkoutBranch() { fi } +clearUpdateFlagOnFailure() { + local status=$? + if [[ $status -ne 0 && $DRY_RUN -eq 0 ]]; then + mosquitto_pub -p 1886 -t "openWB/system/update_in_progress" -r -m 'false' || true + fi +} +trap clearUpdateFlagOnFailure EXIT + echo "#### running update ####" >"$LOG_FILE" { From dec5eb4ca9c7820f5c82bbd64a26269bdbd35a20 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 12 Oct 2026 12:55:29 +0200 Subject: [PATCH 08/14] use local git if offline at boot --- runs/atreboot.sh | 3 ++- runs/update_available_versions.sh | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/runs/atreboot.sh b/runs/atreboot.sh index 8166249e82..39aea4b82d 100755 --- a/runs/atreboot.sh +++ b/runs/atreboot.sh @@ -337,7 +337,8 @@ chmod 666 "$LOGFILE" echo "load versions..." "$OPENWBBASEDIR/runs/update_available_versions.sh" else - echo "no internet connection, skipping version update" + echo "no internet connection, updating versions from local git data" + "$OPENWBBASEDIR/runs/update_available_versions.sh" --no-fetch fi # set restore dir permissions to allow file upload for apache diff --git a/runs/update_available_versions.sh b/runs/update_available_versions.sh index cefa5a2e59..29c265a878 100755 --- a/runs/update_available_versions.sh +++ b/runs/update_available_versions.sh @@ -55,8 +55,12 @@ runUpdate() { writeFile "$OPENWB_BASE_DIR/web/lastcommit" "$currentCommit" # fetch data from git - echo "fetching latest data from '$GIT_REMOTE'..." - git -C "$OPENWB_BASE_DIR" fetch --verbose --prune --tags --prune-tags --force "$GIT_REMOTE" && echo "done" + if [[ ${1:-} == "--no-fetch" ]]; then + echo "skipping remote fetch, using locally cached refs" + else + echo "fetching latest data from '$GIT_REMOTE'..." + git -C "$OPENWB_BASE_DIR" fetch --verbose --prune --tags --prune-tags --force "$GIT_REMOTE" && echo "done" + fi # update branches from $GIT_REMOTE echo "branches:" @@ -197,4 +201,4 @@ runUpdate() { mqttPublish "openWB/system/current_missing_commits" "$commitDiffMessage" } -runUpdate >"$LOG_FILE" 2>&1 +runUpdate "$@" >"$LOG_FILE" 2>&1 From 1d5e90aacf7cea5bfd4f926a5adfb6ef6926f71d Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 12 Oct 2026 12:56:00 +0200 Subject: [PATCH 09/14] catch failure on git reset --- runs/update_self.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/runs/update_self.sh b/runs/update_self.sh index 9dac13d203..dd8b2a287d 100755 --- a/runs/update_self.sh +++ b/runs/update_self.sh @@ -142,7 +142,11 @@ echo "#### running update ####" >"$LOG_FILE" if [[ $DRY_RUN -eq 0 ]]; then echo "#### resetting working dir to '$resetTarget' ####" - git -C "$OPENWB_BASE_DIR" reset --hard "$resetTarget" && echo "#### done" + if ! git -C "$OPENWB_BASE_DIR" reset --hard "$resetTarget"; then + echo "#### ERROR: reset to '$resetTarget' failed, aborting update ####" + exit 1 + fi + echo "#### done" else echo "DRY RUN: would reset working dir to '$resetTarget'" fi From a3a005984b10672a4594e13357ed9607454069b7 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 12 Oct 2026 12:56:32 +0200 Subject: [PATCH 10/14] add virtual branch selection to backup --- runs/backup.sh | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/runs/backup.sh b/runs/backup.sh index 489c0040fd..18438caa6e 100755 --- a/runs/backup.sh +++ b/runs/backup.sh @@ -181,18 +181,31 @@ force_mosquitto_write() { collect_git_info() { echo "collecting git information" - if git branch --no-color --show-current >"$TEMPDIR/GIT_BRANCH"; then + if git -C "$OPENWBBASEDIR" branch --no-color --show-current >"$TEMPDIR/GIT_BRANCH"; then echo "current branch: $(<"$TEMPDIR/GIT_BRANCH")" else echo "failed to collect git branch info" return 1 fi - if git log --pretty='format:%H' -n1 >"$TEMPDIR/GIT_HASH"; then + if git -C "$OPENWBBASEDIR" log --pretty='format:%H' -n1 >"$TEMPDIR/GIT_HASH"; then echo "current commit hash: $(<"$TEMPDIR/GIT_HASH")" else echo "failed to collect git commit hash" return 1 fi + local logicalBranch="" + if [[ -z $(<"$TEMPDIR/GIT_BRANCH") ]]; then + logicalBranch=$(git -C "$OPENWBBASEDIR" config --local --get openwb.updateBranch) || logicalBranch="" + fi + case "$logicalBranch" in + "Release"|"Beta"|"") ;; + *) + echo "invalid logical update branch '$logicalBranch'" + return 1 + ;; + esac + printf '%s\n' "$logicalBranch" >"$TEMPDIR/GIT_UPDATE_BRANCH" + echo "logical update branch: $logicalBranch" return 0 } @@ -216,6 +229,7 @@ create_archive() { "${DB_FILES[@]}" \ "GIT_BRANCH" \ "GIT_HASH" \ + "GIT_UPDATE_BRANCH" \ --directory="/etc/mosquitto/" \ "conf_local.d/" \ --directory="$TARBASEDIR/" \ From a11e681e91d04b265a19c4ef666a8a1f1c4594e2 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 12 Oct 2026 12:57:54 +0200 Subject: [PATCH 11/14] handle virtual branches on restore --- runs/prepare_restore.sh | 32 ++++++++++++++++++++----- runs/restore.sh | 52 ++++++++++++++++++++++++++++++++++------- 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/runs/prepare_restore.sh b/runs/prepare_restore.sh index 184c629dd7..112050ce79 100755 --- a/runs/prepare_restore.sh +++ b/runs/prepare_restore.sh @@ -4,6 +4,7 @@ RESTORE_DIR="$OPENWB_BASE_DIR/data/restore" SOURCE_FILE="$RESTORE_DIR/restore.tar.gz" WORKING_DIR="/home/openwb/openwb_restore" LOG_FILE="$OPENWB_BASE_DIR/data/log/restore.log" +GIT_REMOTE="origin" declare resultMessage declare resultStatus @@ -12,6 +13,11 @@ declare resultStatus echo "$(date +"%Y-%m-%d %H:%M:%S") Preparation of restore started..." echo "****************************************" echo "Step 1: creating working directory \"$WORKING_DIR\"" + echo "Step 1.1: ensure working directory is empty" + if [[ -d "$WORKING_DIR" ]]; then + echo "Removing existing working directory" + sudo rm -rf "$WORKING_DIR" + fi mkdir -p "$WORKING_DIR" echo "****************************************" echo "Step 2: extract archive to working directory" @@ -54,17 +60,31 @@ declare resultStatus else echo "****************************************" echo "Step 4: sync with git" - GIT_REMOTE="origin" BRANCH=$(<"$WORKING_DIR/GIT_BRANCH") - # TAG=$(<"$WORKING_DIR/GIT_HASH") + HASH=$(<"$WORKING_DIR/GIT_HASH") + UPDATE_BRANCH="" + if [[ -f "$WORKING_DIR/GIT_UPDATE_BRANCH" ]]; then + UPDATE_BRANCH=$(<"$WORKING_DIR/GIT_UPDATE_BRANCH") + fi echo "Step 4.1: fetch info from git" - if ! git -C "$OPENWB_BASE_DIR" fetch -v "$GIT_REMOTE"; then + if [[ -n $UPDATE_BRANCH && $UPDATE_BRANCH != "Release" && $UPDATE_BRANCH != "Beta" ]]; then + echo "invalid logical update branch '$UPDATE_BRANCH'" + resultMessage="Der logische Update-Zweig des Archivs ist ungültig." + resultStatus=1 + elif [[ -n $BRANCH && -n $UPDATE_BRANCH ]]; then + echo "logical update branch requires detached HEAD" + resultMessage="Das Archiv enthält widersprüchliche Git-Zweige." + resultStatus=1 + elif ! git -C "$OPENWB_BASE_DIR" fetch -v --prune --tags --prune-tags --force "$GIT_REMOTE"; then resultMessage="Beim Abgleich mit dem openWB Git ist ein Fehler aufgetreten!" resultStatus=1 else - echo "Step 4.2: verify branch \"$BRANCH\" from archive" - if ! git -C "$OPENWB_BASE_DIR" branch | grep "$BRANCH"; then - resultMessage="Der Entwicklungszweig \"$BRANCH\" des Archivs ist ungültig." + echo "Step 4.2: verify git state from archive" + if ! git -C "$OPENWB_BASE_DIR" rev-parse --verify --quiet "$HASH^{commit}" >/dev/null; then + resultMessage="Der Git-Stand \"$HASH\" des Archivs ist ungültig." + resultStatus=1 + elif [[ -n $BRANCH ]] && ! git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/remotes/$GIT_REMOTE/$BRANCH"; then + resultMessage="Der Entwicklungszweig \"$GIT_REMOTE/$BRANCH\" des Archivs ist ungültig." resultStatus=1 else echo "Step 4.3: clean mosquitto configuration, will be recreated on next boot" diff --git a/runs/restore.sh b/runs/restore.sh index e928e19115..b4d4dcebc3 100755 --- a/runs/restore.sh +++ b/runs/restore.sh @@ -7,6 +7,7 @@ MOSQUITTO_DB_DIR="/var/lib/mosquitto" MOSQUITTO_LOCAL_DB_DIR="/var/lib/mosquitto_local" MOSQUITTO_CONF_DIR="/etc/mosquitto" LOG_FILE="$OPENWB_BASE_DIR/data/log/restore.log" +GIT_REMOTE="origin" { echo "$(date +"%Y-%m-%d %H:%M:%S") Restore of backup started..." @@ -22,19 +23,54 @@ LOG_FILE="$OPENWB_BASE_DIR/data/log/restore.log" # give systemctl some time to finish, may be unnecessary? sleep 2 echo "****************************************" - echo "Step 6: checkout matching git branch and tag" + echo "Step 6: checkout matching git branch and hash" BRANCH=$(<"$WORKING_DIR/GIT_BRANCH") - TAG=$(<"$WORKING_DIR/GIT_HASH") - echo "Step 6.1: checkout branch: $BRANCH" - if ! git -C "$OPENWB_BASE_DIR" checkout --force "$BRANCH"; then - echo "checkout of branch \"$BRANCH\" failed! aborting restore" + HASH=$(<"$WORKING_DIR/GIT_HASH") + echo "Step 6.1: checkout" + UPDATE_BRANCH="" + if [[ -f "$WORKING_DIR/GIT_UPDATE_BRANCH" ]]; then + UPDATE_BRANCH=$(<"$WORKING_DIR/GIT_UPDATE_BRANCH") + fi + case "$UPDATE_BRANCH" in + "Release"|"Beta"|"") ;; + *) + echo "invalid logical update branch '$UPDATE_BRANCH'! aborting restore" + exit 1 + ;; + esac + if [[ -n $BRANCH && -n $UPDATE_BRANCH ]]; then + echo "logical update branch requires detached HEAD! aborting restore" exit 1 fi - echo "Step 6.2: reset to matching version: [$TAG]" - if ! git -C "$OPENWB_BASE_DIR" reset --hard "$TAG"; then - echo "reset to version [$TAG] failed! aborting restore" + if [[ -z $BRANCH ]]; then + echo "Step 6.1a: checkout detached commit: $HASH" + if ! git -C "$OPENWB_BASE_DIR" checkout --detach --force "$HASH"; then + echo "checkout of commit [$HASH] failed! aborting restore" + exit 1 + fi + else + echo "Step 6.1b: checkout branch from remote: $GIT_REMOTE/$BRANCH" + if ! git -C "$OPENWB_BASE_DIR" checkout --force -B "$BRANCH" --track "refs/remotes/$GIT_REMOTE/$BRANCH"; then + echo "checkout of remote branch \"$GIT_REMOTE/$BRANCH\" failed! aborting restore" + exit 1 + fi + fi + echo "Step 6.2: reset to matching version: [$HASH]" + if ! git -C "$OPENWB_BASE_DIR" reset --hard "$HASH"; then + echo "reset to version [$HASH] failed! aborting restore" exit 1 fi + echo "Step 6.3: set logical update branch" + if [[ -n $UPDATE_BRANCH ]]; then + git -C "$OPENWB_BASE_DIR" config --local openwb.updateBranch "$UPDATE_BRANCH" || exit 1 + else + git -C "$OPENWB_BASE_DIR" config --local --unset-all openwb.updateBranch + configStatus=$? + if [[ $configStatus -ne 0 && $configStatus -ne 5 ]]; then + echo "failed to clear logical update branch! aborting restore" + exit 1 + fi + fi echo "****************************************" echo "Step 7: restore contents of backup" # we use cp not mv because of not empty directories in destination From 97d1fcbcfe2b319967440d74fe424b58081daa94 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Mon, 12 Oct 2026 13:29:08 +0200 Subject: [PATCH 12/14] centralize more helper functions to remove duplicate code --- runs/prepare_restore.sh | 12 +++++--- runs/restore.sh | 18 ++++++------ runs/update_available_versions.sh | 6 ++-- runs/update_self.sh | 12 +++----- runs/update_version_helpers.sh | 47 +++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 25 deletions(-) diff --git a/runs/prepare_restore.sh b/runs/prepare_restore.sh index 112050ce79..788e98c70e 100755 --- a/runs/prepare_restore.sh +++ b/runs/prepare_restore.sh @@ -6,6 +6,8 @@ WORKING_DIR="/home/openwb/openwb_restore" LOG_FILE="$OPENWB_BASE_DIR/data/log/restore.log" GIT_REMOTE="origin" +source "$OPENWB_BASE_DIR/runs/update_version_helpers.sh" || exit 1 + declare resultMessage declare resultStatus @@ -66,16 +68,18 @@ declare resultStatus if [[ -f "$WORKING_DIR/GIT_UPDATE_BRANCH" ]]; then UPDATE_BRANCH=$(<"$WORKING_DIR/GIT_UPDATE_BRANCH") fi + metadataStatus=0 + validateRestoreGitMetadata "$BRANCH" "$UPDATE_BRANCH" || metadataStatus=$? echo "Step 4.1: fetch info from git" - if [[ -n $UPDATE_BRANCH && $UPDATE_BRANCH != "Release" && $UPDATE_BRANCH != "Beta" ]]; then + if [[ $metadataStatus -eq 1 ]]; then echo "invalid logical update branch '$UPDATE_BRANCH'" resultMessage="Der logische Update-Zweig des Archivs ist ungültig." resultStatus=1 - elif [[ -n $BRANCH && -n $UPDATE_BRANCH ]]; then + elif [[ $metadataStatus -eq 2 ]]; then echo "logical update branch requires detached HEAD" resultMessage="Das Archiv enthält widersprüchliche Git-Zweige." resultStatus=1 - elif ! git -C "$OPENWB_BASE_DIR" fetch -v --prune --tags --prune-tags --force "$GIT_REMOTE"; then + elif ! fetchVersionRefs "$OPENWB_BASE_DIR" "$GIT_REMOTE"; then resultMessage="Beim Abgleich mit dem openWB Git ist ein Fehler aufgetreten!" resultStatus=1 else @@ -83,7 +87,7 @@ declare resultStatus if ! git -C "$OPENWB_BASE_DIR" rev-parse --verify --quiet "$HASH^{commit}" >/dev/null; then resultMessage="Der Git-Stand \"$HASH\" des Archivs ist ungültig." resultStatus=1 - elif [[ -n $BRANCH ]] && ! git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/remotes/$GIT_REMOTE/$BRANCH"; then + elif [[ -n $BRANCH ]] && ! remoteBranchExists "$OPENWB_BASE_DIR" "$GIT_REMOTE" "$BRANCH"; then resultMessage="Der Entwicklungszweig \"$GIT_REMOTE/$BRANCH\" des Archivs ist ungültig." resultStatus=1 else diff --git a/runs/restore.sh b/runs/restore.sh index b4d4dcebc3..bb4cf22bf2 100755 --- a/runs/restore.sh +++ b/runs/restore.sh @@ -9,6 +9,8 @@ MOSQUITTO_CONF_DIR="/etc/mosquitto" LOG_FILE="$OPENWB_BASE_DIR/data/log/restore.log" GIT_REMOTE="origin" +source "$OPENWB_BASE_DIR/runs/update_version_helpers.sh" || exit 1 + { echo "$(date +"%Y-%m-%d %H:%M:%S") Restore of backup started..." echo "****************************************" @@ -31,14 +33,12 @@ GIT_REMOTE="origin" if [[ -f "$WORKING_DIR/GIT_UPDATE_BRANCH" ]]; then UPDATE_BRANCH=$(<"$WORKING_DIR/GIT_UPDATE_BRANCH") fi - case "$UPDATE_BRANCH" in - "Release"|"Beta"|"") ;; - *) + metadataStatus=0 + validateRestoreGitMetadata "$BRANCH" "$UPDATE_BRANCH" || metadataStatus=$? + if [[ $metadataStatus -eq 1 ]]; then echo "invalid logical update branch '$UPDATE_BRANCH'! aborting restore" exit 1 - ;; - esac - if [[ -n $BRANCH && -n $UPDATE_BRANCH ]]; then + elif [[ $metadataStatus -eq 2 ]]; then echo "logical update branch requires detached HEAD! aborting restore" exit 1 fi @@ -62,11 +62,9 @@ GIT_REMOTE="origin" fi echo "Step 6.3: set logical update branch" if [[ -n $UPDATE_BRANCH ]]; then - git -C "$OPENWB_BASE_DIR" config --local openwb.updateBranch "$UPDATE_BRANCH" || exit 1 + setLogicalUpdateBranch "$OPENWB_BASE_DIR" "$UPDATE_BRANCH" || exit 1 else - git -C "$OPENWB_BASE_DIR" config --local --unset-all openwb.updateBranch - configStatus=$? - if [[ $configStatus -ne 0 && $configStatus -ne 5 ]]; then + if ! setLogicalUpdateBranch "$OPENWB_BASE_DIR" ""; then echo "failed to clear logical update branch! aborting restore" exit 1 fi diff --git a/runs/update_available_versions.sh b/runs/update_available_versions.sh index 29c265a878..b067c5914c 100755 --- a/runs/update_available_versions.sh +++ b/runs/update_available_versions.sh @@ -59,7 +59,7 @@ runUpdate() { echo "skipping remote fetch, using locally cached refs" else echo "fetching latest data from '$GIT_REMOTE'..." - git -C "$OPENWB_BASE_DIR" fetch --verbose --prune --tags --prune-tags --force "$GIT_REMOTE" && echo "done" + fetchVersionRefs "$OPENWB_BASE_DIR" "$GIT_REMOTE" && echo "done" fi # update branches from $GIT_REMOTE @@ -156,7 +156,7 @@ runUpdate() { if [[ -n $logicalBranch ]]; then echo "inferred update branch '$logicalBranch' from tags at HEAD" if [[ $DRY_RUN -eq 0 ]]; then - git -C "$OPENWB_BASE_DIR" config --local openwb.updateBranch "$logicalBranch" || return 1 + setLogicalUpdateBranch "$OPENWB_BASE_DIR" "$logicalBranch" || return 1 else echo "DRY RUN: would persist update branch '$logicalBranch'" fi @@ -183,7 +183,7 @@ runUpdate() { mqttPublish "openWB/system/current_branch_commit" "\"$currentBranchCommit\"" IFS=$'\n' read -r -d '' -a commitDiff < <(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h] - %s' "HEAD..refs/tags/$latestTrainTag" && printf '\0') - elif [[ -n $currentBranch ]] && git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/remotes/$remoteCurrentBranch"; then + elif [[ -n $currentBranch ]] && remoteBranchExists "$OPENWB_BASE_DIR" "$GIT_REMOTE" "$currentBranch"; then currentBranchCommit=$(git -C "$OPENWB_BASE_DIR" log --pretty='format:%ci [%h]' -n1 "$remoteCurrentBranch") echo "last commit in '$currentBranch' branch: $currentBranchCommit" mqttPublish "openWB/system/current_branch_commit" "\"$currentBranchCommit\"" diff --git a/runs/update_self.sh b/runs/update_self.sh index dd8b2a287d..c1857b04d7 100755 --- a/runs/update_self.sh +++ b/runs/update_self.sh @@ -35,7 +35,7 @@ checkoutTag() { echo "#### checking out tag '$tag' ####" if [[ $DRY_RUN -eq 0 ]]; then git -C "$OPENWB_BASE_DIR" checkout --detach --force "refs/tags/$tag" || return 1 - git -C "$OPENWB_BASE_DIR" config --local openwb.updateBranch "$SELECTED_BRANCH" || return 1 + setLogicalUpdateBranch "$OPENWB_BASE_DIR" "$SELECTED_BRANCH" || return 1 echo "#### done" else echo "DRY RUN: would checkout tag '$tag'" @@ -45,7 +45,7 @@ checkoutTag() { validateBranch() { local branch=$1 - if ! git -C "$OPENWB_BASE_DIR" show-ref --verify --quiet "refs/remotes/$GIT_REMOTE/$branch"; then + if ! remoteBranchExists "$OPENWB_BASE_DIR" "$GIT_REMOTE" "$branch"; then echo "#### ERROR: remote branch '$GIT_REMOTE/$branch' does not exist ####" return 1 fi @@ -58,11 +58,7 @@ checkoutBranch() { echo "#### checking out branch '$branch' ####" if [[ $DRY_RUN -eq 0 ]]; then git -C "$OPENWB_BASE_DIR" checkout --force -B "$branch" --track "refs/remotes/$GIT_REMOTE/$branch" || return 1 - git -C "$OPENWB_BASE_DIR" config --local --unset-all openwb.updateBranch - local configStatus=$? - if [[ $configStatus -ne 0 && $configStatus -ne 5 ]]; then - return "$configStatus" - fi + setLogicalUpdateBranch "$OPENWB_BASE_DIR" "" || return $? echo "#### done" else echo "DRY RUN: would checkout branch '$branch' from '$GIT_REMOTE/$branch'" @@ -88,7 +84,7 @@ echo "#### running update ####" >"$LOG_FILE" # fetch new release from GitHub echo "#### 1. fetching latest data from '$GIT_REMOTE' ####" - git -C "$OPENWB_BASE_DIR" fetch -v --prune --tags --prune-tags --force "$GIT_REMOTE" || exit 1 + fetchVersionRefs "$OPENWB_BASE_DIR" "$GIT_REMOTE" || exit 1 echo "#### done" if [[ -z $SELECTED_TAG ]] || [[ $SELECTED_TAG == "$DEFAULT_TAG" ]]; then diff --git a/runs/update_version_helpers.sh b/runs/update_version_helpers.sh index ddf80197b7..040861ba72 100644 --- a/runs/update_version_helpers.sh +++ b/runs/update_version_helpers.sh @@ -1,5 +1,52 @@ #!/bin/bash +fetchVersionRefs() { + local baseDir=$1 + local remote=$2 + git -C "$baseDir" fetch --verbose --prune --tags --prune-tags --force "$remote" +} + +remoteBranchExists() { + local baseDir=$1 + local remote=$2 + local branch=$3 + git -C "$baseDir" show-ref --verify --quiet "refs/remotes/$remote/$branch" +} + +setLogicalUpdateBranch() { + local baseDir=$1 + local train=$2 + case "$train" in + "Release"|"Beta") + git -C "$baseDir" config --local openwb.updateBranch "$train" + ;; + "") + local configStatus=0 + git -C "$baseDir" config --local --unset-all openwb.updateBranch || configStatus=$? + if [[ $configStatus -eq 5 ]]; then + return 0 + fi + return "$configStatus" + ;; + *) + return 1 + ;; + esac +} + +validateRestoreGitMetadata() { + local branch=$1 + local train=$2 + case "$train" in + "Release"|"Beta"|"") ;; + *) return 1 ;; + esac + if [[ -n $branch && -n $train ]]; then + return 2 + fi + return 0 +} + getTrainTagPattern() { local branch=$1 case "$branch" in From 7ca5ad94b1267c056921bf2ed1ff9db80971e8f8 Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Tue, 13 Oct 2026 08:56:31 +0200 Subject: [PATCH 13/14] centralize "applyVersion" logic for restore and update --- runs/restore.sh | 33 +++++------------ runs/update_self.sh | 65 ++++++++++------------------------ runs/update_version_helpers.sh | 29 +++++++++++++++ 3 files changed, 56 insertions(+), 71 deletions(-) diff --git a/runs/restore.sh b/runs/restore.sh index bb4cf22bf2..1bb35321fe 100755 --- a/runs/restore.sh +++ b/runs/restore.sh @@ -28,7 +28,6 @@ source "$OPENWB_BASE_DIR/runs/update_version_helpers.sh" || exit 1 echo "Step 6: checkout matching git branch and hash" BRANCH=$(<"$WORKING_DIR/GIT_BRANCH") HASH=$(<"$WORKING_DIR/GIT_HASH") - echo "Step 6.1: checkout" UPDATE_BRANCH="" if [[ -f "$WORKING_DIR/GIT_UPDATE_BRANCH" ]]; then UPDATE_BRANCH=$(<"$WORKING_DIR/GIT_UPDATE_BRANCH") @@ -43,36 +42,22 @@ source "$OPENWB_BASE_DIR/runs/update_version_helpers.sh" || exit 1 exit 1 fi if [[ -z $BRANCH ]]; then - echo "Step 6.1a: checkout detached commit: $HASH" - if ! git -C "$OPENWB_BASE_DIR" checkout --detach --force "$HASH"; then - echo "checkout of commit [$HASH] failed! aborting restore" - exit 1 - fi + echo "checkout detached commit: $HASH" else - echo "Step 6.1b: checkout branch from remote: $GIT_REMOTE/$BRANCH" - if ! git -C "$OPENWB_BASE_DIR" checkout --force -B "$BRANCH" --track "refs/remotes/$GIT_REMOTE/$BRANCH"; then - echo "checkout of remote branch \"$GIT_REMOTE/$BRANCH\" failed! aborting restore" - exit 1 - fi + echo "checkout branch from remote: $GIT_REMOTE/$BRANCH" fi - echo "Step 6.2: reset to matching version: [$HASH]" - if ! git -C "$OPENWB_BASE_DIR" reset --hard "$HASH"; then - echo "reset to version [$HASH] failed! aborting restore" + echo "apply saved version: [$HASH]" + if ! applyVersion "$OPENWB_BASE_DIR" "$GIT_REMOTE" "$BRANCH" "$HASH" "$UPDATE_BRANCH"; then + echo "applying version [$HASH] failed! aborting restore" exit 1 fi - echo "Step 6.3: set logical update branch" - if [[ -n $UPDATE_BRANCH ]]; then - setLogicalUpdateBranch "$OPENWB_BASE_DIR" "$UPDATE_BRANCH" || exit 1 - else - if ! setLogicalUpdateBranch "$OPENWB_BASE_DIR" ""; then - echo "failed to clear logical update branch! aborting restore" - exit 1 - fi - fi echo "****************************************" echo "Step 7: restore contents of backup" # we use cp not mv because of not empty directories in destination - sudo cp -v -p -r "${WORKING_DIR}/openWB/." "${OPENWB_BASE_DIR}/" + if ! sudo cp -v -p -r "${WORKING_DIR}/openWB/." "${OPENWB_BASE_DIR}/"; then + echo "restoring openWB files failed! aborting restore" + exit 1 + fi if [[ -f "$WORKING_DIR/configuration.json" ]]; then sudo mv -v -f "${WORKING_DIR}/configuration.json" "/home/openwb/" else diff --git a/runs/update_self.sh b/runs/update_self.sh index c1857b04d7..53dc979718 100755 --- a/runs/update_self.sh +++ b/runs/update_self.sh @@ -28,21 +28,6 @@ validateTag() { return 0 } -checkoutTag() { - local tag=$1 - if [[ -n $tag ]]; then - validateTag "$tag" || return 1 - echo "#### checking out tag '$tag' ####" - if [[ $DRY_RUN -eq 0 ]]; then - git -C "$OPENWB_BASE_DIR" checkout --detach --force "refs/tags/$tag" || return 1 - setLogicalUpdateBranch "$OPENWB_BASE_DIR" "$SELECTED_BRANCH" || return 1 - echo "#### done" - else - echo "DRY RUN: would checkout tag '$tag'" - fi - fi -} - validateBranch() { local branch=$1 if ! remoteBranchExists "$OPENWB_BASE_DIR" "$GIT_REMOTE" "$branch"; then @@ -52,20 +37,6 @@ validateBranch() { return 0 } -checkoutBranch() { - local branch=$1 - if [[ -n $branch ]]; then - echo "#### checking out branch '$branch' ####" - if [[ $DRY_RUN -eq 0 ]]; then - git -C "$OPENWB_BASE_DIR" checkout --force -B "$branch" --track "refs/remotes/$GIT_REMOTE/$branch" || return 1 - setLogicalUpdateBranch "$OPENWB_BASE_DIR" "" || return $? - echo "#### done" - else - echo "DRY RUN: would checkout branch '$branch' from '$GIT_REMOTE/$branch'" - fi - fi -} - clearUpdateFlagOnFailure() { local status=$? if [[ $status -ne 0 && $DRY_RUN -eq 0 ]]; then @@ -103,49 +74,49 @@ echo "#### running update ####" >"$LOG_FILE" fi fi - # checkout tag if selected and branch is "Release" or "Beta", as tags are not part of any branch + versionBranch="" + versionRef="" + logicalTrain="" if [[ $SELECTED_BRANCH == "Release" || $SELECTED_BRANCH == "Beta" ]]; then if [[ -n $SELECTED_TAG ]] && [[ $SELECTED_TAG != "$DEFAULT_TAG" ]]; then echo "#### 2. checkout selected tag '$SELECTED_TAG' for virtual branch '$SELECTED_BRANCH' ####" - checkoutTag "$SELECTED_TAG" || exit 1 + versionRef="refs/tags/$SELECTED_TAG" + logicalTrain="$SELECTED_BRANCH" else echo "#### ERROR: no tag available for virtual branch '$SELECTED_BRANCH', aborting update ####" exit 1 fi else - # checkout selected branch echo "#### 2. checkout selected branch ####" if ! validateBranch "$SELECTED_BRANCH"; then echo "#### ERROR: selected remote branch '$GIT_REMOTE/$SELECTED_BRANCH' does not exist, aborting update ####" exit 1 fi - checkoutBranch "$SELECTED_BRANCH" || exit 1 + versionBranch="$SELECTED_BRANCH" # set Selected_Tag to default if branch is not "master" if [[ $SELECTED_BRANCH != "master" ]]; then echo "#### branch '$SELECTED_BRANCH' is not 'master', ignoring selected tag and using default tag '$DEFAULT_TAG' ####" SELECTED_TAG="$DEFAULT_TAG" fi - # reset to latest revision or selected tag - echo "#### 3. reset working dir ###" - resetTarget="refs/remotes/$GIT_REMOTE/$SELECTED_BRANCH" + versionRef="refs/remotes/$GIT_REMOTE/$SELECTED_BRANCH" echo "#### SELECTED_TAG: $SELECTED_TAG ####" if [[ -n $SELECTED_TAG ]] && [[ $SELECTED_TAG != "$DEFAULT_TAG" ]]; then echo "#### resetting working dir to selected tag '$SELECTED_TAG' ####" - resetTarget="refs/tags/$SELECTED_TAG" + versionRef="refs/tags/$SELECTED_TAG" else echo "#### no tag or default selected, resetting to latest remote revision" fi + fi - if [[ $DRY_RUN -eq 0 ]]; then - echo "#### resetting working dir to '$resetTarget' ####" - if ! git -C "$OPENWB_BASE_DIR" reset --hard "$resetTarget"; then - echo "#### ERROR: reset to '$resetTarget' failed, aborting update ####" - exit 1 - fi - echo "#### done" - else - echo "DRY RUN: would reset working dir to '$resetTarget'" - fi + echo "#### 3. apply selected version '$versionRef' ####" + if ! applyVersion "$OPENWB_BASE_DIR" "$GIT_REMOTE" "$versionBranch" "$versionRef" "$logicalTrain" "$DRY_RUN"; then + echo "#### ERROR: applying version '$versionRef' failed, aborting update ####" + exit 1 + fi + if [[ $DRY_RUN -eq 0 ]]; then + echo "#### done" + else + echo "DRY RUN: would apply version '$versionRef' with branch '$versionBranch' and train '$logicalTrain'" fi # clean mosquitto configuration directory to remove possibly outdated files diff --git a/runs/update_version_helpers.sh b/runs/update_version_helpers.sh index 040861ba72..6b44678ffb 100644 --- a/runs/update_version_helpers.sh +++ b/runs/update_version_helpers.sh @@ -47,6 +47,35 @@ validateRestoreGitMetadata() { return 0 } +applyVersion() { + local baseDir=$1 + local remote=$2 + local branch=$3 + local targetRef=$4 + local train=$5 + local dryRun=${6:-0} + local targetCommit + + validateRestoreGitMetadata "$branch" "$train" || return $? + if [[ -n $branch ]]; then + remoteBranchExists "$baseDir" "$remote" "$branch" || return 1 + fi + targetCommit=$(git -C "$baseDir" rev-parse --verify --quiet "$targetRef^{commit}") || return 1 + if [[ $dryRun == "1" ]]; then + return 0 + elif [[ $dryRun != "0" ]]; then + return 1 + fi + + if [[ -z $branch ]]; then + git -C "$baseDir" checkout --detach --force "$targetCommit" || return 1 + else + git -C "$baseDir" checkout --force -B "$branch" --track "refs/remotes/$remote/$branch" || return 1 + fi + git -C "$baseDir" reset --hard "$targetCommit" || return 1 + setLogicalUpdateBranch "$baseDir" "$train" +} + getTrainTagPattern() { local branch=$1 case "$branch" in From 2fe07bc68cedc9f56c4a36b6dcbab3d0f133872f Mon Sep 17 00:00:00 2001 From: Lutz Bender Date: Tue, 13 Oct 2026 08:57:34 +0200 Subject: [PATCH 14/14] remove dry-run flag --- runs/update_self.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runs/update_self.sh b/runs/update_self.sh index 53dc979718..e2b8a82a46 100755 --- a/runs/update_self.sh +++ b/runs/update_self.sh @@ -5,7 +5,7 @@ GIT_REMOTE="origin" SELECTED_BRANCH="$1" DEFAULT_TAG="*HEAD*" SELECTED_TAG="${2:-$DEFAULT_TAG}" -DRY_RUN=1 # set to 1 for testing without writing to files or publishing to MQTT +DRY_RUN=0 # set to 1 for testing without writing to files or publishing to MQTT source "$OPENWB_BASE_DIR/runs/update_version_helpers.sh"