#!/bin/sh # 🤖 Xcode Cloud post-clone hook. # # The Xcode project is NOT committed to this repo — it is generated from # ios/project.yml by XcodeGen (see ios/.gitignore). Xcode Cloud clones the repo # and then expects to find ios/LChat.xcodeproj, so we regenerate it here, right # after the clone and before dependency resolution + the build. # # LOCATION MATTERS: Xcode Cloud only runs ci_scripts/ when it sits next to the # Xcode project/workspace. The project lives in ios/, so this folder must be # ios/ci_scripts/ — NOT the repo root. (A repo-root ci_scripts is silently # ignored for a subdirectory project, which looks like "the hook never ran".) # # Xcode Cloud runs this from the ci_scripts/ directory and exports # CI_PRIMARY_REPOSITORY_PATH pointing at the cloned checkout root. Homebrew is # preinstalled on the runners, so we install XcodeGen with it. # # Scope: iOS only for now (scheme "LChat"). The Mac scheme (LChatMac) pulls in # Sparkle and an "Embed eleven CLI" step that shells out to `go build`; when we # add Mac to Xcode Cloud this script will also need to install Go 1.25. Left out # deliberately until then. set -eu echo "════════════ ci_post_clone: start ════════════" echo "pwd = $(pwd)" echo "script = $0" echo "CI_PRIMARY_REPOSITORY_PATH = ${CI_PRIMARY_REPOSITORY_PATH:-}" echo "CI_WORKSPACE = ${CI_WORKSPACE:-}" echo "CI_BUILD_NUMBER = ${CI_BUILD_NUMBER:-}" # Don't let brew spend minutes auto-updating itself/formulae on every build. export HOMEBREW_NO_AUTO_UPDATE=1 export HOMEBREW_NO_INSTALL_CLEANUP=1 # The ios/ directory holds project.yml. Prefer the documented repo-root env var; # fall back to the parent of this script's dir (this script lives in ios/ci_scripts). if [ -n "${CI_PRIMARY_REPOSITORY_PATH:-}" ]; then IOS_DIR="$CI_PRIMARY_REPOSITORY_PATH/ios" else IOS_DIR="$(cd "$(dirname "$0")/.." && pwd)" echo "▸ CI_PRIMARY_REPOSITORY_PATH unset — derived IOS_DIR from script dir" fi echo "IOS_DIR = $IOS_DIR" if [ ! -f "$IOS_DIR/project.yml" ]; then echo "✗ ERROR: $IOS_DIR/project.yml not found — repo layout is not what we expect" >&2 exit 1 fi if ! command -v xcodegen >/dev/null 2>&1; then echo "▸ installing xcodegen via Homebrew" brew install xcodegen fi echo "xcodegen at $(command -v xcodegen) — $(xcodegen --version)" cd "$IOS_DIR" echo "──────── ios/ before generate ────────" ls -la # TestFlight rejects a re-uploaded build number, so stamp Xcode Cloud's # monotonic CI_BUILD_NUMBER into CURRENT_PROJECT_VERSION before generating. # CFBundleVersion is driven from that build setting (see project.yml), so this # flows through to the app and both extensions. Only touches project.yml when # running under Xcode Cloud (CI_BUILD_NUMBER set) — local generates are unchanged. if [ -n "${CI_BUILD_NUMBER:-}" ]; then echo "▸ stamping build number $CI_BUILD_NUMBER into project.yml" sed -i '' -E "s/^([[:space:]]*CURRENT_PROJECT_VERSION:[[:space:]]*).*/\1\"$CI_BUILD_NUMBER\"/" project.yml fi xcodegen generate echo "──────── ios/ after generate ────────" ls -la if [ ! -d "$IOS_DIR/LChat.xcodeproj" ]; then echo "✗ ERROR: xcodegen ran but $IOS_DIR/LChat.xcodeproj does not exist" >&2 exit 1 fi echo "──────── generated schemes ────────" ls -la "$IOS_DIR/LChat.xcodeproj/xcshareddata/xcschemes/" || true echo "✓ project present: $IOS_DIR/LChat.xcodeproj" # Xcode Cloud's build step runs with automatic package resolution DISABLED # (environment-wide), so it demands a Package.resolved already inside the # project and refuses to resolve one itself. Our .xcodeproj is generated fresh # (and gitignored), and we can't resolve on the runner either (same disabled # state — `xcodebuild -resolvePackageDependencies` exits 74 there). So we ship a # committed Package.resolved next to this script and stage it into the generated # workspace. Xcode Cloud then finds it and never needs to resolve. # # KEEP IN SYNC with the Sparkle pin in project.yml: when Sparkle's version # changes, regenerate locally and re-copy — # cd ios && xcodebuild -resolvePackageDependencies -project LChat.xcodeproj -scheme LChat # cp LChat.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved ci_scripts/Package.resolved SRC_RESOLVED="$IOS_DIR/ci_scripts/Package.resolved" SWIFTPM_DIR="$IOS_DIR/LChat.xcodeproj/project.xcworkspace/xcshareddata/swiftpm" echo "──────── staging committed Package.resolved ────────" if [ ! -f "$SRC_RESOLVED" ]; then echo "✗ ERROR: $SRC_RESOLVED missing — commit it (see comment above)" >&2 exit 1 fi mkdir -p "$SWIFTPM_DIR" cp "$SRC_RESOLVED" "$SWIFTPM_DIR/Package.resolved" echo "✓ staged Package.resolved:" cat "$SWIFTPM_DIR/Package.resolved" echo "════════════ ci_post_clone: done ════════════"