apple build stops before the archive in an SSH / non-GUI session (errSecInternalComponent) with how to run it in the logged-in session, --allow-ssh to skip; relative credential paths resolve from the project and xcodebuild gets an absolute ASC key path; tests, pitfall 101

This commit is contained in:
CRTkafa 2026-10-22 02:38:45 +08:00
parent 467bacc00a
commit b97f23701f
7 changed files with 72 additions and 6 deletions

View file

@ -23,7 +23,7 @@ import { parseMobileprovision, toXmlPlist } from '../lib/plist';
import { nextBuildNumber } from '../lib/release';
import { exportOptions, profileDirs } from '../lib/signing';
import { capacitorProject, webStep } from '../lib/web-assets';
import { archiveArgs, type AscAuth, distributionErrors, exportArgs, foreignRsync, xcodePath, flutterConfigArgs, ipaInfo, pickXcode, scanXcode, showCmd } from '../lib/xcode';
import { archiveArgs, type AscAuth, distributionErrors, exportArgs, foreignRsync, remoteBuildSession, xcodePath, flutterConfigArgs, ipaInfo, pickXcode, scanXcode, showCmd } from '../lib/xcode';
import { bundleTrackingIssues, ipaManifests } from '../lib/privacy-files';
import { ascClient } from './asc';
import { findBundleId } from './signing';
@ -168,6 +168,10 @@ export async function run(ctx: Ctx): Promise<void> {
return;
}
if (process.platform !== 'darwin' || !rt.which('xcodebuild')) throw new Error('apple build needs macOS with Xcode (xcode-select --install is not enough: the full Xcode app)');
// codesign in an SSH session cannot use the login keychain: the archive fails late with errSecInternalComponent
// (Embed Pods Frameworks). Stop before the web build and the archive (pitfall 101).
const remote = remoteBuildSession(process.env, rt.spawnSync(['launchctl', 'managername'], { timeout: 5000 }).stdout.toString().trim());
if (remote && !a.has('allow-ssh')) throw new Error(`apple build: ${remote}; codesign there fails with errSecInternalComponent (locked keychain). Run it in the Mac's logged-in session: a Jenkins / Forgejo agent started in that session, or from SSH: write the command into a .command file and \`open -a Terminal <file>\` (it runs in the GUI session; unset SSH_CONNECTION SSH_CLIENT SSH_TTY inside). --allow-ssh skips this check after \`security unlock-keychain\`.`);
const web = await webStep({ ...webOpts, dry: false });
for (const n of target.notes) log(TAG, n);
const rsync = foreignRsync(process.env.PATH);