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

[WIP][spaceship] add initial App Clips support #19043

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

ainame
Copy link
Contributor

@ainame ainame commented Jul 2, 2021

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've read the Contribution Guidelines
  • I've updated the documentation if necessary.

Motivation and Context

#17639

We got no App Clips support in the official App Store Connect API from WWDC21 so I came to start supporting it with the web session one.

Description

I have added the following four new models to support the basic settings of App Clips' metadata on App Store Connect console, which represents the information on the screenshot.

  • appClips - this will be automatically created once you upload an ipa file including an App Clip
  • appClipVersions - includes Action
  • appClipVersionLocalizations - includes locale and subtitle
  • appClipHeaderImages - image

Screenshot 2021-07-04 at 00 46 57

JFYI: I haven't looked into things that can be edited within "Edit Advanced Experiences" pages.

Testing Steps

Screenshot 2021-07-04 at 11 36 23

As the above says, to see the App Clip section enabled on App Store Connect, you would need to follow these.

Then you'll see the section enabled, which means appClips and appClipVersions resources are created internally already. You can play APIs with the spaceship playground command, like below.

Note that this currently works with only the web session. App Store Connect API key wont' work for this.

app = Spaceship::ConnectAPI::App.find('YOUR_APP_BUNDLE_ID')
app_clip = app.get_app_clips.first
app_clip_version = app_clip.get_app_clip_versions.first

app_clip_version.update(attributes: { invocationVerb: Spaceship::ConnectAPI::AppClipVersion::InvocationVerb::OPEN })
app_clip_version.create_app_clip_version_localization(attributes: { locale: 'ja', subtitle: 'サブタイトル' } )

localizations = app_clip_version.get_app_clip_version_localizations
localizations[0].update(attributes: { subtitle: 'updated subtitle!' })

app_clip_header_image = Spaceship::ConnectAPI::AppClipHeaderImage.create(app_clip_version_localization_id: localizations[0].id, path: 'path/to/image')
app_clip_header_image.delete!

FYI: Apparently, once you change things within "Edit Adavanced Experiences", you won't be able to modify some attributes via AppClipVersion#update 🤔

[4] pry(#Spaceship::Playground)> app_clip_version.update(attributes: { invocationVerb: Spaceship::ConnectAPI::AppClipVersion::InvocationVerb::VIEW })
Spaceship::UnexpectedResponse: An attribute value is not acceptable for the current resource state. - The attribute 'invocationVerb' cannot be modified at this time. - /data/attributes/invocationVerb

@google-cla google-cla bot added the cla: yes label Jul 2, 2021
@ainame ainame self-assigned this Jul 3, 2021
@ainame ainame marked this pull request as ready for review July 4, 2021 02:48
@ainame
Copy link
Contributor Author

ainame commented Jul 4, 2021

CI failure might be related to this 🤔
fastlane/docs#1051 (comment)


module Spaceship
class ConnectAPI
class AppClipHeaderImage
Copy link
Contributor Author

@ainame ainame Jul 4, 2021

Choose a reason for hiding this comment

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

This class's implementation is almost identical to AppScreenshot and AppPreview but I didn't go refactoring to extract common interfaces for now.

I personally feel like -

  • Having the list of attr_accesor in each class should be fine
  • awaiting_upload? or other helpers functions can be extracted to a module to be shared
  • Asset uploading logic should be extracted to a class to enforce exactly the same flow for each and write tests but that requires a bit of abstraction since APIs used are different

Comment on lines 1181 to 1189
def get_app_clip_version_release_with_app_store_version(app_clip_version_id:, filter: {}, includes: nil, limit: nil, sort: nil)
params = tunes_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
tunes_request_client.get("appClipVersions/#{app_clip_version_id}/relationships/releaseWithAppStoreVersion", params)
end

def get_app_clip_app_store_review_detail(app_clip_version_id:, filter: {}, includes: nil, limit: nil, sort: nil)
params = tunes_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
tunes_request_client.get("appClipVersions/#{app_clip_version_id}/relationships/appClipAppStoreReviewDetail", params)
end
Copy link
Contributor Author

@ainame ainame Jul 4, 2021

Choose a reason for hiding this comment

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

There are those resources related to appClipVersions but didn't add models for them since I have no idea how to use them. (releaseWithAppStoreVersion is appStoreVersion type)

Copy link
Member

@crazymanish crazymanish left a comment

Choose a reason for hiding this comment

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

LGTM! 🚀
Learn a lot when reviewing this PR 🙇

Comment on lines 25 to 26
def get_app_clip_version_localizations(client: nil, filter: {}, includes: Spaceship::ConnectAPI::AppClipVersionLocalization::ESSENTIAL_INCLUDES, limit: nil, sort: nil)
client ||= Spaceship::ConnectAPI
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def get_app_clip_version_localizations(client: nil, filter: {}, includes: Spaceship::ConnectAPI::AppClipVersionLocalization::ESSENTIAL_INCLUDES, limit: nil, sort: nil)
client ||= Spaceship::ConnectAPI
def get_app_clip_version_localizations(client: nil, filter: {}, includes: nil, limit: nil, sort: nil)
client ||= Spaceship::ConnectAPI
includes ||= Spaceship::ConnectAPI::AppClipVersionLocalization::ESSENTIAL_INCLUDES

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, well, yes. I know what you are saying here.

But I think the default value of keyword arguments is much simpler than ||= idiom to do this same thing honestly😅 client ||= Spaceship::ConnectAPI appears everywhere right now so I just followed it for the sake of consistency but it should have been consistent with using "default value", IMHO. I may clean it up at some point 🤔

#17475

(Moreover, I don't fully understand the point to pass a client class type to each method 🤔 )

Copy link
Member

Choose a reason for hiding this comment

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

@ainame There are people who use these methods with multiple teams at the same time (which means multiple clients). These users are not able to just use the single session on the Spaceship::ConnectAPI for this reason. So these users create individual Spaceship::ConnectAPI::Client instances and pass them into the models to use. It's a very niche feature but something we need to support 🤷‍♂️

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@joshdholtz Yes, I know that but was just wondering what's the reason behind using multiple sessions🤔 I saw the PR changing it this way but it didn't contain much information, unfortunately.

@EmDee
Copy link
Contributor

EmDee commented Jul 5, 2021

@ainame Thanks a lot for this PR! 🚀 We are currently in the release process, but I can test your branch until the end of the week.

@ainame
Copy link
Contributor Author

ainame commented Jul 5, 2021

@EmDee Thank you for that! Please note this🙂

FYI: Apparently, once you change things within "Edit Adavanced Experiences", you won't be able to modify some attributes via AppClipVersion#update 🤔

@EmDee
Copy link
Contributor

EmDee commented Jul 5, 2021

@EmDee Thank you for that! Please note this🙂

FYI: Apparently, once you change things within "Edit Adavanced Experiences", you won't be able to modify some attributes via AppClipVersion#update 🤔

Thanks, I'll keep that in mind. Will keep you posted.

@EmDee
Copy link
Contributor

EmDee commented Jul 9, 2021

Hey @ainame, I'm currently trying to test our your implementation. I initially thought that this has already been integrated into the deliver action. Either way, I've setup a Fastlane job to run your above snippet, but am getting an undefined method get_apps' for nil:NilClass` error.

My setup is the following:

  1. I have an app update ready where the app clip information is missing
    image
  2. My lane has the following content:
lane :adjustAppClip do
    app = Spaceship::ConnectAPI::App.find('com.foo.bar')
    app_clip = app.get_app_clips.first
    app_clip_version = app_clip.get_app_clip_versions.first

    app_clip_version.update(attributes: { invocationVerb: Spaceship::ConnectAPI::AppClipVersion::InvocationVerb::OPEN })
    app_clip_version.create_app_clip_version_localization(attributes: { locale: 'en', subtitle: 'Test' } )

    localizations = app_clip_version.get_app_clip_version_localizations
    localizations[0].update(attributes: { subtitle: 'Foo' })
    localizations[1].update(attributes: { subtitle: 'Bar' })

    app_clip_header_image = Spaceship::ConnectAPI::AppClipHeaderImage.create(app_clip_version_localization_id: localizations[0].id, path: 'metadata/preview.png')
    app_clip_header_image.delete!
  end

I think I'm missing the web session, therefore no apps can be found, but I'm not entirely sure how to initialize the session here. Pointers?

@ainame
Copy link
Contributor Author

ainame commented Jul 10, 2021

@EmDee Thank you for giving it a try🙂

I initially thought that this has already been integrated into the deliver action.

Well, that's the future plan. This PR hasn't covered that yet.

am getting an undefined method get_apps' for nil:NilClass`

Could you please share the stack trace (backtrace) of that error? Isn't that "undefined method get_app_clips for nil:NilClass"...? If so make sure you get the right value from Spaceship::ConnectAPI::App.find('com.foo.bar') first?
You would need to call Spacehsip::ConnectAPI.login to get the web session.

@EmDee
Copy link
Contributor

EmDee commented Jul 10, 2021

@EmDee Thank you for giving it a try🙂

am getting an undefined method get_apps' for nil:NilClass`

Could you please share the stack trace (backtrace) of that error? Isn't that "undefined method get_app_clips for nil:NilClass"...? If so make sure you get the right value from Spaceship::ConnectAPI::App.find('com.foo.bar') first?

This is the complete stack trace:
bundler: failed to load command: fastlane (/Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bin/fastlane)
/Users/user/.rbenv/versions/2.6.4/lib/ruby/2.6.0/forwardable.rb:228:in `get_apps': [!] undefined method `get_apps' for nil:NilClass (NoMethodError)
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/spaceship/lib/spaceship/connect_api/models/app.rb:74:in `all'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/spaceship/lib/spaceship/connect_api/models/app.rb:80:in `find'
	from Fastfile:438:in `block (2 levels) in parsing_binding'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/lane.rb:33:in `call'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/runner.rb:49:in `block in execute'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/runner.rb:45:in `chdir'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/runner.rb:45:in `execute'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/lane_manager.rb:47:in `cruise_lane'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/command_line_handler.rb:36:in `handle'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/commands_generator.rb:109:in `block (2 levels) in run'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/commander-4.6.0/lib/commander/command.rb:187:in `call'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/commander-4.6.0/lib/commander/command.rb:157:in `run'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/commander-4.6.0/lib/commander/runner.rb:444:in `run_active_command'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:76:in `run!'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/commander-4.6.0/lib/commander/delegates.rb:18:in `run!'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/commands_generator.rb:353:in `run'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/commands_generator.rb:42:in `start'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/cli_tools_distributor.rb:122:in `take_off'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/bin/fastlane:23:in `<top (required)>'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bin/fastlane:23:in `load'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bin/fastlane:23:in `<top (required)>'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/cli/exec.rb:63:in `load'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/cli/exec.rb:63:in `kernel_load'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/cli/exec.rb:28:in `run'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/cli.rb:474:in `exec'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/cli.rb:30:in `dispatch'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/cli.rb:24:in `start'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/exe/bundle:49:in `block in <top (required)>'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/friendly_errors.rb:130:in `with_friendly_errors'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/exe/bundle:37:in `<top (required)>'
	from /Users/user/.rbenv/versions/2.6.4/bin/bundle:23:in `load'
	from /Users/user/.rbenv/versions/2.6.4/bin/bundle:23:in `<main>'
/Users/user/.rbenv/versions/2.6.4/lib/ruby/2.6.0/forwardable.rb:228:in `get_apps': undefined method `get_apps' for nil:NilClass (NoMethodError)
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/spaceship/lib/spaceship/connect_api/models/app.rb:74:in `all'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/spaceship/lib/spaceship/connect_api/models/app.rb:80:in `find'
	from Fastfile:438:in `block (2 levels) in parsing_binding'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/lane.rb:33:in `call'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/runner.rb:49:in `block in execute'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/runner.rb:45:in `chdir'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/runner.rb:45:in `execute'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/lane_manager.rb:47:in `cruise_lane'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/command_line_handler.rb:36:in `handle'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/commands_generator.rb:109:in `block (2 levels) in run'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/commander-4.6.0/lib/commander/command.rb:187:in `call'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/commander-4.6.0/lib/commander/command.rb:157:in `run'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/commander-4.6.0/lib/commander/runner.rb:444:in `run_active_command'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:76:in `run!'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/commander-4.6.0/lib/commander/delegates.rb:18:in `run!'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/commands_generator.rb:353:in `run'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/commands_generator.rb:42:in `start'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/fastlane/lib/fastlane/cli_tools_distributor.rb:122:in `take_off'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bundler/gems/fastlane-2d43d0ccefcf/bin/fastlane:23:in `<top (required)>'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bin/fastlane:23:in `load'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/bin/fastlane:23:in `<top (required)>'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/cli/exec.rb:63:in `load'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/cli/exec.rb:63:in `kernel_load'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/cli/exec.rb:28:in `run'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/cli.rb:474:in `exec'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/cli.rb:30:in `dispatch'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/cli.rb:24:in `start'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/exe/bundle:49:in `block in <top (required)>'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/lib/bundler/friendly_errors.rb:130:in `with_friendly_errors'
	from /Users/user/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/bundler-2.2.19/exe/bundle:37:in `<top (required)>'
	from /Users/user/.rbenv/versions/2.6.4/bin/bundle:23:in `load'
	from /Users/user/.rbenv/versions/2.6.4/bin/bundle:23:in `<main>'
</details>

I tried prepending the lane with Spaceship::ConnectAPI.login, but unfortunately run into different issues there, which I will debug separately.

Do you see any other problems in my lane script? Or how did you test the retrieval of the app clips information?

@ainame
Copy link
Contributor Author

ainame commented Jul 10, 2021

@EmDee
It might be that you forgot to call require 'spaceship' or something necessary...?

@EmDee
Copy link
Contributor

EmDee commented Jul 10, 2021

@EmDee
It might be that you forgot to call require 'spaceship' or something necessary...?

Just to clarify, the adjustAppClip is within my Fastfile, which I can via bundle exec fastlane adjustAppClip. I've tried adding require 'spaceship' and fastlane_require 'spaceship', with no success.

I feel like I'm doing something fundamentally wrong here 🙈

@ainame
Copy link
Contributor Author

ainame commented Jul 10, 2021

Hmm🤔 This page is a bit old but you can test the pieces of code I shared on the playground opened by "bundle exec fastlane spaceship". You may want to give it a try?

https://github.com/fastlane/fastlane/blob/master/spaceship/README.md#playground

Either way your issue feels like it's not related to my change though.

@EmDee
Copy link
Contributor

EmDee commented Jul 10, 2021

Hmm🤔 This page is a bit old but you can test the pieces of code I shared on the playground opened by "bundle exec fastlane spaceship". You may want to give it a try?

https://github.com/fastlane/fastlane/blob/master/spaceship/README.md#playground

Either way your issue feels like it's not related to my change though.

Awesome! I only had a quick chance to play around with the playground, but was already able to retrieve the App Clips.

I'm currently ob the road, but will try out later today again. But already looks promising :)

@EmDee
Copy link
Contributor

EmDee commented Jul 10, 2021

@ainame I was able to test this further. With the spaceship playground I was able to run all of your commands.

The response seems a bit strange though. When I call get_app_clip_version_localizations I get back results that I don't see anywhere in App Store Connect (ASC), neither in the "Advanced App Clip Experiences" nor in the overview before that.

For example this is what the API is returning:

=> [#<Spaceship::ConnectAPI::AppClipVersionLocalization:0x00007fedad5e5ce8
  @app_clip_header_image=
   #<Spaceship::ConnectAPI::AppClipHeaderImage:0x00007fedad5e5a40
    @asset_delivery_state={"errors"=>[], "warnings"=>nil, "state"=>"COMPLETE"},
    @asset_token=
     "PurpleSource114/v4/4a/b0/35/4ab03560-fa51-6106-84f0-5b60478f70b6/0b78134f-7a54-42b3-a879-34fa7bc55fb4_app_clip_card_preview_light.png",
    @asset_type="AppClip_Header",
    @file_name="app_clip_card_preview_light.png",
    @file_size=1105883,
    @id="0b78134f-7a54-42b3-a879-34fa7bc55fb4",
    @image_asset=
     {"templateUrl"=>
       "https://is1-ssl.mzstatic.com/image/thumb/PurpleSource114/v4/4a/b0/35/4ab03560-fa51-6106-84f0-5b60478f70b6/0b78134f-7a54-42b3-a879-34fa7bc55fb4_app_clip_card_preview_light.png/{w}x{h}bb.{f}",
      "width"=>1800,
      "height"=>1200},
    @source_file_checksum="96a24eba5cf61af44f6858029381ca05",
    @upload_operations=nil>,
  @id="9263801c-64c8-4be2-89fd-35baa3ff5439",
  @locale="de-DE",
  @subtitle="Jetzt mobil bezahlen">,
 #<Spaceship::ConnectAPI::AppClipVersionLocalization:0x00007fedad5e5770
  @app_clip_header_image=
   #<Spaceship::ConnectAPI::AppClipHeaderImage:0x00007fedad5e5478
    @asset_delivery_state={"errors"=>[], "warnings"=>nil, "state"=>"COMPLETE"},
    @asset_token=
     "PurpleSource124/v4/89/03/fd/8903fde3-5894-7f2e-e1a0-311a4807bc34/b96247a0-ca5c-48ca-a7f8-d98845439f45_app_clip_card_preview_light.png",
    @asset_type="AppClip_Header",
    @file_name="app_clip_card_preview_light.png",
    @file_size=1105883,
    @id="b96247a0-ca5c-48ca-a7f8-d98845439f45",
    @image_asset=
     {"templateUrl"=>
       "https://is5-ssl.mzstatic.com/image/thumb/PurpleSource124/v4/89/03/fd/8903fde3-5894-7f2e-e1a0-311a4807bc34/b96247a0-ca5c-48ca-a7f8-d98845439f45_app_clip_card_preview_light.png/{w}x{h}bb.{f}",
      "width"=>1800,
      "height"=>1200},
    @source_file_checksum="96a24eba5cf61af44f6858029381ca05",
    @upload_operations=nil>,
  @id="dc795b44-7544-4900-8fe1-4b496ae7d548",
  @locale="en-US",
  @subtitle="Mobile payment now">]

But ASC is showing the following:

Version information Advanced App Clip Experiences
image image

Note the German subtitle for example. The API is returning "@subtitle="Jetzt mobil bezahlen">,", whereas ASC shows "Jetzt hier mobil bezahlen". So I don't even know where the API is getting that information from? But it sounds like an old version of an advanced app clip that we once had (maybe).

Other than that, I'm running into the same problem as you. In case an advanced experience is set, updating some (or all) property won't work.

@ainame
Copy link
Contributor Author

ainame commented Jul 11, 2021

@EmDee Thank you for your additional report! Much appreciated.
Glad to see it's working on your end 😄

Note the German subtitle for example. The API is returning "@subtitle="Jetzt mobil bezahlen">,", whereas ASC shows "Jetzt hier mobil bezahlen". So I don't even know where the API is getting that information from? But it sounds like an old version of an advanced app clip that we once had (maybe).

My guess is that AppClipVersionLocalization represents only what ASC has on the version information page and ASC may have a different model for the advanced experience and that is prioritised over the basic AppClipVersionLocalization🤔 Honestly I don't know what's there as I haven't been able to replicate an app that has "associated domains" to be able to edit "Advanced Experience" yet😂 It's my homework but will see 🤞

@EmDee
Copy link
Contributor

EmDee commented Jul 11, 2021

My guess is that AppClipVersionLocalization represents only what ASC has on the version information page and ASC may have a different model for the advanced experience and that is prioritised over the basic AppClipVersionLocalization🤔 Honestly I don't know what's there as I haven't been able to replicate an app that has "associated domains" to be able to edit "Advanced Experience" yet😂 It's my homework but will see 🤞

Just in case you're missing a domain to host the AASA file, I will gladly host it for you!

@ainame
Copy link
Contributor Author

ainame commented Jul 11, 2021

Just in case you're missing a domain to host the AASA file, I will gladly host it for you!

Oh, thanks. But I did host it by myself but didn't work. I feel like I need to go through all of the related WWDC sessions😄
https://ainame.tokyo/.well-known/apple-app-site-association

@EmDee
Copy link
Contributor

EmDee commented Jul 12, 2021

Just in case you're missing a domain to host the AASA file, I will gladly host it for you!

Oh, thanks. But I did host it by myself but didn't work. I feel like I need to go through all of the related WWDC sessions😄
https://ainame.tokyo/.well-known/apple-app-site-association

@ainame Assuming your ID is correct, I think the problem lies in your AASA's content-type. It should be application/json, but yours is serving the file as text/plain right now.

In case you didn't know, Apple has a tool to verify your AASA: https://search.developer.apple.com/appsearch-validation-tool/

image

@ainame
Copy link
Contributor Author

ainame commented Jul 17, 2021

@EmDee Thanks. I fixed Content-Type header but it's still invalid. It looks like my AASA file won't be valid unless my test app is published in App Store. That won't happen after all as I used Apple's Fruta demo app for testing😂 Unfortunately, I don't have any public app personally right now 😞

@google-cla
Copy link

google-cla bot commented Aug 1, 2021

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@ainame
Copy link
Contributor Author

ainame commented Oct 27, 2021

Just rebased my branch🙂

At my first look, I think I need to change the plan in this PR to support the latest and public App Store Connect APIs. This PR's change did depend on the internal APIs but the API design has been completely changed on the published APIs. Those endpoints are now diverged to support both "default experience" and "advanced experience". So some additions in this PR don't make sense any more. AppClipVersion and AppClipVersionLocalizations also don't exist.

Since the specs are revealed now, my plan is to add supports for new endpoints little by little over a couple of PRs so that each PR review will be easy. I'll leave only things survived and remove rest in this PR to get merged!

We'll get complete APIs support at some point and then might integrate spaceship-level App Clips support with deliver or something like a new action hopefully 🤞

@ainame ainame changed the title [spaceship] add App Clips support [WIP][spaceship] add initial App Clips support Oct 27, 2021
@ainame ainame marked this pull request as draft October 27, 2021 00:15
@EmDee
Copy link
Contributor

EmDee commented Oct 27, 2021

@ainame You can hit me up, if you need someone to test your implementation ☺️

@ainame
Copy link
Contributor Author

ainame commented Oct 28, 2021

AppClipHeaderImage is also changed to take AppClipDefaultExperienceLocalization in its relationship. It's available only for Default Experience now. Advanced Experience has got another endpoint to do almost same thing.

https://developer.apple.com/documentation/appstoreconnectapi/app_clips_and_app_clip_experiences/advanced_app_clip_experiences/advanced_app_clip_experience_images

I'm going to revise appClipHeaderImage and try to support some basics for the default experience in this PR.

@Banck
Copy link

Banck commented Feb 15, 2022

@ainame Hello. Any news here..?(

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

7 participants