Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
[Do iOS '24] Ship your app on a Friday...and en...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Pol Piella Abadia
November 17, 2024
Programming
1.4k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
[Do iOS '24] Ship your app on a Friday...and enjoy your weekend!
Pol Piella Abadia
November 17, 2024
More Decks by Pol Piella Abadia
See All by Pol Piella Abadia
[SwiftConf '24] Shipping your apps should be fast and easy
polpielladev
0
2.3k
[Workshop] Ship your apps faster with Xcode Cloud
polpielladev
0
160
[SwiftCraft '24] Back to the Future: Swift 6 Edition!
polpielladev
0
2.3k
[London Tech Leaders x AppCircle] The future of mobile releases
polpielladev
0
2.2k
[Swift Heroes '24] Delightful on-device AI experiences
polpielladev
0
2.3k
[SwiftLeeds '23] Delightful Swift CLI applications
polpielladev
0
2.1k
[iOS Dev UK 23] Making developer tools with Swift
polpielladev
0
2.4k
[NSBarcelona/AppTalks Manchester] - Delightful Swift CLI applications
polpielladev
0
2.1k
[Swift Heroes 2023] Making developer tools with Swift
polpielladev
0
2.3k
Other Decks in Programming
See All in Programming
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
840
setup-vp GitLab対応の裏側
naokihaba
0
150
Streamlitで実現する自然言語データアプリ開発
ayumu_yamaguchi
1
330
Are APIs Still Relevant in the AI Era?
soyuka
0
400
速く作れる。その次は、速く確かめられる開発へ 〜AIネイティブ開発を支える、Shift Down〜 / Can build fast. Next, moving to development where we can verify fast.
rkaga
8
5.4k
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
470
SONY CISC-NEWS NWS-1750 + NWB-225 フレームバッファの NetBSD/news68k ドライバ実装 / OSC2026Hiroshima
tsutsui
0
170
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
4
410
Verilogで学ぶCPU自作入門.pdf
uyuki234
7
3.9k
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
9
5.3k
Ghostty + Neovimで作る 透明でカッコ良い開発環境
j341nono
0
150
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
590
Featured
See All Featured
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
We Are The Robots
honzajavorek
0
380
Skip the Path - Find Your Career Trail
mkilby
1
240
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
560
How to train your dragon (web standard)
notwaldorf
97
6.8k
Building Adaptive Systems
keathley
44
3.2k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
510
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
390
SEO for Brand Visibility & Recognition
aleyda
0
4.8k
Prompt Engineering for Job Search
mfonobong
0
470
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.4k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
20k
Transcript
Ship your app on a Friday and enjoy your weekend
@POLPIELLADEV @
[email protected]
! Do iOS 2024 /IN/POLPIELLADEV
Indie developer and content creator based in Barcelona Pol Hi!
I’m Pol
None
polpiella.dev
ioscinewsletter.com
None
Mobile releases are difficult there is no denying that!
Accurate representation of an iOS Engineer being asked if they
want to manage a release
None
None
None
None
None
None
None
None
Mobile releases can be risky. Let’s just not ship them
on a Friday.
Gain confidence in your releases and ship anytime! A few
tips to…
#1 Automate as much as possible
None
Fully automated
desc "Distributes a new build to App Store Connect" lane
:distribute do version_number = git_branch.split("/", -1).last setup_ci xcode_select("/Applications/Xcode_16.app") sync_code_signing( type: "appstore", app_identifier: ["com.appdiggershq.fosi"], readonly: true ) increment_version_number(version_number: version_number, xcodeproj: "Fosi.xcodeproj") app_store_connect_api_key( key_id: ENV["APP_STORE_CONNECT_API_KEY_ID"], issuer_id: ENV["APP_STORE_CONNECT_ISSUER_ID"], key_content: ENV["APP_STORE_CONNECT_KEY_CONTENT"] ) build_number = latest_testflight_build_number + 1 increment_build_number(xcodeproj: "Fosi.xcodeproj", build_number: build_number) build_app(scheme: "Fosi", configuration: 'Release', output_name: "Fosi.ipa") upload_to_app_store(ipa: "Fosi.ipa", precheck_include_in_app_purchases: false) if !git_status(path: "Fosi.xcodeproj/project.pbxproj").empty? git_commit(path: "Fosi.xcodeproj/project.pbxproj", message: "[ci skip] [" release] Updating version") push_to_git_remote(remote: "origin", remote_branch: git_branch) end end
name: Distribute to the App Store Connect concurrency: group: $!"
github.workflow !#-$!" github.ref !# cancel-in-progress: true permissions: contents: write on: push: branches: - 'release!!$' jobs: distribute: runs-on: [macos-14] steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: bundler-cache: true - run: bundle exec fastlane distribute env: APP_STORE_CONNECT_API_KEY_ID: $!" secrets.APP_STORE_CONNECT_API_KEY_ID !# APP_STORE_CONNECT_ISSUER_ID: $!" secrets.APP_STORE_CONNECT_ISSUER_ID !# APP_STORE_CONNECT_KEY_CONTENT: $!" secrets.APP_STORE_CONNECT_KEY_CONTENT !# MATCH_GIT_BASIC_AUTHORIZATION: $!" secrets.MATCH_GIT_BASIC_AUTHORIZATION !# MATCH_USERNAME: $!" secrets.MATCH_USERNAME !# MATCH_PASSWORD: $!" secrets.MATCH_PASSWORD !#
A comprehensive test suite will drastically improve confidence
A comprehensive test suite will drastically improve confidence* If you
actually remember to run them!
Where should you run tests? PRs to the development branch
Before uploading to ASC On Nightly or Scheduled Workflows
If there is a manual task that causes friction, automate
it!
None
#2 Test your release pipeline
# App Target $ ModuleA.framework $ ModuleB.framework
None
$ ModuleA.framework $ ModuleB.framework # App Target
None
None
lane :nightly do # Let's make some magic happen %
gym( project: "./AwesomeApp.xcodeproj", clean: true, derived_data_path: "./derived-data", output_directory: "./build", output_name: "AwesomeApp.ipa", scheme: "AwesomeApp", export_options: { provisioningProfiles: { "your.bundle.identifier" !% "Your Provisioning Profile Name", } } ) deliver( ipa: "build/AwesomeApp.ipa", verify_only: true ) end
name: Nightly on: schedule: - cron: '0 0 * *
*' jobs: nightly: runs-on: macos-latest steps: - uses: actions/checkout@v2 - name: Run nightly lane run: bundle exec fastlane nightly
None
None
#3 Adopt a release strategy
None
None
None
None
Quality matters WAY MORE than quantity The silver bullet of
release frequency
Release less, more o!en*! Use release trains to… *Always allowing
ample time for beta testing and QA
You’ll unleash these benefits & Reduced risk ' Predictability (
Faster Feedback
None
#4 Use Feature Toggles
You can just turn it off! If something goes wrong
in production…
enum ToggleableFeature: String { case homeSwiftUIRefactor = "homeRefactor" } struct
HomeViewWrapper: View { @Environment(FeatureToggleService.self) var featureToggles var body: some View { if featureToggles.isOn(.homeSwiftUIRefactor) { HomeView() } else { LegacyHomeView() } } }
None
#5 Observe and Monitor
You first need to know that one is happening! To
quickly react to an incident
Crashes & Performance
Crashes & Performance
Crashes & Performance
None
Analytics
Customer Satisfaction
Customer Satisfaction
User Feedback
User Feedback
User Feedback
None
CI/CD Velocity Metrics
None
#6 Do not release to all users at once
None
None
None
None
None
import AWSLambdaRuntime import AWSLambdaEvents import AppStoreConnect_Swift_SDK @main struct PausePhasedReleaseWebhook: SimpleLambdaHandler
{ func handle(_ event: APIGatewayV2Request, context: LambdaContext) async throws !& APIGatewayV2Response { guard let body = event.body else { return .init(statusCode: .badRequest) } !' Read the webhook payload and decide whehter to stop the release or not!!( } }
func handle(_ event: APIGatewayV2Request, context: LambdaContext) async throws !& APIGatewayV2Response
{ }
func handle(_ event: APIGatewayV2Request, context: LambdaContext) async throws !& APIGatewayV2Response
{ !' … !' Get latest live version let endpoint = APIEndpoint .v1 .apps .id("1234567890") .appStoreVersions .get(parameters: .init(filterPlatform: [.ios], filterAppVersionState: [.readyForDistribution])) let response = try await provider.request(endpoint) let allPhasedReleases = response.included? .compactMap { item in if case .appStoreVersionPhasedRelease(let phasedRelease) = item { return phasedRelease } return nil } guard let id = allPhasedReleases!)first!)id else { return .init(statusCode: .notFound) } }
func handle(_ event: APIGatewayV2Request, context: LambdaContext) async throws !& APIGatewayV2Response
{ !' … let attributes = AppStoreVersionPhasedReleaseUpdateRequest.Data.Attributes( phasedReleaseState: .paused ) let data = AppStoreVersionPhasedReleaseUpdateRequest.Data( type: .appStoreVersionPhasedReleases, id: id, attributes: attributes ) let requestBody = AppStoreVersionPhasedReleaseUpdateRequest(data: data) let phasedReleaseEndpoint = APIEndpoint .v1 .appStoreVersionPhasedReleases .id(id) .patch(requestBody) _ = try await provider.request(phasedReleaseEndpoint) return .init(statusCode: .ok) }
*Things that are out of your control and fail oMen
*Your core business logic that your app depends on #7 Move risky* logic to the server!
None
None
None
Ship bug fixes worldwide for all versions of your app
Within seconds…
# Your App • Risky logic • Risky models
$ Risky Models # Your App • Risky logic
$ Risky Models # Your App ⚙ Risky Logic (BE)
None
#8 Roll back to a stable version immediately
1.0.0
1.0.0 1.0.1
1.0.0
1.0.0 1.0.1
1.0.0 1.0.1 1.0.2
1.0.0 1.0.2
None
Gain confidence on your release process! Automate manual processes Use
Feature Toggles Leverage the BE ecosystem Observe and Monitor Ship less, more o!en! Roll back to stable versions of your app How to use CI/CD to ship your mobile apps
And ship your apps on a Friday… or anytime! Gain
confidence in your releases
Find me online! Last tickets!