apple build exports each build into build/ios/export/<version>-<build>/ (cleaned first), runs xcodebuild with Apple's tool folders first on PATH (Homebrew rsync 3.x broke Xcode's IPA step: exportArchive Copy failed), shows the IDEDistribution log's real error lines and exits non-zero on any export failure; apple upload fails with exit 1 when the IPA's build number is already on App Store Connect (stale IPA after a failed build), --allow-existing re-checks, --build N picks that build's IPA, release and beta flows use both; doctor flags a non-Apple rsync first on PATH; desktop publish calls rsync by absolute path without --chmod (publishSteps); site download notice per OS (macOS signed and notarized, Windows unsigned for now, Linux unsigned); game-report credential tests hermetic against a machine default profile (pitfalls 53, 54)
This commit is contained in:
parent
8fd4ac741e
commit
0e4f579899
20 changed files with 338 additions and 48 deletions
|
|
@ -186,3 +186,46 @@ export function uploadProblems(state: { errors?: { code?: string; message?: stri
|
|||
const f = (x: { code?: string; message?: string; description?: string }) => [x.code, x.message ?? x.description].filter(Boolean).join(': ');
|
||||
return { errors: (state?.errors ?? []).map(f), warnings: (state?.warnings ?? []).map(f) };
|
||||
}
|
||||
|
||||
/** Apple's own tool folders, first on PATH for xcodebuild. */
|
||||
export const APPLE_PATH = ['/usr/bin', '/bin', '/usr/sbin', '/sbin'];
|
||||
|
||||
/**
|
||||
* PATH for xcodebuild: Xcode's developer usr/bin (when known) and Apple's folders first. Xcode's IPA packaging
|
||||
* (IDEDistributionCreateIPAStep) runs `rsync` from PATH and fails with "rsync error: syntax or usage error (code 1)",
|
||||
* shown as "exportArchive Copy failed", when Homebrew's rsync 3.x comes first (pitfall 54).
|
||||
*/
|
||||
export function xcodePath(path: string | undefined, developerDir?: string): string {
|
||||
const first = [...(developerDir ? [join(developerDir, 'usr', 'bin')] : []), ...APPLE_PATH];
|
||||
const rest = (path ?? '').split(':').filter(p => p && !first.includes(p));
|
||||
return [...first, ...rest].join(':');
|
||||
}
|
||||
|
||||
/** The first rsync on PATH when it is not Apple's (/usr/bin, /bin): Homebrew, MacPorts, ...; else null. */
|
||||
export function foreignRsync(path: string | undefined, exists: (p: string) => boolean = existsSync): string | null {
|
||||
for (const d of (path ?? '').split(':').filter(Boolean)) {
|
||||
const p = join(d, 'rsync');
|
||||
if (exists(p)) return d === '/usr/bin' || d === '/bin' ? null : p;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The real reason behind "exportArchive Copy failed": the error lines of the newest IDEDistribution*.log in the
|
||||
* .xcdistributionlogs folder xcodebuild names in its output, else the newest such folder in the temp folder.
|
||||
*/
|
||||
export function distributionErrors(output: string, tmp: string = process.env.TMPDIR ?? '/tmp'): { log: string; lines: string[] } | null {
|
||||
let dir = (output.match(/\/[^\s"']+\.xcdistributionlogs/g) ?? []).filter(p => existsSync(p)).at(-1);
|
||||
if (!dir && existsSync(tmp)) {
|
||||
dir = readdirSync(tmp).filter(f => f.endsWith('.xcdistributionlogs')).map(f => join(tmp, f))
|
||||
.sort((a, b) => statSync(b).mtimeMs - statSync(a).mtimeMs)[0];
|
||||
}
|
||||
if (!dir) return null;
|
||||
const d = dir;
|
||||
const logs = readdirSync(d).filter(f => /^IDEDistribution.*\.log$/.test(f)).map(f => join(d, f)).sort((a, b) => statSync(b).mtimeMs - statSync(a).mtimeMs);
|
||||
for (const l of logs) {
|
||||
const lines = readFileSync(l, 'utf8').split('\n').filter(x => /rsync error|\berror:/i.test(x)).map(x => x.trim().slice(0, 300));
|
||||
if (lines.length) return { log: l, lines: [...new Set(lines)].slice(-10) };
|
||||
}
|
||||
return logs[0] ? { log: logs[0], lines: [] } : null;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue