Skip to content

Commit

Permalink
Use Xcode Cloud to build SDK releases (#4200)
Browse files Browse the repository at this point in the history
## Summary
We set up a "Stripe.framework" project in Xcode Cloud, which will build
the new 'ReleaseFrameworksTarget' target on release branches. All this
does is run the `export_builds.rb` script and copy the results to the
`BUILT_PRODUCTS_DIR`.

The deploy script will no longer build the frameworks locally. Instead,
it will fetch the artifact from the Xcode build matching the current
release hash and copy it to the build products directory.

This is pretty brittle, but should be fine for our purposes. It'll also
break loudly if anything fails.

## Motivation
Allow us to deploy from machines running Sequoia

## Testing
Tested locally. Pushed a `releases/23.test.test` branch, waited for CI
to complete, then ran the first step of `deploy_release.rb`.

## Changelog
None

---------

Co-authored-by: Mel Ludowise <mludowise@stripe.com>
  • Loading branch information
davidme-stripe and mludowise-stripe authored Nov 7, 2024
1 parent 87c139e commit 77ecc4c
Show file tree
Hide file tree
Showing 8 changed files with 263 additions and 14 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ gem "octokit", "~> 4.25.1"
gem "mime-types"
gem "CFPropertyList"
gem "terminal-table"
gem "httparty"

gem "xcode-install", "~> 2.6"
gem "plist"
Expand Down
7 changes: 7 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ GEM
highline (~> 2.0.0)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
csv (3.3.0)
date (3.3.4)
declarative (0.0.20)
digest-crc (0.6.5)
Expand Down Expand Up @@ -214,6 +215,10 @@ GEM
highline (2.0.3)
http-cookie (1.0.5)
domain_name (~> 0.5)
httparty (0.22.0)
csv
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
i18n (1.14.4)
concurrent-ruby (~> 1.0)
Expand All @@ -234,6 +239,7 @@ GEM
minitest (5.22.3)
molinillo (0.8.0)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.4.0)
mutex_m (0.2.0)
nanaimo (0.3.0)
Expand Down Expand Up @@ -322,6 +328,7 @@ DEPENDENCIES
dotstrings
fastlane
fastlane-plugin-emerge
httparty
mail
mime-types
net-ssh
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1600"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E652E5F22CB20B7200081F83"
BuildableName = "ReleaseFrameworksTarget"
BlueprintName = "ReleaseFrameworksTarget"
ReferencedContainer = "container:Stripe/Stripe.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E652E5F22CB20B7200081F83"
BuildableName = "ReleaseFrameworksTarget"
BlueprintName = "ReleaseFrameworksTarget"
ReferencedContainer = "container:Stripe/Stripe.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
66 changes: 66 additions & 0 deletions Stripe/Stripe.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@
objectVersion = 55;
objects = {

/* Begin PBXAggregateTarget section */
E652E5F22CB20B7200081F83 /* ReleaseFrameworksTarget */ = {
isa = PBXAggregateTarget;
buildConfigurationList = E652E5F52CB20B7200081F83 /* Build configuration list for PBXAggregateTarget "ReleaseFrameworksTarget" */;
buildPhases = (
E652E5F62CB20BA200081F83 /* ShellScript */,
);
dependencies = (
);
name = ReleaseFrameworksTarget;
packageProductDependencies = (
);
productName = ReleaseFrameworksTarget;
};
/* End PBXAggregateTarget section */

/* Begin PBXBuildFile section */
013F991AB34E38BDBA6E4521 /* STPFormViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F44327A2B2C9483F52EE343B /* STPFormViewSnapshotTests.swift */; };
0185AC6B123CD73E877D4FCE /* STPPaymentMethodCashAppParamsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABB2CA7E96BE249CE8C0566 /* STPPaymentMethodCashAppParamsTests.swift */; };
Expand Down Expand Up @@ -1223,6 +1239,9 @@
49A14BBD10B1E97F2B43C448 = {
TestTargetID = 1628E8B14F1F7C63CF8C9962;
};
E652E5F22CB20B7200081F83 = {
CreatedOnToolsVersion = 16.0;
};
};
};
buildConfigurationList = 2804CCD7A91C99DF32596147 /* Build configuration list for PBXProject "Stripe" */;
Expand Down Expand Up @@ -1288,6 +1307,7 @@
8BE23AD5D9A3D939AF46F31E /* StripeiOSTests */,
1628E8B14F1F7C63CF8C9962 /* StripeiOSTestHostApp */,
49A14BBD10B1E97F2B43C448 /* StripeiOSAppHostedTests */,
E652E5F22CB20B7200081F83 /* ReleaseFrameworksTarget */,
);
};
/* End PBXProject section */
Expand Down Expand Up @@ -1331,6 +1351,27 @@
};
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
E652E5F62CB20BA200081F83 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "cd \"${PROJECT_DIR}/..\"\nruby ci_scripts/export_builds.rb \ncp \"${PROJECT_DIR}/../build/Stripe.xcframework.zip\" \"${BUILT_PRODUCTS_DIR}\"\n";
};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
24CDC502E3D468F309116FE1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
Expand Down Expand Up @@ -1777,6 +1818,22 @@
};
name = Release;
};
E652E5F32CB20B7200081F83 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
E652E5F42CB20B7200081F83 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
Expand Down Expand Up @@ -1807,6 +1864,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E652E5F52CB20B7200081F83 /* Build configuration list for PBXAggregateTarget "ReleaseFrameworksTarget" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E652E5F32CB20B7200081F83 /* Debug */,
E652E5F42CB20B7200081F83 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F0FCB32AE130ABA66178DD9B /* Build configuration list for PBXNativeTarget "StripeiOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
Expand Down
6 changes: 5 additions & 1 deletion bitrise.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ stages:
- ui-tests-3: {}
- ui-tests-4: {}
- integration-all: {}
- deploy-dry-run: {}
- lokalise-upload: {}
stage-releases-run-all:
workflows:
Expand Down Expand Up @@ -151,6 +150,11 @@ workflows:
- content: bundle exec ./ci_scripts/deploy_release.rb --dry-run
is_always_run: true
title: Deploy release
- script@1:
inputs:
- content: bundle exec ./ci_scripts/export_builds.rb
is_always_run: true
title: Export builds
before_run:
- prep_all
after_run:
Expand Down
16 changes: 13 additions & 3 deletions ci_scripts/deploy_release.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ def verify_xcode_version
abort
end

verify_xcode_version

@version = version_from_file

@changelog = changelog(@version)

@cleanup_branchname = "releases/#{@version}_cleanup"

def export_builds
verify_xcode_version

# Delete Stripe.xcframework.zip if one exists
run_command('rm -f build/Stripe.xcframework.zip')

Expand All @@ -35,6 +35,16 @@ def export_builds
raise 'build/Stripe.xcframework.zip not found. Did the build fail?' unless File.exist?('build/Stripe.xcframework.zip')
end

def export_builds_from_xcode_cloud
return if @is_dry_run
# Delete Stripe.xcframework.zip if one exists
run_command('rm -f build/Stripe.xcframework.zip')

run_command('ci_scripts/export_builds_from_xcode_cloud.rb')

raise 'build/Stripe.xcframework.zip not found. Did we fail to fetch it from Xcode Cloud?' unless File.exist?('build/Stripe.xcframework.zip')
end

def approve_pr
rputs 'Open the PR, approve it, and merge it.'
rputs '(Use "Squash and merge")'
Expand Down Expand Up @@ -116,7 +126,7 @@ def sync_owner_list
end

steps = [
method(:export_builds),
method(:export_builds_from_xcode_cloud),
method(:approve_pr),
method(:create_docs_pr),
method(:push_tag),
Expand Down
15 changes: 5 additions & 10 deletions ci_scripts/export_builds.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/usr/bin/env ruby

require 'fileutils'
require 'zip'
require 'yaml'

# MARK: - Helpers
Expand Down Expand Up @@ -55,6 +54,7 @@ def File.join_if_safe(arg1, *otherArgs)
-scheme "AllStripeFrameworks" \
-configuration "Release" \
-archivePath "#{build_dir}/StripeFrameworks-iOS.xcarchive" \
-derivedDataPath "#{build_dir}/DerivedData" \
-sdk iphoneos \
-destination 'generic/platform=iOS' \
SUPPORTS_MACCATALYST=NO \
Expand All @@ -75,6 +75,7 @@ def File.join_if_safe(arg1, *otherArgs)
-destination 'generic/platform=iOS Simulator' \
-configuration "Release" \
-archivePath "#{build_dir}/StripeFrameworks-sim.xcarchive" \
-derivedDataPath "#{build_dir}/DerivedData" \
-sdk iphonesimulator \
SUPPORTS_MACCATALYST=NO \
BUILD_LIBRARIES_FOR_DISTRIBUTION=YES \
Expand All @@ -93,6 +94,7 @@ def File.join_if_safe(arg1, *otherArgs)
-scheme "AllStripeFrameworksCatalyst" \
-configuration "Release" \
-archivePath "#{build_dir}/StripeFrameworks-mac.xcarchive" \
-derivedDataPath "#{build_dir}/DerivedData" \
-sdk macosx \
-destination 'generic/platform=macOS,variant=Mac Catalyst' \
SUPPORTS_MACCATALYST=YES \
Expand Down Expand Up @@ -125,13 +127,6 @@ def File.join_if_safe(arg1, *otherArgs)
end # modules.each
end # Dir.chdir

Zip::File.open(File.join_if_safe(build_dir, 'Stripe.xcframework.zip'), create: true) do |zipfile|
# Add module framework directories to zip
modules.each do |m|
framework_name = m['framework_name']
Dir.glob("#{build_dir}/#{framework_name}.xcframework/**/*").each do |file|
file_name = Pathname.new(file).relative_path_from(Pathname.new(build_dir))
zipfile.add(file_name, file)
end
end
Dir.chdir(build_dir) do
`zip -r Stripe.xcframework.zip *.xcframework`
end
Loading

0 comments on commit 77ecc4c

Please sign in to comment.