Files
openclaw/scripts/lib/build-metadata.sh
Peter Steinberger 7fe004d852 feat: show build identity in About screens (#103595)
* feat: show build identity in About screens

* chore: leave root changelog to release automation

* fix: translate Control UI About build details
2026-07-10 10:42:36 +01:00

120 lines
3.9 KiB
Bash

#!/usr/bin/env bash
openclaw_trim_build_metadata_value() {
local value="${1:-}"
value="${value#"${value%%[![:space:]]*}"}"
value="${value%"${value##*[![:space:]]}"}"
printf '%s' "${value}"
}
openclaw_is_full_git_commit() {
[[ "${1:-}" =~ ^[0-9a-fA-F]{40}$ ]]
}
openclaw_normalize_utc_build_timestamp() {
local value="${1:-}"
local LC_ALL=C
[[ "${value}" =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})([.][0-9]{1,3})?Z$ ]] || return 1
local year="${BASH_REMATCH[1]}"
local month="${BASH_REMATCH[2]}"
local day="${BASH_REMATCH[3]}"
local hour="${BASH_REMATCH[4]}"
local minute="${BASH_REMATCH[5]}"
local second="${BASH_REMATCH[6]}"
local fraction="${BASH_REMATCH[7]:-}"
local year_number=$((10#${year}))
local month_number=$((10#${month}))
local day_number=$((10#${day}))
local hour_number=$((10#${hour}))
local minute_number=$((10#${minute}))
local second_number=$((10#${second}))
local max_day
((month_number >= 1 && month_number <= 12)) || return 1
((hour_number <= 23 && minute_number <= 59 && second_number <= 59)) || return 1
case "${month_number}" in
1 | 3 | 5 | 7 | 8 | 10 | 12) max_day=31 ;;
4 | 6 | 9 | 11) max_day=30 ;;
2)
max_day=28
if ((year_number % 400 == 0 || (year_number % 4 == 0 && year_number % 100 != 0))); then
max_day=29
fi
;;
esac
((day_number >= 1 && day_number <= max_day)) || return 1
fraction="${fraction#.}"
case "${#fraction}" in
0) fraction="000" ;;
1) fraction="${fraction}00" ;;
2) fraction="${fraction}0" ;;
esac
printf '%s-%s-%sT%s:%s:%s.%sZ' \
"${year}" "${month}" "${day}" "${hour}" "${minute}" "${second}" "${fraction}"
}
openclaw_is_utc_build_timestamp() {
openclaw_normalize_utc_build_timestamp "${1:-}" >/dev/null
}
openclaw_resolve_git_commit() {
local root_dir="$1"
local candidate
local source_name
for source_name in GIT_COMMIT GIT_SHA; do
candidate="$(openclaw_trim_build_metadata_value "${!source_name:-}")"
[[ -n "${candidate}" ]] && break
done
if [[ -n "${candidate}" ]]; then
if ! openclaw_is_full_git_commit "${candidate}"; then
echo "ERROR: ${source_name} must be a full 40-character hexadecimal commit." >&2
return 1
fi
printf '%s' "${candidate}" | tr '[:upper:]' '[:lower:]'
return 0
fi
candidate="$( (cd "${root_dir}" && git rev-parse HEAD) 2>/dev/null || true)"
if [[ -n "${candidate}" ]] && ! openclaw_is_full_git_commit "${candidate}"; then
echo "ERROR: git rev-parse HEAD must return a full 40-character hexadecimal commit." >&2
return 1
fi
# GITHUB_SHA names the workflow invocation and can differ from a checked-out tag.
if [[ -z "${candidate}" ]]; then
candidate="$(openclaw_trim_build_metadata_value "${GITHUB_SHA:-}")"
if [[ -n "${candidate}" ]] && ! openclaw_is_full_git_commit "${candidate}"; then
echo "ERROR: GITHUB_SHA must be a full 40-character hexadecimal commit." >&2
return 1
fi
fi
if [[ -z "${candidate}" ]]; then
if [[ "${OPENCLAW_REQUIRE_BUILD_METADATA:-0}" == "1" ]]; then
echo "ERROR: Unable to resolve a full Git commit for the release build." >&2
return 1
fi
printf 'unknown'
return 0
fi
printf '%s' "${candidate}" | tr '[:upper:]' '[:lower:]'
}
openclaw_resolve_build_timestamp() {
local candidate
candidate="$(openclaw_trim_build_metadata_value "${OPENCLAW_BUILD_TIMESTAMP:-}")"
if [[ -n "${candidate}" ]]; then
if ! candidate="$(openclaw_normalize_utc_build_timestamp "${candidate}")"; then
echo "ERROR: OPENCLAW_BUILD_TIMESTAMP must be an ISO-8601 UTC timestamp." >&2
return 1
fi
else
candidate="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
if ! candidate="$(openclaw_normalize_utc_build_timestamp "${candidate}")"; then
echo "ERROR: Unable to resolve an ISO-8601 UTC timestamp for the build." >&2
return 1
fi
fi
printf '%s' "${candidate}"
}