getreadystack commited on
Commit
54c0c18
·
verified ·
1 Parent(s): d630db8

Upload index.html with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +332 -17
index.html CHANGED
@@ -1,19 +1,334 @@
1
  <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
  <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <title>Xcode 26 SDK Gate for GitHub Actions — free online check</title>
7
+ <style>
8
+ :root{color-scheme:light}body{margin:0;font:15px/1.55 system-ui,-apple-system,"Segoe UI",sans-serif;background:#faf9f5;color:#1a1512}
9
+ .wrap{max-width:960px;margin:0 auto;padding:28px 18px 60px}h1{font-size:26px;margin:0 0 6px}.lede{color:#4a403a;margin:0 0 16px}
10
+ textarea{width:100%;min-height:260px;font:13px/1.45 ui-monospace,Menlo,Consolas,monospace;padding:12px;border:1px solid #d9d0c4;border-radius:8px;box-sizing:border-box}
11
+ .bar{display:flex;gap:10px;align-items:center;margin:12px 0}button{font:600 15px system-ui;padding:10px 18px;border:0;border-radius:8px;background:#1a1512;color:#fff;cursor:pointer}
12
+ input[type=date]{font:14px system-ui;padding:8px;border:1px solid #d9d0c4;border-radius:6px}
13
+ table{border-collapse:collapse;width:100%;font-size:14px;margin-top:10px}th,td{text-align:left;padding:8px 10px;border-bottom:1px solid #eee;vertical-align:top}th{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:#7a6e65}
14
+ .sev.error{color:#a8551f;font-weight:700}.sev.warn,.sev.warning{color:#96691f}.ok{color:#2a6446;font-weight:600}.sum{font-weight:600}
15
+ .note{font-size:13px;color:#7a6e65;margin-top:18px}#paid{margin-top:22px;padding:14px 16px;border:1px solid #e2d8cb;border-radius:10px;background:#fffdfa}
16
+ </style>
17
+ <script data-grow-initializer="">!(function(){window.growMe||((window.growMe=function(e){window.growMe._.push(e);}),(window.growMe._=[]));var e=document.createElement("script");(e.type="text/javascript"),(e.src="https://faves.grow.me/main.js"),(e.defer=!0),e.setAttribute("data-grow-faves-site-id","U2l0ZTphZjljMzgyMC0yMmU5LTRhYjgtYTIxNS03OTRhMGY1N2ExYzM=");var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t);})();</script>
18
+ <!--yj-canon-s101--><link rel="canonical" href="https://getreadystack.com/tools/xcode-26-sdk-gate"><style data-yj-mfit="1">#out{max-width:100%}#out td,#out th{overflow-wrap:anywhere}#out pre,#out code{white-space:pre-wrap;overflow-wrap:anywhere}@media (max-width:640px){table{display:block;max-width:100%;overflow-x:auto}pre{max-width:100%;overflow-x:auto}code,a{overflow-wrap:anywhere}img,svg,video,canvas,iframe{max-width:100%}textarea,input,select{max-width:100%;box-sizing:border-box}.yj-lgbar{position:static!important;justify-content:flex-end;margin:0 0 10px}h1,h2,h3,h4,p,li,dd,dt,blockquote,figcaption,summary,label,.res,.lead{overflow-wrap:anywhere}label{max-width:100%;box-sizing:border-box}#out table:not(:has(tr>:nth-child(4))){display:table;table-layout:fixed;width:100%}#out table:has(tr>:nth-child(4)),#out table:has(tr>:nth-child(4)) tbody,#out table:has(tr>:nth-child(4)) tr,#out table:has(tr>:nth-child(4)) td{display:block;width:auto;overflow:visible}#out table:has(tr>:nth-child(4)) thead{display:none}#out table:has(tr>:nth-child(4)) tr{padding:10px 0;border-bottom:1px solid rgba(128,128,128,.28)}#out table:has(tr>:nth-child(4)) td{border:0;padding:1px 0}#out table:has(tr>:nth-child(4)) td:nth-child(-n+3){display:inline-block;margin-right:10px;font-size:12px;opacity:.78}}</style>
19
+ </head>
20
+ <body>
21
+ <div class="wrap">
22
+ <h1>Xcode 26 SDK Gate for GitHub Actions</h1>
23
+ <p class="lede">Maps every macOS job in .github/workflows to the Xcode it really builds with and flags uploads App Store Connect rejects since 28 Apr 2026 (Xcode 26 / iOS 26 SDK), plus the xcode-select fix line. Runs entirely in your browser — nothing is uploaded.</p>
24
+ <textarea id="src" spellcheck="false">name: ios-release
25
+ on:
26
+ push:
27
+ tags: ['v*']
28
+ jobs:
29
+ archive-legacy:
30
+ runs-on: macos-14
31
+ steps:
32
+ - uses: actions/checkout@v4
33
+ - run: xcodebuild -scheme App -sdk iphoneos18.5 -configuration Release archive IPHONEOS_DEPLOYMENT_TARGET=12.0
34
+ testflight:
35
+ runs-on: macos-15
36
+ steps:
37
+ - uses: actions/checkout@v4
38
+ - run: bundle exec fastlane beta
39
+ appstore:
40
+ runs-on: macos-15
41
+ steps:
42
+ - uses: maxim-lobanov/setup-xcode@v1
43
+ with:
44
+ xcode-version: '16.4'
45
+ - run: bundle exec fastlane release
46
+ widget-build:
47
+ runs-on: macos-15-xlarge
48
+ steps:
49
+ - run: sudo xcode-select -s /Applications/Xcode_26.6.app
50
+ - run: xcodebuild -scheme Widget archive
51
+ matrix-build:
52
+ strategy:
53
+ matrix:
54
+ os: [macos-13, macos-latest]
55
+ runs-on: ${{ matrix.os }}
56
+ steps:
57
+ - run: flutter build ipa --release
58
+ studio-mac:
59
+ runs-on: [self-hosted, macOS, ARM64]
60
+ steps:
61
+ - run: xcodebuild -scheme App archive</textarea>
62
+ <div class="bar"><button id="go">Check</button><label>as of <input type="date" id="today"></label></div>
63
+ <div id="out" aria-live="polite"></div>
64
+ <div id="paid"><strong>Free here:</strong> Shows, for the workflow you have open, which Xcode each macOS job builds with and marks every job App Store Connect will reject, with the exact replacement line. <strong>In the editor:</strong> Scans every workflow in the repository at once and exports a dated SDK-compliance report (Markdown + JSON) for release sign-off, one licence key per person or team seat. — that part asks for a licence key. <a href="https://getreadystack.com/api/buy/cl/polar_cl_9GcYCuRt3auGWhF1S2qpt0JzVgCvrrwJv3I9D26uFfl">Full version: sweep every workflow and write a dated SDK-compliance report — $29 once, one licence key per person or team seat</a></div>
65
+ <p class="note">Same engine as the VS Code extension, byte for byte.</p>
66
+ </div>
67
+ <script>var XCG_RULES = [
68
+ {
69
+ "id": "runner-macos-14",
70
+ "sev": "error",
71
+ "title": "macos-14 runner cannot build with Xcode 26",
72
+ "detail": "The macos-14 image ships Xcode 15.0.1 to 16.2 (default 15.4). Since 28 Apr 2026 App Store Connect requires Xcode 26 or later with an iOS 26 SDK. GitHub retires macos-14 on 2 Nov 2026 with brownouts from 5 Oct 2026.",
73
+ "fix": "runs-on: macos-26",
74
+ "source": "developer.apple.com/news/upcoming-requirements · actions/runner-images macos-14-Readme + issue 13518"
75
+ },
76
+ {
77
+ "id": "runner-removed",
78
+ "sev": "error",
79
+ "title": "macOS runner label no longer offered by GitHub",
80
+ "detail": "macos-13 and older labels are not in the actions/runner-images list any more; the job never starts, and those images never had Xcode 26.",
81
+ "fix": "runs-on: macos-26",
82
+ "source": "actions/runner-images README"
83
+ },
84
+ {
85
+ "id": "macos-15-default-xcode",
86
+ "sev": "error",
87
+ "title": "macos-15 builds with Xcode 16.4 unless you select Xcode 26",
88
+ "detail": "The macos-15 image (arm64 and Intel) defaults to Xcode 16.4. A job that archives or uploads without selecting Xcode 26 produces a build App Store Connect rejects since 28 Apr 2026.",
89
+ "fix": "- run: sudo xcode-select -s /Applications/Xcode_26.3.app",
90
+ "source": "actions/runner-images macos-15-Readme + macos-15-arm64-Readme"
91
+ },
92
+ {
93
+ "id": "xcode-pin-below-26",
94
+ "sev": "error",
95
+ "title": "Pinned Xcode is below 26",
96
+ "detail": "The job selects an Xcode older than 26 (setup-xcode xcode-version, xcode-select -s or DEVELOPER_DIR). App Store Connect rejects uploads built with it since 28 Apr 2026.",
97
+ "fix": "xcode-version: '26.3' (or: sudo xcode-select -s /Applications/Xcode_26.3.app)",
98
+ "source": "developer.apple.com/news/upcoming-requirements"
99
+ },
100
+ {
101
+ "id": "xcode-not-on-image",
102
+ "sev": "error",
103
+ "title": "Pinned Xcode is not installed on this runner image",
104
+ "detail": "The runner image does not ship the Xcode version the job selects, so the select step fails before the build starts. macos-15 has 26.0.1, 26.1.1, 26.2 and 26.3; macos-26 has 26.0.1 to 26.6.",
105
+ "fix": "pick a version the image lists, or runs-on: macos-26",
106
+ "source": "actions/runner-images macos-15-Readme + macos-26-Readme"
107
+ },
108
+ {
109
+ "id": "deployment-target-below-13",
110
+ "sev": "error",
111
+ "title": "iOS deployment target below 13",
112
+ "detail": "Since 9 Sep 2026 iOS and iPadOS apps uploaded to App Store Connect must target iOS 13 or later.",
113
+ "fix": "IPHONEOS_DEPLOYMENT_TARGET=13.0 (or higher)",
114
+ "source": "developer.apple.com/news/upcoming-requirements"
115
+ },
116
+ {
117
+ "id": "sdk-flag-below-26",
118
+ "sev": "error",
119
+ "title": "xcodebuild -sdk names an SDK below 26",
120
+ "detail": "An explicit versioned -sdk (for example iphoneos18.5) builds against an SDK older than iOS 26; uploads need an iOS, iPadOS, tvOS, visionOS or watchOS 26 SDK since 28 Apr 2026.",
121
+ "fix": "-sdk iphoneos",
122
+ "source": "developer.apple.com/news/upcoming-requirements"
123
+ },
124
+ {
125
+ "id": "self-hosted-unpinned",
126
+ "sev": "warning",
127
+ "title": "Self-hosted Mac job does not select an Xcode",
128
+ "detail": "A self-hosted macOS runner builds with whatever /Applications/Xcode.app is on that machine; nothing in the workflow proves it is Xcode 26.",
129
+ "fix": "- run: sudo xcode-select -s /Applications/Xcode_26.app \u0026\u0026 xcodebuild -version",
130
+ "source": "developer.apple.com/news/upcoming-requirements"
131
+ },
132
+ {
133
+ "id": "macos-latest-floating",
134
+ "sev": "info",
135
+ "title": "macos-latest moves without notice",
136
+ "detail": "macos-latest points to the macOS 26 arm64 image today (default Xcode 26.6). GitHub migrates -latest labels over 1-2 months, so a release job gets a different Xcode on a later run.",
137
+ "fix": "runs-on: macos-26",
138
+ "source": "actions/runner-images README"
139
+ },
140
+ {
141
+ "id": "job-xcode-map",
142
+ "sev": "info",
143
+ "title": "Which Xcode this job builds with",
144
+ "detail": "For every job that archives or uploads an Apple build: the runner image, the Xcode it resolves to (explicit pin or image default) and whether that meets the Xcode 26 upload minimum.",
145
+ "fix": "",
146
+ "source": "actions/runner-images macOS Readmes (images 20260824 / 20260907)"
147
+ }
148
+ ];</script>
149
+ <script>/* Xcode 26 SDK Gate — engine shared by the VS Code extension and the free web page. */
150
+ (function () {
151
+ var RULES = (typeof module !== 'undefined') ? require('./rules.json') : window.XCG_RULES;
152
+ var BY_ID = {};
153
+ RULES.forEach(function (r) { BY_ID[r.id] = r; });
154
+
155
+ // GitHub-hosted macOS images (actions/runner-images, macos-14 20260629, macos-15 20260824/20260907, macos-26 20260824)
156
+ var IMAGES = {
157
+ '14': { name: 'macos-14', def: '15.4', xcodes: ['15.0.1', '15.1', '15.2', '15.3', '15.4', '16.1', '16.2'] },
158
+ '15': { name: 'macos-15', def: '16.4', xcodes: ['16.0', '16.1', '16.2', '16.3', '16.4', '26.0.1', '26.1.1', '26.2', '26.3'] },
159
+ '26': { name: 'macos-26', def: '26.6', xcodes: ['26.0.1', '26.1.1', '26.2', '26.3', '26.4.1', '26.5', '26.6'] }
160
+ };
161
+ IMAGES.latest = { name: 'macos-latest (macos-26)', def: '26.6', xcodes: IMAGES['26'].xcodes };
162
+
163
+ var SHIPS = /xcodebuild|fastlane|\bgym\b|build_app|upload_to_testflight|upload_to_app_store|\bpilot\b|altool|flutter\s+build\s+(ipa|ios)|exportArchive|\.ipa\b|testflight/i;
164
+ var LABEL = /\bmacos-(\d+|latest)(?:-(?:large|xlarge|intel|arm64))?\b/ig;
165
+ var SEL = [
166
+ /xcode-version:\s*['"]?([0-9][\w.]*|latest-stable|latest)['"]?/i,
167
+ /xcode-select\s+(?:-s|--switch)\s+['"]?\/Applications\/Xcode(?:[_-]([0-9][0-9.]*))?(?:[_-]beta)?\.app/i,
168
+ /DEVELOPER_DIR\s*[:=]\s*['"]?\/Applications\/Xcode(?:[_-]([0-9][0-9.]*))?(?:[_-]beta)?\.app/i
169
+ ];
170
+
171
+ function indentOf(s) { return s.match(/^\s*/)[0].length; }
172
+ function major(v) { return parseInt(String(v).split('.')[0], 10); }
173
+ function installed(img, v) {
174
+ return img.xcodes.some(function (x) { return x === v || x.indexOf(v + '.') === 0; });
175
+ }
176
+ function newest(img) { return img.xcodes[img.xcodes.length - 1]; }
177
+
178
+ function findSelection(lines, from, to) {
179
+ for (var i = from; i < to; i++) {
180
+ if (/^\s*#/.test(lines[i])) continue;
181
+ for (var k = 0; k < SEL.length; k++) {
182
+ var m = lines[i].match(SEL[k]);
183
+ if (m) return { version: m[1] || '', line: i + 1, text: lines[i].trim() };
184
+ }
185
+ }
186
+ return null;
187
+ }
188
+
189
+ function splitJobs(lines) {
190
+ var j = -1, i;
191
+ for (i = 0; i < lines.length; i++) if (/^jobs:\s*$/.test(lines[i])) { j = i; break; }
192
+ if (j < 0) return { head: [0, 0], jobs: [{ name: '(file)', start: 0, end: lines.length }] };
193
+ var ind = -1, jobs = [];
194
+ for (i = j + 1; i < lines.length; i++) {
195
+ var s = lines[i];
196
+ if (!s.trim() || /^\s*#/.test(s)) continue;
197
+ var d = indentOf(s);
198
+ if (ind < 0) ind = d;
199
+ if (d < ind) break;
200
+ var m = d === ind && s.match(/^\s*([A-Za-z0-9_.-]+):\s*$/);
201
+ if (m) {
202
+ if (jobs.length) jobs[jobs.length - 1].end = i;
203
+ jobs.push({ name: m[1], start: i, end: lines.length });
204
+ }
205
+ }
206
+ if (jobs.length) jobs[jobs.length - 1].end = i;
207
+ return { head: [0, j], jobs: jobs };
208
+ }
209
+
210
+ function check(text, opts) {
211
+ opts = opts || {};
212
+ var lines = String(text || '').split(/\r?\n/);
213
+ var findings = [], map = [];
214
+ function add(id, line, extra) {
215
+ var r = BY_ID[id];
216
+ findings.push({ check: id, sev: r.sev, line: line, msg: r.title + (extra ? ' — ' + extra : '') + (r.fix ? ' · Fix: ' + r.fix : ''), fix: r.fix, source: r.source });
217
+ }
218
+ var parts = splitJobs(lines);
219
+ var globalSel = findSelection(lines, parts.head[0], parts.head[1]);
220
+
221
+ parts.jobs.forEach(function (job) {
222
+ var body = lines.slice(job.start, job.end);
223
+ var code = body.filter(function (l) { return !/^\s*#/.test(l); }).join('\n');
224
+ if (!SHIPS.test(code)) return;
225
+ var labels = [], selfHosted = 0;
226
+ for (var i = job.start; i < job.end; i++) {
227
+ var l = lines[i];
228
+ if (/^\s*#/.test(l)) continue;
229
+ if (/runs-on:/.test(l) && /self-hosted/i.test(l) && /mac/i.test(l)) selfHosted = i + 1;
230
+ var m; LABEL.lastIndex = 0;
231
+ while ((m = LABEL.exec(l))) labels.push({ key: m[1].toLowerCase(), label: m[0], line: i + 1 });
232
+ }
233
+ var sel = findSelection(lines, job.start, job.end) || globalSel;
234
+ if (sel && sel.version && !/^latest/i.test(sel.version) && major(sel.version) < 26) {
235
+ add('xcode-pin-below-26', sel.line, 'job "' + job.name + '" selects Xcode ' + sel.version);
236
+ }
237
+ if (selfHosted && !sel) add('self-hosted-unpinned', selfHosted, 'job "' + job.name + '"');
238
+ if (selfHosted && !labels.length) map.push({ job: job.name, line: selfHosted, runner: 'self-hosted', xcode: sel && sel.version ? sel.version : 'unknown', via: sel ? 'pin' : 'machine default', ok: sel && sel.version ? major(sel.version) >= 26 : null });
239
+
240
+ labels.forEach(function (lb) {
241
+ var n = parseInt(lb.key, 10);
242
+ if (lb.key !== 'latest' && n <= 13) { add('runner-removed', lb.line, lb.label + ' in job "' + job.name + '"'); return; }
243
+ var img = IMAGES[lb.key];
244
+ if (!img) return;
245
+ var xc = img.def, via = 'image default';
246
+ if (sel) {
247
+ if (!sel.version) { via = 'Xcode.app = image default'; }
248
+ else if (/^latest/i.test(sel.version)) { xc = newest(img); via = 'setup-xcode ' + sel.version; }
249
+ else if (!installed(img, sel.version)) {
250
+ add('xcode-not-on-image', sel.line, 'Xcode ' + sel.version + ' on ' + img.name + ' (has ' + img.xcodes.join(', ') + ')');
251
+ xc = sel.version + ' (missing)'; via = 'pin';
252
+ } else { xc = sel.version; via = 'pin'; }
253
+ }
254
+ if (lb.key === '14') add('runner-macos-14', lb.line, 'job "' + job.name + '" builds with Xcode ' + xc);
255
+ else if (lb.key === '15' && !sel) add('macos-15-default-xcode', lb.line, 'job "' + job.name + '"');
256
+ else if (lb.key === 'latest') add('macos-latest-floating', lb.line, 'job "' + job.name + '"');
257
+ var ok = major(xc) >= 26 && !/missing/.test(xc);
258
+ map.push({ job: job.name, line: lb.line, runner: lb.label, xcode: xc, via: via, ok: ok });
259
+ });
260
+ });
261
+
262
+ lines.forEach(function (l, i) {
263
+ if (/^\s*#/.test(l)) return;
264
+ var m = l.match(/IPHONEOS_DEPLOYMENT_TARGET\s*[=:]\s*['"]?(\d+)(?:\.\d+)?/);
265
+ if (m && parseInt(m[1], 10) < 13) add('deployment-target-below-13', i + 1, 'targets iOS ' + m[1]);
266
+ var s = l.match(/-sdk\s+['"]?(iphoneos|appletvos|xros|watchos)(\d+)(\.\d+)?/);
267
+ if (s && parseInt(s[2], 10) < 26) add('sdk-flag-below-26', i + 1, s[1] + s[2] + (s[3] || ''));
268
+ });
269
+
270
+ if (opts.map !== false) map.forEach(function (e) {
271
+ findings.push({ check: 'job-xcode-map', sev: 'info', line: e.line, msg: 'job "' + e.job + '" → ' + e.runner + ' → Xcode ' + e.xcode + ' (' + e.via + ') → ' + (e.ok === null ? 'not provable from the workflow — add xcode-select' : e.ok ? 'meets the Xcode 26 upload minimum' : 'rejected by App Store Connect since 28 Apr 2026') });
272
+ });
273
+ findings.sort(function (a, b) { return a.line - b.line; });
274
+ return { findings: findings, map: map, today: opts.today || '' };
275
+ }
276
+
277
+ var api = { engine: { check: check }, RULES: RULES, RULE_COUNT: RULES.length, IMAGES: IMAGES };
278
+ if (typeof module !== 'undefined') module.exports = api;
279
+ if (typeof window !== 'undefined') window.XCGENGINE = api;
280
+ })();
281
+ </script>
282
+ <script>// ⛔뼈대 — kit/scaffold.py 가 찍는다 (s143). findings [{check,sev,msg,line?}] → 글/HTML. 같은 파일이 Node 와 브라우저에서 산다.
283
+ 'use strict';
284
+ function escapeHtml(s) { return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;'); }
285
+ function summaryLine(res) {
286
+ const f = (res && res.findings) || []; const e = f.filter(function (x) { return String(x.sev || 'error').toLowerCase().startsWith('err'); }).length;
287
+ return f.length ? (f.length + ' finding' + (f.length === 1 ? '' : 's') + ' (' + e + ' error' + (e === 1 ? '' : 's') + ')') : 'Clean — no findings.';
288
+ }
289
+ function toText(res, label) {
290
+ const f = (res && res.findings) || [];
291
+ const lines = ['== ' + (label || '') + ' — ' + summaryLine(res)];
292
+ f.forEach(function (x) { lines.push(' ' + String(x.sev || 'error').toUpperCase().slice(0, 4) + ' ' + (x.line ? 'L' + x.line + ' ' : '') + (x.check || x.id || '') + ' ' + (x.msg || x.message || '')); });
293
+ return lines.join('\n');
294
+ }
295
+ function toHtml(res) {
296
+ const f = (res && res.findings) || [];
297
+ if (!f.length) return '<p class="ok">' + escapeHtml(summaryLine(res)) + '</p>';
298
+ const rows = f.map(function (x) { return '<tr><td class="sev ' + escapeHtml(String(x.sev || 'error')) + '">' + escapeHtml(String(x.sev || 'error')) + '</td><td>' + (x.line ? 'L' + escapeHtml(x.line) : '') + '</td><td><code>' + escapeHtml(x.check || x.id || '') + '</code></td><td>' + escapeHtml(x.msg || x.message || '') + '</td></tr>'; }).join('');
299
+ return '<p class="sum">' + escapeHtml(summaryLine(res)) + '</p><table><thead><tr><th>Level</th><th>Line</th><th>Check</th><th>What</th></tr></thead><tbody>' + rows + '</tbody></table>';
300
+ }
301
+ var XCGREPORT = { escapeHtml: escapeHtml, summaryLine: summaryLine, toText: toText, toHtml: toHtml };
302
+ if (typeof module !== 'undefined' && module.exports) module.exports = XCGREPORT;
303
+ else window.XCGREPORT = XCGREPORT;
304
+ </script>
305
+ <script>
306
+ (function(){
307
+ var src=document.getElementById('src'), out=document.getElementById('out'), go=document.getElementById('go'), today=document.getElementById('today');
308
+ today.value=new Date().toISOString().slice(0,10);
309
+ function run(){ try { var res=window.XCGENGINE.engine.check(src.value,{today:today.value}); out.innerHTML=window.XCGREPORT.toHtml(res); } catch(e){ out.innerHTML='<p class="sev error">Could not run: '+String(e.message||e)+'</p>'; } }
310
+ go.onclick=run; if (src.value.trim()) run();
311
+ })();
312
+ </script>
313
+
314
+
315
+ <section data-yj-install="free" style="margin:2rem auto 1rem;max-width:46rem;padding:1.25rem 1.25rem;border:1px solid #cfe3d6;border-radius:12px;background:#f6fbf8;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .4rem;font-size:1.2rem">Install free</h2><p style="margin:0 0 .8rem;color:#41505f">Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.</p><a href="https://open-vsx.org/extension/readystack/xcode-26-sdk-gate" rel="noopener" data-yj-install-door="ovsx" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'xcode-26-sdk-gate',src:'ovsx',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Open VSX (Cursor, VSCodium)</a><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://getreadystack.com/api/buy/team" rel="nofollow" style="color:#0f7b3f;text-decoration:underline">Team? One key for every ReadyStack linter, 5 seats, $149 once</a></p></section>
316
+ <section data-yj-alert="rule" style="margin:1rem auto 1.5rem;max-width:46rem;padding:1.1rem 1.25rem;border:1px solid #d9dee6;border-radius:12px;background:#fbfcfd;font:15px/1.55 system-ui,-apple-system,Segoe UI,sans-serif"><b style="font-size:1.05rem">Get one email when this rule changes</b><div style="opacity:.78;margin:.35rem 0 .8rem">We watch the regulation and vendor sources behind Xcode 26 SDK Gate for GitHub Actions every day. When a rule changes, you get a single email with what changed and the updated check. No newsletter.</div><div style="display:flex;gap:8px;flex-wrap:wrap"><input id="yjae" type="email" placeholder="you@example.com" style="flex:1;min-width:210px;padding:11px 13px;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:#fff;color:inherit"><button id="yjab" style="padding:11px 18px;border-radius:8px;border:0;cursor:pointer;background:#0f7b3f;color:#fff;font:600 15px system-ui,sans-serif">Notify me</button></div><div id="yjao" hidden style="margin-top:.6rem;color:#0f7b3f">You're on the list. One email when it changes.</div><script>(function(){var b=document.getElementById("yjab"),e=document.getElementById("yjae");if(!b||!e)return;b.addEventListener("click",function(){var v=e.value.trim();if(!/.+@.+\..+/.test(v))return;try{localStorage.setItem("yj_em","1");}catch(_){}fetch(location.origin+"/api/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:v,slug:"xcode-26-sdk-gate",lang:"en",source:"rule_alert"+((b.closest&&b.closest("section")&&b.closest("section").getAttribute("data-yj-moved"))?"_at_result":"")})}).then(function(r){var o=document.getElementById("yjao");o.hidden=false;if(!r.ok){o.textContent="Could not save - please try again.";}}).catch(function(){var o=document.getElementById("yjao");o.hidden=false;o.textContent="Could not save - please try again.";});});})();</script><script>(function(){var e=document.getElementById("yjae"),s=e&&e.closest?e.closest("section"):null,o=document.getElementById("out");if(!s||!o)return;var d=false;function mv(ev){if(d)return;if(ev&&ev.target&&s.contains(ev.target))return;d=true;var b=o;while(b.parentNode&&b.parentNode!==document.body&&b.parentNode.tagName!=="MAIN"&&b.parentNode.tagName!=="ARTICLE")b=b.parentNode;if(!b.parentNode||b===s||b.contains(s))return;try{b.parentNode.insertBefore(s,b.nextSibling);s.setAttribute("data-yj-moved","1");}catch(_){}}document.addEventListener("input",mv,true);document.addEventListener("change",mv,true);document.addEventListener("click",function(ev){var b=ev.target&&ev.target.closest?ev.target.closest("button,input[type=submit]"):null;if(b&&!b.closest("[data-yj],[data-yj-cta],[data-yj-install],[data-yj-alert],.yj-find,.yj-related,#yj-ask,.yjp"))mv(ev);},true);})();</script></section>
317
+
318
+ <section data-yj-cta="paid" style="margin:3rem auto;max-width:46rem;padding:1.5rem 1.25rem;border:1px solid #d8dee9;border-radius:12px;background:#fbfcfe;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .5rem;font-size:1.25rem">Get the full version <span class="yj-price">$29</span></h2><p class="yj-cta-paid" style="margin:.25rem 0 .6rem;color:#1f2a37">$29 once, one licence key per person or team seat: sweeps every workflow in the repository at once and writes a dated SDK-compliance report (Markdown + JSON) for release sign-off.</p><p class="yj-cta-pay" style="margin:.25rem 0 1rem;color:#5b6b7c;font-size:.94rem">One payment, one licence key for this tool. The key is shown right after payment.</p><p class="yj-cta-anchor" style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">US software developer median wage $65.38 per hour (BLS OEWS 2025)</p><a href="https://getreadystack.com/api/buy/cl/polar_cl_9GcYCuRt3auGWhF1S2qpt0JzVgCvrrwJv3I9D26uFfl" rel="nofollow" style="display:inline-block;padding:.7rem 1.3rem;border-radius:8px;background:#1b64f2;color:#fff;text-decoration:none;font-weight:600">Buy the full version — $29</a></section>
319
+ <!--yj-share-s101--><div style="margin:28px 0 8px;text-align:center"><button id="yjcp" type="button" style="font:inherit;padding:10px 18px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Copy link</button><button id="yjimg" type="button" style="font:inherit;padding:10px 18px;margin-left:8px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Save result as image</button></div><script>(function(){var b=document.getElementById("yjimg");if(!b)return;b.addEventListener("click",function(){var o=document.getElementById("out");var txt=(o&&(o.innerText||o.textContent)||"").trim();if(!txt){b.textContent="(no result yet)";setTimeout(function(){b.textContent="Save result as image";},1500);return;}var lines=txt.split(String.fromCharCode(10)).filter(function(x){return x.trim();}).slice(0,10);var W=1200,P=56,c=document.createElement("canvas");c.width=W;var lh=38,H=P*2+70+lines.length*lh+60;c.height=H;var x=c.getContext("2d");x.fillStyle="#1a1512";x.fillRect(0,0,W,H);x.fillStyle="#f3e9d2";x.font="600 34px system-ui,Segoe UI,Arial";var t=(document.title||"").split("|")[0].trim();x.fillText(t.slice(0,54),P,P+34);x.font="22px ui-monospace,Menlo,Consolas,monospace";x.fillStyle="#e8dcc4";for(var i=0;i<lines.length;i++){x.fillText(lines[i].slice(0,88),P,P+70+i*lh+22);}x.font="600 22px system-ui,Segoe UI,Arial";x.fillStyle="#c9a227";var d=location.hostname.replace("www.","");x.fillText(d,W-P-x.measureText(d).width,H-P+6);c.toBlob(function(bl){var u=URL.createObjectURL(bl),a=document.createElement("a");a.href=u;a.download=(t||"result").replace(/[^a-z0-9]+/gi,"-").toLowerCase()+"-"+d+".png";document.body.appendChild(a);a.click();setTimeout(function(){URL.revokeObjectURL(u);a.remove();},2000);},"image/png");});})();</script><script>(function(){var b=document.getElementById("yjcp");if(!b)return;var t=b.textContent;b.addEventListener("click",function(){var u=location.href.split("#")[0];function d(){b.textContent="Link copied";setTimeout(function(){b.textContent=t;},1800);}if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(u).then(d,function(){prompt("",u);});}else{prompt("",u);}});})();</script>
320
+ <script data-yj="yj-view-beacon">(function(){try{var p=location.pathname;var k='yjv:'+p;if(sessionStorage.getItem(k))return;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",ref:(document.referrer||''),src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}catch(e){}})();</script>
321
+
322
+ <script data-yj="yj-use-beacon">(function(){try{var o=document.getElementById('out');if(!o)return;var p=location.pathname,k='yju:'+p,sent=false;function fire(){if(sent||sessionStorage.getItem(k))return;if(!(o.textContent||'').replace(/\s+/g,'').length)return;sent=true;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",t:'use',src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}var mo=new MutationObserver(function(){fire();if(sent)mo.disconnect();});mo.observe(o,{childList:true,characterData:true,subtree:true});}catch(e){}})();</script><div class="yj-home-find"><div class="yj-lgbar"><a href="/" class="yj-lg on">EN</a><a href="/de/" class="yj-lg">DE</a><a href="/ja/" class="yj-lg">JA</a><a href="/es/" class="yj-lg">ES</a><a href="/pt/" class="yj-lg">PT</a></div><section class="yj-find"><h2>Find a tool</h2><input id="yjq" type="search" autocomplete="off" placeholder="Type a product name, format or task"><div id="yjr"></div></section><style>.yj-lgbar{position:absolute;top:14px;right:18px;display:flex;gap:6px;z-index:60}.yj-lg{font:600 12px/1 system-ui,sans-serif;padding:6px 9px;border-radius:4px;text-decoration:none;color:#8b96a3;border:1px solid rgba(140,150,165,.28)}.yj-lg:hover{color:#e8eaed;border-color:rgba(160,175,195,.6)}.yj-lg.on{color:#0e1116;background:#cfd6de;border-color:#cfd6de}.yj-find{max-width:760px;margin:34px auto 8px;padding:0 20px}.yj-find h2{font:600 20px/1.3 system-ui,sans-serif;margin:0 0 10px}#yjq{width:100%;box-sizing:border-box;padding:13px 15px;font:400 15.5px system-ui,sans-serif;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:rgba(255,255,255,.04);color:inherit}#yjq:focus{outline:none;border-color:#7FD1C4}#yjr{margin-top:10px;display:flex;flex-direction:column;gap:6px}#yjr a{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;border:1px solid rgba(140,150,165,.22);border-radius:6px;text-decoration:none;font:400 14.5px/1.4 system-ui,sans-serif;color:inherit}#yjr a:hover{border-color:#7FD1C4}#yjr .pr{font:600 13px system-ui,sans-serif;color:#5fbf9a;white-space:nowrap}</style><script>(function(){var q=document.getElementById("yjq"),r=document.getElementById("yjr"),D=null;function load(){if(D)return Promise.resolve(D);return fetch("/search-index.json").then(function(x){return x.json();}).then(function(j){D=j;return j;}).catch(function(){D=[];return D;});}function esc(t){return String(t).replace(/[&<>"]/g,function(c){return {"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"}[c];});}function run(){var v=q.value.trim().toLowerCase();if(v.length<2){r.innerHTML="";return;}load().then(function(j){var w=v.split(/\s+/),o=[];for(var i=0;i<j.length&&o.length<12;i++){var t=j[i].t.toLowerCase();var ok=true;for(var k=0;k<w.length;k++){if(t.indexOf(w[k])<0){ok=false;break;}}if(ok)o.push(j[i]);}r.innerHTML=o.length?o.map(function(x){return "<a href=\""+esc(x.u)+"\">"+"<span>"+esc(x.t)+"</span>"+(x.p?"<span class=\"pr\">$"+x.p+"</span>":"")+"</a>";}).join(""):"";});}q.addEventListener("input",run);q.addEventListener("focus",load);})();</script></div><section data-yj="yj-facts-v1" style="max-width:920px;margin:48px auto 0;padding:0 20px;font-family:system-ui,sans-serif"><style>.yj-article p{font:400 15.5px/1.7 system-ui,sans-serif;color:#26313b;margin:0 0 12px;max-width:72ch}.yj-article h2,.yj-article h3,.yj-article h4{font:600 17px/1.35 system-ui,sans-serif;color:#1b1f24;margin:22px 0 8px}.yj-article table{border-collapse:collapse;margin:10px 0 16px;font:14px/1.45 system-ui,sans-serif}.yj-article th,.yj-article td{border:1px solid #e2e6ea;padding:6px 10px;text-align:left}.yj-article th{background:#f4f6f8}.yj-article pre{background:#0f1720;color:#e6edf3;padding:12px 14px;border-radius:8px;overflow:auto;font:13px/1.5 ui-monospace,Menlo,monospace}.yj-article code{font:13px ui-monospace,Menlo,monospace;background:#f1f3f5;padding:1px 4px;border-radius:3px}.yj-article pre code{background:none;padding:0}.yj-article ul,.yj-article ol{font:15px/1.6 system-ui,sans-serif;color:#26313b}</style><p style="font:400 13px/1.5 system-ui,sans-serif;color:#6b7680;margin:0 0 14px"><time datetime="2026-10-01">Updated 2026-10-01</time> · ReadyStack</p><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","dateModified":"2026-10-01","author":{"@type":"Organization","name":"ReadyStack"}}</script><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Worked example</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 16px;color:#5b6570">Real numbers from this tool, line by line.</p><div class="yj-article"><p><img src="https://getreadystack.com/img/promo/sku436475_result_card.jpg" alt="Xcode 26 SDK Gate for GitHub Actions" loading="lazy" style="max-width:100%;border-radius:6px"></p>
323
+ <p>Six lines in the sample workflow block an iOS upload, for iOS teams shipping from GitHub Actions: a runner label, an Xcode pin, an SDK flag, a deployment target.</p>
324
+ <p>Since 28 April 2026, Apple&#x27;s Upcoming Requirements page says apps uploaded to App Store Connect must be built with Xcode 26 or later using an SDK for iOS 26, iPadOS 26, tvOS 26, visionOS 26 or watchOS 26. Since 9 September 2026, iOS and iPadOS apps must also target iOS 13 or later. The app code does not decide any of this. The CI workflow does, because the runner label and the Xcode selection step decide which Xcode compiles the archive.</p>
325
+ <p>Here is the part that catches teams. The GitHub-hosted macos-15 image, arm64 and Intel, has Xcode 26.0.1, 26.1.1, 26.2 and 26.3 installed, but its default is still Xcode 16.4. A job that says runs-on: macos-15 and then calls fastlane or xcodebuild without selecting an Xcode builds with 16.4, and the upload is rejected. The macos-14 image is worse: it ships Xcode 15.0.1 up to 16.2 with 15.4 as default, so no pin can reach Xcode 26 there. GitHub also deprecates that image: brownouts start on 5 October 2026 and it is unsupported from 2 November 2026.</p>
326
+ <p>Xcode 26 SDK Gate for GitHub Actions reads the workflow you have open and does two things. First it draws a map: for every job that archives or uploads an Apple build, it prints the runner, the Xcode that runner resolves to (an explicit setup-xcode pin, an xcode-select path, DEVELOPER_DIR, or the image default) and whether that meets the upload minimum. Second it marks every line that breaks, with the replacement line next to it.</p>
327
+ <p>The bundled sample workflow has six shipping jobs. The gate reports seven errors, one warning and one info line besides the six map lines:</p>
328
+ <ul><li>runs-on: macos-14 in the archive job. Fix: runs-on: macos-26.</li><li>runs-on: macos-15 in the TestFlight job with no Xcode selection, so it builds with 16.4. Fix: sudo xcode-select -s /Applications/Xcode_26.3.app.</li><li>xcode-version: &#x27;16.4&#x27; in the App Store job. Fix: xcode-version: &#x27;26.3&#x27;.</li><li>Xcode_26.6.app on macos-15-xlarge. That image does not ship 26.6, so the select step fails before the build. Fix: Xcode_26.3.app, or runs-on: macos-26.</li><li>-sdk iphoneos18.5. Fix: -sdk iphoneos.</li><li>IPHONEOS_DEPLOYMENT_TARGET=12.0. Fix: IPHONEOS_DEPLOYMENT_TARGET=13.0.</li></ul>
329
+ <p>It also flags a macos-13 leg in a matrix (that label is gone from the runner list), a self-hosted Mac job that never selects an Xcode, and macos-latest, which points to macOS 26 with Xcode 26.6 today but moves when GitHub migrates the label.</p>
330
+ <p>In total there are 10 rules, and the runner table behind them comes straight from the actions/runner-images Readmes for macos-14, macos-15 and macos-26. The clean sample, with a macos-26 archive job and a macos-15 job that selects Xcode 26.3, produces only its two map lines.</p>
331
+ <p>Why not ask a chatbot? Because the answer depends on which Xcode each image ships this month, and on your file. The Readmes list versions per image, but they do not read your workflow or point at the job line.</p>
332
+ <p>Everything above is free for the open file, in VS Code and on the web page, with no key. The full version sweeps every workflow in the repository at once and writes a dated SDK-compliance report in Markdown and JSON. For scale: an hour of a US software developer costs $65.38 at the BLS OEWS 2025 median, and finding the runner, the default Xcode and every pin by hand takes a search through each workflow.</p>
333
+ <p>Open .github/workflows, look at the map, and replace the lines it marks before the next release tag.</p></div><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:30px 0 10px;color:#1b1f24">15 seconds — what it actually does</h2><video controls muted playsinline preload="none" poster="/img/promo/sku436475_result_card.jpg" style="width:100%;max-width:360px;border-radius:10px;display:block;margin:0 auto"><source src="/media/sku436475_short.mp4" type="video/mp4"></video><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:34px 0 6px;color:#1b1f24">Questions people ask</h2><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does Xcode 26 SDK Gate for GitHub Actions do?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads a GitHub Actions workflow and shows, for every job that archives or uploads an iOS build, which Xcode that job really builds with: the explicit pin or the runner image default. It marks each line that App Store Connect rejects since 28 April 2026, when uploads must use Xcode 26 and an iOS 26 SDK, and prints the exact fix line. It has 10 rules.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Who is this Xcode 26 CI check for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">iOS, iPadOS, tvOS, visionOS and watchOS teams that archive and upload from GitHub Actions: release engineers, mobile leads and solo developers using fastlane, xcodebuild or flutter build ipa on macos-14, macos-15, macos-26, macos-latest or a self-hosted Mac. It helps when a TestFlight upload starts failing and nobody changed the app.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why not just ask a chatbot or read the GitHub runner docs?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">A chatbot does not know which Xcode each runner image ships this month: macos-15 still defaults to Xcode 16.4 even though Xcode 26.0.1, 26.1.1, 26.2 and 26.3 are installed, and macos-14 tops out at 16.2. The runner Readmes list versions per image but do not read your workflow or tell you which job line breaks.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What is free and what does the full version add?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free: the check, the per-job Xcode map and every fix line for the workflow you have open, in VS Code or on the web page, with no key. The full version is $29 once, one licence key per person or team seat: it sweeps every workflow in the repository at once and writes a dated SDK-compliance report in Markdown and JSON for release sign-off.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does fixing this by hand cost?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">An engineer has to open each workflow, find the runner label, look up that image&#x27;s default Xcode in the actions/runner-images Readme, check every setup-xcode pin and xcode-select path, then rerun the build. At the BLS OEWS 2025 median wage for US software developers, $65.38 per hour, every hour of that search is the yardstick.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does Xcode 26 SDK Gate for GitHub Actions do?", "acceptedAnswer": {"@type": "Answer", "text": "It reads a GitHub Actions workflow and shows, for every job that archives or uploads an iOS build, which Xcode that job really builds with: the explicit pin or the runner image default. It marks each line that App Store Connect rejects since 28 April 2026, when uploads must use Xcode 26 and an iOS 26 SDK, and prints the exact fix line. It has 10 rules."}}, {"@type": "Question", "name": "Who is this Xcode 26 CI check for?", "acceptedAnswer": {"@type": "Answer", "text": "iOS, iPadOS, tvOS, visionOS and watchOS teams that archive and upload from GitHub Actions: release engineers, mobile leads and solo developers using fastlane, xcodebuild or flutter build ipa on macos-14, macos-15, macos-26, macos-latest or a self-hosted Mac. It helps when a TestFlight upload starts failing and nobody changed the app."}}, {"@type": "Question", "name": "Why not just ask a chatbot or read the GitHub runner docs?", "acceptedAnswer": {"@type": "Answer", "text": "A chatbot does not know which Xcode each runner image ships this month: macos-15 still defaults to Xcode 16.4 even though Xcode 26.0.1, 26.1.1, 26.2 and 26.3 are installed, and macos-14 tops out at 16.2. The runner Readmes list versions per image but do not read your workflow or tell you which job line breaks."}}, {"@type": "Question", "name": "What is free and what does the full version add?", "acceptedAnswer": {"@type": "Answer", "text": "Free: the check, the per-job Xcode map and every fix line for the workflow you have open, in VS Code or on the web page, with no key. The full version is $29 once, one licence key per person or team seat: it sweeps every workflow in the repository at once and writes a dated SDK-compliance report in Markdown and JSON for release sign-off."}}, {"@type": "Question", "name": "What does fixing this by hand cost?", "acceptedAnswer": {"@type": "Answer", "text": "An engineer has to open each workflow, find the runner label, look up that image's default Xcode in the actions/runner-images Readme, check every setup-xcode pin and xcode-select path, then rerun the build. At the BLS OEWS 2025 median wage for US software developers, $65.38 per hour, every hour of that search is the yardstick."}}]}</script><div id="yj-ask" style="margin:36px 0 0;padding:18px 18px 16px;border:1px solid #e2e6ea;border-radius:10px;background:#fbfbfc"><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:0 0 4px;color:#1b1f24">Ask about this tool</h2><p style="font:400 13.5px/1.5 system-ui,sans-serif;margin:0 0 12px;color:#5b6570">One question, answered by the person who built it. Your email only if you want the answer sent.</p><form onsubmit="return yjAsk(event)" style="display:grid;gap:8px"><textarea name="question" required minlength="10" maxlength="2000" rows="3" placeholder="Your question" style="font:14px/1.5 system-ui,sans-serif;padding:10px;border:1px solid #cfd6dd;border-radius:6px"></textarea><div style="display:flex;gap:8px;flex-wrap:wrap"><input type="email" name="email" placeholder="Email (optional)" style="flex:1;min-width:200px;font:14px system-ui,sans-serif;padding:9px 10px;border:1px solid #cfd6dd;border-radius:6px"><button type="submit" style="font:600 14px system-ui,sans-serif;padding:9px 18px;border:0;border-radius:6px;background:#1b1f24;color:#fff;cursor:pointer">Send</button></div><p id="yj-ask-msg" style="font:13px system-ui,sans-serif;margin:2px 0 0;color:#0a6238;min-height:1em"></p></form><script>function yjAsk(e){e.preventDefault();var f=e.target,m=document.getElementById("yj-ask-msg");m.style.color="#0a6238";fetch(location.origin+"/api/ask",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sku:436475,slug:"xcode-26-sdk-gate",lang:"en",question:f.question.value,email:f.email.value,page:location.pathname})}).then(function(r){if(!r.ok)throw 0;m.textContent="Thanks \u2014 noted. Answers land on this page and, if you left an email, in your inbox.";f.question.value="";}).catch(function(){m.style.color="#a8551f";m.textContent="Could not send. Please try again in a minute.";});return false;}</script></div></section><section class="yj-related" style="max-width:920px;margin:56px auto 40px;padding:0 20px"><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Same job, next tool</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 20px;color:#5b6570">Free in the browser. The full version is a one-time licence.</p><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px"><a class="yj-rel-c" href="https://getreadystack.com/tools/maui-ios-submission-gate"><span class="yj-rel-t">MAUI iOS Submission Gate</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/gomod-release-gate"><span class="yj-rel-t">go.mod Release Gate: /vN suffix and go line check</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/mobile-app-ui-kit-account-deletion"><span class="yj-rel-t">Mobile App UI Kit — Account Deletion Flow for App Store 5.1.1(v) &amp; Google Play</span><span class="yj-rel-p">$168</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/cron-schedule-lint"><span class="yj-rel-t">Cron Schedule Lint for crontab, Kubernetes CronJob, GitHub Actions, Spring and</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/firmware-release-gate"><span class="yj-rel-t">Firmware Release Gate for sdkconfig and prj.conf</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/actions-deprecation-lint-2026"><span class="yj-rel-t">GitHub Actions Deprecation Lint: the 2026 runner and action EOL dates</span><span class="yj-rel-p">$29</span></a></div><style>.yj-rel-c{display:flex;flex-direction:column;gap:8px;padding:15px 16px;border:1px solid #e2e6ea;border-radius:6px;text-decoration:none;background:#fff}.yj-rel-c:hover{border-color:#b9c2cb;background:#fafbfc}.yj-rel-t{font:500 14.5px/1.42 system-ui,sans-serif;color:#1b1f24}.yj-rel-p{font:600 13px system-ui,sans-serif;color:#0a6238}</style></section></body>
334
  </html>