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
[deliver] fetch live app info if no edit info is present, fixing scenario of having both macOS and iOS apps present #21472
Conversation
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Hi @loremattei 👋 could you merge Thank you! |
Thanks @rogerluan! I rebased and now CI checks are all green :-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @loremattei 😊 Thanks for fixing this!
Could you add comments to the code explaining why we fallback to the live version, and why it is ok to use the live version? This edge case of having both iOS + macOS apps is not straightforward to understand when reading the code 😅
Also, could you test the case where all apps (macOS + iOS) are in non-edit mode? What message is it shown to the user? 🤔 If no useful error message is displayed, are we able to handle this scenario in our code and display a more user-friendly message?
Hi @rogerluan! I think there are different cases where all apps (macOS + iOS) are in non-edit mode and the failure likely depends on the requested flow (i.e. on the options). As long as the fetch step passes, the failure depends on whether the requested action is allowed. I've tested the case where no apps is in edit mode and the user tries to upload new metadata without passing any specific version as it looked the one which could be troublesome and it returns |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding those comments! 🙌
However, I don't think this message:
The provided entity includes an attribute with a value that has already been used - The version number has been previously used.
is intuitive enough 😬 working with fastlane for a few years and knowing the specific jargon Apple's APIs use, I kinda understand why it's failing, but not what I need to do to fix it, or what's wrong, if it's an issue on my side or not, etc... now if this was presented to a user with less experience, they'd probably be lost 😢
Any chances we can catch this error and provide a custom-generated message to the user? Either before the request is actually made (validate before sending), or after (handling the error)?
If we can find a hook to do that, then a good message candidate would be e.g.:
Unable to upload metadata: It seems that the app you're attempting to upload metadata for isn't currently in an editable state across any platform. Please ensure that the app you're working with falls into one of these states: Prepare for Submission, Developer Rejected, Rejected, Metadata Rejected, Waiting for Review, or Invalid Binary.
This would be a helpful and user-friendly message, which is what I'd expect as a user 😃
The challenge isn't the message though, it's finding the right hook to add this to 🙈
# When there are iOS and macOS implementations of the same app, | ||
# fetch_edit_app_info will fail when trying to fetch data for one platform | ||
# if the other is in not editable state. | ||
# We still keep fetch_edit_app_info as first option to make sure | ||
# latest data is fetched when apps are in an editable state. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think?
# When there are iOS and macOS implementations of the same app, | |
# fetch_edit_app_info will fail when trying to fetch data for one platform | |
# if the other is in not editable state. | |
# We still keep fetch_edit_app_info as first option to make sure | |
# latest data is fetched when apps are in an editable state. | |
# When there are iOS and macOS implementations of the same app, | |
# fetch_edit_app_info will fail when trying to fetch data for one platform | |
# if the other isn't in an editable state, so we use the live app info. | |
# We still keep fetch_edit_app_info as first option to make sure | |
# latest data is fetched when apps are in an editable state. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for the comment you left below
Thanks @rogerluan!
I see what you mean and I agree with your proposal. My point was mostly that we are not introducing any big regression here as the current error message ("Cannot update languages - could not find an editable info") is not drastically more intuitive when users don't have any app in an editable state. Anyway, I'm happy to try and improve this solution. I took a deeper look at the API and I think I've found a suitable approach, but I'll need some more time to figure it our properly. I'll be back asap. |
Fully agree 💯 😅 the point isn't which custom message we show though, but the fact that we show a custom one, instead of the API's response. If we replace I hope your approach works 🙌 looking forward to reviewing it! |
@rogerluan I updated this branch with a first draft. I haven't fully tested it yet, but I wanted to validate the idea with you before committing more time to it. While investigating better the API and the current Fastlane implementation, I found that Version info handling per platform is already working correctly and the problem is with App Info. App Info can't be actually edited when one platform is under review, so I think the correct behaviour in that scenario is that the upload fails if the user tries to update App Info, but succeeds otherwise. The current implementation of I think that the right solution here is to only execute The rest of Wdyt? Does this solution look correct to you and worth more investigation and testing? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love these findings @loremattei !! I think you're definitely on the right track now, but there are some open questions that need more digging so we can cover scenarios where users aren't explicitly passing those arguments 😬
Good stuff so far! 🙌
@@ -462,14 +451,18 @@ def retry_if_nil(message, tries: 5, wait_time: 10) | |||
end | |||
end | |||
|
|||
# Checking if the metadata to update includes App Info | |||
def is_updating_app_info(options) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function could look more Ruby-y 😊 simply:
def updating_app_info?(options)
LOCALISED_APP_VALUES.keys.any? { |key| options[key] }
end
updating_app_info?
is the Ruby naming convention for functions that return boolean values (instead of e.g. is…(…)
) 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Clearly, I'm not a ruby-ist :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just know a thing or two! Always happy to share knowledge and help others ❤️
@rogerluan this should be ready for another look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job you did here so far! 🙌 Your algo looks solid to me!
Just left some questions and minor suggestions :) but I think we could use some more rspecs 👀
Co-authored-by: Roger Oba <rogerluan.oba@gmail.com>
Co-authored-by: Roger Oba <rogerluan.oba@gmail.com>
Co-authored-by: Roger Oba <rogerluan.oba@gmail.com>
deliver/spec/upload_metadata_spec.rb
Outdated
|
||
expect(version).to receive(:update).with(attributes: {}) | ||
|
||
# Get app info localization English (Used to compare with data to upload) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the new code work as expected if I change the info in just 1 language and that language happens to not be English or the primary language?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# Get app info localization English (Used to compare with data to upload) | |
# Get app info localization in English (used to compare with data to upload) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it does. I used English in tests as it's the language used in the other tests, but the new code goes through all languages and doesn't rely on default or English in particular for anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Latest changes look good @loremattei ! just left a some feedbacks and a question 😊 once those are addressed I think this will be clear from my side! Good hustle! 💪
This PR could use a second pair of 👀 as it touches a critical code path 🙇 @AliSoftware @getaaron |
Co-authored-by: Roger Oba <rogerluan.oba@gmail.com>
Thank you for all your support with this @rogerluan! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey Lorenzo! Small world 😄 Fancy seeing you here!
The changes in your PR make sense to me, all looking good, thanks for the contribution! 👍
I just left some nitpicky suggestions about wording, but nothing blocking 🙂
UI.important("Can't find edit or live App info. Skipping upload.") | ||
return false | ||
end | ||
localizations = app_info.get_app_info_localizations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Unrelated to this PR]
@rogerluan we definitively need to improve our YARD doc on many of our model methods. This isn't clear at all from the definition of the AppInfo#get_app_info_localizations
what that method is supposed to return, which makes it harder to read code that uses it like here and why Lore needed to use localizations.find
below.
(After some digging, the answer is that it returns Array<Spaceship::ConnectAPI::AppInfo>
; which makes sense in retrospect I guess, but was't obvious to me at first sight, and RubyMine isn't able to deduce it automatically)
deliver/spec/upload_metadata_spec.rb
Outdated
expect(app_info).to receive(:get_app_info_localizations).and_return([app_info_localization_en]) | ||
|
||
# Get app info localization English (Used to compare with data to upload) | ||
expect(app_info_localization_en).to receive(:name).and_return("") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💭 rubocop
might complain if you use double-quotes while you don't need any interpolation
expect(app_info_localization_en).to receive(:name).and_return("") | |
expect(app_info_localization_en).to receive(:name).and_return('') |
💡 Also, might make it clearer and easier to understand the logic of the spec to provide a dummy name instead? Or was it intentional and important to the test that this was blank?
expect(app_info_localization_en).to receive(:name).and_return("") | |
expect(app_info_localization_en).to receive(:name).and_return('Old App Name') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💭 rubocop might complain if you use double-quotes while you don't need any interpolation
The rubocop rules we have in fastlane explicitly allows both "
and '
to be used whenever 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL!
end | ||
|
||
# Finding languages to enable | ||
def verify_available_info_languages!(options, app, app_info, languages) | ||
unless app_info | ||
UI.user_error!("Cannot update languages - could not find an editable info") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit outside of the scope of this PR, but while we're updating the code around that logic, I feel we could use message that could be a tad more helpful. Wdyt?
UI.user_error!("Cannot update languages - could not find an editable info") | |
UI.user_error!("Cannot update languages - could not find an editable version. Verify that your app is in one of the editable states in App Store Connect") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point!
I wonder if "version" would be confusing, as in this case the user may have an editable version (on one platform), but not editable App info (e.g. because the other platform is under review).
I used your wording, but switched 'version' to 'App info'.
Let me know if it doesn't look good to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd use either quoted an capitalized 'App Info'
or simple nouns (thus all lowercase) app info
@loremattei 😊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've pushed a commit to change to 'App Info'
so we can move forward with this PR, I hope you don't mind 😊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last thing! What do you guys think about the message I suggested earlier? User-friendlier and more specific?
What I suggested earlier:
Unable to upload metadata: It seems that the app you're attempting to upload metadata for isn't currently in an editable state across any platform. Please ensure that the app you're working with falls into one of these states: Prepare for Submission, Developer Rejected, Rejected, Metadata Rejected, Waiting for Review, or Invalid Binary.
What I think we could use now, after the latest changes to the logic:
Unable to upload metadata: It seems that the app you're attempting to upload metadata for isn't currently in an editable state. Please ensure that the app you're working with falls into one of these states: Prepare for Submission, Developer Rejected, Rejected, Metadata Rejected, Waiting for Review, or Invalid Binary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WFM 👍
Co-authored-by: Olivier Halligon <olivier@halligon.net>
Co-authored-by: Olivier Halligon <olivier@halligon.net>
Hey @AliSoftware ! |
@rogerluan I think I've done everything requested here. Please, let me know if there's anything I need to do to move this forward :-) |
deliver/spec/upload_metadata_spec.rb
Outdated
expect(app_info).to receive(:get_app_info_localizations).and_return([app_info_localization_en]) | ||
|
||
# Get app info localization English (Used to compare with data to upload) | ||
expect(app_info_localization_en).to receive(:name).and_return("") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💭 rubocop might complain if you use double-quotes while you don't need any interpolation
The rubocop rules we have in fastlane explicitly allows both "
and '
to be used whenever 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💪 LGTM!
Hey @rogerluan 👋 Is there anything I can do to move this forward? |
Thanks for the ping! Gonna merge this in, but it will only be released whenever we have the next release cut off 🙇 |
Thanks @rogerluan! Sounds great! Looking forward for it :-) |
…ing scenario of having both macOS and iOS apps present (fastlane#21472)" This reverts commit c4ed1a4.
end | ||
end | ||
|
||
UI.message('No changes to localized App Info detected. Skipping upload.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that skipping upload here is causing a regression with editing the privacy url #21654
Is there a way we can force upload so that we can edit the privacy url even though none of the other localized app info will change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checklist
bundle exec rspec
from the root directory to see all new and existing tests passbundle exec rubocop -a
to ensure the code style is validci/circleci
builds in the "All checks have passed" section of my PR (connect CircleCI to GitHub if not)Motivation and Context
When an app has an iOS and a macOS implementation, Deliver fails to upload one of the apps if the other one is under review:
Resolves #17321
Resolves #21003
Description
This PR updates
update_metadata
so that it fetcheslive_app_info
if it can't findedit_app_info
.live_app_info
as a backup solution will allow the upload flow to continue. The flow will succeed if the user uploads only platform specific metadata, or fail later if they try to upload something that can't be modified in this state.Testing Steps
To test this specific scenario:
and verify that it works.
Minimum regression testing: