2323 with :
2424 xcode-version : latest
2525
26- - name : Install xcpretty
27- shell : bash
28- run : |
29- set -euo pipefail
30- sudo gem install xcpretty
3126
3227 - name : Select iOS Simulator Runtime (installed)
3328 id : pick_ios
@@ -132,7 +127,6 @@ jobs:
132127 echo "Using simulator: $DEVICE_NAME (iOS ${IOS_VER})"
133128
134129 # 예시: 시뮬레이터 대상으로 빌드/테스트 시 destination에서 OS 지정
135- mkdir -p build/test-results
136130 set -o pipefail
137131 set +e
138132 xcodebuild \
@@ -143,19 +137,70 @@ jobs:
143137 -skipMacroValidation \
144138 -showBuildTimingSummary \
145139 build \
146- | tee build.log \
147- | xcpretty
140+ | tee build.log
148141 XC_STATUS=${PIPESTATUS[0]}
149142 set -e
150143
151144 if [ -f build.log ]; then
152- xcpretty -r junit -o build/test-results/junit.xml < build.log || true
145+ echo "== error: lines =="
146+ grep -i "error:" build.log || true
153147 fi
154148
155149 exit $XC_STATUS
156150
157151 - name : Comment build failure on PR
158- uses : mikepenz/action-junit-report@v4
159- if : always() && github.event.pull_request.head.repo.fork == false
152+ if : failure() && github.event.pull_request.head.repo.fork == false
153+ uses : actions/ github-script@v7
160154 with :
161- report_paths : ' build/test-results/junit.xml'
155+ script : |
156+ const fs = require('fs');
157+ const path = 'build.log';
158+ let body = '❌ iOS CI build failed.\n\n';
159+ if (fs.existsSync(path)) {
160+ const log = fs.readFileSync(path, 'utf8');
161+ const lines = log.split(/\r?\n/);
162+ const errorLines = lines.filter((line) => /error:/i.test(line));
163+ if (errorLines.length > 0) {
164+ body += "Lines containing 'error:':\n\n```\n" + errorLines.join('\n') + '\n```\n';
165+
166+ const repoRoot = process.env.GITHUB_WORKSPACE || process.cwd();
167+ const pathMod = require('path');
168+ const snippets = [];
169+ for (const line of errorLines) {
170+ const match = line.match(/^(.*?):(\d+):(\d+):\s+error:/);
171+ if (!match) continue;
172+ const filePath = match[1];
173+ const lineNum = parseInt(match[2], 10);
174+ const absPath = filePath.startsWith('/') ? filePath : pathMod.join(repoRoot, filePath);
175+ if (!fs.existsSync(absPath)) continue;
176+ const fileLines = fs.readFileSync(absPath, 'utf8').split(/\r?\n/);
177+ const start = Math.max(0, lineNum - 3);
178+ const end = Math.min(fileLines.length, lineNum + 2);
179+ const snippet = fileLines
180+ .slice(start, end)
181+ .map((l, idx) => {
182+ const ln = start + idx + 1;
183+ return `${ln.toString().padStart(4, ' ')}| ${l}`;
184+ })
185+ .join('\n');
186+ snippets.push(`File: ${filePath}:${lineNum}\n${snippet}`);
187+ }
188+ if (snippets.length > 0) {
189+ body += "\nCode excerpts:\n\n```\n" + snippets.join('\n\n') + "\n```\n";
190+ }
191+ } else {
192+ body += "No lines containing 'error:' were found in build.log.";
193+ }
194+ } else {
195+ body += 'build.log not found.';
196+ }
197+ if (!context.payload.pull_request) {
198+ core.info('No PR context; skipping comment.');
199+ return;
200+ }
201+ await github.rest.issues.createComment({
202+ owner: context.repo.owner,
203+ repo: context.repo.repo,
204+ issue_number: context.payload.pull_request.number,
205+ body
206+ });
0 commit comments