itsgoin/deploy.sh
Scott Reimers 7e1e1dd738 Platform: Reset wipe, empty name, Android browse + backup-off, import as personas
Reset All Data:
- Sentinel now written at the app-level data_dir instead of the
  active identity's subdir. On Android the subdir path was never
  checked at startup, so reset silently did nothing.
- On detection, wipe EVERYTHING under the app data_dir: identity.key,
  itsgoin.db + WAL + SHM, blobs, all identity subdirs. Next launch
  is truly fresh — new network key, new posting key, no prior data.

First-run name:
- Display name is optional. Blank submits as anonymous.
- First-run modal + profile overlay placeholder updated to say
  "Display name (optional)".

Android file picker:
- pick_file on Android now uses tauri-plugin-android-fs'
  show_open_file_dialog (Storage Access Framework OPEN_DOCUMENT).
  Read the picked URI's bytes, stage them in the app's private cache
  as a timestamped file, return the staged path so existing
  import_* code can read it as a regular filesystem path.
- Zip filter passes application/zip + application/octet-stream (some
  file providers report the latter for .zip).

Android auto-backup off:
- AndroidManifest: allowBackup="false", fullBackupContent="false",
  dataExtractionRules pointing at new data_extraction_rules.xml
- New data_extraction_rules.xml excludes all domains from both
  cloud-backup and device-transfer. Prior default (allowBackup=true)
  silently replicated identity.key to Google Drive for any user with
  cloud backup on — which effectively published the root secret to
  a third party without asking. Users who want off-device backup use
  Settings -> Export (explicit zip they control).

Import as personas:
- New import_as_personas function in core/import.rs + new
  import_as_personas_cmd Tauri IPC.
- Reads identity.key from the bundle and adds it to posting_identities
  as a persona. Also reads posting_identities.json (v0.6+ bundles)
  and adds each entry. Dedupes by node_id.
- Posts stay AS-AUTHORED — original post_id, original author,
  original signatures, original wrapped_key recipients. No
  re-encryption. Content encrypted to any of the imported keys
  becomes decryptable because we now hold the secrets.
- Blobs, follows, profiles copied across.
- If current device has <=1 posting identity (the fresh-install one)
  and the bundle brings more, auto-switch the default to the first
  imported persona. Covers first-run-then-import flow cleanly.

Import wizard UI:
- New default option: "Restore as personas" — posts keep original
  authors; source's keys become personas you can post as.
- Old "Merge with decryption key" retained as "Consolidate under
  current default persona (requires source key)" for the case where
  a user intentionally abandons a persona.
- "Public posts only" and "Add as separate identity" retained.

deploy.sh made executable (chmod +x tracked).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 17:40:21 -04:00

81 lines
2.8 KiB
Bash
Executable file

#!/bin/bash
# Full build + deploy: AppImage, APK, CLI, website, anchor
# Usage: ./deploy.sh
# Requires: cargo, cargo-tauri, Android SDK, sshpass
set -e
# Load credentials from .deploy-creds (not in git)
if [ -f .deploy-creds ]; then
source .deploy-creds
else
echo "ERROR: .deploy-creds not found. Create it with:"
echo ' SSH_PASS="your-ssh-password"'
echo ' KS_PASS="your-keystore-password"'
exit 1
fi
SSH_HOST="itsgoin@itsgoin.com"
SSH_OPTS="-o StrictHostKeyChecking=no"
KEYSTORE="itsgoin.keystore"
KS_ALIAS="itsgoin"
VERSION=$(grep '"version"' crates/tauri-app/tauri.conf.json | head -1 | sed 's/.*"\([0-9.]*\)".*/\1/')
echo "=== Deploying v${VERSION} ==="
# Build CLI
echo "=== Building CLI ==="
cargo build -p itsgoin-cli --release &
CLI_PID=$!
# Build APK
echo "=== Building APK ==="
cargo tauri android build --apk &
APK_PID=$!
# Build AppImage (includes GStreamer patch)
echo "=== Building AppImage ==="
./build-appimage.sh
wait $CLI_PID
echo "=== CLI build complete ==="
wait $APK_PID
echo "=== APK build complete ==="
# Sign APK
echo "=== Signing APK ==="
UNSIGNED="crates/tauri-app/gen/android/app/build/outputs/apk/universal/release/app-universal-release-unsigned.apk"
ALIGNED="itsgoin-aligned.apk"
SIGNED="itsgoin-${VERSION}.apk"
ZIPALIGN=$(find ~/Android/Sdk/build-tools -name "zipalign" 2>/dev/null | sort -V | tail -1)
APKSIGNER=$(find ~/Android/Sdk/build-tools -name "apksigner" 2>/dev/null | sort -V | tail -1)
"$ZIPALIGN" -f 4 "$UNSIGNED" "$ALIGNED"
"$APKSIGNER" sign --ks "$KEYSTORE" --ks-pass "pass:$KS_PASS" --ks-key-alias "$KS_ALIAS" --out "$SIGNED" "$ALIGNED"
echo "Signed: $SIGNED"
# Upload (sequential to avoid SSH rate limiting)
echo "=== Uploading website ==="
sshpass -p "$SSH_PASS" scp $SSH_OPTS website/*.html website/style.css "$SSH_HOST:~/public_html/"
sleep 5
echo "=== Uploading AppImage ==="
sshpass -p "$SSH_PASS" scp $SSH_OPTS "target/release/bundle/appimage/itsgoin_${VERSION}_amd64.AppImage" "$SSH_HOST:~/public_html/itsgoin_${VERSION}_amd64.AppImage"
sleep 5
echo "=== Uploading APK ==="
sshpass -p "$SSH_PASS" scp $SSH_OPTS "$SIGNED" "$SSH_HOST:~/public_html/"
sleep 5
echo "=== Uploading CLI ==="
sshpass -p "$SSH_PASS" scp $SSH_OPTS target/release/itsgoin "$SSH_HOST:~/public_html/itsgoin-cli-${VERSION}-linux-amd64"
sleep 5
echo "=== Uploading anchor binary ==="
sshpass -p "$SSH_PASS" scp $SSH_OPTS target/release/itsgoin "$SSH_HOST:~/bin/itsgoin.new"
sleep 5
echo "=== Swapping anchor ==="
sshpass -p "$SSH_PASS" ssh $SSH_OPTS "$SSH_HOST" 'kill $(cat ~/itsgoin-anchor.pid 2>/dev/null) 2>/dev/null; sleep 1; mv ~/bin/itsgoin.new ~/bin/itsgoin && chmod +x ~/bin/itsgoin && bash ~/bin/start-anchor.sh'
sleep 2
echo "=== Verifying anchor ==="
sshpass -p "$SSH_PASS" ssh $SSH_OPTS "$SSH_HOST" 'ps aux | grep "[i]tsgoin.*daemon"'
echo "=== Deploy complete: v${VERSION} ==="