Skip to content

Commit ce6becb

Browse files
[CI] Comment SDK size on every commit (#560)
1 parent 1db476b commit ce6becb

File tree

5 files changed

+173
-1
lines changed

5 files changed

+173
-1
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: SDK Size
2+
3+
on:
4+
pull_request:
5+
6+
workflow_dispatch:
7+
8+
push:
9+
branches:
10+
- develop
11+
12+
env:
13+
HOMEBREW_NO_INSTALL_CLEANUP: 1 # Disable cleanup for homebrew, we don't need it on CI
14+
15+
jobs:
16+
sdk_size:
17+
name: Metrics
18+
runs-on: macos-14
19+
env:
20+
GITHUB_TOKEN: '${{ secrets.CI_BOT_GITHUB_TOKEN }}'
21+
steps:
22+
- name: Install Bot SSH Key
23+
uses: webfactory/ssh-agent@v0.7.0
24+
with:
25+
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
26+
27+
- uses: actions/checkout@v3.1.0
28+
29+
- uses: ./.github/actions/bootstrap
30+
31+
- name: Run SDK Size Metrics
32+
run: bundle exec fastlane show_frameworks_sizes
33+
timeout-minutes: 30
34+
env:
35+
GITHUB_PR_NUM: ${{ github.event.pull_request.number }}
36+
GITHUB_EVENT_NAME: ${{ github.event_name }}
37+
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
38+
APPSTORE_API_KEY: ${{ secrets.APPSTORE_API_KEY }}

.github/workflows/smoke-checks.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ jobs:
165165
env:
166166
ALLURE_TOKEN: ${{ secrets.ALLURE_TOKEN }}
167167
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
168+
GITHUB_PR_NUM: ${{ github.event.number }}
168169
GITHUB_EVENT: ${{ toJson(github.event) }}
169170
- id: get_launch_id
170171
run: echo "launch_id=${{env.LAUNCH_ID}}" >> $GITHUB_OUTPUT

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ fastlane/screenshots
7171
fastlane/test_output
7272
fastlane/allurectl
7373
fastlane/xcresults
74+
fastlane/metrics
7475
fastlane/recordings
7576
StreamChatCore.framework.coverage.txt
7677
StreamChatCoreTests.xctest.coverage.txt
@@ -87,4 +88,6 @@ derived_data/
8788
spm_cache/
8889
.buildcache
8990
buildcache
91+
App Thinning Size Report.txt
92+
app-thinning.plist
9093
*.dmg

fastlane/Fastfile

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,18 @@ sdk_names = ['StreamChatSwiftUI']
1313
github_repo = ENV['GITHUB_REPOSITORY'] || 'GetStream/stream-chat-swiftui'
1414
derived_data_path = 'derived_data'
1515
source_packages_path = 'spm_cache'
16+
metrics_git = 'git@github.com:GetStream/apple-internal-metrics.git'
17+
sdk_size_path = "metrics/#{github_repo.split('/').last}-size.json"
1618
buildcache_xcargs = 'CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++'
1719
is_localhost = !is_ci
1820
project_package_resolved = "#{xcode_project}/project.xcworkspace/xcshareddata/swiftpm/Package.resolved"
1921
@force_check = false
2022

23+
warning_status = '🟡' # Warning if a branch is #{max_tolerance} less performant than the benchmark
24+
fail_status = '🔴' # Failure if a branch is more than #{max_tolerance} less performant than the benchmark
25+
success_status = '🟢' # Success if a branch is more performant or equals to the benchmark
26+
outstanding_status = '🚀' # Outstanding performance
27+
2128
before_all do |lane|
2229
if is_ci
2330
setup_ci
@@ -463,7 +470,8 @@ lane :sources_matrix do
463470
e2e: ['Sources', 'StreamChatSwiftUITestsAppTests', 'StreamChatSwiftUITestsApp'],
464471
ui: ['Sources', 'StreamChatSwiftUITests', xcode_project],
465472
sample_apps: ['Sources', 'DemoAppSwiftUI', xcode_project],
466-
ruby: ['fastlane', 'Gemfile', 'Gemfile.lock']
473+
ruby: ['fastlane', 'Gemfile', 'Gemfile.lock'],
474+
size: ['Sources', xcode_project]
467475
}
468476
end
469477

@@ -477,6 +485,93 @@ lane :copyright do
477485
)
478486
end
479487

488+
desc 'Show current frameworks size'
489+
lane :show_frameworks_sizes do |options|
490+
next unless is_check_required(sources: sources_matrix[:size], force_check: @force_check)
491+
492+
['metrics/'].each { |dir| FileUtils.remove_dir(dir, force: true) }
493+
494+
sh("git clone #{metrics_git} #{File.dirname(sdk_size_path)}")
495+
develop_sizes = JSON.parse(File.read(sdk_size_path))
496+
branch_sizes = options[:sizes] || frameworks_sizes
497+
498+
table_header = '## SDK Size'
499+
markdown_table = "#{table_header}\n| `title` | `develop` | `branch` | `diff` | `status` |\n| - | - | - | - | - |\n"
500+
sdk_names.each do |title|
501+
benchmark_value = develop_sizes[title]
502+
branch_value = branch_sizes[title.to_sym]
503+
max_tolerance = 0.5 # Max Tolerance is 0.5MB
504+
fine_tolerance = 0.25 # Fine Tolerance is 0.25MB
505+
506+
diff = (branch_value - benchmark_value).round(2)
507+
508+
status_emoji =
509+
if diff < 0
510+
outstanding_status
511+
elsif diff >= max_tolerance
512+
fail_status
513+
elsif diff >= fine_tolerance
514+
warning_status
515+
else
516+
success_status
517+
end
518+
519+
markdown_table << "|#{title}|#{benchmark_value}MB|#{branch_value}MB|#{diff}MB|#{status_emoji}|\n"
520+
end
521+
522+
FastlaneCore::PrintTable.print_values(title: 'Benchmark', config: develop_sizes)
523+
FastlaneCore::PrintTable.print_values(title: 'SDK Size', config: branch_sizes)
524+
525+
if is_ci
526+
if ENV['GITHUB_EVENT_NAME'].to_s == 'push'
527+
File.write(sdk_size_path, JSON.pretty_generate(branch_sizes))
528+
Dir.chdir(File.dirname(sdk_size_path)) do
529+
if sh('git status -s', log: false).to_s.empty?
530+
UI.important('No changes in SDK sizes benchmarks.')
531+
else
532+
sh('git add -A')
533+
sh("git commit -m 'Update #{sdk_size_path}'")
534+
sh('git push')
535+
end
536+
end
537+
end
538+
539+
create_pr_comment(pr_num: ENV.fetch('GITHUB_PR_NUM'), text: markdown_table, edit_last_comment_with_text: table_header)
540+
end
541+
542+
UI.user_error!("#{table_header} benchmark failed.") if markdown_table.include?(fail_status)
543+
end
544+
545+
def frameworks_sizes
546+
root_dir = 'Build/SDKSize'
547+
archive_dir = "#{root_dir}/DemoApp.xcarchive"
548+
549+
FileUtils.rm_rf("../#{root_dir}/")
550+
551+
match_me
552+
553+
gym(
554+
scheme: 'DemoAppSwiftUI',
555+
archive_path: archive_dir,
556+
export_method: 'ad-hoc',
557+
export_options: 'fastlane/sdk_size_export_options.plist'
558+
)
559+
560+
# Parse the thinned size of Assets.car from Packaging.log
561+
assets_size_regex = %r{\b(\d+)\sbytes\sfor\s./Payload/DemoAppSwiftUI.app/Frameworks/StreamChatSwiftUI.framework/Assets.car\b}
562+
packaging_log_content = File.read("#{Gym.cache[:temporary_output_path]}/Packaging.log")
563+
match = packaging_log_content.match(assets_size_regex)
564+
assets_thinned_size = match[1].to_i
565+
566+
frameworks_path = "../#{archive_dir}/Products/Applications/DemoAppSwiftUI.app/Frameworks"
567+
stream_chat_swiftui_size = File.size("#{frameworks_path}/StreamChatSwiftUI.framework/StreamChatSwiftUI")
568+
stream_chat_swiftui_size_mb = ((stream_chat_swiftui_size + assets_thinned_size).to_f / 1024 / 1024).round(2)
569+
570+
{
571+
StreamChatSwiftUI: stream_chat_swiftui_size_mb
572+
}
573+
end
574+
480575
private_lane :create_pr do |options|
481576
options[:base_branch] ||= 'develop'
482577
sh("git checkout -b #{options[:head_branch]}")
@@ -494,6 +589,14 @@ private_lane :create_pr do |options|
494589
)
495590
end
496591

592+
private_lane :create_pr_comment do |options|
593+
if is_ci && !options[:pr_num].to_s.empty?
594+
last_comment = sh("gh pr view #{options[:pr_num]} --json comments --jq '.comments | map(select(.author.login == \"Stream-iOS-Bot\")) | last'")
595+
edit_last_comment = last_comment.include?(options[:edit_last_comment_with_text]) ? '--edit-last' : ''
596+
sh("gh pr comment #{options[:pr_num]} #{edit_last_comment} -b '#{options[:text]}'")
597+
end
598+
end
599+
497600
private_lane :current_branch do
498601
ENV['BRANCH_NAME'].to_s.empty? ? git_branch : ENV.fetch('BRANCH_NAME')
499602
end
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>compileBitcode</key>
6+
<false/>
7+
<key>destination</key>
8+
<string>export</string>
9+
<key>method</key>
10+
<string>release-testing</string>
11+
<key>provisioningProfiles</key>
12+
<dict>
13+
<key>io.getstream.iOS.DemoAppSwiftUI</key>
14+
<string>match AdHoc io.getstream.iOS.DemoAppSwiftUI</string>
15+
</dict>
16+
<key>signingCertificate</key>
17+
<string>Apple Distribution</string>
18+
<key>signingStyle</key>
19+
<string>manual</string>
20+
<key>stripSwiftSymbols</key>
21+
<true/>
22+
<key>teamID</key>
23+
<string>EHV7XZLAHA</string>
24+
<key>thinning</key>
25+
<string>iPhone15,2</string>
26+
</dict>
27+
</plist>

0 commit comments

Comments
 (0)