[#377] 최초 가입 직후 ProfileView를 들어가면 얼럿이 뜨는 이슈를 해결한다 #358
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: iOS CI | |
| on: | |
| pull_request: | |
| env: | |
| SCHEME: DevLog | |
| XCODE_VERSION: latest | |
| MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }} | |
| MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }} | |
| permissions: | |
| contents: read | |
| issues: write | |
| pull-requests: write | |
| checks: write | |
| jobs: | |
| build: | |
| runs-on: macos-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Install private config files | |
| uses: ./.github/actions/install-private-config | |
| with: | |
| git_url: ${{ env.MATCH_GIT_URL }} | |
| git_basic_authorization: ${{ env.MATCH_GIT_BASIC_AUTHORIZATION }} | |
| - name: Select Xcode | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [ "$XCODE_VERSION" = "latest" ]; then | |
| XCODE_APP="$(find /Applications -maxdepth 1 -name 'Xcode*.app' -type d | sort -V | tail -n 1)" | |
| else | |
| XCODE_APP="/Applications/Xcode_${XCODE_VERSION}.app" | |
| if [ ! -d "$XCODE_APP" ]; then | |
| XCODE_APP="/Applications/Xcode-${XCODE_VERSION}.app" | |
| fi | |
| fi | |
| if [ ! -d "${XCODE_APP:-}" ]; then | |
| echo "Requested Xcode not found for version: $XCODE_VERSION" >&2 | |
| exit 1 | |
| fi | |
| sudo xcode-select -s "$XCODE_APP/Contents/Developer" | |
| xcodebuild -version | |
| - name: Cache SwiftPM | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.swiftpm | |
| ~/Library/Caches/org.swift.swiftpm | |
| ~/Library/Developer/Xcode/SourcePackages | |
| .spm | |
| key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }} | |
| restore-keys: | | |
| ${{ runner.os }}-spm- | |
| - name: Select iOS Simulator Runtime (installed) | |
| id: pick_ios | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| RESULT=$(python3 - <<'PY' | |
| import re, subprocess, sys | |
| def ver_key(version): | |
| return tuple(int(part) for part in version.split('.')) | |
| text = subprocess.check_output(["xcrun", "simctl", "list", "devices"], text=True) | |
| lines = text.splitlines() | |
| current_ver = None | |
| candidates = [] | |
| for line in lines: | |
| header = re.match(r"^-- iOS ([0-9]+(?:\.[0-9]+)*) --$", line.strip()) | |
| if header: | |
| current_ver = header.group(1) | |
| continue | |
| if current_ver is None: | |
| continue | |
| if "(unavailable)" in line: | |
| continue | |
| if "iPhone" not in line: | |
| continue | |
| raw = line.strip() | |
| if "platform:" in raw and "name:" in raw and "OS:" in raw: | |
| kv = {} | |
| for part in raw.split(","): | |
| if ":" not in part: | |
| continue | |
| k, v = part.split(":", 1) | |
| kv[k.strip()] = v.strip() | |
| name = kv.get("name", raw) | |
| else: | |
| name = raw | |
| name = re.sub(r"\s+\([0-9A-Fa-f-]{36}\)\s+\(.*\)$", "", name) | |
| candidates.append((current_ver, name)) | |
| if len(candidates) <= 0: | |
| print("No available iPhone simulators found", file=sys.stderr) | |
| sys.exit(1) | |
| latest_version = max((candidate[0] for candidate in candidates), key=ver_key) | |
| latest_candidates = [ | |
| candidate for candidate in candidates | |
| if candidate[0] == latest_version | |
| ] | |
| chosen_version, chosen_device_name = min( | |
| latest_candidates, | |
| key=lambda candidate: candidate[1] | |
| ) | |
| print(f"{chosen_version}|{chosen_device_name}") | |
| sys.exit(0) | |
| PY | |
| ) | |
| if [ -z "${RESULT:-}" ]; then | |
| echo "No iPhone simulator devices detected." >&2 | |
| exit 1 | |
| fi | |
| IFS='|' read -r IOS_VER DEVICE_NAME <<< "$RESULT" | |
| echo "Chosen iOS runtime version (iPhone): $IOS_VER" | |
| echo "Chosen simulator: $DEVICE_NAME" | |
| echo "ios_version=$IOS_VER" >> "$GITHUB_OUTPUT" | |
| echo "device_name=$DEVICE_NAME" >> "$GITHUB_OUTPUT" | |
| - name: Build | |
| shell: bash | |
| env: | |
| IOS_VER: ${{ steps.pick_ios.outputs.ios_version }} | |
| DEVICE_NAME: ${{ steps.pick_ios.outputs.device_name }} | |
| run: | | |
| set -euo pipefail | |
| set -x | |
| SPM_DIR="$GITHUB_WORKSPACE/.spm" | |
| mkdir -p "$SPM_DIR" | |
| xcodebuild -version | |
| echo "Using scheme: $SCHEME" | |
| echo "Using simulator: $DEVICE_NAME (iOS ${IOS_VER})" | |
| set -o pipefail | |
| set +e | |
| echo "== Resolving Swift Package dependencies ==" | |
| xcodebuild \ | |
| -scheme "$SCHEME" \ | |
| -configuration Debug \ | |
| -clonedSourcePackagesDirPath "$SPM_DIR" \ | |
| -resolvePackageDependencies | |
| echo "== Starting xcodebuild build ==" | |
| xcodebuild \ | |
| -scheme "$SCHEME" \ | |
| -configuration Debug \ | |
| -destination "platform=iOS Simulator,OS=${IOS_VER},name=${DEVICE_NAME}" \ | |
| -clonedSourcePackagesDirPath "$SPM_DIR" \ | |
| -skipPackagePluginValidation \ | |
| -skipMacroValidation \ | |
| -showBuildTimingSummary \ | |
| build \ | |
| | tee build.log | |
| echo "== xcodebuild finished ==" | |
| XC_STATUS=${PIPESTATUS[0]} | |
| set -e | |
| exit $XC_STATUS | |
| - name: Comment build failure on PR | |
| if: failure() && github.event.pull_request.head.repo.fork == false | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const path = 'build.log'; | |
| let body = '❌ iOS CI build failed.\n\n'; | |
| if (fs.existsSync(path)) { | |
| const log = fs.readFileSync(path, 'utf8'); | |
| const lines = log.split(/\r?\n/); | |
| const errorLines = lines.filter((line) => /^(.*?):(\d+):(\d+):\s+error:/i.test(line)); | |
| if (errorLines.length > 0) { | |
| body += "Compiler error lines:\n\n```\n" + errorLines.join('\n') + '\n```\n'; | |
| const repoRoot = process.env.GITHUB_WORKSPACE || process.cwd(); | |
| const pathMod = require('path'); | |
| const snippets = []; | |
| for (const line of errorLines) { | |
| const match = line.match(/^(.*?):(\d+):(\d+):\s+error:/); | |
| if (!match) continue; | |
| const filePath = match[1]; | |
| const lineNum = parseInt(match[2], 10); | |
| const absPath = filePath.startsWith('/') ? filePath : pathMod.join(repoRoot, filePath); | |
| if (!fs.existsSync(absPath)) continue; | |
| const fileLines = fs.readFileSync(absPath, 'utf8').split(/\r?\n/); | |
| const start = Math.max(0, lineNum - 3); | |
| const end = Math.min(fileLines.length, lineNum + 2); | |
| const snippet = fileLines | |
| .slice(start, end) | |
| .map((l, idx) => { | |
| const ln = start + idx + 1; | |
| return `${ln.toString().padStart(4, ' ')}| ${l}`; | |
| }) | |
| .join('\n'); | |
| snippets.push(`File: ${filePath}:${lineNum}\n${snippet}`); | |
| } | |
| if (snippets.length > 0) { | |
| body += "\nCode excerpts:\n\n```\n" + snippets.join('\n\n') + "\n```\n"; | |
| } | |
| } else { | |
| body += "No compiler-style error diagnostics were found in build.log."; | |
| } | |
| } else { | |
| body += 'build.log not found.'; | |
| } | |
| if (!context.payload.pull_request) { | |
| core.info('No PR context; skipping comment.'); | |
| return; | |
| } | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.payload.pull_request.number, | |
| body | |
| }); |