#!/bin/bash # Round0 smoke QA entrypoint. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" OUTPUT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" # shellcheck source=build-output-paths.sh source "$SCRIPT_DIR/build-output-paths.sh" SOURCE_ROOT="$OUTPUT_ROOT/C1.source" BUILD_ROOT="$OUTPUT_ROOT/C2.builds" ARCHIVE_ROOT="$BUILD_OLD_RELEASE_ROOT" APP="$BUILD_CURRENT_APP" fail() { echo "QA failed: $*" >&2 exit 1 } aligner_pids_for_current_app() { ps -axo pid=,args= | while read -r pid command; do case "$command" in "$APP/Contents/MacOS/Aligner"*) echo "$pid" ;; esac done } stop_current_aligner() { for pid in $(aligner_pids_for_current_app); do kill "$pid" 2>/dev/null || true done for _ in {1..20}; do [ -z "$(aligner_pids_for_current_app)" ] && return sleep 0.1 done fail "current Aligner app did not exit" } cd "$SOURCE_ROOT" swift build swift test "$SCRIPT_DIR/check-signing.sh" stop_current_aligner "$SCRIPT_DIR/package-app.sh" [ -d "$APP" ] || fail "missing $APP" codesign --verify --deep --strict "$APP" APP_REQUIREMENT="$(codesign -d -r- "$APP" 2>&1)" echo "$APP_REQUIREMENT" if echo "$APP_REQUIREMENT" | grep -Fq 'cdhash H"'; then fail "app is signed with a cdhash-only ad-hoc requirement" fi ROOT_DMG_COUNT="$(find "$BUILD_ROOT" -maxdepth 1 -type f \( -name 'Aligner_*.dmg' -o -name 'Aligner-*.dmg' \) | wc -l | tr -d ' ')" [ "$ROOT_DMG_COUNT" = "0" ] || fail "expected no root DMG, found $ROOT_DMG_COUNT" LATEST_RELEASE_DIR="$(find "$BUILD_ROOT" -maxdepth 1 -type d -name 'Aligner-*-build*' | sort | tail -n 1)" [ -n "$LATEST_RELEASE_DIR" ] || fail "missing latest release directory" LATEST_DMG="$(find "$LATEST_RELEASE_DIR" -maxdepth 1 -type f -name 'Aligner-*-build*.dmg' | sort | tail -n 1)" [ -n "$LATEST_DMG" ] || fail "missing latest DMG" hdiutil verify "$LATEST_DMG" if [ ! -f "$LATEST_RELEASE_DIR/SHA256SUMS.txt" ]; then fail "missing SHA256SUMS.txt in $LATEST_RELEASE_DIR" fi if find "$BUILD_ROOT" "$BUILD_TMP_ROOT" -maxdepth 1 -type f -name '.*tmp*.dmg' | grep -q .; then fail "temporary DMG left in $BUILD_ROOT" fi if find "$ARCHIVE_ROOT" -maxdepth 2 -name '*.app' | grep -q .; then fail "old build archives must not contain .app bundles" fi if [ -n "$(aligner_pids_for_current_app)" ]; then fail "package-app.sh must not open Aligner by default" fi swift "$SCRIPT_DIR/window-logic-qa.swift" frontmost_app() { swift -e 'import AppKit; print(NSWorkspace.shared.frontmostApplication?.localizedName ?? "")' 2>/dev/null || true } FRONTMOST_BEFORE="$(frontmost_app)" "$APP/Contents/MacOS/Aligner" \ --round0-skip-permissions \ --round0-debug-overlay \ --round0-debug-settings-child \ --round0-debug-auto-hide-after=1.0 \ --round0-debug-quit-after=3.0 & DEBUG_PID="$!" cleanup_debug_app() { kill "$DEBUG_PID" 2>/dev/null || true } trap cleanup_debug_app EXIT sleep 0.8 swift "$SCRIPT_DIR/window-logic-qa.swift" --expect-debug-overlay --expect-debug-settings-child FRONTMOST_AFTER="$(frontmost_app)" if [ -n "$FRONTMOST_BEFORE" ] && [ -n "$FRONTMOST_AFTER" ] && [ "$FRONTMOST_BEFORE" != "$FRONTMOST_AFTER" ]; then fail "debug overlay changed frontmost app from '$FRONTMOST_BEFORE' to '$FRONTMOST_AFTER'" fi sleep 1.0 swift "$SCRIPT_DIR/window-logic-qa.swift" --expect-no-debug-overlay --expect-no-debug-settings-child for _ in {1..30}; do if ! kill -0 "$DEBUG_PID" 2>/dev/null; then break fi sleep 0.1 done if kill -0 "$DEBUG_PID" 2>/dev/null; then kill "$DEBUG_PID" 2>/dev/null || true fail "debug overlay app did not quit" fi wait "$DEBUG_PID" 2>/dev/null || true trap - EXIT echo "Round0 QA passed"