Skip to content

[spaceship][deliver][pilot] Add support for App Clips default experience metadata and review information#30010

Merged
iBotPeaches merged 35 commits into
fastlane:masterfrom
Krych:pilot-app-clips
May 15, 2026
Merged

[spaceship][deliver][pilot] Add support for App Clips default experience metadata and review information#30010
iBotPeaches merged 35 commits into
fastlane:masterfrom
Krych:pilot-app-clips

Conversation

@Krych

@Krych Krych commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Checklist

Motivation and Context

This PR is a rebase of #29738 (by @daniel-l2) onto the current master. The original PR has been stalled due to merge conflicts since November 2025. @iBotPeaches expressed interest in reviewing it once it was brought up to date — this PR
does exactly that.

The full history of this feature goes back to #19043#20300#21180#22041#29738 → this PR.

Our team ships an app with an App Clip and relies on these features in production (as does @bassrock's team per this comment (#29738 (comment))).

Description

All credit for the implementation goes to the original contributors of #29738 and #22041. This PR only resolves rebase conflicts against current master — no logic changes were made.

What's included:

  1. Deliver — App Clip metadata support
  • app_clip_default_experience_action option (PLAY, VIEW, OPEN, etc.)
  • app_clip_default_experience_subtitle — localized hash
  • app_clip_header_images_path — localized header images (1800x1200 enforced)
  • app_clip_review_information — App Clip review details
  • deliver download_app_clip_header_images command
  • Automatic metadata copy from live version when no options specified
  1. Pilot — Beta testing support
  • beta_app_clip_invocations option
  1. Spaceship — API layer
  • New models: AppClip, AppClipDefaultExperience, AppClipDefaultExperienceLocalization, AppClipHeaderImage, AppClipAppStoreReviewDetail
  • New endpoints in tunes.rb and connect_api.rb
  1. Default folder support
  • Place a single header image in default/ to apply it to all languages
  • Override per-language by adding a language-specific folder

Example usage:

 deliver(
   app_clip_default_experience_action: "PLAY",
   app_clip_default_experience_subtitle: {
     "en-US" => "Quick access to our app",
     "ko" => "앱에 빠르게 접근"
   },
   app_clip_header_images_path: "./fastlane/app-clip-header-images"
 )

Testing Steps

  1. Create an app with an App Clip target
  2. Set up folder structure: fastlane/app-clip-header-images/default/header.jpg # 1800x1200
  3. Run fastlane deliver
  4. Verify in App Store Connect that all enabled languages have the header image and subtitle

Related

Closes #29738
Closes #22041
Closes #21180
Closes #20300
Closes #19043
Fixes: #17639

@iBotPeaches

Copy link
Copy Markdown
Member

thanks. Adding Copilot to take a look.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds App Clip support across spaceship (ASC API layer), deliver (App Clip default experience metadata, header images, review info + download command), and pilot (TestFlight beta App Clip invocations), rebased onto current master.

Changes:

  • Spaceship: add App Clip and Beta App Clip Invocation endpoints + new ConnectAPI models.
  • Deliver: add upload/download support for App Clip default experience metadata, header images, and App Clip review information (including “default/” folder fallback behavior).
  • Pilot: add options and implementation to create/update/delete beta App Clip invocations on a build.

Reviewed changes

Copilot reviewed 27 out of 29 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
spaceship/lib/spaceship/connect_api/tunes/tunes.rb Adds Tunes API endpoints for App Clip default experience, header images, review details, and beta invocations.
spaceship/lib/spaceship/connect_api/models/build_bundle.rb Adds APP_CLIP bundle type constant.
spaceship/lib/spaceship/connect_api/models/beta_app_clip_invocation.rb New model for beta App Clip invocations.
spaceship/lib/spaceship/connect_api/models/beta_app_clip_invocation_localization.rb New model for beta App Clip invocation localizations.
spaceship/lib/spaceship/connect_api/models/app_store_version.rb Adds mapping/accessor for app_clip_default_experience.
spaceship/lib/spaceship/connect_api/models/app_clip_header_image.rb New model + upload logic for App Clip header images.
spaceship/lib/spaceship/connect_api/models/app_clip_default_experience_localization.rb New model for App Clip default experience localizations.
spaceship/lib/spaceship/connect_api/models/app_clip_default_experience.rb New model for the default App Clip experience.
spaceship/lib/spaceship/connect_api/models/app_clip_app_store_review_detail.rb New model for App Clip review details (invocation URLs).
spaceship/lib/spaceship/connect_api/models/app_clip.rb New model for App Clip resource.
spaceship/lib/spaceship/connect_api/models/app.rb Adds App Clip relationship mapping + get_app_clips.
spaceship/lib/spaceship/connect_api.rb Wires new App Clip / beta invocation models into ConnectAPI requires.
pilot/lib/pilot/options.rb Adds app_clip_invocations and overwrite_app_clip_invocations options.
pilot/lib/pilot/build_manager.rb Implements creation/update/deletion of beta App Clip invocations/localizations.
fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb Documents Deliver App Clip options, folder structure, and review info.
deliver/spec/upload_app_clip_default_experience_header_images_spec.rb Adds unit tests for default-folder header image assignment logic.
deliver/spec/loader_spec.rb Adds loader specs for App Clip header images + default folder behavior.
deliver/lib/deliver/upload_metadata.rb Adds App Clip review info support + includes default experience when fetching versions.
deliver/lib/deliver/upload_app_clip_default_experience_metadata.rb New uploader for App Clip default experience metadata (incl. live-copy behavior).
deliver/lib/deliver/upload_app_clip_default_experience_header_images.rb New uploader for App Clip header images (incl. default folder behavior).
deliver/lib/deliver/runner.rb Ensures App Clip default experience + header images upload runs before main metadata upload.
deliver/lib/deliver/options.rb Adds Deliver config items for App Clip metadata/images/review info/action/subtitle.
deliver/lib/deliver/loader.rb Adds filesystem loader + validation for App Clip header images.
deliver/lib/deliver/languages.rb Adds shared language detection helper used by new App Clip flows.
deliver/lib/deliver/download_app_clip_header_images.rb New command implementation to download existing App Clip header images.
deliver/lib/deliver/commands_generator.rb Adds deliver download_app_clip_header_images command.
deliver/lib/deliver/app_clip_header_image.rb New Deliver-side value object for a localized App Clip header image.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread deliver/lib/deliver/upload_app_clip_default_experience_header_images.rb Outdated
Comment thread deliver/lib/deliver/upload_app_clip_default_experience_metadata.rb
Comment thread deliver/lib/deliver/upload_metadata.rb Outdated
Comment thread spaceship/lib/spaceship/connect_api/models/app_clip_header_image.rb
Comment thread deliver/lib/deliver/upload_metadata.rb Outdated
Comment thread deliver/lib/deliver/upload_app_clip_default_experience_metadata.rb Outdated
Comment thread deliver/lib/deliver/upload_metadata.rb
Comment thread pilot/lib/pilot/build_manager.rb
Comment thread spaceship/lib/spaceship/connect_api/models/app_clip_default_experience.rb Outdated
blesson3 and others added 22 commits May 12, 2026 10:03
@Krych

Krych commented May 12, 2026

Copy link
Copy Markdown
Contributor Author

iBotPeaches there was conflict I resolved. Any option to take a look again?

@iBotPeaches

Copy link
Copy Markdown
Member

@Krych - I added Copilot who found a few things above

- Remove unused `localizations` variable and parameter from
  UploadAppClipDefaultExperienceHeaderImages#upload

- Fix operator precedence bug: `or` → `||` in has_options_specified
  assignment so action-only input is correctly detected

- Fix wrong hash key in resolve_app_clip_review_info_path: was checking
  app_review_information instead of app_clip_review_information, which
  prevented loading App Clip review info from the filesystem

- Fix transform_keys called before Hash check in app_clip_review_information:
  move kind_of?(Hash) guard before transform_keys to avoid NoMethodError

- Fix nil crash in AppClipHeaderImage.create: rescue now re-raises via
  UI.user_error! instead of silently continuing with a nil object

- Fix nil dereference in update_app_clip_invocations: add early return
  when app_clip_build_bundle is nil

- Fix AppClipDefaultExperience.get: change includes default from {} to nil
  to avoid producing an invalid API query

- Rename AppClipDefaultExperienceLocalizations → AppClipDefaultExperienceLocalization
  (singular) to match file name and other model naming conventions;
  update all references

Co-authored-by: Copilot <[email protected]>
@Krych Krych force-pushed the pilot-app-clips branch from b596166 to 2a0a4ee Compare May 12, 2026 12:36
@iBotPeaches

Copy link
Copy Markdown
Member

thanks. Okay let me watch the current release for another 24-48h to wait for any regressions. I'll start off v2.235.0 with a bang of dropping Ruby 2.7 support & adding App Clips.

You just have some lint issues now.

…uble leak

- AppClipHeaderImage.create rescue block now re-raises instead of
  swallowing the error and leaving app_clip_header_image as nil,
  which would have crashed on the next line

- Build Manager #upload specs: add before(:each) to stub
  Spaceship::ConnectAPI.client to nil, preventing leaked doubles
  from spaceship_spec.rb (which stores a real client with expired
  let doubles as a class-level variable) from causing failures when
  running spaceship/spec and pilot/spec together

Co-authored-by: Copilot <[email protected]>
@Krych

Krych commented May 12, 2026

Copy link
Copy Markdown
Contributor Author

thanks. Okay let me watch the current release for another 24-48h to wait for any regressions. I'll start off v2.235.0 with a bang of dropping Ruby 2.7 support & adding App Clips.

You just have some lint issues now.

fixed

Comment thread deliver/lib/deliver/options.rb Outdated
Comment thread deliver/lib/deliver/options.rb Outdated
Comment thread deliver/lib/deliver/options.rb
Comment thread .gitignore Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 30 changed files in this pull request and generated 5 comments.

Comment thread deliver/lib/deliver/upload_metadata.rb Outdated
Comment thread deliver/lib/deliver/upload_app_clip_default_experience_metadata.rb Outdated
Comment thread spaceship/lib/spaceship/connect_api/tunes/tunes.rb
Comment thread spaceship/lib/spaceship/connect_api/models/app_clip_header_image.rb Outdated

@iBotPeaches iBotPeaches left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

very close! I missed more env names.

Comment thread pilot/lib/pilot/options.rb Outdated
Comment thread pilot/lib/pilot/options.rb Outdated
@iBotPeaches iBotPeaches changed the title [spaceship][deliver][pilot] Add support for App Clips default experience metadata and review information (rebase of #29738) [spaceship][deliver][pilot] Add support for App Clips default experience metadata and review information May 15, 2026
@iBotPeaches iBotPeaches merged commit aa161f9 into fastlane:master May 15, 2026
9 checks passed

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey @Krych 👋

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 month, 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 🚀"

@iBotPeaches

Copy link
Copy Markdown
Member

End of an era (#19043#20300#21180#22041#29738 → this PR.)

Lets be sure to get some testing on master prior to next month's release to ensure this works for all parties using clips. Thanks for getting it across finish line.

@Krych

Krych commented May 19, 2026

Copy link
Copy Markdown
Contributor Author

End of an era (#19043#20300#21180#22041#29738 → this PR.)

Lets be sure to get some testing on master prior to next month's release to ensure this works for all parties using clips. Thanks for getting it across finish line.

I have successfully tested on master branch that submitting app with app clips worked ✅ Probably it would be nice to also test app without app clips, but unfortunately I do not have such possibility.

@bassrock

Copy link
Copy Markdown
Contributor

Tested here too, working perfectly.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Congratulations! 🎉 This was released as part of fastlane 2.235.0 🚀

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.

Deliver error for App containing an App Clip