feat: add tauri desktop app (#1478)
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
TMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||
OUT_FILE="$TMP_DIR/out"
|
||||
ERR_FILE="$TMP_DIR/err"
|
||||
|
||||
fail() {
|
||||
echo "FAIL: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
pass() {
|
||||
echo "PASS: $*"
|
||||
}
|
||||
|
||||
write_runtime() {
|
||||
local dir="$1"
|
||||
local helper="${2:-with-helper}"
|
||||
mkdir -p "$dir/bin"
|
||||
printf '#!/usr/bin/env bash\nexit 0\n' > "$dir/bin/kandev"
|
||||
printf '#!/usr/bin/env bash\nexit 0\n' > "$dir/bin/agentctl"
|
||||
if [ "$helper" = "with-helper" ]; then
|
||||
printf '#!/usr/bin/env bash\nexit 0\n' > "$dir/bin/agentctl-linux-amd64"
|
||||
fi
|
||||
}
|
||||
|
||||
chmod_runtime() {
|
||||
local dir="$1"
|
||||
chmod +x "$dir/bin/kandev" "$dir/bin/agentctl"
|
||||
if [ -f "$dir/bin/agentctl-linux-amd64" ]; then
|
||||
chmod +x "$dir/bin/agentctl-linux-amd64"
|
||||
fi
|
||||
}
|
||||
|
||||
runtime_dir="$TMP_DIR/runtime"
|
||||
write_runtime "$runtime_dir"
|
||||
|
||||
if "$ROOT_DIR/scripts/release/verify-desktop-runtime.sh" --platform macos-arm64 "$runtime_dir" >"$OUT_FILE" 2>"$ERR_FILE"; then
|
||||
fail "verify-desktop-runtime should reject non-executable binaries"
|
||||
fi
|
||||
grep -q "not executable" "$ERR_FILE" || fail "verify-desktop-runtime did not explain non-executable binaries"
|
||||
pass "verify-desktop-runtime rejects non-executable binaries"
|
||||
|
||||
chmod_runtime "$runtime_dir"
|
||||
"$ROOT_DIR/scripts/release/verify-desktop-runtime.sh" --platform macos-arm64 "$runtime_dir" >"$OUT_FILE"
|
||||
grep -q "verified for macos-arm64" "$OUT_FILE" || fail "verify-desktop-runtime did not include platform output"
|
||||
pass "verify-desktop-runtime accepts executable runtime"
|
||||
|
||||
missing_helper_runtime_dir="$TMP_DIR/missing-helper-runtime"
|
||||
write_runtime "$missing_helper_runtime_dir" without-helper
|
||||
chmod_runtime "$missing_helper_runtime_dir"
|
||||
if "$ROOT_DIR/scripts/release/verify-desktop-runtime.sh" --platform linux-x64 "$missing_helper_runtime_dir" >"$OUT_FILE" 2>"$ERR_FILE"; then
|
||||
fail "verify-desktop-runtime should require helper for linux-x64"
|
||||
fi
|
||||
grep -q "Missing agentctl linux/amd64 helper" "$ERR_FILE" || fail "verify-desktop-runtime did not explain missing helper"
|
||||
pass "verify-desktop-runtime requires helper for linux-x64 runtime"
|
||||
|
||||
linux_output_dir="$TMP_DIR/linux-output"
|
||||
"$ROOT_DIR/scripts/release/prepare-desktop-runtime.sh" \
|
||||
--bundle-dir "$runtime_dir" \
|
||||
--platform linux-x64 \
|
||||
--output-dir "$linux_output_dir" >"$OUT_FILE"
|
||||
grep -q "prepared for linux-x64" "$OUT_FILE" || fail "prepare-desktop-runtime did not include platform output"
|
||||
if [ ! -x "$linux_output_dir/bin/agentctl-linux-amd64" ]; then
|
||||
fail "prepare-desktop-runtime should copy executable helper for linux-x64"
|
||||
fi
|
||||
pass "prepare-desktop-runtime copies helper for linux-x64"
|
||||
|
||||
macos_output_dir="$TMP_DIR/macos-output"
|
||||
"$ROOT_DIR/scripts/release/prepare-desktop-runtime.sh" \
|
||||
--bundle-dir "$runtime_dir" \
|
||||
--platform macos-arm64 \
|
||||
--output-dir "$macos_output_dir" >/dev/null
|
||||
if [ ! -x "$macos_output_dir/bin/agentctl-linux-amd64" ]; then
|
||||
fail "prepare-desktop-runtime should copy executable helper for macos-arm64"
|
||||
fi
|
||||
pass "prepare-desktop-runtime copies helper for non-linux-x64"
|
||||
|
||||
if "$ROOT_DIR/scripts/release/prepare-desktop-runtime.sh" --bundle-dir "$runtime_dir" --output-dir / >"$OUT_FILE" 2>"$ERR_FILE"; then
|
||||
fail "prepare-desktop-runtime should reject root output directory"
|
||||
fi
|
||||
grep -q "Refusing dangerous desktop runtime output directory" "$ERR_FILE" || fail "prepare-desktop-runtime did not explain dangerous output directory"
|
||||
pass "prepare-desktop-runtime rejects dangerous output directory"
|
||||
|
||||
safe_cwd="$TMP_DIR/safe-cwd"
|
||||
mkdir -p "$safe_cwd"
|
||||
if (cd "$safe_cwd" && "$ROOT_DIR/scripts/release/prepare-desktop-runtime.sh" --bundle-dir "$runtime_dir" --output-dir . >"$OUT_FILE" 2>"$ERR_FILE"); then
|
||||
fail "prepare-desktop-runtime should reject current-directory output"
|
||||
fi
|
||||
grep -q "Refusing dangerous desktop runtime output directory" "$ERR_FILE" || fail "prepare-desktop-runtime did not explain current-directory output"
|
||||
pass "prepare-desktop-runtime rejects current-directory output"
|
||||
|
||||
assets_dir="$TMP_DIR/assets"
|
||||
mkdir -p "$assets_dir"
|
||||
artifact="$assets_dir/kandev-desktop-linux-x64-test.deb"
|
||||
printf 'desktop artifact\n' > "$artifact"
|
||||
(cd "$assets_dir" && shasum -a 256 "$(basename "$artifact")" > "$(basename "$artifact").sha256")
|
||||
"$ROOT_DIR/scripts/release/verify-desktop-assets.sh" "$assets_dir" linux-x64 >/dev/null
|
||||
pass "verify-desktop-assets accepts matching checksums"
|
||||
|
||||
printf 'tampered artifact\n' > "$artifact"
|
||||
if "$ROOT_DIR/scripts/release/verify-desktop-assets.sh" "$assets_dir" linux-x64 >"$OUT_FILE" 2>"$ERR_FILE"; then
|
||||
fail "verify-desktop-assets should reject checksum mismatches"
|
||||
fi
|
||||
grep -q "Checksum verification failed" "$ERR_FILE" || fail "verify-desktop-assets did not explain checksum mismatch"
|
||||
pass "verify-desktop-assets rejects checksum mismatches"
|
||||
Executable
+114
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copy the native release bundle into the resource layout used by Tauri.
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: prepare-desktop-runtime.sh [--bundle-dir DIR] [--output-dir DIR] [--platform PLATFORM]
|
||||
|
||||
Prepare apps/desktop/src-tauri/resources/kandev from an existing release
|
||||
runtime bundle. The input bundle must contain:
|
||||
|
||||
bin/kandev[.exe]
|
||||
bin/agentctl[.exe]
|
||||
bin/agentctl-linux-amd64
|
||||
|
||||
Options:
|
||||
--bundle-dir DIR Source runtime bundle. Defaults to dist/kandev.
|
||||
--output-dir DIR Destination runtime resource directory.
|
||||
Defaults to apps/desktop/src-tauri/resources/kandev.
|
||||
--platform NAME Release platform to include in verification output.
|
||||
-h, --help Show this help.
|
||||
EOF
|
||||
}
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
BUNDLE_DIR="${ROOT_DIR}/dist/kandev"
|
||||
OUTPUT_DIR="${ROOT_DIR}/apps/desktop/src-tauri/resources/kandev"
|
||||
VERIFY_SCRIPT="${ROOT_DIR}/scripts/release/verify-desktop-runtime.sh"
|
||||
PLATFORM=""
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--bundle-dir)
|
||||
BUNDLE_DIR="${2:?Missing value for --bundle-dir}"
|
||||
shift 2
|
||||
;;
|
||||
--output-dir)
|
||||
OUTPUT_DIR="${2:?Missing value for --output-dir}"
|
||||
shift 2
|
||||
;;
|
||||
--platform)
|
||||
PLATFORM="${2:?Missing value for --platform}"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
printf 'Unknown argument: %s\n\n' "$1" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
refuse_dangerous_output_dir() {
|
||||
local output_parent output_base resolved_parent resolved_output
|
||||
case "$OUTPUT_DIR" in
|
||||
""|"."|".."|"/"|"/."|"/..")
|
||||
printf 'Refusing dangerous desktop runtime output directory: %s\n' "${OUTPUT_DIR:-<empty>}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
output_parent="$(dirname "$OUTPUT_DIR")"
|
||||
output_base="$(basename "$OUTPUT_DIR")"
|
||||
if resolved_parent="$(cd "$output_parent" 2>/dev/null && pwd -P)"; then
|
||||
resolved_output="$resolved_parent/$output_base"
|
||||
if [ "$resolved_output" = "/" ] || [ "$resolved_output" = "$ROOT_DIR" ]; then
|
||||
printf 'Refusing dangerous desktop runtime output directory: %s\n' "$OUTPUT_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
refuse_dangerous_output_dir
|
||||
chmod +x "$BUNDLE_DIR/bin/kandev" "$BUNDLE_DIR/bin/agentctl" "$BUNDLE_DIR/bin/agentctl-linux-amd64" 2>/dev/null || true
|
||||
chmod +x "$BUNDLE_DIR/bin/kandev.exe" "$BUNDLE_DIR/bin/agentctl.exe" 2>/dev/null || true
|
||||
VERIFY_ARGS=()
|
||||
if [ -n "$PLATFORM" ]; then
|
||||
VERIFY_ARGS=(--platform "$PLATFORM")
|
||||
fi
|
||||
"$VERIFY_SCRIPT" "${VERIFY_ARGS[@]}" "$BUNDLE_DIR" >/dev/null
|
||||
|
||||
rm -rf -- "$OUTPUT_DIR"
|
||||
mkdir -p "$OUTPUT_DIR/bin"
|
||||
printf '*\n!.gitignore\n' > "$OUTPUT_DIR/.gitignore"
|
||||
|
||||
copy_one() {
|
||||
local label="$1"
|
||||
shift
|
||||
local source
|
||||
for source in "$@"; do
|
||||
if [ -f "$source" ]; then
|
||||
cp "$source" "$OUTPUT_DIR/bin/$(basename "$source")"
|
||||
chmod +x "$OUTPUT_DIR/bin/$(basename "$source")" 2>/dev/null || true
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
printf 'Missing %s in %s\n' "$label" "$BUNDLE_DIR/bin" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
copy_one "Kandev launcher binary" "$BUNDLE_DIR/bin/kandev" "$BUNDLE_DIR/bin/kandev.exe"
|
||||
copy_one "agentctl binary" "$BUNDLE_DIR/bin/agentctl" "$BUNDLE_DIR/bin/agentctl.exe"
|
||||
cp "$BUNDLE_DIR/bin/agentctl-linux-amd64" "$OUTPUT_DIR/bin/agentctl-linux-amd64"
|
||||
chmod +x "$OUTPUT_DIR/bin/agentctl-linux-amd64" 2>/dev/null || true
|
||||
|
||||
"$VERIFY_SCRIPT" "${VERIFY_ARGS[@]}" "$OUTPUT_DIR" >/dev/null
|
||||
if [ -n "$PLATFORM" ]; then
|
||||
printf 'Desktop runtime prepared for %s at %s\n' "$PLATFORM" "$OUTPUT_DIR"
|
||||
else
|
||||
printf 'Desktop runtime prepared at %s\n' "$OUTPUT_DIR"
|
||||
fi
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env bash
|
||||
# Verify desktop installer artifacts and checksums before publishing a release.
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: verify-desktop-assets.sh <assets-dir> [platform...]
|
||||
|
||||
Checks that each required platform has at least one desktop artifact named:
|
||||
|
||||
kandev-desktop-<platform>-*
|
||||
|
||||
and that every matching artifact has a sibling .sha256 file. If no platform is
|
||||
given, all supported desktop platforms are required.
|
||||
EOF
|
||||
}
|
||||
|
||||
if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ASSETS_DIR="${1:?Usage: verify-desktop-assets.sh <assets-dir> [platform...]}"
|
||||
shift || true
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
REQUIRED_PLATFORMS=("$@")
|
||||
else
|
||||
REQUIRED_PLATFORMS=(macos-arm64 macos-x64 linux-x64 linux-arm64 windows-x64)
|
||||
fi
|
||||
|
||||
if [ ! -d "$ASSETS_DIR" ]; then
|
||||
echo "Missing desktop assets directory: $ASSETS_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
for platform in "${REQUIRED_PLATFORMS[@]}"; do
|
||||
artifacts=("$ASSETS_DIR"/kandev-desktop-"$platform"-*)
|
||||
found=0
|
||||
|
||||
for artifact in "${artifacts[@]}"; do
|
||||
if [[ "$artifact" == *.sha256 ]]; then
|
||||
continue
|
||||
fi
|
||||
found=$((found + 1))
|
||||
checksum_file="$artifact.sha256"
|
||||
if [ ! -f "$checksum_file" ]; then
|
||||
echo "Missing desktop checksum: $checksum_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
(
|
||||
cd "$ASSETS_DIR"
|
||||
shasum -a 256 -c "$(basename "$checksum_file")" >/dev/null
|
||||
) || {
|
||||
echo "Checksum verification failed for: $artifact" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
if [ "$found" -eq 0 ]; then
|
||||
echo "Missing desktop artifact for platform: $platform" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Desktop release assets verified in $ASSETS_DIR"
|
||||
Executable
+112
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env bash
|
||||
# Validate the runtime resource layout consumed by the Tauri desktop app.
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: verify-desktop-runtime.sh [--platform PLATFORM] [runtime-dir]
|
||||
|
||||
Validate a desktop runtime directory with this layout:
|
||||
|
||||
kandev/
|
||||
bin/
|
||||
kandev[.exe]
|
||||
agentctl[.exe]
|
||||
agentctl-linux-amd64
|
||||
|
||||
If runtime-dir is omitted, apps/desktop/src-tauri/resources/kandev is checked.
|
||||
EOF
|
||||
}
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
RUNTIME_DIR="${ROOT_DIR}/apps/desktop/src-tauri/resources/kandev"
|
||||
RUNTIME_DIR_SET=false
|
||||
PLATFORM=""
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--platform)
|
||||
PLATFORM="${2:?Missing value for --platform}"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-*)
|
||||
printf 'Unknown argument: %s\n\n' "$1" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
*)
|
||||
if [ "$RUNTIME_DIR_SET" = true ]; then
|
||||
printf 'Unexpected extra runtime directory: %s\n\n' "$1" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
fi
|
||||
RUNTIME_DIR="$1"
|
||||
RUNTIME_DIR_SET=true
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
BIN_DIR="$RUNTIME_DIR/bin"
|
||||
|
||||
is_executable_file() {
|
||||
local path="$1"
|
||||
if [ -x "$path" ]; then
|
||||
return 0
|
||||
fi
|
||||
# MSYS/Git Bash can report Windows executables differently from Unix mode bits.
|
||||
[ "${OS:-}" = "Windows_NT" ] && [[ "$path" == *.exe ]]
|
||||
}
|
||||
|
||||
require_one() {
|
||||
local label="$1"
|
||||
shift
|
||||
local candidate
|
||||
local found=""
|
||||
for candidate in "$@"; do
|
||||
if [ -f "$candidate" ]; then
|
||||
found="$candidate"
|
||||
if is_executable_file "$candidate"; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ -n "$found" ]; then
|
||||
printf '%s is not executable: %s\n' "$label" "$found" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf 'Missing %s in %s\n' "$label" "$BIN_DIR" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_executable() {
|
||||
local label="$1"
|
||||
local path="$2"
|
||||
if [ ! -f "$path" ]; then
|
||||
printf 'Missing %s at %s\n' "$label" "$path" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! is_executable_file "$path"; then
|
||||
printf '%s is not executable: %s\n' "$label" "$path" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
if [ ! -d "$BIN_DIR" ]; then
|
||||
printf 'Missing desktop runtime bin directory at %s\n' "$BIN_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
require_one "Kandev launcher binary" "$BIN_DIR/kandev" "$BIN_DIR/kandev.exe"
|
||||
require_one "agentctl binary" "$BIN_DIR/agentctl" "$BIN_DIR/agentctl.exe"
|
||||
require_executable "agentctl linux/amd64 helper" "$BIN_DIR/agentctl-linux-amd64"
|
||||
|
||||
if [ -n "$PLATFORM" ]; then
|
||||
printf 'Desktop runtime verified for %s at %s\n' "$PLATFORM" "$RUNTIME_DIR"
|
||||
else
|
||||
printf 'Desktop runtime verified at %s\n' "$RUNTIME_DIR"
|
||||
fi
|
||||
Reference in New Issue
Block a user