app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit 7a5f0b4704f8403302bf1036a376df4a80e292a2
parent 4c9054172553e738e769c741f1b29add17bf6f6f
Author: triesap <tyson@radroots.org>
Date:   Sat, 18 Apr 2026 00:17:26 +0000

app: harden macos host run lane

Diffstat:
Mplatforms/macos/Scripts/build-macos-host.sh | 49++++++++++++++++++++++++++++++++++++++-----------
Mplatforms/macos/Scripts/run-macos-host.sh | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mplatforms/macos/Scripts/test-macos-host.sh | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ascripts/launch-config.sh | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mscripts/run.sh | 116+++++++++----------------------------------------------------------------------
5 files changed, 325 insertions(+), 117 deletions(-)

diff --git a/platforms/macos/Scripts/build-macos-host.sh b/platforms/macos/Scripts/build-macos-host.sh @@ -4,16 +4,9 @@ set -euo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" platform_root="$(cd "${script_dir}/.." && pwd -P)" repo_root="$(git -C "${script_dir}" rev-parse --show-toplevel)" -configuration="${CONFIGURATION:-Debug}" +requested_configuration="${CONFIGURATION:-Debug}" bundle_name="Radroots.app" -bundle_root="${platform_root}/.derived-data/Build/Products/${configuration}/${bundle_name}" -contents_root="${bundle_root}/Contents" -executable_root="${contents_root}/MacOS" -resources_root="${contents_root}/Resources" plist_template="${platform_root}/App/Resources/Info.plist" -plist_path="${contents_root}/Info.plist" -binary_target="${executable_root}/Radroots" -app_icon_path="${resources_root}/AppIcon.icns" require_command() { if command -v "$1" >/dev/null 2>&1; then @@ -41,7 +34,27 @@ PY } cargo_target_dir() { - cargo metadata --format-version 1 --no-deps | python3 -c 'import json, sys; print(json.load(sys.stdin)["target_directory"], end="")' + ( + cd "${repo_root}" + cargo metadata --format-version 1 --no-deps | python3 -c 'import json, sys; print(json.load(sys.stdin)["target_directory"], end="")' + ) +} + +configure_build_lane() { + case "${requested_configuration}" in + Debug|debug) + bundle_configuration="Debug" + cargo_profile="debug" + ;; + Release|release) + bundle_configuration="Release" + cargo_profile="release" + ;; + *) + echo "unsupported CONFIGURATION: ${requested_configuration}" >&2 + exit 1 + ;; + esac } require_command cargo @@ -49,12 +62,26 @@ require_command git require_command python3 require_command /usr/libexec/PlistBuddy +configure_build_lane + +bundle_root="${platform_root}/.derived-data/Build/Products/${bundle_configuration}/${bundle_name}" +contents_root="${bundle_root}/Contents" +executable_root="${contents_root}/MacOS" +resources_root="${contents_root}/Resources" +plist_path="${contents_root}/Info.plist" +binary_target="${executable_root}/Radroots" +app_icon_path="${resources_root}/AppIcon.icns" + ( cd "${repo_root}" - cargo build -p radroots_app + if [[ "${cargo_profile}" == "release" ]]; then + cargo build -p radroots_app --release + else + cargo build -p radroots_app + fi ) -binary_source="$(cargo_target_dir)/debug/radroots_app" +binary_source="$(cargo_target_dir)/${cargo_profile}/radroots_app" if [[ ! -x "${binary_source}" ]]; then echo "missing desktop launcher binary: ${binary_source}" >&2 diff --git a/platforms/macos/Scripts/run-macos-host.sh b/platforms/macos/Scripts/run-macos-host.sh @@ -2,6 +2,7 @@ set -euo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +date_utc="$(date -u +%F)" require_command() { if command -v "$1" >/dev/null 2>&1; then @@ -11,7 +12,27 @@ require_command() { exit 1 } +require_env() { + local name="$1" + + if [[ -z "${!name:-}" ]]; then + echo "missing required environment variable: ${name}" >&2 + exit 1 + fi +} + +forward_signal() { + local signal="$1" + + if [[ -n "${app_pid:-}" ]] && kill -0 "${app_pid}" 2>/dev/null; then + kill "-${signal}" "${app_pid}" 2>/dev/null || kill "${app_pid}" 2>/dev/null || true + fi +} + +require_command grep require_command /usr/libexec/PlistBuddy +require_env RADROOTS_APP_RUNTIME_CONFIG_JSON +require_env RADROOTS_APP_LOCAL_LOG_ROOT app_path="$("${script_dir}/build-macos-host.sh")" plist_path="${app_path}/Contents/Info.plist" @@ -19,6 +40,43 @@ executable_name="$( /usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "${plist_path}" )" executable_path="${app_path}/Contents/MacOS/${executable_name}" +app_log_root="${RADROOTS_APP_LOCAL_LOG_ROOT}/apps/local/app/app-macos-native" +structured_log_file="${app_log_root}/${date_utc}.jsonl" +stdout_file="${app_log_root}/raw/stdout.${date_utc}.log" +stderr_file="${app_log_root}/raw/stderr.${date_utc}.log" + +mkdir -p "${app_log_root}/raw" +export RUST_LOG="${RADROOTS_APP_RUST_LOG:-info}" + +trap 'forward_signal TERM' TERM +trap 'forward_signal INT' INT +trap 'forward_signal HUP' HUP + +"${executable_path}" "$@" >>"${stdout_file}" 2>>"${stderr_file}" & +app_pid="$!" + +launch_confirmed=false +for _ in $(seq 1 100); do + if [[ -f "${structured_log_file}" ]] && grep -q '"event":"runtime.launch"' "${structured_log_file}" 2>/dev/null; then + launch_confirmed=true + break + fi + + if ! kill -0 "${app_pid}" 2>/dev/null; then + wait "${app_pid}" + exit $? + fi + + sleep 0.1 +done + +if [[ "${launch_confirmed}" != "true" ]]; then + if kill -0 "${app_pid}" 2>/dev/null; then + kill "${app_pid}" 2>/dev/null || true + wait "${app_pid}" || true + fi + echo "app launch did not emit runtime.launch within startup timeout" >&2 + exit 1 +fi -"${executable_path}" "$@" & -disown +wait "${app_pid}" diff --git a/platforms/macos/Scripts/test-macos-host.sh b/platforms/macos/Scripts/test-macos-host.sh @@ -2,6 +2,11 @@ set -euo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +platform_root="$(cd "${script_dir}/.." && pwd -P)" +repo_root="$(git -C "${script_dir}" rev-parse --show-toplevel)" +date_utc="$(date -u +%F)" + +source "${repo_root}/scripts/launch-config.sh" require_command() { if command -v "$1" >/dev/null 2>&1; then @@ -12,6 +17,7 @@ require_command() { } require_command /usr/libexec/PlistBuddy +require_command mktemp app_path="$("${script_dir}/build-macos-host.sh")" plist_path="${app_path}/Contents/Info.plist" @@ -47,3 +53,95 @@ icon_name="$( echo "missing bundle icon: ${app_path}/Contents/Resources/${icon_name}.icns" >&2 exit 1 } + +release_app_path="$( + CONFIGURATION=Release "${script_dir}/build-macos-host.sh" +)" +[[ "${release_app_path}" == "${platform_root}/.derived-data/Build/Products/Release/Radroots.app" ]] || { + echo "unexpected release bundle path: ${release_app_path}" >&2 + exit 1 +} +[[ -x "${release_app_path}/Contents/MacOS/Radroots" ]] || { + echo "missing release bundle executable: ${release_app_path}/Contents/MacOS/Radroots" >&2 + exit 1 +} + +tmp_root="$(mktemp -d)" +cleanup() { + if [[ -n "${runner_pid:-}" ]] && kill -0 "${runner_pid}" 2>/dev/null; then + kill "${runner_pid}" 2>/dev/null || true + wait "${runner_pid}" || true + fi + rm -rf "${tmp_root}" +} +trap cleanup EXIT + +runtime_mode="localhost-dev" +run_id="$(radroots_app_run_id "${runtime_mode}")" +platform_name="$(radroots_app_platform_name)" +bundle_identifier="$(radroots_app_bundle_identifier)" +local_log_root="${tmp_root}/logs" +structured_log_file="${local_log_root}/apps/local/app/app-macos-native/${date_utc}.jsonl" +latest_log_path="${local_log_root}/apps/local/app/app-macos-native/latest.jsonl" +stdout_file="${local_log_root}/apps/local/app/app-macos-native/raw/stdout.${date_utc}.log" +stderr_file="${local_log_root}/apps/local/app/app-macos-native/raw/stderr.${date_utc}.log" + +RADROOTS_APP_RUN_ID="${run_id}" \ +RADROOTS_APP_LOCAL_LOG_ROOT="${local_log_root}" \ +RADROOTS_APP_RUNTIME_CONFIG_JSON="$( + radroots_app_build_runtime_config_json \ + "${repo_root}" \ + "${runtime_mode}" \ + "${run_id}" \ + "${bundle_identifier}" \ + "${platform_name}" \ + "${local_log_root}" +)" \ +"${script_dir}/run-macos-host.sh" & +runner_pid="$!" + +launch_verified=false +for _ in $(seq 1 150); do + if [[ -f "${structured_log_file}" ]] && grep -q '"event":"runtime.launch"' "${structured_log_file}" 2>/dev/null; then + launch_verified=true + break + fi + + if ! kill -0 "${runner_pid}" 2>/dev/null; then + wait "${runner_pid}" + exit $? + fi + + sleep 0.1 +done + +[[ "${launch_verified}" == "true" ]] || { + echo "runtime.launch was not recorded by run-macos-host.sh" >&2 + exit 1 +} + +[[ -e "${latest_log_path}" ]] || { + echo "missing latest structured log alias: ${latest_log_path}" >&2 + exit 1 +} + +[[ -f "${stdout_file}" ]] || { + echo "missing raw stdout log: ${stdout_file}" >&2 + exit 1 +} + +[[ -f "${stderr_file}" ]] || { + echo "missing raw stderr log: ${stderr_file}" >&2 + exit 1 +} + +kill "${runner_pid}" 2>/dev/null || true +set +e +wait "${runner_pid}" +exit_code="$?" +set -e +[[ "${exit_code}" == "0" ]] || [[ "${exit_code}" == "143" ]] || [[ "${exit_code}" == "130" ]] || { + echo "unexpected runner exit code after termination: ${exit_code}" >&2 + exit 1 +} +runner_pid="" diff --git a/scripts/launch-config.sh b/scripts/launch-config.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash + +radroots_app_workspace_version() { + local repo_root="$1" + + python3 - <<'PY' "${repo_root}/Cargo.toml" +import re +import sys + +path = sys.argv[1] +with open(path, "r", encoding="utf-8") as handle: + cargo_toml = handle.read() + +match = re.search(r'^\[workspace\.package\][\s\S]*?^version\s*=\s*"([^"]+)"', cargo_toml, re.MULTILINE) +if not match: + raise SystemExit("missing workspace.package.version") + +print(match.group(1), end="") +PY +} + +radroots_app_runtime_mode() { + printf '%s' "${RADROOTS_APP_RUNTIME_MODE:-localhost-dev}" +} + +radroots_app_run_id() { + local runtime_mode="$1" + + if [[ -n "${RADROOTS_APP_RUN_ID:-}" ]]; then + printf '%s' "${RADROOTS_APP_RUN_ID}" + return + fi + + RADROOTS_APP_RUNTIME_MODE_FOR_RUN_ID="${runtime_mode}" python3 - <<'PY' +import os +import secrets +import time + +runtime_mode = os.environ["RADROOTS_APP_RUNTIME_MODE_FOR_RUN_ID"].strip().lower() or "unknown" +timestamp = time.strftime("%Y%m%dT%H%M%SZ", time.gmtime()) +suffix = secrets.token_hex(8) +print(f"app-{runtime_mode}-{timestamp}-{suffix}", end="") +PY +} + +radroots_app_platform_name() { + case "$(uname -s)" in + Darwin) printf 'macos' ;; + Linux) printf 'linux' ;; + *) uname -s | tr '[:upper:]' '[:lower:]' ;; + esac +} + +radroots_app_bundle_identifier() { + if [[ "$(uname -s)" == "Darwin" ]]; then + printf 'org.radroots.app.macos' + return + fi + + printf 'org.radroots.app.desktop' +} + +radroots_app_os_version() { + printf '%s-%s' "$(radroots_app_platform_name)" "$(uname -r)" +} + +radroots_app_local_log_root() { + local repo_root="$1" + + if [[ -n "${RADROOTS_APP_LOCAL_LOG_ROOT:-}" ]]; then + printf '%s' "${RADROOTS_APP_LOCAL_LOG_ROOT}" + return + fi + + printf '%s' "${repo_root}/logs" +} + +radroots_app_build_runtime_config_json() { + local repo_root="$1" + local runtime_mode="$2" + local run_id="$3" + local bundle_identifier="$4" + local platform_name="$5" + local local_log_root="$6" + + RADROOTS_APP_RUNTIME_CONFIG_SCHEMA="radroots.app.runtime-config.v1" \ + RADROOTS_APP_RUNTIME_MODE="${runtime_mode}" \ + RADROOTS_APP_RUN_ID="${run_id}" \ + RADROOTS_APP_BUNDLE_IDENTIFIER="${bundle_identifier}" \ + RADROOTS_APP_BUNDLE_NAME="Radroots" \ + RADROOTS_APP_MARKETING_VERSION="$(radroots_app_workspace_version "${repo_root}")" \ + RADROOTS_APP_BUILD_NUMBER="${RADROOTS_APP_BUILD:-dev}" \ + RADROOTS_APP_PLATFORM_NAME="${platform_name}" \ + RADROOTS_APP_OS_VERSION="$(radroots_app_os_version)" \ + RADROOTS_APP_HOST_LOCALE="${LANG:-system-default}" \ + RADROOTS_APP_RUNTIME_ORIGIN="gpui://localhost" \ + RADROOTS_APP_LOCAL_LOG_ROOT="${local_log_root}" \ + python3 - <<'PY' +import json +import os + +print(json.dumps({ + "schema_version": os.environ["RADROOTS_APP_RUNTIME_CONFIG_SCHEMA"], + "runtime_mode": os.environ["RADROOTS_APP_RUNTIME_MODE"], + "run_id": os.environ["RADROOTS_APP_RUN_ID"], + "bundle_identifier": os.environ["RADROOTS_APP_BUNDLE_IDENTIFIER"], + "bundle_name": os.environ["RADROOTS_APP_BUNDLE_NAME"], + "marketing_version": os.environ["RADROOTS_APP_MARKETING_VERSION"], + "build_number": os.environ["RADROOTS_APP_BUILD_NUMBER"], + "platform_name": os.environ["RADROOTS_APP_PLATFORM_NAME"], + "operating_system_version": os.environ["RADROOTS_APP_OS_VERSION"], + "host_locale": os.environ["RADROOTS_APP_HOST_LOCALE"], + "runtime_origin": os.environ["RADROOTS_APP_RUNTIME_ORIGIN"], + "local_log_root": os.environ["RADROOTS_APP_LOCAL_LOG_ROOT"], +}, sort_keys=True, separators=(",", ":")), end="") +PY +} diff --git a/scripts/run.sh b/scripts/run.sh @@ -4,119 +4,27 @@ set -euo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" repo_root="$(git -C "${script_dir}" rev-parse --show-toplevel)" -workspace_version() { - python3 - <<'PY' "${repo_root}/Cargo.toml" -import re -import sys - -path = sys.argv[1] -with open(path, "r", encoding="utf-8") as handle: - cargo_toml = handle.read() - -match = re.search(r'^\[workspace\.package\][\s\S]*?^version\s*=\s*"([^"]+)"', cargo_toml, re.MULTILINE) -if not match: - raise SystemExit("missing workspace.package.version") - -print(match.group(1), end="") -PY -} - -current_runtime_mode() { - printf '%s' "${RADROOTS_APP_RUNTIME_MODE:-localhost-dev}" -} - -current_run_id() { - if [[ -n "${RADROOTS_APP_RUN_ID:-}" ]]; then - printf '%s' "${RADROOTS_APP_RUN_ID}" - return - fi - - RADROOTS_APP_RUNTIME_MODE_FOR_RUN_ID="$(current_runtime_mode)" python3 - <<'PY' -import os -import secrets -import time - -runtime_mode = os.environ["RADROOTS_APP_RUNTIME_MODE_FOR_RUN_ID"].strip().lower() or "unknown" -timestamp = time.strftime("%Y%m%dT%H%M%SZ", time.gmtime()) -suffix = secrets.token_hex(8) -print(f"app-{runtime_mode}-{timestamp}-{suffix}", end="") -PY -} - -current_platform_name() { - case "$(uname -s)" in - Darwin) printf 'macos' ;; - Linux) printf 'linux' ;; - *) uname -s | tr '[:upper:]' '[:lower:]' ;; - esac -} - -current_bundle_identifier() { - if [[ "$(uname -s)" == "Darwin" ]]; then - printf 'org.radroots.app.macos' - return - fi - - printf 'org.radroots.app.desktop' -} - -current_os_version() { - printf '%s-%s' "$(current_platform_name)" "$(uname -r)" -} - -build_runtime_config_json() { - local runtime_mode="$1" - local run_id="$2" - local bundle_identifier="$3" - local platform_name="$4" - - RADROOTS_APP_RUNTIME_CONFIG_SCHEMA="radroots.app.runtime-config.v1" \ - RADROOTS_APP_RUNTIME_MODE="${runtime_mode}" \ - RADROOTS_APP_RUN_ID="${run_id}" \ - RADROOTS_APP_BUNDLE_IDENTIFIER="${bundle_identifier}" \ - RADROOTS_APP_BUNDLE_NAME="Radroots" \ - RADROOTS_APP_MARKETING_VERSION="$(workspace_version)" \ - RADROOTS_APP_BUILD_NUMBER="${RADROOTS_APP_BUILD:-dev}" \ - RADROOTS_APP_PLATFORM_NAME="${platform_name}" \ - RADROOTS_APP_OS_VERSION="$(current_os_version)" \ - RADROOTS_APP_HOST_LOCALE="${LANG:-system-default}" \ - RADROOTS_APP_RUNTIME_ORIGIN="gpui://localhost" \ - RADROOTS_APP_LOCAL_LOG_ROOT="${repo_root}/logs" \ - python3 - <<'PY' -import json -import os - -print(json.dumps({ - "schema_version": os.environ["RADROOTS_APP_RUNTIME_CONFIG_SCHEMA"], - "runtime_mode": os.environ["RADROOTS_APP_RUNTIME_MODE"], - "run_id": os.environ["RADROOTS_APP_RUN_ID"], - "bundle_identifier": os.environ["RADROOTS_APP_BUNDLE_IDENTIFIER"], - "bundle_name": os.environ["RADROOTS_APP_BUNDLE_NAME"], - "marketing_version": os.environ["RADROOTS_APP_MARKETING_VERSION"], - "build_number": os.environ["RADROOTS_APP_BUILD_NUMBER"], - "platform_name": os.environ["RADROOTS_APP_PLATFORM_NAME"], - "operating_system_version": os.environ["RADROOTS_APP_OS_VERSION"], - "host_locale": os.environ["RADROOTS_APP_HOST_LOCALE"], - "runtime_origin": os.environ["RADROOTS_APP_RUNTIME_ORIGIN"], - "local_log_root": os.environ["RADROOTS_APP_LOCAL_LOG_ROOT"], -}, sort_keys=True, separators=(",", ":")), end="") -PY -} +source "${script_dir}/launch-config.sh" cd "${repo_root}" -runtime_mode="$(current_runtime_mode)" -run_id="$(current_run_id)" -platform_name="$(current_platform_name)" -bundle_identifier="$(current_bundle_identifier)" +runtime_mode="$(radroots_app_runtime_mode)" +run_id="$(radroots_app_run_id "${runtime_mode}")" +platform_name="$(radroots_app_platform_name)" +bundle_identifier="$(radroots_app_bundle_identifier)" +local_log_root="$(radroots_app_local_log_root "${repo_root}")" export RADROOTS_APP_RUN_ID="${run_id}" +export RADROOTS_APP_LOCAL_LOG_ROOT="${local_log_root}" +export RUST_LOG="${RADROOTS_APP_RUST_LOG:-info}" export RADROOTS_APP_RUNTIME_CONFIG_JSON="$( - build_runtime_config_json \ + radroots_app_build_runtime_config_json \ + "${repo_root}" \ "${runtime_mode}" \ "${run_id}" \ "${bundle_identifier}" \ - "${platform_name}" + "${platform_name}" \ + "${local_log_root}" )" if [[ "$(uname -s)" == "Darwin" ]]; then