fix(ios): keep system rsync paired during export

This commit is contained in:
joshavant
2026-07-17 15:24:40 -07:00
parent 72d597c202
commit 6a053f59cd
2 changed files with 34 additions and 18 deletions

View File

@@ -1142,15 +1142,19 @@ def shell_join(parts)
Shellwords.join(parts.compact)
end
def xcodebuild_shell_join(parts)
# Keep caller-provided pinned Swift tools ahead of Homebrew. Replacing PATH
# here makes archive build phases bypass the versions verified by the caller.
xcode_path = [
*ENV.fetch("PATH", "").split(File::PATH_SEPARATOR),
def xcodebuild_shell_join(parts, system_tools_first: false)
caller_path = ENV.fetch("PATH", "").split(File::PATH_SEPARATOR)
system_path = [
"/usr/bin",
"/bin",
"/usr/sbin",
"/sbin",
]
# Archive build phases need caller-pinned Swift tools ahead of Homebrew.
# Export needs Apple's rsync ahead of incompatible Homebrew rsync helpers.
preferred_path = system_tools_first ? [*system_path, *caller_path] : [*caller_path, *system_path]
xcode_path = [
*preferred_path,
"/opt/homebrew/bin",
"/usr/local/bin",
].reject(&:empty?).uniq.join(File::PATH_SEPARATOR)
@@ -1341,16 +1345,19 @@ def build_app_store_release(context)
)
sh(
xcodebuild_shell_join([
"xcodebuild",
"-exportArchive",
"-archivePath",
archive_path,
"-exportPath",
output_directory,
"-exportOptionsPlist",
export_options_path,
])
xcodebuild_shell_join(
[
"xcodebuild",
"-exportArchive",
"-archivePath",
archive_path,
"-exportPath",
output_directory,
"-exportOptionsPlist",
export_options_path,
],
system_tools_first: true,
)
)
exported_ipas = Dir[File.join(output_directory, "*.ipa")]

View File

@@ -99,15 +99,24 @@ describe("iOS Fastlane release upload gates", () => {
it("preserves caller-pinned Swift tools in archive build PATH", () => {
const fastfile = readFastfile();
const pathBuilder = functionBody(fastfile, "xcodebuild_shell_join");
const callerPath = '*ENV.fetch("PATH", "").split(File::PATH_SEPARATOR)';
const callerPath = 'ENV.fetch("PATH", "").split(File::PATH_SEPARATOR)';
expect(pathBuilder).toContain(callerPath);
expect(pathBuilder).toContain(".reject(&:empty?).uniq.join(File::PATH_SEPARATOR)");
expect(pathBuilder.indexOf(callerPath)).toBeLessThan(
pathBuilder.indexOf('"/opt/homebrew/bin"'),
expect(pathBuilder).toContain(
"system_tools_first ? [*system_path, *caller_path] : [*caller_path, *system_path]",
);
});
it("uses Apple's matched rsync pair when exporting the IPA", () => {
const fastfile = readFastfile();
const builder = functionBody(fastfile, "build_app_store_release");
const exportStart = builder.indexOf('"-exportArchive"');
expect(exportStart).toBeGreaterThanOrEqual(0);
expect(builder.slice(exportStart)).toContain("system_tools_first: true");
});
it("requires clean matching source before preparing and building release artifacts", () => {
const fastfile = readFastfile();
const verifier = functionBody(fastfile, "verify_apple_release_source!");