Skip to content

Commit

Permalink
[fastlane_core][pilot][deliver] fix when polling for build processing…
Browse files Browse the repository at this point in the history
… to poll for X.Y and X.Y.0 (#18547)

* [fastlane_core][pilot][deliver] fix when polling for build processing to poll for X.Y and X.Y.0

* Let's try shellcheck orb

* This is bad but lets try

* This is bad but lets try

* Added more tests
  • Loading branch information
Josh Holtz committed Apr 14, 2021
1 parent 970f795 commit 8aed3be
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 22 deletions.
5 changes: 3 additions & 2 deletions .circleci/config.yml
@@ -1,6 +1,8 @@
---

version: 2.1
orbs:
shellcheck: circleci/shellcheck@2.2.2 # brew install shellcheck stopped working so using this

aliases:
# common - cache
Expand Down Expand Up @@ -94,7 +96,6 @@ jobs:
name: Setup Build
command: |
mkdir -p ~/test-reports
brew install shellcheck
- *bundle_install
- *cache_save_bundler
- run:
Expand Down Expand Up @@ -178,7 +179,7 @@ jobs:
name: Setup Build
command: |
mkdir -p ~/test-reports
brew install shellcheck
brew update # Needed because this lane uses "brew bundle" and CircleCI's brew install is too old for that
- *bundle_install
- *cache_save_bundler
- run: bundle exec fastlane generate_swift_api
Expand Down
59 changes: 50 additions & 9 deletions fastlane_core/lib/fastlane_core/build_watcher.rb
Expand Up @@ -4,6 +4,8 @@

module FastlaneCore
class BuildWatcher
VersionMatches = Struct.new(:version, :builds)

class << self
# @return The build we waited for. This method will always return a build
def wait_for_build_processing_to_be_complete(app_id: nil, platform: nil, train_version: nil, app_version: nil, build_version: nil, poll_interval: 10, strict_build_watch: false, return_when_build_appears: false, return_spaceship_testflight_build: true, select_latest: false)
Expand All @@ -23,7 +25,7 @@ def wait_for_build_processing_to_be_complete(app_id: nil, platform: nil, train_v

showed_info = false
loop do
matched_build = matching_build(watched_app_version: app_version, watched_build_version: build_version, app_id: app_id, platform: platform, select_latest: select_latest)
matched_build, app_version_queried = matching_build(watched_app_version: app_version, watched_build_version: build_version, app_id: app_id, platform: platform, select_latest: select_latest)

if matched_build.nil? && !showed_info
UI.important("Read more information on why this build isn't showing up yet - https://github.com/fastlane/fastlane/issues/14997")
Expand All @@ -37,6 +39,13 @@ def wait_for_build_processing_to_be_complete(app_id: nil, platform: nil, train_v
# having a build resource appear in AppStoreConnect (matched_build) may be enough (i.e. setting a changelog)
# so here we may choose to skip the full processing of the build if return_when_build_appears is true
if matched_build && (return_when_build_appears || matched_build.processed?)

if !app_version.nil? && app_version != app_version_queried
UI.important("App version is #{app_version} but build was found while querying #{app_version_queried}")
UI.important("This shouldn't be an issue as Apple sees #{app_version} and #{app_version_queried} as equal")
UI.important("See docs for more info - https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102364")
end

if return_spaceship_testflight_build
return matched_build.to_testflight_build
else
Expand All @@ -60,15 +69,31 @@ def matching_build(watched_app_version: nil, watched_build_version: nil, app_id:
watched_app_version = remove_version_leading_zeros(version: watched_app_version)
watched_build_version = remove_version_leading_zeros(version: watched_build_version)

matched_builds = Spaceship::ConnectAPI::Build.all(
app_id: app_id,
version: watched_app_version,
build_number: watched_build_version,
platform: platform
)
# App Store Connect will allow users to upload X.Y is the same as X.Y.0 and treat them as the same version
# However, only the first uploaded version format will be the one that is queryable
# This could lead to BuildWatcher never finding X.Y.0 if X.Y was upoaded first as X.Y will only yield results
#
# This will add an additional request to search for both X.Y and X.Y.0 but
# will give preference to the version format specified passed in
watched_app_version_alternate = alternate_version(watched_app_version)
versions = [watched_app_version, watched_app_version_alternate].compact

version_matches = versions.map do |version|
match = VersionMatches.new
match.version = version
match.builds = Spaceship::ConnectAPI::Build.all(
app_id: app_id,
version: version,
build_number: watched_build_version,
platform: platform
)

match
end.flatten

# Raise error if more than 1 build is returned
# This should never happen but need to inform the user if it does
matched_builds = version_matches.map(&:builds).flatten
if matched_builds.size > 1 && !select_latest
error_builds = matched_builds.map do |build|
"#{build.app_version}(#{build.version}) for #{build.platform} - #{build.processing_state}"
Expand All @@ -77,9 +102,25 @@ def matching_build(watched_app_version: nil, watched_build_version: nil, app_id:
UI.crash!(error_message)
end

matched_build = matched_builds.first
version_match = version_matches.reject do |match|
match.builds.empty?
end.first
matched_build = version_match&.builds&.first

return matched_build, version_match&.version
end

def alternate_version(version)
return nil if version.nil?

version_info = Gem::Version.new(version)
if version_info.segments.size == 3 && version_info.segments[2] == 0
return version_info.segments[0..1].join(".")
elsif version_info.segments.size == 2
return "#{version}.0"
end

return matched_build
return nil
end

def report_status(build: nil)
Expand Down

0 comments on commit 8aed3be

Please sign in to comment.