Files
audi-app/companion-app/scripts/ios-luftweg.sh
T

137 lines
5.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Bereitet die Installation ueber die Luft vor: legt neben der signierten .ipa
# die manifest.plist und eine kleine Installationsseite ab.
#
# bash scripts/ios-luftweg.sh https://mein-mac.tailnetname.ts.net
#
# Warum das noetig ist: iOS installiert eine App nur dann ueber die Luft, wenn
# ein itms-services-Link auf eine manifest.plist zeigt, die wiederum die
# Adresse der .ipa enthaelt. Beide Adressen muessen ueber **HTTPS mit einem
# oeffentlich vertrauenswuerdigen Zertifikat** erreichbar sein - einfaches HTTP
# und selbstsignierte Zertifikate lehnt iOS kommentarlos ab. Home Assistant
# unter /local/ genuegt dafuer nicht, das laeuft im Tailnet unverschluesselt.
#
# Passend dazu und ohne offenen Port: `tailscale serve` liefert ein echtes
# Let's-Encrypt-Zertifikat auf <maschine>.<tailnet>.ts.net aus. Voraussetzung
# ist, dass in der Tailscale-Verwaltung HTTPS-Zertifikate aktiviert sind.
#
# tailscale serve --bg ios/build/luftweg
#
# Danach den ausgegebenen Link auf dem iPhone in **Safari** oeffnen (andere
# Browser reichen itms-services nicht an das System weiter).
set -euo pipefail
if [ $# -lt 1 ]; then
echo "Aufruf: bash scripts/ios-luftweg.sh <basis-url> [zielordner]" >&2
echo "Beispiel: bash scripts/ios-luftweg.sh https://mein-mac.tailnetname.ts.net" >&2
echo "Gitea: bash scripts/ios-luftweg.sh \\" >&2
echo " https://gitea.nothaft.cloud/paul/audi-app/raw/branch/main/companion-app/auslieferung \\" >&2
echo " auslieferung" >&2
exit 1
fi
BASIS="${1%/}"
if [ "${BASIS#https://}" = "$BASIS" ]; then
echo "FEHLER: Die Basis-Adresse muss mit https:// beginnen." >&2
echo "iOS verweigert die Installation ueber die Luft ueber unverschluesseltes HTTP." >&2
exit 1
fi
HIER="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
APP="$(dirname "$HIER")"
IPA="$APP/auslieferung/App.ipa"
# Zweites Argument erlaubt es, direkt in den versionierten Ordner zu schreiben -
# noetig, wenn nicht ein eigener Host ausliefert, sondern das Repository selbst.
ZIEL="$APP/${2:-ios/build/luftweg}"
[ -f "$IPA" ] || { echo "FEHLER: $IPA fehlt - erst scripts/ios-signieren.sh laufen lassen." >&2; exit 1; }
# Version aus der .ipa selbst lesen statt sie hier zu wiederholen: zwei Quellen
# fuer dieselbe Angabe waeren eine zu viel.
AUSPACK="$(mktemp -d)"
trap 'rm -rf "$AUSPACK"' EXIT
unzip -q "$IPA" -d "$AUSPACK"
PLIST="$(find "$AUSPACK/Payload" -maxdepth 2 -name Info.plist | head -1)"
KENNUNG="$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$PLIST")"
VERSION="$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$PLIST")"
mkdir -p "$ZIEL"
[ "$IPA" -ef "$ZIEL/App.ipa" ] || cp "$IPA" "$ZIEL/App.ipa"
cp "$APP/public/symbol-192.png" "$ZIEL/symbol-192.png"
cp "$APP/public/symbol-512.png" "$ZIEL/symbol-512.png"
cat > "$ZIEL/manifest.plist" <<PLISTENDE
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key><string>software-package</string>
<key>url</key><string>$BASIS/App.ipa</string>
</dict>
<dict>
<key>kind</key><string>display-image</string>
<key>url</key><string>$BASIS/symbol-192.png</string>
</dict>
<dict>
<key>kind</key><string>full-size-image</string>
<key>url</key><string>$BASIS/symbol-512.png</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key><string>$KENNUNG</string>
<key>bundle-version</key><string>$VERSION</string>
<key>kind</key><string>software</string>
<key>title</key><string>DataMetric360</string>
</dict>
</dict>
</array>
</dict>
</plist>
PLISTENDE
# Das kaufmaennische Und muss in HTML maskiert werden, sonst schneidet Safari
# den Link hinter dem url-Parameter ab.
cat > "$ZIEL/index.html" <<HTMLENDE
<!doctype html>
<html lang="de">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>DataMetric360 installieren</title>
<style>
body { font-family: -apple-system, sans-serif; background: #161b23; color: #eef1f6;
margin: 0; display: grid; place-items: center; min-height: 100vh; }
main { text-align: center; padding: 2rem; }
h1 { font-weight: 300; font-size: 1.5rem; }
a { display: inline-block; margin-top: 1.5rem; padding: 0.9rem 2rem; border-radius: 999px;
background: #eef1f6; color: #161b23; text-decoration: none; font-size: 1.1rem; }
p { color: #8a94a3; font-size: 0.9rem; line-height: 1.5; }
</style>
<main>
<h1>DataMetric360</h1>
<p>Version $VERSION</p>
<a href="itms-services://?action=download-manifest&amp;url=$BASIS/manifest.plist">Installieren</a>
<p>In Safari oeffnen. Nach dem Antippen fragt iOS einmal nach,<br>danach erscheint die App auf dem Startbildschirm.</p>
</main>
</html>
HTMLENDE
echo "Ordner fertig: $ZIEL"
echo
echo "Wenn ein eigener Host ausliefert:"
echo " tailscale serve --bg $ZIEL"
echo " dann auf dem iPhone in Safari oeffnen: $BASIS/"
echo
# Gitea liefert rohe Dateien grundsaetzlich als text/plain aus - die
# index.html wird dort also als Quelltext angezeigt statt gerendert. Deshalb
# hier zusaetzlich der fertige Link zum Einfuegen in die Safari-Adresszeile;
# der funktioniert unabhaengig davon, ob eine Seite drumherum existiert.
echo "Ohne Seite (z. B. aus dem Repository heraus) direkt in Safari einfuegen:"
echo " itms-services://?action=download-manifest&url=$BASIS/manifest.plist"