Initial Commit
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# Tarnax build and release
|
||||
|
||||
Run from the project folder (scripts also work from other working directories):
|
||||
|
||||
```sh
|
||||
./scripts/test.sh # Plist/script validation, contract checks, unsigned Debug build
|
||||
./scripts/test.sh --contracts-only # Fast validation and contract checks
|
||||
./scripts/build.sh # Unsigned Debug device build
|
||||
./scripts/build.sh --release # Unsigned optimized Release device build
|
||||
./scripts/build.sh --release --signed # Signed build using existing provisioning
|
||||
./scripts/release.sh # Release archive + registered-device distribution IPA
|
||||
./scripts/release.sh --method debugging # Release archive + development-signed device IPA
|
||||
```
|
||||
|
||||
Requirements: macOS, Xcode selected with xcode-select, Xcode command-line tools and Python 3. Signed builds require the relevant certificate/private key, a provisioning profile for `net.absdev.Tarnax`, and the configured team. The default team is `39R6U3437D`; override it with `DEVELOPMENT_TEAM` if necessary.
|
||||
|
||||
The release configuration is optimized for both export methods. `release-testing` requires distribution signing and an ad hoc profile listing the recipient devices. `debugging` uses development signing and requires Developer Mode on recipient devices. Neither is an unrestricted public-install IPA. Install the exported IPA on a provisioned device with Xcode or Apple Configurator. Distribution to arbitrary public users requires a supported Apple distribution channel.
|
||||
|
||||
Provisioning updates are disabled by default. If you explicitly want Xcode to contact Apple and create/update signing certificates, app identifiers or profiles, add `--allow-provisioning-updates`. Sign in to the appropriate account in Xcode first. This flag does not upload the app to App Store Connect; export destination is local.
|
||||
|
||||
Outputs:
|
||||
|
||||
- Builds: `build/Debug/` or `build/Release/`, including `build.log` and DerivedData.
|
||||
- Releases: a unique folder under `build/releases/`, containing `Tarnax.xcarchive`, `ExportOptions.plist`, logs, and `export/Tarnax.ipa` with a SHA-256 checksum.
|
||||
- Override roots with `BUILD_OUTPUT_DIR` or `RELEASE_OUTPUT_DIR`.
|
||||
|
||||
Release export fails on any archive/export/signature/profile verification error. No unsigned ZIP is passed off as an installable IPA. Profiles include device identifiers: share only the intended IPA with testers and keep the remaining release diagnostics private.
|
||||
|
||||
The current contract harness exercises mocked transport and model behavior. It does not sign in to a live server or exercise the physical-device UI. This project has no XCTest target; the script compiles and runs the existing executable contract harness.
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
CONFIGURATION=Debug
|
||||
SIGNED=NO
|
||||
while (($#)); do
|
||||
case "$1" in
|
||||
--release) CONFIGURATION=Release ;;
|
||||
--signed) SIGNED=YES ;;
|
||||
-h|--help) echo 'Usage: scripts/build.sh [--release] [--signed]'; exit 0 ;;
|
||||
*) echo "Unknown option: $1" >&2; exit 2 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
OUTPUT="${BUILD_OUTPUT_DIR:-$ROOT/build/$CONFIGURATION}"
|
||||
mkdir -p "$OUTPUT"
|
||||
xcodebuild -project "$ROOT/Tarnax.xcodeproj" -scheme Tarnax \
|
||||
-configuration "$CONFIGURATION" -destination 'generic/platform=iOS' \
|
||||
-derivedDataPath "$OUTPUT/DerivedData" CODE_SIGNING_ALLOWED="$SIGNED" \
|
||||
build 2>&1 | tee "$OUTPUT/build.log"
|
||||
echo "App: $OUTPUT/DerivedData/Build/Products/$CONFIGURATION-iphoneos/Tarnax.app"
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
METHOD=release-testing
|
||||
PROVISIONING=()
|
||||
while (($#)); do
|
||||
case "$1" in
|
||||
--method)
|
||||
[[ $# -ge 2 ]] || { echo '--method needs a value' >&2; exit 2; }
|
||||
METHOD="$2"; shift ;;
|
||||
--allow-provisioning-updates) PROVISIONING=(-allowProvisioningUpdates) ;;
|
||||
-h|--help)
|
||||
echo 'Usage: scripts/release.sh [--method release-testing|debugging] [--allow-provisioning-updates]'
|
||||
echo 'Always archives Release configuration. Default: registered-device distribution IPA.'
|
||||
exit 0 ;;
|
||||
*) echo "Unknown option: $1" >&2; exit 2 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
case "$METHOD" in release-testing|debugging) ;; *) echo 'Supported methods: release-testing, debugging' >&2; exit 2 ;; esac
|
||||
TEAM="${DEVELOPMENT_TEAM:-39R6U3437D}"
|
||||
BASE="${RELEASE_OUTPUT_DIR:-$ROOT/build/releases}"
|
||||
mkdir -p "$BASE"
|
||||
OUTPUT="$(mktemp -d "$BASE/$(date +%Y%m%d-%H%M%S)-$METHOD.XXXXXX")"
|
||||
ARCHIVE="$OUTPUT/Tarnax.xcarchive"
|
||||
EXPORT="$OUTPUT/export"
|
||||
echo "Release output: $OUTPUT"
|
||||
python3 - "$OUTPUT/ExportOptions.plist" "$METHOD" "$TEAM" <<'PY'
|
||||
import plistlib, sys
|
||||
with open(sys.argv[1], 'wb') as f:
|
||||
plistlib.dump({'method':sys.argv[2], 'teamID':sys.argv[3], 'signingStyle':'automatic',
|
||||
'destination':'export', 'stripSwiftSymbols':True, 'thinning':'<none>',
|
||||
'manageAppVersionAndBuildNumber':False}, f)
|
||||
PY
|
||||
xcodebuild -project "$ROOT/Tarnax.xcodeproj" -scheme Tarnax \
|
||||
-configuration Release -destination 'generic/platform=iOS' \
|
||||
-derivedDataPath "$OUTPUT/DerivedData" -archivePath "$ARCHIVE" \
|
||||
DEVELOPMENT_TEAM="$TEAM" CODE_SIGN_STYLE=Automatic \
|
||||
${PROVISIONING[@]+"${PROVISIONING[@]}"} archive 2>&1 | tee "$OUTPUT/archive.log"
|
||||
xcodebuild -exportArchive -archivePath "$ARCHIVE" -exportPath "$EXPORT" \
|
||||
-exportOptionsPlist "$OUTPUT/ExportOptions.plist" \
|
||||
${PROVISIONING[@]+"${PROVISIONING[@]}"} 2>&1 | tee "$OUTPUT/export.log"
|
||||
IPA="$EXPORT/Tarnax.ipa"
|
||||
[[ -f "$IPA" ]] || { echo 'Export finished without Tarnax.ipa' >&2; exit 1; }
|
||||
VERIFY="$(mktemp -d "$OUTPUT/verify.XXXXXX")"
|
||||
trap 'rm -rf "$VERIFY"' EXIT
|
||||
unzip -q "$IPA" -d "$VERIFY"
|
||||
APP="$VERIFY/Payload/Tarnax.app"
|
||||
codesign --verify --deep --strict "$APP"
|
||||
[[ -f "$APP/embedded.mobileprovision" ]] || { echo 'No embedded provisioning profile' >&2; exit 1; }
|
||||
security cms -D -i "$APP/embedded.mobileprovision" > "$VERIFY/profile.plist"
|
||||
python3 - "$APP/Info.plist" "$VERIFY/profile.plist" "$METHOD" <<'PY'
|
||||
import plistlib, sys, datetime
|
||||
with open(sys.argv[1],'rb') as f: app=plistlib.load(f)
|
||||
with open(sys.argv[2],'rb') as f: profile=plistlib.load(f)
|
||||
assert app['CFBundleIdentifier']=='net.absdev.Tarnax', 'Unexpected app identifier'
|
||||
assert profile.get('ProvisionedDevices'), 'Profile does not include registered devices'
|
||||
assert profile['ExpirationDate']>datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None), 'Profile expired'
|
||||
assert profile['Entitlements']['application-identifier'].endswith('.'+app['CFBundleIdentifier']), 'Profile/app mismatch'
|
||||
if sys.argv[3]=='release-testing':
|
||||
assert not profile['Entitlements'].get('get-task-allow',False), 'Distribution IPA has debugging enabled'
|
||||
print('Verified:', app['CFBundleDisplayName'], app['CFBundleShortVersionString'], 'build', app['CFBundleVersion'])
|
||||
print('Registered devices:',len(profile['ProvisionedDevices']))
|
||||
print('Profile expiry:',profile['ExpirationDate'].isoformat()+'Z')
|
||||
PY
|
||||
(cd "$EXPORT" && shasum -a 256 Tarnax.ipa > Tarnax.ipa.sha256)
|
||||
echo "Verified IPA: $IPA"
|
||||
echo "SHA-256: $EXPORT/Tarnax.ipa.sha256"
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
CONTRACTS_ONLY=NO
|
||||
case "${1:-}" in
|
||||
--contracts-only) CONTRACTS_ONLY=YES ;;
|
||||
'') ;;
|
||||
-h|--help) echo 'Usage: scripts/test.sh [--contracts-only]'; exit 0 ;;
|
||||
*) echo "Unknown option: $1" >&2; exit 2 ;;
|
||||
esac
|
||||
if (($# > 1)); then echo 'Too many arguments' >&2; exit 2; fi
|
||||
cd "$ROOT"
|
||||
plutil -lint Tarnax/Info.plist Tarnax.xcodeproj/project.pbxproj
|
||||
for script in scripts/*.sh Tests/run.sh; do bash -n "$script"; done
|
||||
bash Tests/run.sh
|
||||
if [[ "$CONTRACTS_ONLY" == NO ]]; then bash scripts/build.sh; fi
|
||||
echo 'All requested checks passed.'
|
||||
Reference in New Issue
Block a user