2121 outputs :
2222 has_qa_tag : ${{ steps.detect.outputs.has_qa_tag }}
2323 steps :
24- - uses : actions/checkout@v4
24+ - uses : actions/checkout@v5
2525 with :
2626 fetch-depth : 0
2727 fetch-tags : true
@@ -49,21 +49,38 @@ jobs:
4949 runs-on : macos-latest
5050 timeout-minutes : 30
5151 steps :
52- - uses : actions/checkout@v4
52+ - uses : actions/checkout@v5
5353
5454 - name : Install private config files
5555 uses : ./.github/actions/install-private-config
5656 with :
5757 git_url : ${{ env.MATCH_GIT_URL }}
5858 git_basic_authorization : ${{ env.MATCH_GIT_BASIC_AUTHORIZATION }}
5959
60- - name : Set up Xcode
61- uses : maxim-lobanov/setup-xcode@v1
62- with :
63- xcode-version : ${{ env.XCODE_VERSION }}
60+ - name : Select Xcode
61+ shell : bash
62+ run : |
63+ set -euo pipefail
64+
65+ if [ "$XCODE_VERSION" = "latest" ]; then
66+ XCODE_APP="$(find /Applications -maxdepth 1 -name 'Xcode*.app' -type d | sort -V | tail -n 1)"
67+ else
68+ XCODE_APP="/Applications/Xcode_${XCODE_VERSION}.app"
69+ if [ ! -d "$XCODE_APP" ]; then
70+ XCODE_APP="/Applications/Xcode-${XCODE_VERSION}.app"
71+ fi
72+ fi
73+
74+ if [ ! -d "${XCODE_APP:-}" ]; then
75+ echo "Requested Xcode not found for version: $XCODE_VERSION" >&2
76+ exit 1
77+ fi
78+
79+ sudo xcode-select -s "$XCODE_APP/Contents/Developer"
80+ xcodebuild -version
6481
6582 - name : Cache SwiftPM
66- uses : actions/cache@v4
83+ uses : actions/cache@v5
6784 with :
6885 path : |
6986 ~/.swiftpm
@@ -74,10 +91,131 @@ jobs:
7491 restore-keys : |
7592 ${{ runner.os }}-spm-
7693
94+ - name : Select iOS Simulator Runtime (installed)
95+ id : pick_ios
96+ shell : bash
97+ run : |
98+ set -euo pipefail
99+
100+ RESULT=$(python3 - <<'PY'
101+ import re, subprocess, sys
102+
103+ def ver_key(version):
104+ return tuple(int(part) for part in version.split('.'))
105+
106+ text = subprocess.check_output(["xcrun", "simctl", "list", "devices"], text=True)
107+ lines = text.splitlines()
108+ current_ver = None
109+ candidates = []
110+
111+ for line in lines:
112+ header = re.match(r"^-- iOS ([0-9]+(?:\.[0-9]+)*) --$", line.strip())
113+ if header:
114+ current_ver = header.group(1)
115+ continue
116+ if current_ver is None:
117+ continue
118+ if "(unavailable)" in line:
119+ continue
120+ if "iPhone" not in line:
121+ continue
122+
123+ raw = line.strip()
124+ if "platform:" in raw and "name:" in raw and "OS:" in raw:
125+ kv = {}
126+ for part in raw.split(","):
127+ if ":" not in part:
128+ continue
129+ k, v = part.split(":", 1)
130+ kv[k.strip()] = v.strip()
131+ name = kv.get("name", raw)
132+ else:
133+ name = raw
134+ name = re.sub(r"\s+\([0-9A-Fa-f-]{36}\)\s+\(.*\)$", "", name)
135+
136+ candidates.append((current_ver, name))
137+
138+ if len(candidates) <= 0:
139+ print("No available iPhone simulators found", file=sys.stderr)
140+ sys.exit(1)
141+
142+ latest_version = max((candidate[0] for candidate in candidates), key=ver_key)
143+ latest_candidates = [
144+ candidate for candidate in candidates
145+ if candidate[0] == latest_version
146+ ]
147+ chosen_version, chosen_device_name = min(
148+ latest_candidates,
149+ key=lambda candidate: candidate[1]
150+ )
151+
152+ print(f"{chosen_version}|{chosen_device_name}")
153+ sys.exit(0)
154+ PY
155+ )
156+
157+ if [ -z "${RESULT:-}" ]; then
158+ echo "No iPhone simulator devices detected." >&2
159+ exit 1
160+ fi
161+
162+ IFS='|' read -r IOS_VER DEVICE_NAME <<< "$RESULT"
163+
164+ echo "Chosen iOS runtime version (iPhone): $IOS_VER"
165+ echo "Chosen simulator: $DEVICE_NAME"
166+
167+ echo "ios_version=$IOS_VER" >> "$GITHUB_OUTPUT"
168+ echo "device_name=$DEVICE_NAME" >> "$GITHUB_OUTPUT"
169+
77170 - name : Build
78- uses : ./.github/actions/ios-simulator-build
79- with :
80- scheme : ${{ env.SCHEME }}
171+ shell : bash
172+ env :
173+ IOS_VER : ${{ steps.pick_ios.outputs.ios_version }}
174+ DEVICE_NAME : ${{ steps.pick_ios.outputs.device_name }}
175+ run : |
176+ set -euo pipefail
177+ set -x
178+ SPM_DIR="$GITHUB_WORKSPACE/.spm"
179+ mkdir -p "$SPM_DIR"
180+
181+ xcodebuild -version
182+
183+ echo "Using scheme: $SCHEME"
184+ echo "Using simulator: $DEVICE_NAME (iOS ${IOS_VER})"
185+
186+ set -o pipefail
187+ set +e
188+ echo "== Resolving Swift Package dependencies =="
189+ xcodebuild \
190+ -scheme "$SCHEME" \
191+ -configuration Debug \
192+ -clonedSourcePackagesDirPath "$SPM_DIR" \
193+ -resolvePackageDependencies
194+ echo "== Starting xcodebuild build =="
195+ xcodebuild \
196+ -scheme "$SCHEME" \
197+ -configuration Debug \
198+ -destination "platform=iOS Simulator,OS=${IOS_VER},name=${DEVICE_NAME}" \
199+ -clonedSourcePackagesDirPath "$SPM_DIR" \
200+ -skipPackagePluginValidation \
201+ -skipMacroValidation \
202+ -showBuildTimingSummary \
203+ build \
204+ | tee build.log
205+ echo "== xcodebuild finished =="
206+ XC_STATUS=${PIPESTATUS[0]}
207+ set -e
208+
209+ if [ -f build.log ]; then
210+ echo "== error: lines =="
211+ if grep -i "error:" build.log; then
212+ if [ "$XC_STATUS" -eq 0 ]; then
213+ XC_STATUS=1
214+ fi
215+ fi
216+ fi
217+
218+ exit $XC_STATUS
81219
82220 - name : Comment build failure on PR
83221 if : failure() && github.event.pull_request.head.repo.fork == false
0 commit comments