Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[spaceship] support fetching build_bundle_file_sizes for a BuildBundle #20860

Merged
merged 4 commits into from Nov 16, 2022

Conversation

liamnichols
Copy link
Contributor

@liamnichols liamnichols commented Nov 15, 2022

Checklist

  • I've run bundle exec rspec from the root directory to see all new and existing tests pass
  • I've followed the fastlane code style and run bundle exec rubocop -a to ensure the code style is valid
  • I see several green ci/circleci builds in the "All checks have passed" section of my PR (connect CircleCI to GitHub if not)
  • I've read the Contribution Guidelines
  • I've updated the documentation if necessary.

Motivation and Context

We recently started using Xcode 14 to submit to the App Store but it wasn't until I read this article that I became aware that by removing Bitcode support, we were unintentionally bloating our app size by an additional ~5mb.

It annoyed me that I had to find this by digging into App Store Connect so instead I wanted to write a custom action to pull that data and compare for me. The first hurdle that I got stuck at however was that Spaceship didn't currently offer a way to pull bundle file size data from App Store Connect.

Description

With some external help, I was pointed to the buildBundles/{id}/buildBundleFileSizes API.

The Build model already fetches buildBundles by default it seems (since there is a relationship) however fetching a build alone is not enough to fetch the buildBundleFileSizes. To support this, I think that I followed the correct pattern and introduced a BuildBundleFileSizes model.

The naming confused me a bit here, because I thought that it was pluralised because there are an array of sizes for different device/os combinations, but it wasn't that, it was because the model includes two sizes: the installed size and the download size. This makes things a little odd when it came to defining the models, but I tried to stick to the API structure as much as possible.

On BuildBundle, I then added a build_bundle_file_sizes method to fetch them.. It can be used like the following:

app = Spaceship::ConnectAPI::App.find('com.my.app')
builds = Spaceship::ConnectAPI::Build.all(app_id: app.id, version: '1.0.0')

build = builds.first
build_bundles = build.build_bundles
bundle = build_bundles.detect { _1.bundle_type == Spaceship::ConnectAPI::BuildBundle::BundleType::APP }
file_sizes = bundle.build_bundle_file_sizes
universal = file_sizes.detect { _1.device_model == "Universal" }

UI.success("Download Size: #{(universal.download_bytes.to_f / 1000000).round(2)} MB, Install Size: #{(universal.install_bytes.to_f / 1000000).round(2)} MB")

Now I wasn't entirely sure on the best way to implement this so I've given it my best shot. Please call out anything that seems wrong. While there is a convenience method on the BuildBundle type, it just calls though to the BuildBundleFileTypes.all(...) class method.

I've left my own review inline regarding parts that I wasn't quite sure of.

Testing Steps

I added a spec to cover this although I'm not sure if there is a better way? I could write more if there is so just let me know!

Additionally, you can implement a test lane like the one above to try it out for yourself.

Copy link
Contributor Author

@liamnichols liamnichols left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Started off the discussion around some areas where I still had questions


def get_build_bundle_build_bundle_file_sizes(build_bundle_id:, limit: nil)
params = test_flight_request_client.build_params(filter: nil, includes: nil, limit: limit, sort: nil, cursor: nil)
test_flight_request_client.get("buildBundles/#{build_bundle_id}/buildBundleFileSizes", params)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I in the right place? Is the TestFlight client the right place to implement this kind of thing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This client names are a little bit weird since App Store Connect API has changed a bit since this was create 🙈 But yup! This would be the correct place for this 💪

# buildBundles
#

def get_build_bundles_build_bundle_file_sizes(build_bundle_id:, limit: nil)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name is quite the mouthful 😄

I stuck with it because the endpoint is buildBundles/{id}/buildBundleFileSizes so there is some repetition here already... There are other buildBundles methods that don't have the repetition, so if we implemented everything, I was imagining that it would look like this:

Method Endpoint
get_build_bundles_build_bundle_file_sizes buildBundles/{id}/buildBundleFileSizes
get_build_bundles_ app_clip_domain_cache_status buildBundles/{id}/appClipDomainCacheStatus
get_build_bundles_app_clip_domain_debug_status buildBundles/{id}/appClipDomainDebugStatus
get_build_bundles_beta_app_clip_invocations buildBundles/{id}/betaAppClipInvocations

Would that make sense? If there is a better approach, please let me know 🙏 I couldn't really find any other examples to follow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name is quite the mouthful 😅 I feel like this is generally okay here though. We provide helper methods in th models to make this easier to use for most users.

Eventually maybe we can namespace this better but that would require a whole redesign so I think this method name makes sense on the route that it's doing.

# buildBundles
#

def get_build_bundles_build_bundle_file_sizes(build_bundle_id:, limit: nil)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with build_bundle_id over bundle_id to avoid confusion with the bundle identifier (i.e com.my.app).

Comment on lines +92 to +95
def stub_build_bundles
stub_request(:get, "https://appstoreconnect.apple.com/iris/v1/buildBundles/48a9bb1f-5f0f-4133-8c72-3fb93e92603a/buildBundleFileSizes").
to_return(status: 200, body: read_fixture_file('build_bundles_build_bundle_file_sizes.json'), headers: { 'Content-Type' => 'application/json' })
end
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this right for the tests? The actual URL that I hit when I run locally is https://api.appstoreconnect.apple.com/ but all of these stubs are registered against https://appstoreconnect.apple.com/iris.

I assume this is because we used a private API before the official one? So it should be safe to leave this how it is, but I just wanted to confirm 🙏

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually didn't realize that the tests are using the private API 😱 We should probably able be making tests that hit the official API (at some point).

But this is good for now 😊 Thanks for checking!

@liamnichols liamnichols marked this pull request as ready for review November 15, 2022 17:25
@joshdholtz joshdholtz changed the title [Spaceship] Support fetching build_bundle_file_sizes for a BuildBundle [spaceship] support fetching build_bundle_file_sizes for a BuildBundle Nov 16, 2022
Copy link
Member

@joshdholtz joshdholtz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works great and thanks for commenting on your own PR! 🙌 That made this super easy to review 😊 Really appreciate the PR!

# buildBundles
#

def get_build_bundles_build_bundle_file_sizes(build_bundle_id:, limit: nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name is quite the mouthful 😅 I feel like this is generally okay here though. We provide helper methods in th models to make this easier to use for most users.

Eventually maybe we can namespace this better but that would require a whole redesign so I think this method name makes sense on the route that it's doing.


def get_build_bundle_build_bundle_file_sizes(build_bundle_id:, limit: nil)
params = test_flight_request_client.build_params(filter: nil, includes: nil, limit: limit, sort: nil, cursor: nil)
test_flight_request_client.get("buildBundles/#{build_bundle_id}/buildBundleFileSizes", params)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This client names are a little bit weird since App Store Connect API has changed a bit since this was create 🙈 But yup! This would be the correct place for this 💪

Comment on lines +92 to +95
def stub_build_bundles
stub_request(:get, "https://appstoreconnect.apple.com/iris/v1/buildBundles/48a9bb1f-5f0f-4133-8c72-3fb93e92603a/buildBundleFileSizes").
to_return(status: 200, body: read_fixture_file('build_bundles_build_bundle_file_sizes.json'), headers: { 'Content-Type' => 'application/json' })
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually didn't realize that the tests are using the private API 😱 We should probably able be making tests that hit the official API (at some point).

But this is good for now 😊 Thanks for checking!

@joshdholtz joshdholtz merged commit 8b307b1 into fastlane:master Nov 16, 2022
@liamnichols liamnichols deleted the ln/build_bundle_file_sizes branch November 16, 2022 08:53
@liamnichols
Copy link
Contributor Author

Cheers @joshdholtz for the review and the quick merge 🚀🙌

@fastlane-bot
Copy link

Hey @liamnichols 👋

Thank you for your contribution to fastlane and congrats on getting this pull request merged 🎉
The code change now lives in the master branch, however it wasn't released to RubyGems yet.
We usually ship about once a week, and your PR will be included in the next one.

Please let us know if this change requires an immediate release by adding a comment here 👍
We'll notify you once we shipped a new release with your changes 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants