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

[deliver] Implements verify with altool for Xcode 14 validation #20738

Merged
merged 14 commits into from Mar 28, 2023

Conversation

polpielladev
Copy link
Contributor

@polpielladev polpielladev commented Oct 11, 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

As part of our CI, we use deliver's --verify_only flag (implemented by myself a few months back) to validate that our binary is fit to be uploaded to the App Store every night.

Description

Since the removal of the Transporter app from the Xcode 14.0 toolchain, this has stopped working for us. I have seen that some changes have already been implemented by @freddi-kit and released to migrate some of deliver and pilot's functionalities to using altool.

This PR builds on top of those changes and adds missing functionality to make the --verify_only flag work with altool by using its --validate-app option.

Testing Steps

  1. Archive an app and export an IPA with an invalid (for upload) version of Xcode. An example of this would be Xcode 14.1 beta 2.
  2. Run deliver with the verify_only flag: bundle exec fastlane deliver --ipa your_awesome_app.ipa --verify_only --verbose
  3. Validation should fail with the following error

CleanShot 2022-10-11 at 22 54 39@2x

@joshdholtz @freddi-kit Feel free to give me a shout if you need extra context or if there is something you'd like me to change 👍

@polpielladev
Copy link
Contributor Author

Hey @giginet 👋

Did you get a chance to look over this PR? I can see that you assigned yourself to it and was wondering if you had any updates. This flag is something we use at work on a nightly workflow and has quite a lot of value for us, so I'm happy to pick up any improvements/fixes that need to be done to get the flag working again with altool.

@polpielladev polpielladev changed the title Implements verify with altool for Xcode 14 validation [deliver] Implements verify with altool for Xcode 14 validation Nov 30, 2022
@iwc
Copy link

iwc commented Jan 10, 2023

Yes, this breaks a workflow for my team as well. This would be great to have.

@polpielladev
Copy link
Contributor Author

@giginet Did you get a chance to take a look at this PR? Happy to go through any changes that need making or give some more context on what the changes are doing 👍

Copy link
Collaborator

@giginet giginet left a comment

Choose a reason for hiding this comment

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

@pol-piella

Hi! I apologize to keep waiting for you for such a long time.

I noticed altool_compatible_command might be removed in this implementation.
What do you think?
https://github.com/fastlane/fastlane/pull/20738/files#r1070544411

If you can fix this, could you try fixing it?

@@ -47,7 +47,7 @@ def build_upload_command(username, password, source = "/tmp", provider_short_nam
not_implemented(__method__)
end

def build_verify_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil)
def build_verify_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil)
Copy link
Collaborator

Choose a reason for hiding this comment

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

[nits] I think it's better to use **kwargs in the method signatures of the abstract method.

jwt is only needed for ITMSTransporter, and platform and api_key are only needed for altool.
So it's not better to have all parameters on the super method for code readability.

But this point is not important.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a very good point, I have just modified the abstract method to use **kwargs 👍

use_api_key = !@api_key.nil?
api_key_placeholder = use_api_key ? { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_dir: "YourTmpP8KeyDir" } : nil

api_key = nil
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's unnecessary

Suggested change
api_key = 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.

Removed 👍

@@ -266,7 +266,7 @@ def submit_for_review
# If itc_provider was explicitly specified, use it.
# If there are multiple teams, infer the provider from the selected team name.
# If there are fewer than two teams, don't infer the provider.
def transporter_for_selected_team(upload: false)
def transporter_for_selected_team(altool_compatible_command: false)
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's the situation altool_compatible_command to be false?

I think this flag is not necessary for ItunesTransporter.

In the previous implementation, verify task doesn't use altool, so some flags are needed to decide which executors are used.
However, in the current implementation, the transporter always uses altool when meeting the situations.
So I think this is not needed. What do you think?

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 think it will still be needed as not all commands have altool implementations. The reason why the upload property existed was so that even if the conditions were met only upload would use itmstransporter, as it was implemented.

As we go ahead and add more commands, we'll need to mark them as altool_compatible so that we can slowly move them across. I might be missing something but I think it's the only way we can do it at the moment without breaking anything. Let me know what you think 👍

Copy link
Collaborator

Choose a reason for hiding this comment

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

I meant all callers of this method seem to pass true for altool_compatible_command

https://github.com/fastlane/fastlane/pull/20738/files#diff-51e845b40462cd52020ab428469c85f65e24e1343e0b17c88d0c1a11e1ec22ecR172
https://github.com/fastlane/fastlane/pull/20738/files#diff-51e845b40462cd52020ab428469c85f65e24e1343e0b17c88d0c1a11e1ec22ecR209

So we can get rid of this argument. We can always pass true on L284 to reduce unnecessary states.

@giginet giginet self-assigned this Jan 15, 2023
@polpielladev
Copy link
Contributor Author

Thanks so much for reviewing @giginet, I will address the comments this evening 👍

@polpielladev
Copy link
Contributor Author

polpielladev commented Jan 17, 2023

@giginet Also, I have another very small PR to add support for a xcodebuild flag that would help us get some metrics at work, would you mind reviewing it if you get a chance?

#20896

Not sure what the process is to get someone to look at a PR, is there maybe a slack channel I can send a message on?

@polpielladev
Copy link
Contributor Author

@giginet I think I have addressed all comments now, sorry it took a long time to do so, been a busy few weeks 😅

Let me know what you think about them and if you have any further comments/suggestions, happy to push further updates 👍

@giginet
Copy link
Collaborator

giginet commented Mar 24, 2023

Thank you for your effort. I'll review it this weekend. 👍

@giginet giginet self-requested a review March 26, 2023 06:31
Copy link
Collaborator

@giginet giginet left a comment

Choose a reason for hiding this comment

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

It looks mostly good 👍
I appreciate your contribution and improving code quality.

As I commented, I believe in removing the argument of transporter_for_selected_team.

If you can fix the comments, I'll merge this soon.

diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb
index a2b433efe..2494af5a3 100644
--- a/deliver/lib/deliver/runner.rb
+++ b/deliver/lib/deliver/runner.rb
@@ -169,7 +169,7 @@ module Deliver
       pkg_path = options[:pkg]
 
       platform = options[:platform]
-      transporter = transporter_for_selected_team(altool_compatible_command: true)
+      transporter = transporter_for_selected_team
 
       case platform
       when "ios", "appletvos"
@@ -206,7 +206,7 @@ module Deliver
       pkg_path = options[:pkg]
 
       platform = options[:platform]
-      transporter = transporter_for_selected_team(altool_compatible_command: true)
+      transporter = transporter_for_selected_team
 
       case platform
       when "ios", "appletvos"
@@ -266,7 +266,7 @@ module Deliver
     # If itc_provider was explicitly specified, use it.
     # If there are multiple teams, infer the provider from the selected team name.
     # If there are fewer than two teams, don't infer the provider.
-    def transporter_for_selected_team(altool_compatible_command: false)
+    def transporter_for_selected_team
       # Use JWT auth
       api_token = Spaceship::ConnectAPI.token
       api_key = if options[:api_key].nil? && !api_token.nil?
@@ -281,12 +281,12 @@ module Deliver
 
       unless api_token.nil?
         api_token.refresh! if api_token.expired?
-        return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, altool_compatible_command: altool_compatible_command, api_key: api_key)
+        return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, altool_compatible_command: true, api_key: api_key)
       end
 
       tunes_client = Spaceship::ConnectAPI.client.tunes_client
 
-      generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], altool_compatible_command: altool_compatible_command, api_key: api_key)
+      generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], altool_compatible_command: true, api_key: api_key)
       return generic_transporter unless options[:itc_provider].nil? && tunes_client.teams.count > 1
 
       begin
@@ -294,7 +294,7 @@ module Deliver
         name = team['name']
         provider_id = generic_transporter.provider_ids[name]
         UI.verbose("Inferred provider id #{provider_id} for team #{name}.")
-        return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id, altool_compatible_command: altool_compatible_command, api_key: api_key)
+        return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id, altool_compatible_command: true, api_key: api_key)
       rescue => ex
         UI.verbose("Couldn't infer a provider short name for team with id #{tunes_client.team_id} automatically: #{ex}. Proceeding without provider short name.")
         return generic_transporter

@@ -266,7 +266,7 @@ def submit_for_review
# If itc_provider was explicitly specified, use it.
# If there are multiple teams, infer the provider from the selected team name.
# If there are fewer than two teams, don't infer the provider.
def transporter_for_selected_team(upload: false)
def transporter_for_selected_team(altool_compatible_command: false)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I meant all callers of this method seem to pass true for altool_compatible_command

https://github.com/fastlane/fastlane/pull/20738/files#diff-51e845b40462cd52020ab428469c85f65e24e1343e0b17c88d0c1a11e1ec22ecR172
https://github.com/fastlane/fastlane/pull/20738/files#diff-51e845b40462cd52020ab428469c85f65e24e1343e0b17c88d0c1a11e1ec22ecR209

So we can get rid of this argument. We can always pass true on L284 to reduce unnecessary states.

@@ -281,20 +281,20 @@ def transporter_for_selected_team(upload: false)

unless api_token.nil?
api_token.refresh! if api_token.expired?
return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, upload: upload, api_key: api_key)
return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, altool_compatible_command: altool_compatible_command, api_key: api_key)
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can always pass altool_compatible_command: true because of the above comment.

UI.verbose(@transporter_executor.build_verify_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder))
# Handle AppStore Connect API
use_api_key = !@api_key.nil?
api_key_placeholder = use_api_key ? { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_dir: "YourTmpP8KeyDir" } : nil
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's better to be commented for code readability 👍

Suggested change
api_key_placeholder = use_api_key ? { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_dir: "YourTmpP8KeyDir" } : nil
# Masking credentials for verbose outputs
api_key_placeholder = use_api_key ? { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_dir: "YourTmpP8KeyDir" } : nil

@polpielladev
Copy link
Contributor Author

Hi @giginet 👋 Thank you so much for the help and the awesome feedback. I have addressed the comments you suggested now 👍

Comment on lines 828 to 830
tmp_asset_path = Dir.mktmpdir
FileUtils.cp(asset_path, tmp_asset_path)
tmp_asset_path
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm so sorry, my suggestion was completely wrong.

Filenames are not randomized. and tmp_asset_path indicates the parent directory path...

It have to revert to your implementation 🙏

Suggested change
tmp_asset_path = Dir.mktmpdir
FileUtils.cp(asset_path, tmp_asset_path)
tmp_asset_path
new_file_name = "#{SecureRandom.uuid}#{File.extname(asset_path)}"
tmp_asset_path = File.join(Dir.tmpdir, new_file_name)
FileUtils.cp(asset_path, tmp_asset_path)
tmp_asset_path

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 no problem! I have reverted the changes to the original implementation now 👍

Copy link
Collaborator

@giginet giginet left a comment

Choose a reason for hiding this comment

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

LGTM 🚀
I'm sorry to wait for you to start reviewing for a long time.
I'll merge this after checking.

Thanks a lot again! 😄

@polpielladev
Copy link
Contributor Author

LGTM 🚀 I'm sorry to wait for you to start reviewing for a long time. I'll merge this after checking.

Thanks a lot again! 😄

No problem at all honestly! Thanks so much for all your help on this, I really appreciate it 🎉

@giginet
Copy link
Collaborator

giginet commented Mar 28, 2023

I tried this command for the latest Xcode, it works!

deliver(
  verify_only: true
)

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

4 participants