fastlane_hotfix 2.165.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +1 -0
- data/LICENSE +21 -0
- data/README.md +208 -0
- data/bin/bin-proxy +19 -0
- data/bin/fastlane +23 -0
- data/cert/README.md +17 -0
- data/cert/lib/cert.rb +4 -0
- data/cert/lib/cert/commands_generator.rb +60 -0
- data/cert/lib/cert/module.rb +16 -0
- data/cert/lib/cert/options.rb +132 -0
- data/cert/lib/cert/runner.rb +239 -0
- data/credentials_manager/README.md +64 -0
- data/credentials_manager/lib/credentials_manager.rb +7 -0
- data/credentials_manager/lib/credentials_manager/account_manager.rb +157 -0
- data/credentials_manager/lib/credentials_manager/appfile_config.rb +196 -0
- data/credentials_manager/lib/credentials_manager/cli.rb +69 -0
- data/deliver/README.md +17 -0
- data/deliver/lib/assets/DeliverfileDefault +3 -0
- data/deliver/lib/assets/DeliverfileDefault.swift +13 -0
- data/deliver/lib/assets/ScreenshotsHelp +7 -0
- data/deliver/lib/assets/summary.html.erb +299 -0
- data/deliver/lib/deliver.rb +15 -0
- data/deliver/lib/deliver/app_screenshot.rb +354 -0
- data/deliver/lib/deliver/app_screenshot_iterator.rb +95 -0
- data/deliver/lib/deliver/commands_generator.rb +190 -0
- data/deliver/lib/deliver/detect_values.rb +102 -0
- data/deliver/lib/deliver/download_screenshots.rb +76 -0
- data/deliver/lib/deliver/generate_summary.rb +13 -0
- data/deliver/lib/deliver/html_generator.rb +78 -0
- data/deliver/lib/deliver/languages.rb +7 -0
- data/deliver/lib/deliver/loader.rb +55 -0
- data/deliver/lib/deliver/module.rb +18 -0
- data/deliver/lib/deliver/options.rb +465 -0
- data/deliver/lib/deliver/queue_worker.rb +49 -0
- data/deliver/lib/deliver/runner.rb +233 -0
- data/deliver/lib/deliver/setup.rb +199 -0
- data/deliver/lib/deliver/submit_for_review.rb +214 -0
- data/deliver/lib/deliver/upload_metadata.rb +688 -0
- data/deliver/lib/deliver/upload_price_tier.rb +40 -0
- data/deliver/lib/deliver/upload_screenshots.rb +333 -0
- data/fastlane/README.md +11 -0
- data/fastlane/lib/assets/ActionDetails.md.erb +106 -0
- data/fastlane/lib/assets/Actions.md.erb +43 -0
- data/fastlane/lib/assets/AppfileTemplate +6 -0
- data/fastlane/lib/assets/AppfileTemplate.swift +7 -0
- data/fastlane/lib/assets/AppfileTemplateAndroid +2 -0
- data/fastlane/lib/assets/DefaultFastfileTemplate +20 -0
- data/fastlane/lib/assets/DefaultFastfileTemplate.swift +13 -0
- data/fastlane/lib/assets/completions/completion.bash +23 -0
- data/fastlane/lib/assets/completions/completion.fish +39 -0
- data/fastlane/lib/assets/completions/completion.sh +12 -0
- data/fastlane/lib/assets/completions/completion.zsh +23 -0
- data/fastlane/lib/assets/custom_action_template.rb +82 -0
- data/fastlane/lib/assets/mailgun_html_template.erb +142 -0
- data/fastlane/lib/assets/report_template.xml.erb +15 -0
- data/fastlane/lib/assets/s3_html_template.erb +105 -0
- data/fastlane/lib/assets/s3_plist_template.erb +31 -0
- data/fastlane/lib/assets/s3_version_template.erb +4 -0
- data/fastlane/lib/fastlane.rb +53 -0
- data/fastlane/lib/fastlane/action.rb +198 -0
- data/fastlane/lib/fastlane/action_collector.rb +35 -0
- data/fastlane/lib/fastlane/actions/README.md +5 -0
- data/fastlane/lib/fastlane/actions/actions_helper.rb +185 -0
- data/fastlane/lib/fastlane/actions/adb.rb +78 -0
- data/fastlane/lib/fastlane/actions/adb_devices.rb +71 -0
- data/fastlane/lib/fastlane/actions/add_extra_platforms.rb +45 -0
- data/fastlane/lib/fastlane/actions/add_git_tag.rb +122 -0
- data/fastlane/lib/fastlane/actions/app_store_build_number.rb +249 -0
- data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +134 -0
- data/fastlane/lib/fastlane/actions/appaloosa.rb +266 -0
- data/fastlane/lib/fastlane/actions/appetize.rb +188 -0
- data/fastlane/lib/fastlane/actions/appetize_viewing_url_generator.rb +146 -0
- data/fastlane/lib/fastlane/actions/appium.rb +206 -0
- data/fastlane/lib/fastlane/actions/appledoc.rb +226 -0
- data/fastlane/lib/fastlane/actions/appstore.rb +14 -0
- data/fastlane/lib/fastlane/actions/apteligent.rb +105 -0
- data/fastlane/lib/fastlane/actions/artifactory.rb +157 -0
- data/fastlane/lib/fastlane/actions/automatic_code_signing.rb +226 -0
- data/fastlane/lib/fastlane/actions/backup_file.rb +41 -0
- data/fastlane/lib/fastlane/actions/backup_xcarchive.rb +135 -0
- data/fastlane/lib/fastlane/actions/badge.rb +155 -0
- data/fastlane/lib/fastlane/actions/build_and_upload_to_appetize.rb +107 -0
- data/fastlane/lib/fastlane/actions/build_android_app.rb +14 -0
- data/fastlane/lib/fastlane/actions/build_app.rb +165 -0
- data/fastlane/lib/fastlane/actions/build_ios_app.rb +47 -0
- data/fastlane/lib/fastlane/actions/build_mac_app.rb +46 -0
- data/fastlane/lib/fastlane/actions/bundle_install.rb +156 -0
- data/fastlane/lib/fastlane/actions/capture_android_screenshots.rb +63 -0
- data/fastlane/lib/fastlane/actions/capture_ios_screenshots.rb +61 -0
- data/fastlane/lib/fastlane/actions/capture_screenshots.rb +14 -0
- data/fastlane/lib/fastlane/actions/carthage.rb +230 -0
- data/fastlane/lib/fastlane/actions/cert.rb +14 -0
- data/fastlane/lib/fastlane/actions/changelog_from_git_commits.rb +197 -0
- data/fastlane/lib/fastlane/actions/chatwork.rb +94 -0
- data/fastlane/lib/fastlane/actions/check_app_store_metadata.rb +54 -0
- data/fastlane/lib/fastlane/actions/clean_build_artifacts.rb +72 -0
- data/fastlane/lib/fastlane/actions/clean_cocoapods_cache.rb +52 -0
- data/fastlane/lib/fastlane/actions/clear_derived_data.rb +70 -0
- data/fastlane/lib/fastlane/actions/clipboard.rb +52 -0
- data/fastlane/lib/fastlane/actions/cloc.rb +89 -0
- data/fastlane/lib/fastlane/actions/cocoapods.rb +170 -0
- data/fastlane/lib/fastlane/actions/commit_github_file.rb +186 -0
- data/fastlane/lib/fastlane/actions/commit_version_bump.rb +301 -0
- data/fastlane/lib/fastlane/actions/copy_artifacts.rb +114 -0
- data/fastlane/lib/fastlane/actions/crashlytics.rb +211 -0
- data/fastlane/lib/fastlane/actions/create_app_on_managed_play_store.rb +174 -0
- data/fastlane/lib/fastlane/actions/create_app_online.rb +75 -0
- data/fastlane/lib/fastlane/actions/create_keychain.rb +177 -0
- data/fastlane/lib/fastlane/actions/create_pull_request.rb +265 -0
- data/fastlane/lib/fastlane/actions/danger.rb +131 -0
- data/fastlane/lib/fastlane/actions/debug.rb +32 -0
- data/fastlane/lib/fastlane/actions/default_platform.rb +47 -0
- data/fastlane/lib/fastlane/actions/delete_keychain.rb +68 -0
- data/fastlane/lib/fastlane/actions/deliver.rb +14 -0
- data/fastlane/lib/fastlane/actions/deploygate.rb +210 -0
- data/fastlane/lib/fastlane/actions/device_grid/README.md +157 -0
- data/fastlane/lib/fastlane/actions/docs/build_app.md +245 -0
- data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +333 -0
- data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +371 -0
- data/fastlane/lib/fastlane/actions/docs/check_app_store_metadata.md +103 -0
- data/fastlane/lib/fastlane/actions/docs/create_app_online.md +282 -0
- data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +349 -0
- data/fastlane/lib/fastlane/actions/docs/get_certificates.md +86 -0
- data/fastlane/lib/fastlane/actions/docs/get_provisioning_profile.md +223 -0
- data/fastlane/lib/fastlane/actions/docs/get_push_certificate.md +134 -0
- data/fastlane/lib/fastlane/actions/docs/run_tests.md +151 -0
- data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +573 -0
- data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +725 -0
- data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +203 -0
- data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +250 -0
- data/fastlane/lib/fastlane/actions/dotgpg_environment.rb +57 -0
- data/fastlane/lib/fastlane/actions/download.rb +76 -0
- data/fastlane/lib/fastlane/actions/download_dsyms.rb +369 -0
- data/fastlane/lib/fastlane/actions/download_from_play_store.rb +61 -0
- data/fastlane/lib/fastlane/actions/dsym_zip.rb +93 -0
- data/fastlane/lib/fastlane/actions/echo.rb +14 -0
- data/fastlane/lib/fastlane/actions/ensure_bundle_exec.rb +59 -0
- data/fastlane/lib/fastlane/actions/ensure_env_vars.rb +58 -0
- data/fastlane/lib/fastlane/actions/ensure_git_branch.rb +69 -0
- data/fastlane/lib/fastlane/actions/ensure_git_status_clean.rb +92 -0
- data/fastlane/lib/fastlane/actions/ensure_no_debug_code.rb +135 -0
- data/fastlane/lib/fastlane/actions/ensure_xcode_version.rb +125 -0
- data/fastlane/lib/fastlane/actions/environment_variable.rb +77 -0
- data/fastlane/lib/fastlane/actions/erb.rb +96 -0
- data/fastlane/lib/fastlane/actions/fastlane_version.rb +15 -0
- data/fastlane/lib/fastlane/actions/flock.rb +82 -0
- data/fastlane/lib/fastlane/actions/frame_screenshots.rb +64 -0
- data/fastlane/lib/fastlane/actions/frameit.rb +14 -0
- data/fastlane/lib/fastlane/actions/gcovr.rb +163 -0
- data/fastlane/lib/fastlane/actions/get_build_number.rb +106 -0
- data/fastlane/lib/fastlane/actions/get_build_number_repository.rb +120 -0
- data/fastlane/lib/fastlane/actions/get_certificates.rb +77 -0
- data/fastlane/lib/fastlane/actions/get_github_release.rb +166 -0
- data/fastlane/lib/fastlane/actions/get_info_plist_value.rb +78 -0
- data/fastlane/lib/fastlane/actions/get_ipa_info_plist_value.rb +82 -0
- data/fastlane/lib/fastlane/actions/get_managed_play_store_publishing_rights.rb +120 -0
- data/fastlane/lib/fastlane/actions/get_provisioning_profile.rb +101 -0
- data/fastlane/lib/fastlane/actions/get_push_certificate.rb +87 -0
- data/fastlane/lib/fastlane/actions/get_version_number.rb +200 -0
- data/fastlane/lib/fastlane/actions/git_add.rb +93 -0
- data/fastlane/lib/fastlane/actions/git_branch.rb +61 -0
- data/fastlane/lib/fastlane/actions/git_commit.rb +80 -0
- data/fastlane/lib/fastlane/actions/git_pull.rb +64 -0
- data/fastlane/lib/fastlane/actions/git_submodule_update.rb +52 -0
- data/fastlane/lib/fastlane/actions/git_tag_exists.rb +74 -0
- data/fastlane/lib/fastlane/actions/github_api.rb +262 -0
- data/fastlane/lib/fastlane/actions/google_play_track_release_names.rb +74 -0
- data/fastlane/lib/fastlane/actions/google_play_track_version_codes.rb +77 -0
- data/fastlane/lib/fastlane/actions/gradle.rb +329 -0
- data/fastlane/lib/fastlane/actions/gym.rb +10 -0
- data/fastlane/lib/fastlane/actions/hg_add_tag.rb +48 -0
- data/fastlane/lib/fastlane/actions/hg_commit_version_bump.rb +183 -0
- data/fastlane/lib/fastlane/actions/hg_ensure_clean_status.rb +53 -0
- data/fastlane/lib/fastlane/actions/hg_push.rb +64 -0
- data/fastlane/lib/fastlane/actions/hipchat.rb +200 -0
- data/fastlane/lib/fastlane/actions/hockey.rb +406 -0
- data/fastlane/lib/fastlane/actions/ifttt.rb +96 -0
- data/fastlane/lib/fastlane/actions/import.rb +49 -0
- data/fastlane/lib/fastlane/actions/import_certificate.rb +77 -0
- data/fastlane/lib/fastlane/actions/import_from_git.rb +83 -0
- data/fastlane/lib/fastlane/actions/increment_build_number.rb +117 -0
- data/fastlane/lib/fastlane/actions/increment_version_number.rb +180 -0
- data/fastlane/lib/fastlane/actions/install_on_device.rb +95 -0
- data/fastlane/lib/fastlane/actions/install_provisioning_profile.rb +58 -0
- data/fastlane/lib/fastlane/actions/install_xcode_plugin.rb +91 -0
- data/fastlane/lib/fastlane/actions/installr.rb +132 -0
- data/fastlane/lib/fastlane/actions/ipa.rb +246 -0
- data/fastlane/lib/fastlane/actions/is_ci.rb +51 -0
- data/fastlane/lib/fastlane/actions/jazzy.rb +56 -0
- data/fastlane/lib/fastlane/actions/jira.rb +115 -0
- data/fastlane/lib/fastlane/actions/lane_context.rb +60 -0
- data/fastlane/lib/fastlane/actions/last_git_commit.rb +58 -0
- data/fastlane/lib/fastlane/actions/last_git_tag.rb +60 -0
- data/fastlane/lib/fastlane/actions/latest_testflight_build_number.rb +155 -0
- data/fastlane/lib/fastlane/actions/lcov.rb +102 -0
- data/fastlane/lib/fastlane/actions/mailgun.rb +197 -0
- data/fastlane/lib/fastlane/actions/make_changelog_from_jenkins.rb +81 -0
- data/fastlane/lib/fastlane/actions/match.rb +14 -0
- data/fastlane/lib/fastlane/actions/min_fastlane_version.rb +57 -0
- data/fastlane/lib/fastlane/actions/modify_services.rb +173 -0
- data/fastlane/lib/fastlane/actions/nexus_upload.rb +230 -0
- data/fastlane/lib/fastlane/actions/notarize.rb +193 -0
- data/fastlane/lib/fastlane/actions/notification.rb +75 -0
- data/fastlane/lib/fastlane/actions/notify.rb +40 -0
- data/fastlane/lib/fastlane/actions/number_of_commits.rb +75 -0
- data/fastlane/lib/fastlane/actions/oclint.rb +269 -0
- data/fastlane/lib/fastlane/actions/onesignal.rb +186 -0
- data/fastlane/lib/fastlane/actions/opt_out_crash_reporting.rb +33 -0
- data/fastlane/lib/fastlane/actions/opt_out_usage.rb +40 -0
- data/fastlane/lib/fastlane/actions/pem.rb +14 -0
- data/fastlane/lib/fastlane/actions/pilot.rb +14 -0
- data/fastlane/lib/fastlane/actions/pod_lib_lint.rb +189 -0
- data/fastlane/lib/fastlane/actions/pod_push.rb +173 -0
- data/fastlane/lib/fastlane/actions/podio_item.rb +217 -0
- data/fastlane/lib/fastlane/actions/precheck.rb +14 -0
- data/fastlane/lib/fastlane/actions/println.rb +14 -0
- data/fastlane/lib/fastlane/actions/produce.rb +14 -0
- data/fastlane/lib/fastlane/actions/prompt.rb +119 -0
- data/fastlane/lib/fastlane/actions/push_git_tags.rb +76 -0
- data/fastlane/lib/fastlane/actions/push_to_git_remote.rb +127 -0
- data/fastlane/lib/fastlane/actions/puts.rb +68 -0
- data/fastlane/lib/fastlane/actions/read_podspec.rb +90 -0
- data/fastlane/lib/fastlane/actions/recreate_schemes.rb +46 -0
- data/fastlane/lib/fastlane/actions/register_device.rb +151 -0
- data/fastlane/lib/fastlane/actions/register_devices.rb +214 -0
- data/fastlane/lib/fastlane/actions/reset_git_repo.rb +121 -0
- data/fastlane/lib/fastlane/actions/reset_simulator_contents.rb +92 -0
- data/fastlane/lib/fastlane/actions/resign.rb +132 -0
- data/fastlane/lib/fastlane/actions/restore_file.rb +44 -0
- data/fastlane/lib/fastlane/actions/rocket.rb +83 -0
- data/fastlane/lib/fastlane/actions/rsync.rb +74 -0
- data/fastlane/lib/fastlane/actions/ruby_version.rb +56 -0
- data/fastlane/lib/fastlane/actions/run_tests.rb +114 -0
- data/fastlane/lib/fastlane/actions/s3.rb +174 -0
- data/fastlane/lib/fastlane/actions/say.rb +56 -0
- data/fastlane/lib/fastlane/actions/scan.rb +14 -0
- data/fastlane/lib/fastlane/actions/scp.rb +114 -0
- data/fastlane/lib/fastlane/actions/screengrab.rb +14 -0
- data/fastlane/lib/fastlane/actions/set_build_number_repository.rb +76 -0
- data/fastlane/lib/fastlane/actions/set_changelog.rb +204 -0
- data/fastlane/lib/fastlane/actions/set_github_release.rb +274 -0
- data/fastlane/lib/fastlane/actions/set_info_plist_value.rb +92 -0
- data/fastlane/lib/fastlane/actions/set_pod_key.rb +78 -0
- data/fastlane/lib/fastlane/actions/setup_ci.rb +132 -0
- data/fastlane/lib/fastlane/actions/setup_circle_ci.rb +58 -0
- data/fastlane/lib/fastlane/actions/setup_jenkins.rb +202 -0
- data/fastlane/lib/fastlane/actions/setup_travis.rb +57 -0
- data/fastlane/lib/fastlane/actions/sh.rb +71 -0
- data/fastlane/lib/fastlane/actions/sigh.rb +14 -0
- data/fastlane/lib/fastlane/actions/skip_docs.rb +52 -0
- data/fastlane/lib/fastlane/actions/slack.rb +288 -0
- data/fastlane/lib/fastlane/actions/slather.rb +329 -0
- data/fastlane/lib/fastlane/actions/snapshot.rb +14 -0
- data/fastlane/lib/fastlane/actions/sonar.rb +177 -0
- data/fastlane/lib/fastlane/actions/spaceship_logs.rb +135 -0
- data/fastlane/lib/fastlane/actions/spaceship_stats.rb +73 -0
- data/fastlane/lib/fastlane/actions/splunkmint.rb +156 -0
- data/fastlane/lib/fastlane/actions/spm.rb +138 -0
- data/fastlane/lib/fastlane/actions/ssh.rb +162 -0
- data/fastlane/lib/fastlane/actions/supply.rb +14 -0
- data/fastlane/lib/fastlane/actions/swiftlint.rb +240 -0
- data/fastlane/lib/fastlane/actions/sync_code_signing.rb +109 -0
- data/fastlane/lib/fastlane/actions/team_id.rb +42 -0
- data/fastlane/lib/fastlane/actions/team_name.rb +42 -0
- data/fastlane/lib/fastlane/actions/testfairy.rb +285 -0
- data/fastlane/lib/fastlane/actions/testflight.rb +14 -0
- data/fastlane/lib/fastlane/actions/tryouts.rb +149 -0
- data/fastlane/lib/fastlane/actions/twitter.rb +89 -0
- data/fastlane/lib/fastlane/actions/typetalk.rb +93 -0
- data/fastlane/lib/fastlane/actions/unlock_keychain.rb +132 -0
- data/fastlane/lib/fastlane/actions/update_app_group_identifiers.rb +91 -0
- data/fastlane/lib/fastlane/actions/update_app_identifier.rb +124 -0
- data/fastlane/lib/fastlane/actions/update_code_signing_settings.rb +203 -0
- data/fastlane/lib/fastlane/actions/update_fastlane.rb +137 -0
- data/fastlane/lib/fastlane/actions/update_icloud_container_identifiers.rb +99 -0
- data/fastlane/lib/fastlane/actions/update_info_plist.rb +143 -0
- data/fastlane/lib/fastlane/actions/update_keychain_access_groups.rb +94 -0
- data/fastlane/lib/fastlane/actions/update_plist.rb +115 -0
- data/fastlane/lib/fastlane/actions/update_project_code_signing.rb +76 -0
- data/fastlane/lib/fastlane/actions/update_project_provisioning.rb +173 -0
- data/fastlane/lib/fastlane/actions/update_project_team.rb +95 -0
- data/fastlane/lib/fastlane/actions/update_urban_airship_configuration.rb +91 -0
- data/fastlane/lib/fastlane/actions/update_url_schemes.rb +123 -0
- data/fastlane/lib/fastlane/actions/upload_symbols_to_crashlytics.rb +231 -0
- data/fastlane/lib/fastlane/actions/upload_symbols_to_sentry.rb +165 -0
- data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +67 -0
- data/fastlane/lib/fastlane/actions/upload_to_play_store.rb +80 -0
- data/fastlane/lib/fastlane/actions/upload_to_play_store_internal_app_sharing.rb +78 -0
- data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +119 -0
- data/fastlane/lib/fastlane/actions/validate_play_store_json_key.rb +104 -0
- data/fastlane/lib/fastlane/actions/verify_build.rb +199 -0
- data/fastlane/lib/fastlane/actions/verify_pod_keys.rb +67 -0
- data/fastlane/lib/fastlane/actions/verify_xcode.rb +159 -0
- data/fastlane/lib/fastlane/actions/version_bump_podspec.rb +105 -0
- data/fastlane/lib/fastlane/actions/version_get_podspec.rb +71 -0
- data/fastlane/lib/fastlane/actions/xcode_install.rb +105 -0
- data/fastlane/lib/fastlane/actions/xcode_select.rb +68 -0
- data/fastlane/lib/fastlane/actions/xcode_server_get_assets.rb +312 -0
- data/fastlane/lib/fastlane/actions/xcodebuild.rb +641 -0
- data/fastlane/lib/fastlane/actions/xcov.rb +66 -0
- data/fastlane/lib/fastlane/actions/xctool.rb +55 -0
- data/fastlane/lib/fastlane/actions/xcversion.rb +55 -0
- data/fastlane/lib/fastlane/actions/zip.rb +120 -0
- data/fastlane/lib/fastlane/auto_complete.rb +82 -0
- data/fastlane/lib/fastlane/boolean.rb +5 -0
- data/fastlane/lib/fastlane/cli_tools_distributor.rb +207 -0
- data/fastlane/lib/fastlane/command_line_handler.rb +49 -0
- data/fastlane/lib/fastlane/commands_generator.rb +369 -0
- data/fastlane/lib/fastlane/configuration_helper.rb +26 -0
- data/fastlane/lib/fastlane/core_ext/bundler_monkey_patch.rb +14 -0
- data/fastlane/lib/fastlane/documentation/actions_list.rb +214 -0
- data/fastlane/lib/fastlane/documentation/docs_generator.rb +89 -0
- data/fastlane/lib/fastlane/documentation/markdown_docs_generator.rb +228 -0
- data/fastlane/lib/fastlane/environment_printer.rb +303 -0
- data/fastlane/lib/fastlane/erb_template_helper.rb +30 -0
- data/fastlane/lib/fastlane/fast_file.rb +439 -0
- data/fastlane/lib/fastlane/fastlane_require.rb +75 -0
- data/fastlane/lib/fastlane/features.rb +4 -0
- data/fastlane/lib/fastlane/helper/README.md +29 -0
- data/fastlane/lib/fastlane/helper/adb_helper.rb +66 -0
- data/fastlane/lib/fastlane/helper/crashlytics_helper.rb +157 -0
- data/fastlane/lib/fastlane/helper/dotenv_helper.rb +50 -0
- data/fastlane/lib/fastlane/helper/gem_helper.rb +26 -0
- data/fastlane/lib/fastlane/helper/git_helper.rb +137 -0
- data/fastlane/lib/fastlane/helper/gradle_helper.rb +62 -0
- data/fastlane/lib/fastlane/helper/lane_helper.rb +13 -0
- data/fastlane/lib/fastlane/helper/podspec_helper.rb +75 -0
- data/fastlane/lib/fastlane/helper/s3_client_helper.rb +78 -0
- data/fastlane/lib/fastlane/helper/sh_helper.rb +134 -0
- data/fastlane/lib/fastlane/helper/xcodeproj_helper.rb +12 -0
- data/fastlane/lib/fastlane/helper/xcversion_helper.rb +25 -0
- data/fastlane/lib/fastlane/junit_generator.rb +27 -0
- data/fastlane/lib/fastlane/lane.rb +97 -0
- data/fastlane/lib/fastlane/lane_list.rb +137 -0
- data/fastlane/lib/fastlane/lane_manager.rb +130 -0
- data/fastlane/lib/fastlane/lane_manager_base.rb +92 -0
- data/fastlane/lib/fastlane/markdown_table_formatter.rb +62 -0
- data/fastlane/lib/fastlane/new_action.rb +47 -0
- data/fastlane/lib/fastlane/one_off.rb +45 -0
- data/fastlane/lib/fastlane/other_action.rb +29 -0
- data/fastlane/lib/fastlane/plugins/plugin_fetcher.rb +55 -0
- data/fastlane/lib/fastlane/plugins/plugin_generator.rb +86 -0
- data/fastlane/lib/fastlane/plugins/plugin_generator_ui.rb +19 -0
- data/fastlane/lib/fastlane/plugins/plugin_info.rb +49 -0
- data/fastlane/lib/fastlane/plugins/plugin_info_collector.rb +159 -0
- data/fastlane/lib/fastlane/plugins/plugin_manager.rb +399 -0
- data/fastlane/lib/fastlane/plugins/plugin_search.rb +46 -0
- data/fastlane/lib/fastlane/plugins/plugin_update_manager.rb +70 -0
- data/fastlane/lib/fastlane/plugins/plugins.rb +12 -0
- data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +35 -0
- data/fastlane/lib/fastlane/plugins/template/.circleci/config.yml +43 -0
- data/fastlane/lib/fastlane/plugins/template/.github/workflows/test.yml +29 -0
- data/fastlane/lib/fastlane/plugins/template/.gitignore +12 -0
- data/fastlane/lib/fastlane/plugins/template/.rspec +5 -0
- data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +188 -0
- data/fastlane/lib/fastlane/plugins/template/.travis.yml +4 -0
- data/fastlane/lib/fastlane/plugins/template/Gemfile +6 -0
- data/fastlane/lib/fastlane/plugins/template/LICENSE.erb +21 -0
- data/fastlane/lib/fastlane/plugins/template/README.md.erb +52 -0
- data/fastlane/lib/fastlane/plugins/template/Rakefile +9 -0
- data/fastlane/lib/fastlane/plugins/template/fastlane/Fastfile.erb +3 -0
- data/fastlane/lib/fastlane/plugins/template/fastlane/Pluginfile.erb +1 -0
- data/fastlane/lib/fastlane/plugins/template/lib/fastlane/plugin/%plugin_name%.rb.erb +16 -0
- data/fastlane/lib/fastlane/plugins/template/lib/fastlane/plugin/%plugin_name%/actions/%plugin_name%_action.rb.erb +47 -0
- data/fastlane/lib/fastlane/plugins/template/lib/fastlane/plugin/%plugin_name%/helper/%plugin_name%_helper.rb.erb +16 -0
- data/fastlane/lib/fastlane/plugins/template/lib/fastlane/plugin/%plugin_name%/version.rb.erb +5 -0
- data/fastlane/lib/fastlane/plugins/template/spec/%plugin_name%_action_spec.rb.erb +9 -0
- data/fastlane/lib/fastlane/plugins/template/spec/spec_helper.rb.erb +15 -0
- data/fastlane/lib/fastlane/runner.rb +378 -0
- data/fastlane/lib/fastlane/server/action_command.rb +61 -0
- data/fastlane/lib/fastlane/server/action_command_return.rb +14 -0
- data/fastlane/lib/fastlane/server/command_executor.rb +7 -0
- data/fastlane/lib/fastlane/server/command_parser.rb +44 -0
- data/fastlane/lib/fastlane/server/control_command.rb +23 -0
- data/fastlane/lib/fastlane/server/json_return_value_processor.rb +72 -0
- data/fastlane/lib/fastlane/server/socket_server.rb +238 -0
- data/fastlane/lib/fastlane/server/socket_server_action_command_executor.rb +101 -0
- data/fastlane/lib/fastlane/setup/setup.rb +355 -0
- data/fastlane/lib/fastlane/setup/setup_android.rb +97 -0
- data/fastlane/lib/fastlane/setup/setup_ios.rb +504 -0
- data/fastlane/lib/fastlane/shells.rb +6 -0
- data/fastlane/lib/fastlane/supported_platforms.rb +28 -0
- data/fastlane/lib/fastlane/swift_fastlane_api_generator.rb +477 -0
- data/fastlane/lib/fastlane/swift_fastlane_function.rb +419 -0
- data/fastlane/lib/fastlane/swift_lane_manager.rb +296 -0
- data/fastlane/lib/fastlane/swift_runner_upgrader.rb +210 -0
- data/fastlane/lib/fastlane/tools.rb +33 -0
- data/fastlane/lib/fastlane/version.rb +6 -0
- data/fastlane/swift/Actions.swift +16 -0
- data/fastlane/swift/Appfile.swift +15 -0
- data/fastlane/swift/ArgumentProcessor.swift +89 -0
- data/fastlane/swift/ControlCommand.swift +74 -0
- data/fastlane/swift/Deliverfile.swift +20 -0
- data/fastlane/swift/DeliverfileProtocol.swift +259 -0
- data/fastlane/swift/Fastfile.swift +16 -0
- data/fastlane/swift/Fastlane.swift +9402 -0
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.pbxproj +434 -0
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/xcshareddata/xcschemes/FastlaneRunner.xcscheme +97 -0
- data/fastlane/swift/FastlaneSwiftRunner/README.txt +10 -0
- data/fastlane/swift/Gymfile.swift +20 -0
- data/fastlane/swift/GymfileProtocol.swift +187 -0
- data/fastlane/swift/LaneFileProtocol.swift +149 -0
- data/fastlane/swift/MainProcess.swift +77 -0
- data/fastlane/swift/Matchfile.swift +20 -0
- data/fastlane/swift/MatchfileProtocol.swift +187 -0
- data/fastlane/swift/Plugins.swift +16 -0
- data/fastlane/swift/Precheckfile.swift +20 -0
- data/fastlane/swift/PrecheckfileProtocol.swift +51 -0
- data/fastlane/swift/RubyCommand.swift +157 -0
- data/fastlane/swift/RubyCommandable.swift +43 -0
- data/fastlane/swift/Runner.swift +275 -0
- data/fastlane/swift/RunnerArgument.swift +20 -0
- data/fastlane/swift/Scanfile.swift +20 -0
- data/fastlane/swift/ScanfileProtocol.swift +263 -0
- data/fastlane/swift/Screengrabfile.swift +20 -0
- data/fastlane/swift/ScreengrabfileProtocol.swift +99 -0
- data/fastlane/swift/Snapshotfile.swift +20 -0
- data/fastlane/swift/SnapshotfileProtocol.swift +187 -0
- data/fastlane/swift/SocketClient.swift +327 -0
- data/fastlane/swift/SocketClientDelegateProtocol.swift +21 -0
- data/fastlane/swift/SocketResponse.swift +82 -0
- data/fastlane/swift/formatting/Brewfile +1 -0
- data/fastlane/swift/formatting/Brewfile.lock.json +47 -0
- data/fastlane/swift/formatting/Rakefile +18 -0
- data/fastlane/swift/main.swift +47 -0
- data/fastlane/swift/upgrade_manifest.json +1 -0
- data/fastlane_core/README.md +79 -0
- data/fastlane_core/lib/assets/XMLTemplate.xml.erb +12 -0
- data/fastlane_core/lib/fastlane_core.rb +46 -0
- data/fastlane_core/lib/fastlane_core/analytics/action_completion_context.rb +34 -0
- data/fastlane_core/lib/fastlane_core/analytics/action_launch_context.rb +38 -0
- data/fastlane_core/lib/fastlane_core/analytics/analytics_event_builder.rb +23 -0
- data/fastlane_core/lib/fastlane_core/analytics/analytics_ingester_client.rb +54 -0
- data/fastlane_core/lib/fastlane_core/analytics/analytics_session.rb +70 -0
- data/fastlane_core/lib/fastlane_core/analytics/app_identifier_guesser.rb +64 -0
- data/fastlane_core/lib/fastlane_core/android_package_name_guesser.rb +79 -0
- data/fastlane_core/lib/fastlane_core/build_watcher.rb +96 -0
- data/fastlane_core/lib/fastlane_core/cert_checker.rb +144 -0
- data/fastlane_core/lib/fastlane_core/command_executor.rb +100 -0
- data/fastlane_core/lib/fastlane_core/configuration/commander_generator.rb +103 -0
- data/fastlane_core/lib/fastlane_core/configuration/config_item.rb +321 -0
- data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +332 -0
- data/fastlane_core/lib/fastlane_core/configuration/configuration_file.rb +182 -0
- data/fastlane_core/lib/fastlane_core/core_ext/cfpropertylist.rb +23 -0
- data/fastlane_core/lib/fastlane_core/core_ext/shellwords.rb +63 -0
- data/fastlane_core/lib/fastlane_core/core_ext/string.rb +17 -0
- data/fastlane_core/lib/fastlane_core/device_manager.rb +374 -0
- data/fastlane_core/lib/fastlane_core/env.rb +9 -0
- data/fastlane_core/lib/fastlane_core/fastlane_folder.rb +72 -0
- data/fastlane_core/lib/fastlane_core/fastlane_pty.rb +57 -0
- data/fastlane_core/lib/fastlane_core/feature/feature.rb +51 -0
- data/fastlane_core/lib/fastlane_core/features.rb +4 -0
- data/fastlane_core/lib/fastlane_core/globals.rb +27 -0
- data/fastlane_core/lib/fastlane_core/helper.rb +437 -0
- data/fastlane_core/lib/fastlane_core/ios_app_identifier_guesser.rb +112 -0
- data/fastlane_core/lib/fastlane_core/ipa_file_analyser.rb +63 -0
- data/fastlane_core/lib/fastlane_core/ipa_upload_package_builder.rb +52 -0
- data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +595 -0
- data/fastlane_core/lib/fastlane_core/keychain_importer.rb +120 -0
- data/fastlane_core/lib/fastlane_core/languages.rb +16 -0
- data/fastlane_core/lib/fastlane_core/module.rb +31 -0
- data/fastlane_core/lib/fastlane_core/pkg_file_analyser.rb +51 -0
- data/fastlane_core/lib/fastlane_core/pkg_upload_package_builder.rb +48 -0
- data/fastlane_core/lib/fastlane_core/print_table.rb +131 -0
- data/fastlane_core/lib/fastlane_core/project.rb +509 -0
- data/fastlane_core/lib/fastlane_core/provisioning_profile.rb +124 -0
- data/fastlane_core/lib/fastlane_core/string_filters.rb +51 -0
- data/fastlane_core/lib/fastlane_core/swag.rb +85 -0
- data/fastlane_core/lib/fastlane_core/tag_version.rb +31 -0
- data/fastlane_core/lib/fastlane_core/test_parser.rb +107 -0
- data/fastlane_core/lib/fastlane_core/ui/disable_colors.rb +17 -0
- data/fastlane_core/lib/fastlane_core/ui/errors.rb +1 -0
- data/fastlane_core/lib/fastlane_core/ui/errors/fastlane_common_error.rb +19 -0
- data/fastlane_core/lib/fastlane_core/ui/errors/fastlane_crash.rb +11 -0
- data/fastlane_core/lib/fastlane_core/ui/errors/fastlane_error.rb +25 -0
- data/fastlane_core/lib/fastlane_core/ui/errors/fastlane_exception.rb +19 -0
- data/fastlane_core/lib/fastlane_core/ui/errors/fastlane_shell_error.rb +11 -0
- data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +294 -0
- data/fastlane_core/lib/fastlane_core/ui/github_issue_inspector_reporter.rb +62 -0
- data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +159 -0
- data/fastlane_core/lib/fastlane_core/ui/interface.rb +205 -0
- data/fastlane_core/lib/fastlane_core/ui/ui.rb +26 -0
- data/fastlane_core/lib/fastlane_core/update_checker/changelog.rb +37 -0
- data/fastlane_core/lib/fastlane_core/update_checker/update_checker.rb +109 -0
- data/frameit/README.md +17 -0
- data/frameit/lib/assets/empty.png +0 -0
- data/frameit/lib/frameit.rb +13 -0
- data/frameit/lib/frameit/commands_generator.rb +140 -0
- data/frameit/lib/frameit/config_parser.rb +136 -0
- data/frameit/lib/frameit/dependency_checker.rb +22 -0
- data/frameit/lib/frameit/device.rb +90 -0
- data/frameit/lib/frameit/device_types.rb +144 -0
- data/frameit/lib/frameit/editor.rb +560 -0
- data/frameit/lib/frameit/frame_downloader.rb +85 -0
- data/frameit/lib/frameit/mac_editor.rb +35 -0
- data/frameit/lib/frameit/module.rb +42 -0
- data/frameit/lib/frameit/offsets.rb +28 -0
- data/frameit/lib/frameit/options.rb +112 -0
- data/frameit/lib/frameit/runner.rb +97 -0
- data/frameit/lib/frameit/screenshot.rb +134 -0
- data/frameit/lib/frameit/strings_parser.rb +46 -0
- data/frameit/lib/frameit/template_finder.rb +45 -0
- data/frameit/lib/frameit/trim_box.rb +35 -0
- data/gym/README.md +17 -0
- data/gym/lib/assets/GymfileTemplate +13 -0
- data/gym/lib/assets/GymfileTemplate.swift +13 -0
- data/gym/lib/assets/wrap_xcodebuild/xcbuild-safe.sh +61 -0
- data/gym/lib/gym.rb +9 -0
- data/gym/lib/gym/code_signing_mapping.rb +210 -0
- data/gym/lib/gym/commands_generator.rb +78 -0
- data/gym/lib/gym/detect_values.rb +206 -0
- data/gym/lib/gym/error_handler.rb +306 -0
- data/gym/lib/gym/generators/README.md +1 -0
- data/gym/lib/gym/generators/build_command_generator.rb +147 -0
- data/gym/lib/gym/generators/package_command_generator.rb +68 -0
- data/gym/lib/gym/generators/package_command_generator_xcode7.rb +232 -0
- data/gym/lib/gym/manager.rb +22 -0
- data/gym/lib/gym/module.rb +74 -0
- data/gym/lib/gym/options.rb +286 -0
- data/gym/lib/gym/runner.rb +365 -0
- data/gym/lib/gym/xcode.rb +27 -0
- data/gym/lib/gym/xcodebuild_fixes/README.md +9 -0
- data/gym/lib/gym/xcodebuild_fixes/generic_archive_fix.rb +35 -0
- data/match/README.md +17 -0
- data/match/lib/assets/MatchfileTemplate +11 -0
- data/match/lib/assets/MatchfileTemplate.swift +9 -0
- data/match/lib/assets/READMETemplate.md +59 -0
- data/match/lib/match.rb +14 -0
- data/match/lib/match/change_password.rb +53 -0
- data/match/lib/match/commands_generator.rb +190 -0
- data/match/lib/match/encryption.rb +49 -0
- data/match/lib/match/encryption/interface.rb +17 -0
- data/match/lib/match/encryption/openssl.rb +161 -0
- data/match/lib/match/generator.rb +122 -0
- data/match/lib/match/importer.rb +157 -0
- data/match/lib/match/migrate.rb +109 -0
- data/match/lib/match/module.rb +32 -0
- data/match/lib/match/nuke.rb +350 -0
- data/match/lib/match/options.rb +315 -0
- data/match/lib/match/runner.rb +369 -0
- data/match/lib/match/setup.rb +40 -0
- data/match/lib/match/spaceship_ensure.rb +97 -0
- data/match/lib/match/storage.rb +46 -0
- data/match/lib/match/storage/git_storage.rb +250 -0
- data/match/lib/match/storage/google_cloud_storage.rb +382 -0
- data/match/lib/match/storage/interface.rb +119 -0
- data/match/lib/match/storage/s3_storage.rb +205 -0
- data/match/lib/match/table_printer.rb +51 -0
- data/match/lib/match/utils.rb +75 -0
- data/pem/README.md +17 -0
- data/pem/lib/pem.rb +4 -0
- data/pem/lib/pem/commands_generator.rb +47 -0
- data/pem/lib/pem/manager.rb +112 -0
- data/pem/lib/pem/module.rb +19 -0
- data/pem/lib/pem/options.rb +103 -0
- data/pilot/README.md +17 -0
- data/pilot/lib/pilot.rb +9 -0
- data/pilot/lib/pilot/build_manager.rb +546 -0
- data/pilot/lib/pilot/commands_generator.rb +174 -0
- data/pilot/lib/pilot/features.rb +0 -0
- data/pilot/lib/pilot/manager.rb +90 -0
- data/pilot/lib/pilot/module.rb +11 -0
- data/pilot/lib/pilot/options.rb +303 -0
- data/pilot/lib/pilot/tester_exporter.rb +58 -0
- data/pilot/lib/pilot/tester_importer.rb +53 -0
- data/pilot/lib/pilot/tester_manager.rb +168 -0
- data/pilot/lib/pilot/tester_util.rb +0 -0
- data/precheck/README.md +17 -0
- data/precheck/lib/assets/PrecheckfileTemplate +27 -0
- data/precheck/lib/assets/PrecheckfileTemplate.swift +19 -0
- data/precheck/lib/precheck.rb +3 -0
- data/precheck/lib/precheck/commands_generator.rb +74 -0
- data/precheck/lib/precheck/item_to_check.rb +58 -0
- data/precheck/lib/precheck/module.rb +21 -0
- data/precheck/lib/precheck/options.rb +104 -0
- data/precheck/lib/precheck/rule.rb +171 -0
- data/precheck/lib/precheck/rule_check_result.rb +19 -0
- data/precheck/lib/precheck/rule_processor.rb +265 -0
- data/precheck/lib/precheck/rules/abstract_text_match_rule.rb +80 -0
- data/precheck/lib/precheck/rules/all.rb +1 -0
- data/precheck/lib/precheck/rules/copyright_date_rule.rb +37 -0
- data/precheck/lib/precheck/rules/curse_words_rule.rb +62 -0
- data/precheck/lib/precheck/rules/custom_text_rule.rb +35 -0
- data/precheck/lib/precheck/rules/free_stuff_iap_rule.rb +31 -0
- data/precheck/lib/precheck/rules/future_functionality_rule.rb +33 -0
- data/precheck/lib/precheck/rules/negative_apple_sentiment_rule.rb +37 -0
- data/precheck/lib/precheck/rules/other_platforms_rule.rb +43 -0
- data/precheck/lib/precheck/rules/placeholder_words_rule.rb +31 -0
- data/precheck/lib/precheck/rules/rules_data/curse_word_hashes/en_us.txt +349 -0
- data/precheck/lib/precheck/rules/test_words_rule.rb +30 -0
- data/precheck/lib/precheck/rules/unreachable_urls_rule.rb +47 -0
- data/precheck/lib/precheck/runner.rb +197 -0
- data/produce/README.md +17 -0
- data/produce/lib/produce.rb +6 -0
- data/produce/lib/produce/available_default_languages.rb +51 -0
- data/produce/lib/produce/cloud_container.rb +82 -0
- data/produce/lib/produce/commands_generator.rb +236 -0
- data/produce/lib/produce/developer_center.rb +143 -0
- data/produce/lib/produce/group.rb +90 -0
- data/produce/lib/produce/itunes_connect.rb +139 -0
- data/produce/lib/produce/manager.rb +15 -0
- data/produce/lib/produce/merchant.rb +121 -0
- data/produce/lib/produce/module.rb +14 -0
- data/produce/lib/produce/options.rb +184 -0
- data/produce/lib/produce/service.rb +319 -0
- data/scan/README.md +17 -0
- data/scan/lib/assets/ScanfileTemplate +16 -0
- data/scan/lib/assets/ScanfileTemplate.swift +13 -0
- data/scan/lib/scan.rb +10 -0
- data/scan/lib/scan/commands_generator.rb +78 -0
- data/scan/lib/scan/detect_values.rb +224 -0
- data/scan/lib/scan/error_handler.rb +57 -0
- data/scan/lib/scan/manager.rb +38 -0
- data/scan/lib/scan/module.rb +32 -0
- data/scan/lib/scan/options.rb +445 -0
- data/scan/lib/scan/runner.rb +197 -0
- data/scan/lib/scan/slack_poster.rb +60 -0
- data/scan/lib/scan/test_command_generator.rb +174 -0
- data/scan/lib/scan/test_result_parser.rb +33 -0
- data/scan/lib/scan/xcpretty_reporter_options_generator.rb +85 -0
- data/screengrab/README.md +17 -0
- data/screengrab/lib/assets/ScreengrabfileTemplate +15 -0
- data/screengrab/lib/assets/ScreengrabfileTemplate.swift +15 -0
- data/screengrab/lib/screengrab.rb +7 -0
- data/screengrab/lib/screengrab/android_environment.rb +91 -0
- data/screengrab/lib/screengrab/commands_generator.rb +70 -0
- data/screengrab/lib/screengrab/dependency_checker.rb +58 -0
- data/screengrab/lib/screengrab/detect_values.rb +16 -0
- data/screengrab/lib/screengrab/module.rb +26 -0
- data/screengrab/lib/screengrab/options.rb +148 -0
- data/screengrab/lib/screengrab/page.html.erb +190 -0
- data/screengrab/lib/screengrab/reports_generator.rb +36 -0
- data/screengrab/lib/screengrab/runner.rb +449 -0
- data/screengrab/lib/screengrab/setup.rb +24 -0
- data/sigh/README.md +17 -0
- data/sigh/lib/assets/resign.sh +909 -0
- data/sigh/lib/sigh.rb +4 -0
- data/sigh/lib/sigh/commands_generator.rb +154 -0
- data/sigh/lib/sigh/download_all.rb +112 -0
- data/sigh/lib/sigh/local_manage.rb +145 -0
- data/sigh/lib/sigh/manager.rb +47 -0
- data/sigh/lib/sigh/module.rb +42 -0
- data/sigh/lib/sigh/options.rb +187 -0
- data/sigh/lib/sigh/repair.rb +34 -0
- data/sigh/lib/sigh/resign.rb +220 -0
- data/sigh/lib/sigh/runner.rb +402 -0
- data/snapshot/README.md +17 -0
- data/snapshot/lib/assets/SnapfileTemplate +37 -0
- data/snapshot/lib/assets/SnapfileTemplate.swift +41 -0
- data/snapshot/lib/assets/SnapshotHelper.swift +301 -0
- data/snapshot/lib/assets/SnapshotHelperXcode8.swift +172 -0
- data/snapshot/lib/snapshot.rb +19 -0
- data/snapshot/lib/snapshot/collector.rb +140 -0
- data/snapshot/lib/snapshot/commands_generator.rb +115 -0
- data/snapshot/lib/snapshot/dependency_checker.rb +69 -0
- data/snapshot/lib/snapshot/detect_values.rb +86 -0
- data/snapshot/lib/snapshot/error_handler.rb +24 -0
- data/snapshot/lib/snapshot/fixes/README.md +5 -0
- data/snapshot/lib/snapshot/fixes/hardware_keyboard_fix.rb +27 -0
- data/snapshot/lib/snapshot/fixes/simulator_shared_pasteboard.rb +16 -0
- data/snapshot/lib/snapshot/fixes/simulator_zoom_fix.rb +27 -0
- data/snapshot/lib/snapshot/latest_os_version.rb +34 -0
- data/snapshot/lib/snapshot/module.rb +44 -0
- data/snapshot/lib/snapshot/options.rb +290 -0
- data/snapshot/lib/snapshot/page.html.erb +285 -0
- data/snapshot/lib/snapshot/reports_generator.rb +139 -0
- data/snapshot/lib/snapshot/reset_simulators.rb +122 -0
- data/snapshot/lib/snapshot/runner.rb +146 -0
- data/snapshot/lib/snapshot/screenshot_flatten.rb +20 -0
- data/snapshot/lib/snapshot/screenshot_rotate.rb +36 -0
- data/snapshot/lib/snapshot/setup.rb +58 -0
- data/snapshot/lib/snapshot/simulator_launchers/launcher_configuration.rb +62 -0
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher.rb +219 -0
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +200 -0
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_xcode_8.rb +113 -0
- data/snapshot/lib/snapshot/test_command_generator.rb +108 -0
- data/snapshot/lib/snapshot/test_command_generator_base.rb +128 -0
- data/snapshot/lib/snapshot/test_command_generator_xcode_8.rb +70 -0
- data/snapshot/lib/snapshot/update.rb +38 -0
- data/spaceship/README.md +183 -0
- data/spaceship/lib/assets/displayFamilies.json +181 -0
- data/spaceship/lib/assets/languageMapping.json +306 -0
- data/spaceship/lib/assets/languageMappingReadable.json +30 -0
- data/spaceship/lib/spaceship.rb +30 -0
- data/spaceship/lib/spaceship/base.rb +310 -0
- data/spaceship/lib/spaceship/client.rb +913 -0
- data/spaceship/lib/spaceship/commands_generator.rb +53 -0
- data/spaceship/lib/spaceship/connect_api.rb +116 -0
- data/spaceship/lib/spaceship/connect_api/api_client.rb +279 -0
- data/spaceship/lib/spaceship/connect_api/client.rb +216 -0
- data/spaceship/lib/spaceship/connect_api/file_uploader.rb +99 -0
- data/spaceship/lib/spaceship/connect_api/model.rb +172 -0
- data/spaceship/lib/spaceship/connect_api/models/age_rating_declaration.rb +114 -0
- data/spaceship/lib/spaceship/connect_api/models/app.rb +388 -0
- data/spaceship/lib/spaceship/connect_api/models/app_category.rb +94 -0
- data/spaceship/lib/spaceship/connect_api/models/app_info.rb +95 -0
- data/spaceship/lib/spaceship/connect_api/models/app_info_localization.rb +39 -0
- data/spaceship/lib/spaceship/connect_api/models/app_preview.rb +131 -0
- data/spaceship/lib/spaceship/connect_api/models/app_preview_set.rb +100 -0
- data/spaceship/lib/spaceship/connect_api/models/app_price.rb +22 -0
- data/spaceship/lib/spaceship/connect_api/models/app_price_point.rb +26 -0
- data/spaceship/lib/spaceship/connect_api/models/app_price_tier.rb +12 -0
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +187 -0
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +153 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_review_attachment.rb +71 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_review_detail.rb +51 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +217 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +85 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_phased_release.rb +57 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_release_request.rb +12 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_submission.rb +26 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_app_localization.rb +28 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_app_review_detail.rb +32 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_app_review_submission.rb +26 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_build_localization.rb +20 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_build_metric.rb +24 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_feedback.rb +75 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +41 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_screenshot.rb +18 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_tester.rb +57 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_tester_metric.rb +44 -0
- data/spaceship/lib/spaceship/connect_api/models/build.rb +172 -0
- data/spaceship/lib/spaceship/connect_api/models/build_beta_detail.rb +61 -0
- data/spaceship/lib/spaceship/connect_api/models/build_delivery.rb +36 -0
- data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +58 -0
- data/spaceship/lib/spaceship/connect_api/models/bundle_id_capability.rb +71 -0
- data/spaceship/lib/spaceship/connect_api/models/certificate.rb +102 -0
- data/spaceship/lib/spaceship/connect_api/models/custom_app_organization.rb +43 -0
- data/spaceship/lib/spaceship/connect_api/models/custom_app_user.rb +41 -0
- data/spaceship/lib/spaceship/connect_api/models/device.rb +58 -0
- data/spaceship/lib/spaceship/connect_api/models/idfa_declaration.rb +41 -0
- data/spaceship/lib/spaceship/connect_api/models/pre_release_version.rb +20 -0
- data/spaceship/lib/spaceship/connect_api/models/profile.rb +97 -0
- data/spaceship/lib/spaceship/connect_api/models/reset_ratings_request.rb +26 -0
- data/spaceship/lib/spaceship/connect_api/models/sandbox_tester.rb +64 -0
- data/spaceship/lib/spaceship/connect_api/models/territory.rb +27 -0
- data/spaceship/lib/spaceship/connect_api/models/user.rb +51 -0
- data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +59 -0
- data/spaceship/lib/spaceship/connect_api/provisioning/client.rb +92 -0
- data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +143 -0
- data/spaceship/lib/spaceship/connect_api/response.rb +67 -0
- data/spaceship/lib/spaceship/connect_api/spaceship.rb +102 -0
- data/spaceship/lib/spaceship/connect_api/testflight/client.rb +24 -0
- data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +391 -0
- data/spaceship/lib/spaceship/connect_api/token.rb +102 -0
- data/spaceship/lib/spaceship/connect_api/token_refresh_middleware.rb +24 -0
- data/spaceship/lib/spaceship/connect_api/tunes/client.rb +24 -0
- data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +1045 -0
- data/spaceship/lib/spaceship/connect_api/users/client.rb +24 -0
- data/spaceship/lib/spaceship/connect_api/users/users.rb +80 -0
- data/spaceship/lib/spaceship/du/du_client.rb +138 -0
- data/spaceship/lib/spaceship/du/upload_file.rb +58 -0
- data/spaceship/lib/spaceship/du/utilities.rb +99 -0
- data/spaceship/lib/spaceship/errors.rb +82 -0
- data/spaceship/lib/spaceship/globals.rb +12 -0
- data/spaceship/lib/spaceship/helper/net_http_generic_request.rb +20 -0
- data/spaceship/lib/spaceship/helper/plist_middleware.rb +16 -0
- data/spaceship/lib/spaceship/helper/rels_middleware.rb +28 -0
- data/spaceship/lib/spaceship/launcher.rb +99 -0
- data/spaceship/lib/spaceship/module.rb +8 -0
- data/spaceship/lib/spaceship/playground.rb +75 -0
- data/spaceship/lib/spaceship/portal/app.rb +201 -0
- data/spaceship/lib/spaceship/portal/app_group.rb +73 -0
- data/spaceship/lib/spaceship/portal/app_service.rb +87 -0
- data/spaceship/lib/spaceship/portal/certificate.rb +365 -0
- data/spaceship/lib/spaceship/portal/cloud_container.rb +74 -0
- data/spaceship/lib/spaceship/portal/device.rb +191 -0
- data/spaceship/lib/spaceship/portal/invite.rb +53 -0
- data/spaceship/lib/spaceship/portal/key.rb +101 -0
- data/spaceship/lib/spaceship/portal/legacy_wrapper.rb +21 -0
- data/spaceship/lib/spaceship/portal/merchant.rb +86 -0
- data/spaceship/lib/spaceship/portal/passbook.rb +78 -0
- data/spaceship/lib/spaceship/portal/person.rb +62 -0
- data/spaceship/lib/spaceship/portal/persons.rb +67 -0
- data/spaceship/lib/spaceship/portal/portal.rb +17 -0
- data/spaceship/lib/spaceship/portal/portal_base.rb +16 -0
- data/spaceship/lib/spaceship/portal/portal_client.rb +862 -0
- data/spaceship/lib/spaceship/portal/provisioning_profile.rb +559 -0
- data/spaceship/lib/spaceship/portal/provisioning_profile_template.rb +52 -0
- data/spaceship/lib/spaceship/portal/spaceship.rb +154 -0
- data/spaceship/lib/spaceship/portal/ui/select_team.rb +116 -0
- data/spaceship/lib/spaceship/portal/website_push.rb +88 -0
- data/spaceship/lib/spaceship/provider.rb +13 -0
- data/spaceship/lib/spaceship/spaceauth_runner.rb +74 -0
- data/spaceship/lib/spaceship/stats_middleware.rb +65 -0
- data/spaceship/lib/spaceship/test_flight.rb +10 -0
- data/spaceship/lib/spaceship/test_flight/app_test_info.rb +40 -0
- data/spaceship/lib/spaceship/test_flight/base.rb +39 -0
- data/spaceship/lib/spaceship/test_flight/beta_review_info.rb +19 -0
- data/spaceship/lib/spaceship/test_flight/build.rb +242 -0
- data/spaceship/lib/spaceship/test_flight/build_trains.rb +50 -0
- data/spaceship/lib/spaceship/test_flight/client.rb +361 -0
- data/spaceship/lib/spaceship/test_flight/export_compliance.rb +12 -0
- data/spaceship/lib/spaceship/test_flight/group.rb +131 -0
- data/spaceship/lib/spaceship/test_flight/test_info.rb +56 -0
- data/spaceship/lib/spaceship/test_flight/tester.rb +136 -0
- data/spaceship/lib/spaceship/tunes/app_analytics.rb +168 -0
- data/spaceship/lib/spaceship/tunes/app_details.rb +147 -0
- data/spaceship/lib/spaceship/tunes/app_image.rb +51 -0
- data/spaceship/lib/spaceship/tunes/app_ratings.rb +58 -0
- data/spaceship/lib/spaceship/tunes/app_review.rb +55 -0
- data/spaceship/lib/spaceship/tunes/app_review_attachment.rb +49 -0
- data/spaceship/lib/spaceship/tunes/app_screenshot.rb +12 -0
- data/spaceship/lib/spaceship/tunes/app_status.rb +63 -0
- data/spaceship/lib/spaceship/tunes/app_submission.rb +161 -0
- data/spaceship/lib/spaceship/tunes/app_trailer.rb +64 -0
- data/spaceship/lib/spaceship/tunes/app_version.rb +970 -0
- data/spaceship/lib/spaceship/tunes/app_version_common.rb +35 -0
- data/spaceship/lib/spaceship/tunes/app_version_generated_promocodes.rb +28 -0
- data/spaceship/lib/spaceship/tunes/app_version_history.rb +52 -0
- data/spaceship/lib/spaceship/tunes/app_version_promocodes.rb +27 -0
- data/spaceship/lib/spaceship/tunes/app_version_ref.rb +15 -0
- data/spaceship/lib/spaceship/tunes/app_version_states_history.rb +27 -0
- data/spaceship/lib/spaceship/tunes/application.rb +453 -0
- data/spaceship/lib/spaceship/tunes/availability.rb +164 -0
- data/spaceship/lib/spaceship/tunes/b2b_organization.rb +50 -0
- data/spaceship/lib/spaceship/tunes/b2b_user.rb +30 -0
- data/spaceship/lib/spaceship/tunes/build.rb +263 -0
- data/spaceship/lib/spaceship/tunes/build_details.rb +184 -0
- data/spaceship/lib/spaceship/tunes/build_train.rb +181 -0
- data/spaceship/lib/spaceship/tunes/developer_response.rb +23 -0
- data/spaceship/lib/spaceship/tunes/device_type.rb +17 -0
- data/spaceship/lib/spaceship/tunes/display_family.rb +84 -0
- data/spaceship/lib/spaceship/tunes/errors.rb +17 -0
- data/spaceship/lib/spaceship/tunes/iap.rb +168 -0
- data/spaceship/lib/spaceship/tunes/iap_detail.rb +264 -0
- data/spaceship/lib/spaceship/tunes/iap_families.rb +68 -0
- data/spaceship/lib/spaceship/tunes/iap_family_details.rb +90 -0
- data/spaceship/lib/spaceship/tunes/iap_family_list.rb +28 -0
- data/spaceship/lib/spaceship/tunes/iap_list.rb +76 -0
- data/spaceship/lib/spaceship/tunes/iap_status.rb +56 -0
- data/spaceship/lib/spaceship/tunes/iap_subscription_pricing_info.rb +46 -0
- data/spaceship/lib/spaceship/tunes/iap_subscription_pricing_tier.rb +25 -0
- data/spaceship/lib/spaceship/tunes/iap_type.rb +45 -0
- data/spaceship/lib/spaceship/tunes/language_converter.rb +65 -0
- data/spaceship/lib/spaceship/tunes/language_item.rb +61 -0
- data/spaceship/lib/spaceship/tunes/legacy_wrapper.rb +13 -0
- data/spaceship/lib/spaceship/tunes/member.rb +84 -0
- data/spaceship/lib/spaceship/tunes/members.rb +35 -0
- data/spaceship/lib/spaceship/tunes/pricing_info.rb +42 -0
- data/spaceship/lib/spaceship/tunes/pricing_tier.rb +25 -0
- data/spaceship/lib/spaceship/tunes/sandbox_tester.rb +74 -0
- data/spaceship/lib/spaceship/tunes/spaceship.rb +39 -0
- data/spaceship/lib/spaceship/tunes/territory.rb +39 -0
- data/spaceship/lib/spaceship/tunes/transit_app_file.rb +23 -0
- data/spaceship/lib/spaceship/tunes/tunes.rb +35 -0
- data/spaceship/lib/spaceship/tunes/tunes_base.rb +17 -0
- data/spaceship/lib/spaceship/tunes/tunes_client.rb +1644 -0
- data/spaceship/lib/spaceship/tunes/user_detail.rb +15 -0
- data/spaceship/lib/spaceship/tunes/version_set.rb +26 -0
- data/spaceship/lib/spaceship/two_step_or_factor_client.rb +346 -0
- data/spaceship/lib/spaceship/ui.rb +27 -0
- data/supply/README.md +17 -0
- data/supply/lib/supply.rb +53 -0
- data/supply/lib/supply/apk_listing.rb +14 -0
- data/supply/lib/supply/client.rb +551 -0
- data/supply/lib/supply/commands_generator.rb +67 -0
- data/supply/lib/supply/languages.rb +88 -0
- data/supply/lib/supply/listing.rb +32 -0
- data/supply/lib/supply/options.rb +324 -0
- data/supply/lib/supply/reader.rb +41 -0
- data/supply/lib/supply/release_listing.rb +18 -0
- data/supply/lib/supply/setup.rb +122 -0
- data/supply/lib/supply/uploader.rb +480 -0
- metadata +1832 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'tunes_base'
|
2
|
+
require_relative 'application'
|
3
|
+
require_relative 'iap'
|
4
|
+
require_relative 'version_set'
|
5
|
+
require_relative 'app_version'
|
6
|
+
require_relative 'app_version_common'
|
7
|
+
require_relative 'app_submission'
|
8
|
+
require_relative 'tunes_client'
|
9
|
+
require_relative 'language_item'
|
10
|
+
require_relative 'app_status'
|
11
|
+
require_relative 'app_image'
|
12
|
+
require_relative 'app_ratings'
|
13
|
+
require_relative 'app_version_ref'
|
14
|
+
require_relative 'app_version_history'
|
15
|
+
require_relative 'app_version_states_history'
|
16
|
+
require_relative 'transit_app_file'
|
17
|
+
require_relative 'user_detail'
|
18
|
+
require_relative 'app_screenshot'
|
19
|
+
require_relative 'language_converter'
|
20
|
+
require_relative 'build'
|
21
|
+
require_relative 'build_details'
|
22
|
+
require_relative 'build_train'
|
23
|
+
require_relative 'device_type'
|
24
|
+
require_relative 'app_trailer'
|
25
|
+
require_relative 'sandbox_tester'
|
26
|
+
require_relative 'app_details'
|
27
|
+
require_relative 'pricing_tier'
|
28
|
+
require_relative 'territory'
|
29
|
+
require_relative 'availability'
|
30
|
+
require_relative 'members'
|
31
|
+
require_relative 'member'
|
32
|
+
|
33
|
+
require_relative 'app_version_promocodes'
|
34
|
+
require_relative 'app_version_generated_promocodes'
|
35
|
+
require_relative 'app_analytics'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative '../base'
|
2
|
+
|
3
|
+
module Spaceship
|
4
|
+
module Tunes
|
5
|
+
class TunesBase < Spaceship::Base
|
6
|
+
class << self
|
7
|
+
def client
|
8
|
+
(
|
9
|
+
@client or
|
10
|
+
Spaceship::Tunes.client or
|
11
|
+
raise "Please login using `Spaceship::Tunes.login('user', 'password')`"
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,1644 @@
|
|
1
|
+
require "securerandom"
|
2
|
+
require_relative '../client'
|
3
|
+
require_relative '../du/du_client'
|
4
|
+
require_relative '../du/upload_file'
|
5
|
+
require_relative 'app_version_common'
|
6
|
+
require_relative 'app_version_ref'
|
7
|
+
require_relative 'availability'
|
8
|
+
require_relative 'errors'
|
9
|
+
require_relative 'iap_subscription_pricing_tier'
|
10
|
+
require_relative 'pricing_tier'
|
11
|
+
require_relative 'territory'
|
12
|
+
require_relative 'user_detail'
|
13
|
+
module Spaceship
|
14
|
+
# rubocop:disable Metrics/ClassLength
|
15
|
+
class TunesClient < Spaceship::Client
|
16
|
+
# Legacy support
|
17
|
+
ITunesConnectError = Tunes::Error
|
18
|
+
ITunesConnectTemporaryError = Tunes::TemporaryError
|
19
|
+
ITunesConnectPotentialServerError = Tunes::PotentialServerError
|
20
|
+
|
21
|
+
attr_reader :du_client
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
super
|
25
|
+
|
26
|
+
@du_client = DUClient.new
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
# trailer preview screenshots are required to have a specific size
|
31
|
+
def video_preview_resolution_for(device, is_portrait)
|
32
|
+
resolutions = {
|
33
|
+
'iphone4' => [1136, 640],
|
34
|
+
'iphone6' => [1334, 750],
|
35
|
+
'iphone6Plus' => [2208, 1242],
|
36
|
+
'iphone58' => [2436, 1125],
|
37
|
+
'iphone65' => [2688, 1242],
|
38
|
+
'ipad' => [1024, 768],
|
39
|
+
'ipad105' => [2224, 1668],
|
40
|
+
'ipadPro' => [2732, 2048],
|
41
|
+
'ipadPro11' => [2388, 1668],
|
42
|
+
'ipadPro129' => [2732, 2048]
|
43
|
+
}
|
44
|
+
|
45
|
+
r = resolutions[device]
|
46
|
+
r = [r[1], r[0]] if is_portrait
|
47
|
+
r
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
#####################################################
|
52
|
+
# @!group Init and Login
|
53
|
+
#####################################################
|
54
|
+
|
55
|
+
def self.hostname
|
56
|
+
"https://appstoreconnect.apple.com/WebObjects/iTunesConnect.woa/"
|
57
|
+
end
|
58
|
+
|
59
|
+
# Shows a team selection for the user in the terminal. This should not be
|
60
|
+
# called on CI systems
|
61
|
+
#
|
62
|
+
# @param team_id (String) (optional): The ID of an App Store Connect team
|
63
|
+
# @param team_name (String) (optional): The name of an App Store Connect team
|
64
|
+
def select_team(team_id: nil, team_name: nil)
|
65
|
+
t_id = (team_id || ENV['FASTLANE_ITC_TEAM_ID'] || '').strip
|
66
|
+
t_name = (team_name || ENV['FASTLANE_ITC_TEAM_NAME'] || '').strip
|
67
|
+
|
68
|
+
if t_name.length > 0 && t_id.length.zero? # we prefer IDs over names, they are unique
|
69
|
+
puts("Looking for App Store Connect Team with name #{t_name}") if Spaceship::Globals.verbose?
|
70
|
+
|
71
|
+
teams.each do |t|
|
72
|
+
t_id = t['contentProvider']['contentProviderId'].to_s if t['contentProvider']['name'].casecmp(t_name).zero?
|
73
|
+
end
|
74
|
+
|
75
|
+
puts("Could not find team with name '#{t_name}', trying to fallback to default team") if t_id.length.zero?
|
76
|
+
end
|
77
|
+
|
78
|
+
t_id = teams.first['contentProvider']['contentProviderId'].to_s if teams.count == 1
|
79
|
+
|
80
|
+
if t_id.length > 0
|
81
|
+
puts("Looking for App Store Connect Team with ID #{t_id}") if Spaceship::Globals.verbose?
|
82
|
+
|
83
|
+
# actually set the team id here
|
84
|
+
self.team_id = t_id
|
85
|
+
return self.team_id
|
86
|
+
end
|
87
|
+
|
88
|
+
# user didn't specify a team... #thisiswhywecanthavenicethings
|
89
|
+
loop do
|
90
|
+
puts("Multiple #{'App Store Connect teams'.yellow} found, please enter the number of the team you want to use: ")
|
91
|
+
if ENV["FASTLANE_HIDE_TEAM_INFORMATION"].to_s.length == 0
|
92
|
+
puts("Note: to automatically choose the team, provide either the App Store Connect Team ID, or the Team Name in your fastlane/Appfile:")
|
93
|
+
puts("Alternatively you can pass the team name or team ID using the `FASTLANE_ITC_TEAM_ID` or `FASTLANE_ITC_TEAM_NAME` environment variable")
|
94
|
+
first_team = teams.first["contentProvider"]
|
95
|
+
puts("")
|
96
|
+
puts(" itc_team_id \"#{first_team['contentProviderId']}\"")
|
97
|
+
puts("")
|
98
|
+
puts("or")
|
99
|
+
puts("")
|
100
|
+
puts(" itc_team_name \"#{first_team['name']}\"")
|
101
|
+
puts("")
|
102
|
+
end
|
103
|
+
|
104
|
+
# We're not using highline here, as spaceship doesn't have a dependency to fastlane_core or highline
|
105
|
+
teams.each_with_index do |team, i|
|
106
|
+
puts("#{i + 1}) \"#{team['contentProvider']['name']}\" (#{team['contentProvider']['contentProviderId']})")
|
107
|
+
end
|
108
|
+
|
109
|
+
unless Spaceship::Client::UserInterface.interactive?
|
110
|
+
puts("Multiple teams found on App Store Connect, Your Terminal is running in non-interactive mode! Cannot continue from here.")
|
111
|
+
puts("Please check that you set FASTLANE_ITC_TEAM_ID or FASTLANE_ITC_TEAM_NAME to the right value.")
|
112
|
+
raise "Multiple App Store Connect Teams found; unable to choose, terminal not interactive!"
|
113
|
+
end
|
114
|
+
|
115
|
+
selected = ($stdin.gets || '').strip.to_i - 1
|
116
|
+
team_to_use = teams[selected] if selected >= 0
|
117
|
+
|
118
|
+
if team_to_use
|
119
|
+
self.team_id = team_to_use['contentProvider']['contentProviderId'].to_s # actually set the team id here
|
120
|
+
return self.team_id
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def send_login_request(user, password)
|
126
|
+
clear_user_cached_data
|
127
|
+
result = send_shared_login_request(user, password)
|
128
|
+
|
129
|
+
store_cookie
|
130
|
+
|
131
|
+
return result
|
132
|
+
end
|
133
|
+
|
134
|
+
# Sometimes we get errors or info nested in our data
|
135
|
+
# This method allows you to pass in a set of keys to check for
|
136
|
+
# along with the name of the sub_section of your original data
|
137
|
+
# where we should check
|
138
|
+
# Returns a mapping of keys to data array if we find anything, otherwise, empty map
|
139
|
+
def fetch_errors_in_data(data_section: nil, sub_section_name: nil, keys: nil)
|
140
|
+
if data_section && sub_section_name
|
141
|
+
sub_section = data_section[sub_section_name]
|
142
|
+
else
|
143
|
+
sub_section = data_section
|
144
|
+
end
|
145
|
+
|
146
|
+
unless sub_section
|
147
|
+
return {}
|
148
|
+
end
|
149
|
+
|
150
|
+
error_map = {}
|
151
|
+
keys.each do |key|
|
152
|
+
errors = sub_section.fetch(key, [])
|
153
|
+
error_map[key] = errors if errors.count > 0
|
154
|
+
end
|
155
|
+
return error_map
|
156
|
+
end
|
157
|
+
|
158
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
159
|
+
# If the response is coming from a flaky api, set flaky_api_call to true so we retry a little.
|
160
|
+
# Patience is a virtue.
|
161
|
+
def handle_itc_response(raw, flaky_api_call: false)
|
162
|
+
return unless raw
|
163
|
+
return unless raw.kind_of?(Hash)
|
164
|
+
|
165
|
+
data = raw['data'] || raw # sometimes it's with data, sometimes it isn't
|
166
|
+
|
167
|
+
error_keys = ["sectionErrorKeys", "validationErrors", "serviceErrors"]
|
168
|
+
info_keys = ["sectionInfoKeys", "sectionWarningKeys"]
|
169
|
+
error_and_info_keys_to_check = error_keys + info_keys
|
170
|
+
|
171
|
+
errors_in_data = fetch_errors_in_data(data_section: data, keys: error_and_info_keys_to_check)
|
172
|
+
errors_in_version_info = fetch_errors_in_data(data_section: data, sub_section_name: "versionInfo", keys: error_and_info_keys_to_check)
|
173
|
+
|
174
|
+
# If we have any errors or "info" we need to treat them as warnings or errors
|
175
|
+
if errors_in_data.count == 0 && errors_in_version_info.count == 0
|
176
|
+
logger.debug("Request was successful")
|
177
|
+
end
|
178
|
+
|
179
|
+
# We pass on the `current_language` so that the error message tells the user
|
180
|
+
# what language the error was caused in
|
181
|
+
handle_response_hash = lambda do |hash, current_language = nil|
|
182
|
+
errors = []
|
183
|
+
if hash.kind_of?(Hash)
|
184
|
+
current_language ||= hash["language"]
|
185
|
+
|
186
|
+
hash.each do |key, value|
|
187
|
+
errors += handle_response_hash.call(value, current_language)
|
188
|
+
|
189
|
+
next unless key == 'errorKeys' && value.kind_of?(Array) && value.count > 0
|
190
|
+
# Prepend the error with the language so it's easier to understand for the user
|
191
|
+
errors += value.collect do |current_error_message|
|
192
|
+
current_language ? "[#{current_language}]: #{current_error_message}" : current_error_message
|
193
|
+
end
|
194
|
+
end
|
195
|
+
elsif hash.kind_of?(Array)
|
196
|
+
hash.each do |value|
|
197
|
+
errors += handle_response_hash.call(value)
|
198
|
+
end
|
199
|
+
# else: We don't care about simple values
|
200
|
+
end
|
201
|
+
return errors
|
202
|
+
end
|
203
|
+
|
204
|
+
errors = handle_response_hash.call(data)
|
205
|
+
|
206
|
+
# Search at data level, as well as "versionInfo" level for errors
|
207
|
+
errors_in_data = fetch_errors_in_data(data_section: data, keys: error_keys)
|
208
|
+
errors_in_version_info = fetch_errors_in_data(data_section: data, sub_section_name: "versionInfo", keys: error_keys)
|
209
|
+
|
210
|
+
errors += errors_in_data.values if errors_in_data.values
|
211
|
+
errors += errors_in_version_info.values if errors_in_version_info.values
|
212
|
+
errors = errors.flat_map { |value| value }
|
213
|
+
|
214
|
+
# Sometimes there is a different kind of error in the JSON response
|
215
|
+
# e.g. {"warn"=>nil, "error"=>["operation_failed"], "info"=>nil}
|
216
|
+
different_error = raw.fetch('messages', {}).fetch('error', nil)
|
217
|
+
errors << different_error if different_error
|
218
|
+
|
219
|
+
if errors.count > 0 # they are separated by `.` by default
|
220
|
+
# Sample `error` content: [["Forbidden"]]
|
221
|
+
if errors.count == 1 && errors.first == "You haven't made any changes."
|
222
|
+
# This is a special error which we really don't care about
|
223
|
+
elsif errors.count == 1 && errors.first.include?("try again later")
|
224
|
+
raise ITunesConnectTemporaryError.new, errors.first
|
225
|
+
elsif errors.count == 1 && errors.first.include?("Forbidden")
|
226
|
+
raise_insufficient_permission_error!
|
227
|
+
elsif flaky_api_call
|
228
|
+
raise ITunesConnectPotentialServerError.new, errors.join(' ')
|
229
|
+
else
|
230
|
+
raise ITunesConnectError.new, errors.join(' ')
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# Search at data level, as well as "versionInfo" level for info and warnings
|
235
|
+
info_in_data = fetch_errors_in_data(data_section: data, keys: info_keys)
|
236
|
+
info_in_version_info = fetch_errors_in_data(data_section: data, sub_section_name: "versionInfo", keys: info_keys)
|
237
|
+
|
238
|
+
info_in_data.each do |info_key, info_value|
|
239
|
+
puts(info_value)
|
240
|
+
end
|
241
|
+
|
242
|
+
info_in_version_info.each do |info_key, info_value|
|
243
|
+
puts(info_value)
|
244
|
+
end
|
245
|
+
|
246
|
+
return data
|
247
|
+
end
|
248
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
249
|
+
|
250
|
+
#####################################################
|
251
|
+
# @!group Applications
|
252
|
+
#####################################################
|
253
|
+
|
254
|
+
def applications
|
255
|
+
r = request(:get, 'ra/apps/manageyourapps/summary/v2')
|
256
|
+
parse_response(r, 'data')['summaries']
|
257
|
+
end
|
258
|
+
|
259
|
+
def app_details(app_id)
|
260
|
+
r = request(:get, "ra/apps/#{app_id}/details")
|
261
|
+
parse_response(r, 'data')
|
262
|
+
end
|
263
|
+
|
264
|
+
def bundle_details(app_id)
|
265
|
+
r = request(:get, "ra/appbundles/metadetail/#{app_id}")
|
266
|
+
parse_response(r, 'data')
|
267
|
+
end
|
268
|
+
|
269
|
+
def update_app_details!(app_id, data)
|
270
|
+
r = request(:post) do |req|
|
271
|
+
req.url("ra/apps/#{app_id}/details")
|
272
|
+
req.body = data.to_json
|
273
|
+
req.headers['Content-Type'] = 'application/json'
|
274
|
+
end
|
275
|
+
|
276
|
+
handle_itc_response(r.body)
|
277
|
+
end
|
278
|
+
|
279
|
+
# Creates a new application on App Store Connect
|
280
|
+
# @param name (String): The name of your app as it will appear on the App Store.
|
281
|
+
# This can't be longer than 255 characters.
|
282
|
+
# @param primary_language (String): If localized app information isn't available in an
|
283
|
+
# App Store territory, the information from your primary language will be used instead.
|
284
|
+
# @param version *DEPRECATED: Use `Spaceship::Tunes::Application.ensure_version!` method instead*
|
285
|
+
# (String): The version number is shown on the App Store and should match the one you used in Xcode.
|
286
|
+
# @param sku (String): A unique ID for your app that is not visible on the App Store.
|
287
|
+
# @param bundle_id (String): The bundle ID must match the one you used in Xcode. It
|
288
|
+
# can't be changed after you submit your first build.
|
289
|
+
def create_application!(name: nil, primary_language: nil, version: nil, sku: nil, bundle_id: nil, bundle_id_suffix: nil, company_name: nil, platform: nil, platforms: nil, itunes_connect_users: nil)
|
290
|
+
puts("The `version` parameter is deprecated. Use `Spaceship::Tunes::Application.ensure_version!` method instead") if version
|
291
|
+
|
292
|
+
# First, we need to fetch the data from Apple, which we then modify with the user's values
|
293
|
+
primary_language ||= "English"
|
294
|
+
platform ||= "ios"
|
295
|
+
r = request(:get, "ra/apps/create/v2/?platformString=#{platform}")
|
296
|
+
data = parse_response(r, 'data')
|
297
|
+
|
298
|
+
# Now fill in the values we have
|
299
|
+
# some values are nil, that's why there is a hash
|
300
|
+
data['name'] = { value: name }
|
301
|
+
data['bundleId'] = { value: bundle_id }
|
302
|
+
data['primaryLanguage'] = { value: primary_language }
|
303
|
+
data['primaryLocaleCode'] = { value: primary_language.to_itc_locale }
|
304
|
+
data['vendorId'] = { value: sku }
|
305
|
+
data['bundleIdSuffix'] = { value: bundle_id_suffix }
|
306
|
+
data['companyName'] = { value: company_name } if company_name
|
307
|
+
data['enabledPlatformsForCreation'] = { value: [platform] }
|
308
|
+
|
309
|
+
data['initialPlatform'] = platform
|
310
|
+
data['enabledPlatformsForCreation'] = { value: platforms || [platform] }
|
311
|
+
|
312
|
+
unless itunes_connect_users.nil?
|
313
|
+
data['iTunesConnectUsers']['grantedAllUsers'] = false
|
314
|
+
data['iTunesConnectUsers']['grantedUsers'] = data['iTunesConnectUsers']['availableUsers'].select { |user| itunes_connect_users.include?(user['username']) }
|
315
|
+
end
|
316
|
+
|
317
|
+
# Now send back the modified hash
|
318
|
+
r = request(:post) do |req|
|
319
|
+
req.url('ra/apps/create/v2')
|
320
|
+
req.body = data.to_json
|
321
|
+
req.headers['Content-Type'] = 'application/json'
|
322
|
+
end
|
323
|
+
|
324
|
+
data = parse_response(r, 'data')
|
325
|
+
handle_itc_response(data)
|
326
|
+
end
|
327
|
+
|
328
|
+
def create_version!(app_id, version_number, platform = 'ios')
|
329
|
+
r = request(:post) do |req|
|
330
|
+
req.url("ra/apps/#{app_id}/platforms/#{platform}/versions/create/")
|
331
|
+
req.body = {
|
332
|
+
version: {
|
333
|
+
value: version_number.to_s
|
334
|
+
}
|
335
|
+
}.to_json
|
336
|
+
req.headers['Content-Type'] = 'application/json'
|
337
|
+
end
|
338
|
+
|
339
|
+
data = parse_response(r, 'data')
|
340
|
+
handle_itc_response(data)
|
341
|
+
end
|
342
|
+
|
343
|
+
def get_available_bundle_ids(platform: nil)
|
344
|
+
platform ||= "ios"
|
345
|
+
r = request(:get, "ra/apps/create/v2/?platformString=#{platform}")
|
346
|
+
data = parse_response(r, 'data')
|
347
|
+
return data['bundleIds'].keys
|
348
|
+
end
|
349
|
+
|
350
|
+
def get_resolution_center(app_id, platform)
|
351
|
+
r = request(:get, "ra/apps/#{app_id}/platforms/#{platform}/resolutionCenter?v=latest")
|
352
|
+
parse_response(r, 'data')
|
353
|
+
end
|
354
|
+
|
355
|
+
def post_resolution_center(app_id, platform, thread_id, version_id, version_number, from, message_body)
|
356
|
+
r = request(:post) do |req|
|
357
|
+
req.url("ra/apps/#{app_id}/platforms/#{platform}/resolutionCenter")
|
358
|
+
req.body = {
|
359
|
+
appNotes: {
|
360
|
+
threads: [{
|
361
|
+
id: thread_id,
|
362
|
+
versionId: version_id,
|
363
|
+
version: version_number,
|
364
|
+
messages: [{
|
365
|
+
from: from,
|
366
|
+
date: DateTime.now.strftime('%Q'),
|
367
|
+
body: message_body,
|
368
|
+
tokens: []
|
369
|
+
}]
|
370
|
+
}]
|
371
|
+
}
|
372
|
+
}.to_json
|
373
|
+
req.headers['Content-Type'] = 'application/json'
|
374
|
+
end
|
375
|
+
|
376
|
+
data = parse_response(r, 'data')
|
377
|
+
handle_itc_response(data)
|
378
|
+
end
|
379
|
+
|
380
|
+
def get_ratings(app_id, platform, version_id = '', storefront = '')
|
381
|
+
# if storefront or version_id is empty api fails
|
382
|
+
rating_url = "ra/apps/#{app_id}/platforms/#{platform}/reviews/summary"
|
383
|
+
params = {}
|
384
|
+
params['storefront'] = storefront unless storefront.empty?
|
385
|
+
params['version_id'] = version_id unless version_id.empty?
|
386
|
+
|
387
|
+
r = request(:get, rating_url, params)
|
388
|
+
parse_response(r, 'data')
|
389
|
+
end
|
390
|
+
|
391
|
+
def get_reviews(app_id, platform, storefront, version_id, upto_date = nil)
|
392
|
+
index = 0
|
393
|
+
per_page = 100 # apple default
|
394
|
+
all_reviews = []
|
395
|
+
|
396
|
+
upto_date = Time.parse(upto_date) unless upto_date.nil?
|
397
|
+
|
398
|
+
loop do
|
399
|
+
rating_url = "ra/apps/#{app_id}/platforms/#{platform}/reviews?"
|
400
|
+
rating_url << "sort=REVIEW_SORT_ORDER_MOST_RECENT"
|
401
|
+
rating_url << "&index=#{index}"
|
402
|
+
rating_url << "&storefront=#{storefront}" unless storefront.empty?
|
403
|
+
rating_url << "&versionId=#{version_id}" unless version_id.empty?
|
404
|
+
|
405
|
+
r = request(:get, rating_url)
|
406
|
+
all_reviews.concat(parse_response(r, 'data')['reviews'])
|
407
|
+
|
408
|
+
# The following lines throw errors when there are no reviews so exit out of the loop before them if the app has no reviews
|
409
|
+
break if all_reviews.count == 0
|
410
|
+
|
411
|
+
last_review_date = Time.at(all_reviews[-1]['value']['lastModified'] / 1000)
|
412
|
+
|
413
|
+
if upto_date && last_review_date < upto_date
|
414
|
+
all_reviews = all_reviews.select { |review| Time.at(review['value']['lastModified'] / 1000) > upto_date }
|
415
|
+
break
|
416
|
+
end
|
417
|
+
|
418
|
+
if all_reviews.count < parse_response(r, 'data')['reviewCount']
|
419
|
+
index += per_page
|
420
|
+
else
|
421
|
+
break
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
all_reviews
|
426
|
+
end
|
427
|
+
|
428
|
+
#####################################################
|
429
|
+
# @!group AppVersions
|
430
|
+
#####################################################
|
431
|
+
|
432
|
+
def app_version(app_id, is_live, platform: nil)
|
433
|
+
raise "app_id is required" unless app_id
|
434
|
+
|
435
|
+
# First we need to fetch the IDs for the edit / live version
|
436
|
+
r = request(:get, "ra/apps/#{app_id}/overview")
|
437
|
+
platforms = parse_response(r, 'data')['platforms']
|
438
|
+
|
439
|
+
platform = Spaceship::Tunes::AppVersionCommon.find_platform(platforms, search_platform: platform)
|
440
|
+
return nil unless platform
|
441
|
+
|
442
|
+
version_id = Spaceship::Tunes::AppVersionCommon.find_version_id(platform, is_live)
|
443
|
+
return nil unless version_id
|
444
|
+
|
445
|
+
version_platform = platform['platformString']
|
446
|
+
|
447
|
+
app_version_data(app_id, version_platform: version_platform, version_id: version_id)
|
448
|
+
end
|
449
|
+
|
450
|
+
def app_version_data(app_id, version_platform: nil, version_id: nil)
|
451
|
+
raise "app_id is required" unless app_id
|
452
|
+
raise "version_platform is required" unless version_platform
|
453
|
+
raise "version_id is required" unless version_id
|
454
|
+
|
455
|
+
r = request(:get, "ra/apps/#{app_id}/platforms/#{version_platform}/versions/#{version_id}")
|
456
|
+
parse_response(r, 'data')
|
457
|
+
end
|
458
|
+
|
459
|
+
def update_app_version!(app_id, version_id, data)
|
460
|
+
raise "app_id is required" unless app_id
|
461
|
+
raise "version_id is required" unless version_id.to_i > 0
|
462
|
+
|
463
|
+
with_tunes_retry do
|
464
|
+
r = request(:post) do |req|
|
465
|
+
req.url("ra/apps/#{app_id}/platforms/ios/versions/#{version_id}")
|
466
|
+
req.body = data.to_json
|
467
|
+
req.headers['Content-Type'] = 'application/json'
|
468
|
+
end
|
469
|
+
|
470
|
+
handle_itc_response(r.body, flaky_api_call: true)
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
#####################################################
|
475
|
+
# @!group Members
|
476
|
+
#####################################################
|
477
|
+
|
478
|
+
def members
|
479
|
+
r = request(:get, "ra/users/itc")
|
480
|
+
parse_response(r, 'data')["users"]
|
481
|
+
end
|
482
|
+
|
483
|
+
def reinvite_member(email)
|
484
|
+
request(:post, "ra/users/itc/#{email}/resendInvitation")
|
485
|
+
end
|
486
|
+
|
487
|
+
def delete_member!(user_id, email)
|
488
|
+
payload = []
|
489
|
+
payload << {
|
490
|
+
dsId: user_id,
|
491
|
+
email: email
|
492
|
+
}
|
493
|
+
request(:post) do |req|
|
494
|
+
req.url("ra/users/itc/delete")
|
495
|
+
req.body = payload.to_json
|
496
|
+
req.headers['Content-Type'] = 'application/json'
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
def create_member!(firstname: nil, lastname: nil, email_address: nil, roles: [], apps: [])
|
501
|
+
r = request(:get, "ra/users/itc/create")
|
502
|
+
data = parse_response(r, 'data')
|
503
|
+
|
504
|
+
data["user"]["firstName"] = { value: firstname }
|
505
|
+
data["user"]["lastName"] = { value: lastname }
|
506
|
+
data["user"]["emailAddress"] = { value: email_address }
|
507
|
+
|
508
|
+
roles << "admin" if roles.length == 0
|
509
|
+
|
510
|
+
data["user"]["roles"] = []
|
511
|
+
roles.each do |role|
|
512
|
+
# find role from template
|
513
|
+
data["roles"].each do |template_role|
|
514
|
+
if template_role["value"]["name"] == role
|
515
|
+
data["user"]["roles"] << template_role
|
516
|
+
end
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
if apps.length == 0
|
521
|
+
data["user"]["userSoftwares"] = { value: { grantAllSoftware: true, grantedSoftwareAdamIds: [] } }
|
522
|
+
else
|
523
|
+
data["user"]["userSoftwares"] = { value: { grantAllSoftware: false, grantedSoftwareAdamIds: apps } }
|
524
|
+
end
|
525
|
+
|
526
|
+
# send the changes back to Apple
|
527
|
+
r = request(:post) do |req|
|
528
|
+
req.url("ra/users/itc/create")
|
529
|
+
req.body = data.to_json
|
530
|
+
req.headers['Content-Type'] = 'application/json'
|
531
|
+
end
|
532
|
+
handle_itc_response(r.body)
|
533
|
+
end
|
534
|
+
|
535
|
+
def update_member_roles!(member, roles: [], apps: [])
|
536
|
+
r = request(:get, "ra/users/itc/#{member.user_id}/roles")
|
537
|
+
data = parse_response(r, 'data')
|
538
|
+
|
539
|
+
roles << "admin" if roles.length == 0
|
540
|
+
|
541
|
+
data["user"]["roles"] = []
|
542
|
+
roles.each do |role|
|
543
|
+
# find role from template
|
544
|
+
data["roles"].each do |template_role|
|
545
|
+
if template_role["value"]["name"] == role
|
546
|
+
data["user"]["roles"] << template_role
|
547
|
+
end
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
if apps.length == 0
|
552
|
+
data["user"]["userSoftwares"] = { value: { grantAllSoftware: true, grantedSoftwareAdamIds: [] } }
|
553
|
+
else
|
554
|
+
data["user"]["userSoftwares"] = { value: { grantAllSoftware: false, grantedSoftwareAdamIds: apps } }
|
555
|
+
end
|
556
|
+
|
557
|
+
# send the changes back to Apple
|
558
|
+
r = request(:post) do |req|
|
559
|
+
req.url("ra/users/itc/#{member.user_id}/roles")
|
560
|
+
req.body = data.to_json
|
561
|
+
req.headers['Content-Type'] = 'application/json'
|
562
|
+
end
|
563
|
+
handle_itc_response(r.body)
|
564
|
+
end
|
565
|
+
|
566
|
+
#####################################################
|
567
|
+
# @!group AppAnalytics
|
568
|
+
#####################################################
|
569
|
+
|
570
|
+
def time_series_analytics(app_ids, measures, start_time, end_time, frequency, view_by)
|
571
|
+
data = {
|
572
|
+
adamId: app_ids,
|
573
|
+
dimensionFilters: [],
|
574
|
+
endTime: end_time,
|
575
|
+
frequency: frequency,
|
576
|
+
group: group_for_view_by(view_by, measures),
|
577
|
+
measures: measures,
|
578
|
+
startTime: start_time
|
579
|
+
}
|
580
|
+
|
581
|
+
r = request(:post) do |req|
|
582
|
+
req.url("https://analytics.itunes.apple.com/analytics/api/v1/data/time-series")
|
583
|
+
req.body = data.to_json
|
584
|
+
req.headers['Content-Type'] = 'application/json'
|
585
|
+
req.headers['X-Requested-By'] = 'analytics.itunes.apple.com'
|
586
|
+
end
|
587
|
+
|
588
|
+
data = parse_response(r)
|
589
|
+
end
|
590
|
+
|
591
|
+
#####################################################
|
592
|
+
# @!group Pricing
|
593
|
+
#####################################################
|
594
|
+
|
595
|
+
def update_price_tier!(app_id, price_tier)
|
596
|
+
r = request(:get, "ra/apps/#{app_id}/pricing/intervals")
|
597
|
+
data = parse_response(r, 'data')
|
598
|
+
|
599
|
+
# preOrder isn't needed for for the request and has some
|
600
|
+
# values that can cause a failure (invalid dates) so we are removing it
|
601
|
+
data.delete('preOrder')
|
602
|
+
|
603
|
+
first_price = (data["pricingIntervalsFieldTO"]["value"] || []).count == 0 # first price
|
604
|
+
data["pricingIntervalsFieldTO"]["value"] ||= []
|
605
|
+
data["pricingIntervalsFieldTO"]["value"] << {} if data["pricingIntervalsFieldTO"]["value"].count == 0
|
606
|
+
data["pricingIntervalsFieldTO"]["value"].first["tierStem"] = price_tier.to_s
|
607
|
+
|
608
|
+
effective_date = (first_price ? nil : Time.now.to_i * 1000)
|
609
|
+
data["pricingIntervalsFieldTO"]["value"].first["priceTierEffectiveDate"] = effective_date
|
610
|
+
data["pricingIntervalsFieldTO"]["value"].first["priceTierEndDate"] = nil
|
611
|
+
data["countriesChanged"] = first_price
|
612
|
+
data["theWorld"] = true
|
613
|
+
|
614
|
+
if first_price # first price, need to set all countries
|
615
|
+
data["countries"] = supported_countries.collect do |c|
|
616
|
+
c.delete('region') # we don't care about le region
|
617
|
+
c
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
621
|
+
# send the changes back to Apple
|
622
|
+
r = request(:post) do |req|
|
623
|
+
req.url("ra/apps/#{app_id}/pricing/intervals")
|
624
|
+
req.body = data.to_json
|
625
|
+
req.headers['Content-Type'] = 'application/json'
|
626
|
+
end
|
627
|
+
handle_itc_response(r.body)
|
628
|
+
end
|
629
|
+
|
630
|
+
def transform_to_raw_pricing_intervals(app_id = nil, purchase_id = nil, pricing_intervals = 5, subscription_price_target = nil)
|
631
|
+
intervals_array = []
|
632
|
+
if pricing_intervals
|
633
|
+
intervals_array = pricing_intervals.map do |interval|
|
634
|
+
{
|
635
|
+
"value" => {
|
636
|
+
"tierStem" => interval[:tier],
|
637
|
+
"priceTierEffectiveDate" => interval[:begin_date],
|
638
|
+
"priceTierEndDate" => interval[:end_date],
|
639
|
+
"country" => interval[:country] || "WW",
|
640
|
+
"grandfathered" => interval[:grandfathered]
|
641
|
+
}
|
642
|
+
}
|
643
|
+
end
|
644
|
+
end
|
645
|
+
|
646
|
+
if subscription_price_target
|
647
|
+
pricing_calculator = iap_subscription_pricing_target(app_id: app_id, purchase_id: purchase_id, currency: subscription_price_target[:currency], tier: subscription_price_target[:tier])
|
648
|
+
intervals_array = pricing_calculator.map do |language_code, value|
|
649
|
+
existing_interval =
|
650
|
+
if pricing_intervals
|
651
|
+
pricing_intervals.find { |interval| interval[:country] == language_code }
|
652
|
+
end
|
653
|
+
grandfathered =
|
654
|
+
if existing_interval
|
655
|
+
existing_interval[:grandfathered].clone
|
656
|
+
else
|
657
|
+
{ "value" => "FUTURE_NONE" }
|
658
|
+
end
|
659
|
+
|
660
|
+
{
|
661
|
+
"value" => {
|
662
|
+
"tierStem" => value["tierStem"],
|
663
|
+
"priceTierEffectiveDate" => value["priceTierEffectiveDate"],
|
664
|
+
"priceTierEndDate" => value["priceTierEndDate"],
|
665
|
+
"country" => language_code,
|
666
|
+
"grandfathered" => grandfathered
|
667
|
+
}
|
668
|
+
}
|
669
|
+
end
|
670
|
+
end
|
671
|
+
|
672
|
+
intervals_array
|
673
|
+
end
|
674
|
+
|
675
|
+
def price_tier(app_id)
|
676
|
+
r = request(:get, "ra/apps/#{app_id}/pricing/intervals")
|
677
|
+
data = parse_response(r, 'data')
|
678
|
+
|
679
|
+
begin
|
680
|
+
data["pricingIntervalsFieldTO"]["value"].first["tierStem"]
|
681
|
+
rescue
|
682
|
+
nil
|
683
|
+
end
|
684
|
+
end
|
685
|
+
|
686
|
+
# Returns an array of all available pricing tiers
|
687
|
+
#
|
688
|
+
# @note Although this information is publicly available, the current spaceship implementation requires you to have a logged in client to access it
|
689
|
+
#
|
690
|
+
# @return [Array] the PricingTier objects (Spaceship::Tunes::PricingTier)
|
691
|
+
# [{
|
692
|
+
# "tierStem": "0",
|
693
|
+
# "tierName": "Free",
|
694
|
+
# "pricingInfo": [{
|
695
|
+
# "country": "United States",
|
696
|
+
# "countryCode": "US",
|
697
|
+
# "currencySymbol": "$",
|
698
|
+
# "currencyCode": "USD",
|
699
|
+
# "wholesalePrice": 0.0,
|
700
|
+
# "retailPrice": 0.0,
|
701
|
+
# "fRetailPrice": "$0.00",
|
702
|
+
# "fWholesalePrice": "$0.00"
|
703
|
+
# }, {
|
704
|
+
# ...
|
705
|
+
# }, {
|
706
|
+
# ...
|
707
|
+
def pricing_tiers
|
708
|
+
@pricing_tiers ||= begin
|
709
|
+
r = request(:get, 'ra/apps/pricing/matrix')
|
710
|
+
data = parse_response(r, 'data')['pricingTiers']
|
711
|
+
data.map { |tier| Spaceship::Tunes::PricingTier.factory(tier) }
|
712
|
+
end
|
713
|
+
end
|
714
|
+
|
715
|
+
#####################################################
|
716
|
+
# @!group Availability
|
717
|
+
#####################################################
|
718
|
+
# Updates the availability
|
719
|
+
#
|
720
|
+
# @note Although this information is publicly available, the current spaceship implementation requires you to have a logged in client to access it
|
721
|
+
# @param app_id (String): The id of your app
|
722
|
+
# @param availability (Availability): The availability update
|
723
|
+
#
|
724
|
+
# @return [Spaceship::Tunes::Availability] the new Availability
|
725
|
+
def update_availability!(app_id, availability)
|
726
|
+
r = request(:get, "ra/apps/#{app_id}/pricing/intervals")
|
727
|
+
data = parse_response(r, 'data')
|
728
|
+
|
729
|
+
data["countriesChanged"] = true
|
730
|
+
data["countries"] = availability.territories.map { |territory| { 'code' => territory.code } }
|
731
|
+
data["theWorld"] = availability.include_future_territories.nil? ? true : availability.include_future_territories
|
732
|
+
|
733
|
+
# InitializespreOrder (if needed)
|
734
|
+
data["preOrder"] ||= {}
|
735
|
+
|
736
|
+
# Sets app_available_date to nil if cleared_for_preorder if false
|
737
|
+
# This is need for apps that have never set either of these before
|
738
|
+
# API will error out if cleared_for_preorder is false and app_available_date has a date
|
739
|
+
cleared_for_preorder = availability.cleared_for_preorder
|
740
|
+
app_available_date = cleared_for_preorder ? availability.app_available_date : nil
|
741
|
+
data["b2bAppEnabled"] = availability.b2b_app_enabled
|
742
|
+
data["educationalDiscount"] = availability.educational_discount
|
743
|
+
data["preOrder"]["clearedForPreOrder"] = { "value" => cleared_for_preorder, "isEditable" => true, "isRequired" => true, "errorKeys" => nil }
|
744
|
+
data["preOrder"]["appAvailableDate"] = { "value" => app_available_date, "isEditable" => true, "isRequired" => true, "errorKeys" => nil }
|
745
|
+
data["b2bUsers"] = availability.b2b_app_enabled ? availability.b2b_users.map { |user| { "value" => { "add" => user.add, "delete" => user.delete, "dsUsername" => user.ds_username } } } : []
|
746
|
+
data["b2bOrganizations"] = availability.b2b_app_enabled ? availability.b2b_organizations.map { |org| { "value" => { "type" => org.type, "depCustomerId" => org.dep_customer_id, "organizationId" => org.dep_organization_id, "name" => org.name } } } : []
|
747
|
+
# send the changes back to Apple
|
748
|
+
r = request(:post) do |req|
|
749
|
+
req.url("ra/apps/#{app_id}/pricing/intervals")
|
750
|
+
req.body = data.to_json
|
751
|
+
req.headers['Content-Type'] = 'application/json'
|
752
|
+
end
|
753
|
+
handle_itc_response(r.body)
|
754
|
+
data = parse_response(r, 'data')
|
755
|
+
Spaceship::Tunes::Availability.factory(data)
|
756
|
+
end
|
757
|
+
|
758
|
+
def availability(app_id)
|
759
|
+
r = request(:get, "ra/apps/#{app_id}/pricing/intervals")
|
760
|
+
data = parse_response(r, 'data')
|
761
|
+
Spaceship::Tunes::Availability.factory(data)
|
762
|
+
end
|
763
|
+
|
764
|
+
# Returns an array of all supported territories
|
765
|
+
#
|
766
|
+
# @note Although this information is publicly available, the current spaceship implementation requires you to have a logged in client to access it
|
767
|
+
#
|
768
|
+
# @return [Array] the Territory objects (Spaceship::Tunes::Territory)
|
769
|
+
def supported_territories
|
770
|
+
data = supported_countries
|
771
|
+
data.map { |country| Spaceship::Tunes::Territory.factory(country) }
|
772
|
+
end
|
773
|
+
|
774
|
+
# An array of supported countries
|
775
|
+
# [{
|
776
|
+
# "code": "AL",
|
777
|
+
# "name": "Albania",
|
778
|
+
# "region": "Europe"
|
779
|
+
# }, {
|
780
|
+
# ...
|
781
|
+
def supported_countries
|
782
|
+
r = request(:get, "ra/apps/pricing/supportedCountries")
|
783
|
+
parse_response(r, 'data')
|
784
|
+
end
|
785
|
+
|
786
|
+
def available_languages
|
787
|
+
r = request(:get, "ra/ref")
|
788
|
+
parse_response(r, 'data')['detailLocales']
|
789
|
+
end
|
790
|
+
|
791
|
+
#####################################################
|
792
|
+
# @!group App Icons
|
793
|
+
#####################################################
|
794
|
+
# Uploads a large icon
|
795
|
+
# @param app_version (AppVersion): The version of your app
|
796
|
+
# @param upload_image (UploadFile): The icon to upload
|
797
|
+
# @return [JSON] the response
|
798
|
+
def upload_large_icon(app_version, upload_image)
|
799
|
+
raise "app_version is required" unless app_version
|
800
|
+
raise "upload_image is required" unless upload_image
|
801
|
+
|
802
|
+
du_client.upload_large_icon(app_version, upload_image, content_provider_id, sso_token_for_image)
|
803
|
+
end
|
804
|
+
|
805
|
+
# Uploads a watch icon
|
806
|
+
# @param app_version (AppVersion): The version of your app
|
807
|
+
# @param upload_image (UploadFile): The icon to upload
|
808
|
+
# @return [JSON] the response
|
809
|
+
def upload_watch_icon(app_version, upload_image)
|
810
|
+
raise "app_version is required" unless app_version
|
811
|
+
raise "upload_image is required" unless upload_image
|
812
|
+
|
813
|
+
du_client.upload_watch_icon(app_version, upload_image, content_provider_id, sso_token_for_image)
|
814
|
+
end
|
815
|
+
|
816
|
+
# Uploads an In-App-Purchase Promotional image
|
817
|
+
# @param upload_image (UploadFile): The icon to upload
|
818
|
+
# @return [JSON] the image data, ready to be added to an In-App-Purchase
|
819
|
+
def upload_purchase_merch_screenshot(app_id, upload_image)
|
820
|
+
data = du_client.upload_purchase_merch_screenshot(app_id, upload_image, content_provider_id, sso_token_for_image)
|
821
|
+
{
|
822
|
+
"images" => [
|
823
|
+
{
|
824
|
+
"id" => nil,
|
825
|
+
"image" => {
|
826
|
+
"value" => {
|
827
|
+
"assetToken" => data["token"],
|
828
|
+
"originalFileName" => upload_image.file_name,
|
829
|
+
"height" => data["height"],
|
830
|
+
"width" => data["width"],
|
831
|
+
"checksum" => data["md5"]
|
832
|
+
},
|
833
|
+
"isEditable" => true,
|
834
|
+
"isREquired" => false,
|
835
|
+
"errorKeys" => nil
|
836
|
+
},
|
837
|
+
"status" => "proposed"
|
838
|
+
}
|
839
|
+
],
|
840
|
+
"showByDefault" => true,
|
841
|
+
"isActive" => false
|
842
|
+
}
|
843
|
+
end
|
844
|
+
|
845
|
+
# Uploads an In-App-Purchase Review screenshot
|
846
|
+
# @param app_id (AppId): The id of the app
|
847
|
+
# @param upload_image (UploadFile): The icon to upload
|
848
|
+
# @return [JSON] the screenshot data, ready to be added to an In-App-Purchase
|
849
|
+
def upload_purchase_review_screenshot(app_id, upload_image)
|
850
|
+
data = du_client.upload_purchase_review_screenshot(app_id, upload_image, content_provider_id, sso_token_for_image)
|
851
|
+
{
|
852
|
+
"value" => {
|
853
|
+
"assetToken" => data["token"],
|
854
|
+
"sortOrder" => 0,
|
855
|
+
"type" => du_client.get_picture_type(upload_image),
|
856
|
+
"originalFileName" => upload_image.file_name,
|
857
|
+
"size" => data["length"],
|
858
|
+
"height" => data["height"],
|
859
|
+
"width" => data["width"],
|
860
|
+
"checksum" => data["md5"]
|
861
|
+
}
|
862
|
+
}
|
863
|
+
end
|
864
|
+
|
865
|
+
# Uploads a screenshot
|
866
|
+
# @param app_version (AppVersion): The version of your app
|
867
|
+
# @param upload_image (UploadFile): The image to upload
|
868
|
+
# @param device (string): The target device
|
869
|
+
# @param is_messages (Bool): True if the screenshot is for iMessage
|
870
|
+
# @return [JSON] the response
|
871
|
+
def upload_screenshot(app_version, upload_image, device, is_messages)
|
872
|
+
raise "app_version is required" unless app_version
|
873
|
+
raise "upload_image is required" unless upload_image
|
874
|
+
raise "device is required" unless device
|
875
|
+
|
876
|
+
du_client.upload_screenshot(app_version, upload_image, content_provider_id, sso_token_for_image, device, is_messages)
|
877
|
+
end
|
878
|
+
|
879
|
+
# Uploads an iMessage screenshot
|
880
|
+
# @param app_version (AppVersion): The version of your app
|
881
|
+
# @param upload_image (UploadFile): The image to upload
|
882
|
+
# @param device (string): The target device
|
883
|
+
# @return [JSON] the response
|
884
|
+
def upload_messages_screenshot(app_version, upload_image, device)
|
885
|
+
raise "app_version is required" unless app_version
|
886
|
+
raise "upload_image is required" unless upload_image
|
887
|
+
raise "device is required" unless device
|
888
|
+
|
889
|
+
du_client.upload_messages_screenshot(app_version, upload_image, content_provider_id, sso_token_for_image, device)
|
890
|
+
end
|
891
|
+
|
892
|
+
# Uploads the transit app file
|
893
|
+
# @param app_version (AppVersion): The version of your app
|
894
|
+
# @param upload_file (UploadFile): The image to upload
|
895
|
+
# @return [JSON] the response
|
896
|
+
def upload_geojson(app_version, upload_file)
|
897
|
+
raise "app_version is required" unless app_version
|
898
|
+
raise "upload_file is required" unless upload_file
|
899
|
+
|
900
|
+
du_client.upload_geojson(app_version, upload_file, content_provider_id, sso_token_for_image)
|
901
|
+
end
|
902
|
+
|
903
|
+
# Uploads the transit app file
|
904
|
+
# @param app_version (AppVersion): The version of your app
|
905
|
+
# @param upload_trailer (UploadFile): The trailer to upload
|
906
|
+
# @return [JSON] the response
|
907
|
+
def upload_trailer(app_version, upload_trailer)
|
908
|
+
raise "app_version is required" unless app_version
|
909
|
+
raise "upload_trailer is required" unless upload_trailer
|
910
|
+
|
911
|
+
du_client.upload_trailer(app_version, upload_trailer, content_provider_id, sso_token_for_video)
|
912
|
+
end
|
913
|
+
|
914
|
+
# Uploads the trailer preview
|
915
|
+
# @param app_version (AppVersion): The version of your app
|
916
|
+
# @param upload_trailer_preview (UploadFile): The trailer preview to upload
|
917
|
+
# @param device (string): The target device
|
918
|
+
# @return [JSON] the response
|
919
|
+
def upload_trailer_preview(app_version, upload_trailer_preview, device)
|
920
|
+
raise "app_version is required" unless app_version
|
921
|
+
raise "upload_trailer_preview is required" unless upload_trailer_preview
|
922
|
+
raise "device is required" unless device
|
923
|
+
|
924
|
+
du_client.upload_trailer_preview(app_version, upload_trailer_preview, content_provider_id, sso_token_for_image, device)
|
925
|
+
end
|
926
|
+
|
927
|
+
#####################################################
|
928
|
+
# @!review attachment file
|
929
|
+
#####################################################
|
930
|
+
# Uploads a attachment file
|
931
|
+
# @param app_version (AppVersion): The version of your app(must be edit version)
|
932
|
+
# @param upload_attachment_file (file): File to upload
|
933
|
+
# @return [JSON] the response
|
934
|
+
def upload_app_review_attachment(app_version, upload_attachment_file)
|
935
|
+
raise "app_version is required" unless app_version
|
936
|
+
raise "app_version must be live version" if app_version.is_live?
|
937
|
+
raise "upload_attachment_file is required" unless upload_attachment_file
|
938
|
+
|
939
|
+
du_client.upload_app_review_attachment(app_version, upload_attachment_file, content_provider_id, sso_token_for_image)
|
940
|
+
end
|
941
|
+
|
942
|
+
# Fetches the App Version Reference information from ITC
|
943
|
+
# @return [AppVersionRef] the response
|
944
|
+
def ref_data
|
945
|
+
r = request(:get, '/WebObjects/iTunesConnect.woa/ra/apps/version/ref')
|
946
|
+
data = parse_response(r, 'data')
|
947
|
+
Spaceship::Tunes::AppVersionRef.factory(data)
|
948
|
+
end
|
949
|
+
|
950
|
+
# Fetches the User Detail information from ITC. This gets called often and almost never changes
|
951
|
+
# so we cache it
|
952
|
+
# @return [UserDetail] the response
|
953
|
+
def user_detail_data
|
954
|
+
@_cached_user_detail_data ||= Spaceship::Tunes::UserDetail.factory(user_details_data, self)
|
955
|
+
end
|
956
|
+
|
957
|
+
#####################################################
|
958
|
+
# @!group CandiateBuilds
|
959
|
+
#####################################################
|
960
|
+
|
961
|
+
def candidate_builds(app_id, version_id)
|
962
|
+
r = request(:get, "ra/apps/#{app_id}/versions/#{version_id}/candidateBuilds")
|
963
|
+
parse_response(r, 'data')['builds']
|
964
|
+
end
|
965
|
+
|
966
|
+
#####################################################
|
967
|
+
# @!group Build Trains
|
968
|
+
#####################################################
|
969
|
+
|
970
|
+
# rubocop:disable Metrics/BlockNesting
|
971
|
+
# @param (testing_type) internal or external
|
972
|
+
def build_trains(app_id, testing_type, tries = 5, platform: nil)
|
973
|
+
raise "app_id is required" unless app_id
|
974
|
+
url = "ra/apps/#{app_id}/trains/?testingType=#{testing_type}"
|
975
|
+
url += "&platform=#{platform}" unless platform.nil?
|
976
|
+
r = request(:get, url)
|
977
|
+
return parse_response(r, 'data')
|
978
|
+
rescue Spaceship::Client::UnexpectedResponse => ex
|
979
|
+
# Build trains fail randomly very often
|
980
|
+
# we need to catch those errors and retry
|
981
|
+
# https://github.com/fastlane/fastlane/issues/6419
|
982
|
+
retry_error_messages = [
|
983
|
+
"ITC.response.error.OPERATION_FAILED",
|
984
|
+
"Internal Server Error",
|
985
|
+
"Service Unavailable"
|
986
|
+
].freeze
|
987
|
+
|
988
|
+
if retry_error_messages.any? { |message| ex.to_s.include?(message) }
|
989
|
+
tries -= 1
|
990
|
+
if tries > 0
|
991
|
+
logger.warn("Received temporary server error from App Store Connect. Retrying the request...")
|
992
|
+
sleep(3) unless Object.const_defined?("SpecHelper")
|
993
|
+
retry
|
994
|
+
end
|
995
|
+
end
|
996
|
+
|
997
|
+
raise Spaceship::Client::UnexpectedResponse, "Temporary App Store Connect error: #{ex}"
|
998
|
+
end
|
999
|
+
# rubocop:enable Metrics/BlockNesting
|
1000
|
+
|
1001
|
+
def update_build_trains!(app_id, testing_type, data)
|
1002
|
+
raise "app_id is required" unless app_id
|
1003
|
+
|
1004
|
+
# The request fails if this key is present in the data
|
1005
|
+
data.delete("dailySubmissionCountByPlatform")
|
1006
|
+
|
1007
|
+
r = request(:post) do |req|
|
1008
|
+
req.url("ra/apps/#{app_id}/testingTypes/#{testing_type}/trains/")
|
1009
|
+
req.body = data.to_json
|
1010
|
+
req.headers['Content-Type'] = 'application/json'
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
handle_itc_response(r.body)
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
def remove_testflight_build_from_review!(app_id: nil, train: nil, build_number: nil, platform: 'ios')
|
1017
|
+
r = request(:post) do |req|
|
1018
|
+
req.url("ra/apps/#{app_id}/platforms/#{platform}/trains/#{train}/builds/#{build_number}/reject")
|
1019
|
+
req.body = {}.to_json
|
1020
|
+
req.headers['Content-Type'] = 'application/json'
|
1021
|
+
end
|
1022
|
+
handle_itc_response(r.body)
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
# All build trains, even if there is no TestFlight
|
1026
|
+
def all_build_trains(app_id: nil, platform: 'ios')
|
1027
|
+
platform = 'ios' if platform.nil?
|
1028
|
+
r = request(:get, "ra/apps/#{app_id}/buildHistory?platform=#{platform}")
|
1029
|
+
handle_itc_response(r.body)
|
1030
|
+
end
|
1031
|
+
|
1032
|
+
def all_builds_for_train(app_id: nil, train: nil, platform: 'ios')
|
1033
|
+
platform = 'ios' if platform.nil?
|
1034
|
+
r = request(:get, "ra/apps/#{app_id}/trains/#{train}/buildHistory?platform=#{platform}")
|
1035
|
+
handle_itc_response(r.body)
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
def build_details(app_id: nil, train: nil, build_number: nil, platform: nil)
|
1039
|
+
r = request(:get, "ra/apps/#{app_id}/platforms/#{platform || 'ios'}/trains/#{train}/builds/#{build_number}/details")
|
1040
|
+
handle_itc_response(r.body)
|
1041
|
+
end
|
1042
|
+
|
1043
|
+
def update_build_information!(app_id: nil,
|
1044
|
+
train: nil,
|
1045
|
+
build_number: nil,
|
1046
|
+
|
1047
|
+
# optional:
|
1048
|
+
whats_new: nil,
|
1049
|
+
description: nil,
|
1050
|
+
feedback_email: nil,
|
1051
|
+
platform: 'ios')
|
1052
|
+
url = "ra/apps/#{app_id}/platforms/#{platform}/trains/#{train}/builds/#{build_number}/testInformation"
|
1053
|
+
|
1054
|
+
build_info = get_build_info_for_review(app_id: app_id, train: train, build_number: build_number, platform: platform)
|
1055
|
+
build_info["details"].each do |current|
|
1056
|
+
current["whatsNew"]["value"] = whats_new if whats_new
|
1057
|
+
current["description"]["value"] = description if description
|
1058
|
+
current["feedbackEmail"]["value"] = feedback_email if feedback_email
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
review_user_name = build_info['reviewUserName']['value']
|
1062
|
+
review_password = build_info['reviewPassword']['value']
|
1063
|
+
build_info['reviewAccountRequired']['value'] = (review_user_name.to_s + review_password.to_s).length > 0
|
1064
|
+
|
1065
|
+
# Now send everything back to iTC
|
1066
|
+
r = request(:post) do |req| # same URL, but a POST request
|
1067
|
+
req.url(url)
|
1068
|
+
req.body = build_info.to_json
|
1069
|
+
req.headers['Content-Type'] = 'application/json'
|
1070
|
+
end
|
1071
|
+
handle_itc_response(r.body)
|
1072
|
+
end
|
1073
|
+
|
1074
|
+
# rubocop:disable Metrics/ParameterLists
|
1075
|
+
def submit_testflight_build_for_review!(app_id: nil, train: nil, build_number: nil, platform: 'ios',
|
1076
|
+
# Required Metadata:
|
1077
|
+
changelog: nil,
|
1078
|
+
description: nil,
|
1079
|
+
feedback_email: nil,
|
1080
|
+
marketing_url: nil,
|
1081
|
+
first_name: nil,
|
1082
|
+
last_name: nil,
|
1083
|
+
review_email: nil,
|
1084
|
+
phone_number: nil,
|
1085
|
+
significant_change: false,
|
1086
|
+
|
1087
|
+
# Optional Metadata:
|
1088
|
+
privacy_policy_url: nil,
|
1089
|
+
review_user_name: nil,
|
1090
|
+
review_password: nil,
|
1091
|
+
review_notes: nil,
|
1092
|
+
encryption: false,
|
1093
|
+
encryption_updated: false,
|
1094
|
+
is_exempt: false,
|
1095
|
+
proprietary: false,
|
1096
|
+
third_party: false)
|
1097
|
+
|
1098
|
+
build_info = get_build_info_for_review(app_id: app_id, train: train, build_number: build_number, platform: platform)
|
1099
|
+
# Now fill in the values provided by the user
|
1100
|
+
|
1101
|
+
# First the localized values:
|
1102
|
+
build_info['details'].each do |current|
|
1103
|
+
current['whatsNew']['value'] = changelog if changelog
|
1104
|
+
current['description']['value'] = description if description
|
1105
|
+
current['feedbackEmail']['value'] = feedback_email if feedback_email
|
1106
|
+
current['marketingUrl']['value'] = marketing_url if marketing_url
|
1107
|
+
current['privacyPolicyUrl']['value'] = privacy_policy_url if privacy_policy_url
|
1108
|
+
current['pageLanguageValue'] = current['language'] # There is no valid reason why we need this, only iTC being iTC
|
1109
|
+
end
|
1110
|
+
|
1111
|
+
review_info = {
|
1112
|
+
"significantChange" => {
|
1113
|
+
"value" => significant_change
|
1114
|
+
},
|
1115
|
+
"buildTestInformationTO" => build_info,
|
1116
|
+
"exportComplianceTO" => {
|
1117
|
+
"usesEncryption" => {
|
1118
|
+
"value" => encryption
|
1119
|
+
},
|
1120
|
+
"encryptionUpdated" => {
|
1121
|
+
"value" => encryption_updated
|
1122
|
+
},
|
1123
|
+
"isExempt" => {
|
1124
|
+
"value" => is_exempt
|
1125
|
+
},
|
1126
|
+
"containsProprietaryCryptography" => {
|
1127
|
+
"value" => proprietary
|
1128
|
+
},
|
1129
|
+
"containsThirdPartyCryptography" => {
|
1130
|
+
"value" => third_party
|
1131
|
+
}
|
1132
|
+
}
|
1133
|
+
}
|
1134
|
+
|
1135
|
+
r = request(:post) do |req| # same URL, but a POST request
|
1136
|
+
req.url("ra/apps/#{app_id}/platforms/#{platform}/trains/#{train}/builds/#{build_number}/review/submit")
|
1137
|
+
|
1138
|
+
req.body = review_info.to_json
|
1139
|
+
req.headers['Content-Type'] = 'application/json'
|
1140
|
+
end
|
1141
|
+
handle_itc_response(r.body)
|
1142
|
+
end
|
1143
|
+
# rubocop:enable Metrics/ParameterLists
|
1144
|
+
|
1145
|
+
def get_build_info_for_review(app_id: nil, train: nil, build_number: nil, platform: 'ios')
|
1146
|
+
url = "ra/apps/#{app_id}/platforms/#{platform}/trains/#{train}/builds/#{build_number}/testInformation"
|
1147
|
+
r = request(:get) do |req|
|
1148
|
+
req.url(url)
|
1149
|
+
req.headers['Content-Type'] = 'application/json'
|
1150
|
+
end
|
1151
|
+
handle_itc_response(r.body)
|
1152
|
+
|
1153
|
+
r.body['data']
|
1154
|
+
end
|
1155
|
+
|
1156
|
+
#####################################################
|
1157
|
+
# @!group Submit for Review
|
1158
|
+
#####################################################
|
1159
|
+
|
1160
|
+
def prepare_app_submissions(app_id, version)
|
1161
|
+
raise "app_id is required" unless app_id
|
1162
|
+
raise "version is required" unless version
|
1163
|
+
|
1164
|
+
r = request(:get) do |req|
|
1165
|
+
req.url("ra/apps/#{app_id}/versions/#{version}/submit/summary")
|
1166
|
+
req.headers['Content-Type'] = 'application/json'
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
handle_itc_response(r.body)
|
1170
|
+
parse_response(r, 'data')
|
1171
|
+
end
|
1172
|
+
|
1173
|
+
def send_app_submission(app_id, version, data)
|
1174
|
+
raise "app_id is required" unless app_id
|
1175
|
+
|
1176
|
+
# ra/apps/1039164429/version/submit/complete
|
1177
|
+
r = request(:post) do |req|
|
1178
|
+
req.url("ra/apps/#{app_id}/versions/#{version}/submit/complete")
|
1179
|
+
req.body = data.to_json
|
1180
|
+
req.headers['Content-Type'] = 'application/json'
|
1181
|
+
end
|
1182
|
+
|
1183
|
+
handle_itc_response(r.body)
|
1184
|
+
|
1185
|
+
# App Store Connect still returns a success status code even the submission
|
1186
|
+
# was failed because of Ad ID Info / Export Compliance. This checks for any section error
|
1187
|
+
# keys in returned adIdInfo / exportCompliance and prints them out.
|
1188
|
+
ad_id_error_keys = r.body.fetch('data').fetch('adIdInfo').fetch('sectionErrorKeys')
|
1189
|
+
export_error_keys = r.body.fetch('data').fetch('exportCompliance').fetch('sectionErrorKeys')
|
1190
|
+
if ad_id_error_keys.any?
|
1191
|
+
raise "Something wrong with your Ad ID information: #{ad_id_error_keys}."
|
1192
|
+
elsif export_error_keys.any?
|
1193
|
+
raise "Something wrong with your Export Compliance: #{export_error_keys}"
|
1194
|
+
elsif r.body.fetch('messages').fetch('info').last == "Successful POST"
|
1195
|
+
# success
|
1196
|
+
else
|
1197
|
+
raise "Something went wrong when submitting the app for review. Make sure to pass valid options to submit your app for review"
|
1198
|
+
end
|
1199
|
+
|
1200
|
+
parse_response(r, 'data')
|
1201
|
+
end
|
1202
|
+
|
1203
|
+
#####################################################
|
1204
|
+
# @!group release
|
1205
|
+
#####################################################
|
1206
|
+
|
1207
|
+
def release!(app_id, version)
|
1208
|
+
raise "app_id is required" unless app_id
|
1209
|
+
raise "version is required" unless version
|
1210
|
+
|
1211
|
+
r = request(:post) do |req|
|
1212
|
+
req.url("ra/apps/#{app_id}/versions/#{version}/releaseToStore")
|
1213
|
+
req.headers['Content-Type'] = 'application/json'
|
1214
|
+
req.body = app_id.to_s
|
1215
|
+
end
|
1216
|
+
|
1217
|
+
handle_itc_response(r.body)
|
1218
|
+
parse_response(r, 'data')
|
1219
|
+
end
|
1220
|
+
|
1221
|
+
#####################################################
|
1222
|
+
# @!group release to all users
|
1223
|
+
#####################################################
|
1224
|
+
|
1225
|
+
def release_to_all_users!(app_id, version)
|
1226
|
+
raise "app_id is required" unless app_id
|
1227
|
+
raise "version is required" unless version
|
1228
|
+
|
1229
|
+
r = request(:post) do |req|
|
1230
|
+
req.url("ra/apps/#{app_id}/versions/#{version}/phasedRelease/state/COMPLETE")
|
1231
|
+
req.headers['Content-Type'] = 'application/json'
|
1232
|
+
req.body = app_id.to_s
|
1233
|
+
end
|
1234
|
+
|
1235
|
+
handle_itc_response(r.body)
|
1236
|
+
parse_response(r, 'data')
|
1237
|
+
end
|
1238
|
+
|
1239
|
+
#####################################################
|
1240
|
+
# @!group in-app-purchases
|
1241
|
+
#####################################################
|
1242
|
+
|
1243
|
+
# Returns list of all available In-App-Purchases
|
1244
|
+
def iaps(app_id: nil)
|
1245
|
+
r = request(:get, "ra/apps/#{app_id}/iaps")
|
1246
|
+
return r.body["data"]
|
1247
|
+
end
|
1248
|
+
|
1249
|
+
# Returns list of all available Families
|
1250
|
+
def iap_families(app_id: nil)
|
1251
|
+
r = request(:get, "ra/apps/#{app_id}/iaps/families")
|
1252
|
+
return r.body["data"]
|
1253
|
+
end
|
1254
|
+
|
1255
|
+
# Deletes a In-App-Purchases
|
1256
|
+
def delete_iap!(app_id: nil, purchase_id: nil)
|
1257
|
+
r = request(:delete, "ra/apps/#{app_id}/iaps/#{purchase_id}")
|
1258
|
+
handle_itc_response(r)
|
1259
|
+
end
|
1260
|
+
|
1261
|
+
# Loads the full In-App-Purchases
|
1262
|
+
def load_iap(app_id: nil, purchase_id: nil)
|
1263
|
+
r = request(:get, "ra/apps/#{app_id}/iaps/#{purchase_id}")
|
1264
|
+
parse_response(r, 'data')
|
1265
|
+
end
|
1266
|
+
|
1267
|
+
# Submit the In-App-Purchase for review
|
1268
|
+
def submit_iap!(app_id: nil, purchase_id: nil)
|
1269
|
+
r = request(:post, "ra/apps/#{app_id}/iaps/#{purchase_id}/submission")
|
1270
|
+
handle_itc_response(r)
|
1271
|
+
end
|
1272
|
+
|
1273
|
+
# Loads the full In-App-Purchases-Family
|
1274
|
+
def load_iap_family(app_id: nil, family_id: nil)
|
1275
|
+
r = request(:get, "ra/apps/#{app_id}/iaps/family/#{family_id}")
|
1276
|
+
parse_response(r, 'data')
|
1277
|
+
end
|
1278
|
+
|
1279
|
+
# Loads the full In-App-Purchases-Pricing-Matrix
|
1280
|
+
# note: the matrix is the same for any app_id
|
1281
|
+
#
|
1282
|
+
# @param app_id (String) The Apple ID of any app
|
1283
|
+
# @return ([Spaceship::Tunes::IAPSubscriptionPricingTier]) An array of pricing tiers
|
1284
|
+
def subscription_pricing_tiers(app_id)
|
1285
|
+
@subscription_pricing_tiers ||= begin
|
1286
|
+
r = request(:get, "ra/apps/#{app_id}/iaps/pricing/matrix/recurring")
|
1287
|
+
data = parse_response(r, "data")["pricingTiers"]
|
1288
|
+
data.map { |tier| Spaceship::Tunes::IAPSubscriptionPricingTier.factory(tier) }
|
1289
|
+
end
|
1290
|
+
end
|
1291
|
+
|
1292
|
+
# updates an In-App-Purchases-Family
|
1293
|
+
def update_iap_family!(app_id: nil, family_id: nil, data: nil)
|
1294
|
+
with_tunes_retry do
|
1295
|
+
r = request(:put) do |req|
|
1296
|
+
req.url("ra/apps/#{app_id}/iaps/family/#{family_id}/")
|
1297
|
+
req.body = data.to_json
|
1298
|
+
req.headers['Content-Type'] = 'application/json'
|
1299
|
+
end
|
1300
|
+
handle_itc_response(r.body)
|
1301
|
+
end
|
1302
|
+
end
|
1303
|
+
|
1304
|
+
# updates an In-App-Purchases
|
1305
|
+
def update_iap!(app_id: nil, purchase_id: nil, data: nil)
|
1306
|
+
with_tunes_retry do
|
1307
|
+
r = request(:put) do |req|
|
1308
|
+
req.url("ra/apps/#{app_id}/iaps/#{purchase_id}")
|
1309
|
+
req.body = data.to_json
|
1310
|
+
req.headers['Content-Type'] = 'application/json'
|
1311
|
+
end
|
1312
|
+
handle_itc_response(r.body)
|
1313
|
+
end
|
1314
|
+
end
|
1315
|
+
|
1316
|
+
def update_recurring_iap_pricing!(app_id: nil, purchase_id: nil, pricing_intervals: nil)
|
1317
|
+
with_tunes_retry do
|
1318
|
+
r = request(:post) do |req|
|
1319
|
+
pricing_data = {}
|
1320
|
+
req.url("ra/apps/#{app_id}/iaps/#{purchase_id}/pricing/subscriptions")
|
1321
|
+
pricing_data["subscriptions"] = pricing_intervals
|
1322
|
+
req.body = pricing_data.to_json
|
1323
|
+
req.headers['Content-Type'] = 'application/json'
|
1324
|
+
end
|
1325
|
+
handle_itc_response(r.body)
|
1326
|
+
end
|
1327
|
+
end
|
1328
|
+
|
1329
|
+
def load_recurring_iap_pricing(app_id: nil, purchase_id: nil)
|
1330
|
+
r = request(:get, "ra/apps/#{app_id}/iaps/#{purchase_id}/pricing")
|
1331
|
+
parse_response(r, 'data')
|
1332
|
+
end
|
1333
|
+
|
1334
|
+
def create_iap_family(app_id: nil, name: nil, product_id: nil, reference_name: nil, versions: [])
|
1335
|
+
r = request(:get, "ra/apps/#{app_id}/iaps/family/template")
|
1336
|
+
data = parse_response(r, 'data')
|
1337
|
+
|
1338
|
+
data['activeAddOns'][0]['productId'] = { value: product_id }
|
1339
|
+
data['activeAddOns'][0]['referenceName'] = { value: reference_name }
|
1340
|
+
data['name'] = { value: name }
|
1341
|
+
data["details"]["value"] = versions
|
1342
|
+
|
1343
|
+
r = request(:post) do |req|
|
1344
|
+
req.url("ra/apps/#{app_id}/iaps/family/")
|
1345
|
+
req.body = data.to_json
|
1346
|
+
req.headers['Content-Type'] = 'application/json'
|
1347
|
+
end
|
1348
|
+
handle_itc_response(r.body)
|
1349
|
+
end
|
1350
|
+
|
1351
|
+
# returns pricing goal array
|
1352
|
+
def iap_subscription_pricing_target(app_id: nil, purchase_id: nil, currency: nil, tier: nil)
|
1353
|
+
r = request(:get, "ra/apps/#{app_id}/iaps/#{purchase_id}/pricing/equalize/#{currency}/#{tier}")
|
1354
|
+
parse_response(r, 'data')
|
1355
|
+
end
|
1356
|
+
|
1357
|
+
# Creates an In-App-Purchases
|
1358
|
+
def create_iap!(app_id: nil, type: nil, versions: nil, reference_name: nil, product_id: nil, cleared_for_sale: true, merch_screenshot: nil, review_notes: nil, review_screenshot: nil, pricing_intervals: nil, family_id: nil, subscription_duration: nil, subscription_free_trial: nil)
|
1359
|
+
# Load IAP Template based on Type
|
1360
|
+
type ||= "consumable"
|
1361
|
+
r = request(:get, "ra/apps/#{app_id}/iaps/#{type}/template")
|
1362
|
+
data = parse_response(r, 'data')
|
1363
|
+
|
1364
|
+
# Now fill in the values we have
|
1365
|
+
# some values are nil, that's why there is a hash
|
1366
|
+
data['familyId'] = family_id.to_s if family_id
|
1367
|
+
data['productId'] = { value: product_id }
|
1368
|
+
data['referenceName'] = { value: reference_name }
|
1369
|
+
data['clearedForSale'] = { value: cleared_for_sale }
|
1370
|
+
|
1371
|
+
data['pricingDurationType'] = { value: subscription_duration } if subscription_duration
|
1372
|
+
data['freeTrialDurationType'] = { value: subscription_free_trial } if subscription_free_trial
|
1373
|
+
|
1374
|
+
# pricing tier
|
1375
|
+
if pricing_intervals
|
1376
|
+
data['pricingIntervals'] = []
|
1377
|
+
pricing_intervals.each do |interval|
|
1378
|
+
data['pricingIntervals'] << {
|
1379
|
+
value: {
|
1380
|
+
country: interval[:country] || "WW",
|
1381
|
+
tierStem: interval[:tier].to_s,
|
1382
|
+
priceTierEndDate: interval[:end_date],
|
1383
|
+
priceTierEffectiveDate: interval[:begin_date]
|
1384
|
+
}
|
1385
|
+
}
|
1386
|
+
end
|
1387
|
+
end
|
1388
|
+
|
1389
|
+
versions_array = []
|
1390
|
+
versions.each do |k, v|
|
1391
|
+
versions_array << {
|
1392
|
+
value: {
|
1393
|
+
description: { value: v[:description] },
|
1394
|
+
name: { value: v[:name] },
|
1395
|
+
localeCode: k.to_s
|
1396
|
+
}
|
1397
|
+
}
|
1398
|
+
end
|
1399
|
+
data["versions"][0]["details"]["value"] = versions_array
|
1400
|
+
data['versions'][0]["reviewNotes"] = { value: review_notes }
|
1401
|
+
|
1402
|
+
if merch_screenshot
|
1403
|
+
# Upload App Store Promotional image (Optional)
|
1404
|
+
upload_file = UploadFile.from_path(merch_screenshot)
|
1405
|
+
merch_data = upload_purchase_merch_screenshot(app_id, upload_file)
|
1406
|
+
data["versions"][0]["merch"] = merch_data
|
1407
|
+
end
|
1408
|
+
|
1409
|
+
if review_screenshot
|
1410
|
+
# Upload Screenshot:
|
1411
|
+
upload_file = UploadFile.from_path(review_screenshot)
|
1412
|
+
screenshot_data = upload_purchase_review_screenshot(app_id, upload_file)
|
1413
|
+
data["versions"][0]["reviewScreenshot"] = screenshot_data
|
1414
|
+
end
|
1415
|
+
|
1416
|
+
# Now send back the modified hash
|
1417
|
+
r = request(:post) do |req|
|
1418
|
+
req.url("ra/apps/#{app_id}/iaps")
|
1419
|
+
req.body = data.to_json
|
1420
|
+
req.headers['Content-Type'] = 'application/json'
|
1421
|
+
end
|
1422
|
+
handle_itc_response(r.body)
|
1423
|
+
end
|
1424
|
+
|
1425
|
+
# Retrieves app-specific shared secret key
|
1426
|
+
def get_shared_secret(app_id: nil)
|
1427
|
+
r = request(:get, "ra/apps/#{app_id}/iaps/appSharedSecret")
|
1428
|
+
data = parse_response(r, 'data')
|
1429
|
+
data['sharedSecret']
|
1430
|
+
end
|
1431
|
+
|
1432
|
+
# Generates app-specific shared secret key
|
1433
|
+
def generate_shared_secret(app_id: nil)
|
1434
|
+
r = request(:post, "ra/apps/#{app_id}/iaps/appSharedSecret")
|
1435
|
+
data = parse_response(r, 'data')
|
1436
|
+
data['sharedSecret']
|
1437
|
+
end
|
1438
|
+
|
1439
|
+
#####################################################
|
1440
|
+
# @!group Sandbox Testers
|
1441
|
+
#####################################################
|
1442
|
+
def sandbox_testers(tester_class)
|
1443
|
+
url = tester_class.url[:index]
|
1444
|
+
r = request(:get, url)
|
1445
|
+
parse_response(r, 'data')
|
1446
|
+
end
|
1447
|
+
|
1448
|
+
def create_sandbox_tester!(tester_class: nil, email: nil, password: nil, first_name: nil, last_name: nil, country: nil)
|
1449
|
+
url = tester_class.url[:create]
|
1450
|
+
r = request(:post) do |req|
|
1451
|
+
req.url(url)
|
1452
|
+
req.body = {
|
1453
|
+
user: {
|
1454
|
+
emailAddress: { value: email },
|
1455
|
+
password: { value: password },
|
1456
|
+
confirmPassword: { value: password },
|
1457
|
+
firstName: { value: first_name },
|
1458
|
+
lastName: { value: last_name },
|
1459
|
+
storeFront: { value: country },
|
1460
|
+
birthDay: { value: 1 },
|
1461
|
+
birthMonth: { value: 1 },
|
1462
|
+
secretQuestion: { value: SecureRandom.hex },
|
1463
|
+
secretAnswer: { value: SecureRandom.hex },
|
1464
|
+
sandboxAccount: nil
|
1465
|
+
}
|
1466
|
+
}.to_json
|
1467
|
+
req.headers['Content-Type'] = 'application/json'
|
1468
|
+
end
|
1469
|
+
response_object = parse_response(r, 'data')
|
1470
|
+
errors = response_object['sectionErrorKeys']
|
1471
|
+
raise ITunesConnectError, errors.join(' ') unless errors.empty?
|
1472
|
+
response_object['user']
|
1473
|
+
end
|
1474
|
+
|
1475
|
+
def delete_sandbox_testers!(tester_class, emails)
|
1476
|
+
url = tester_class.url[:delete]
|
1477
|
+
request(:post) do |req|
|
1478
|
+
req.url(url)
|
1479
|
+
req.body = emails.map do |email|
|
1480
|
+
{
|
1481
|
+
emailAddress: {
|
1482
|
+
value: email
|
1483
|
+
}
|
1484
|
+
}
|
1485
|
+
end.to_json
|
1486
|
+
req.headers['Content-Type'] = 'application/json'
|
1487
|
+
end
|
1488
|
+
true
|
1489
|
+
end
|
1490
|
+
|
1491
|
+
#####################################################
|
1492
|
+
# @!group State History
|
1493
|
+
#####################################################
|
1494
|
+
def versions_history(app_id, platform)
|
1495
|
+
r = request(:get, "ra/apps/#{app_id}/stateHistory?platform=#{platform}")
|
1496
|
+
parse_response(r, 'data')['versions']
|
1497
|
+
end
|
1498
|
+
|
1499
|
+
def version_states_history(app_id, platform, version_id)
|
1500
|
+
r = request(:get, "ra/apps/#{app_id}/versions/#{version_id}/stateHistory?platform=#{platform}")
|
1501
|
+
parse_response(r, 'data')
|
1502
|
+
end
|
1503
|
+
|
1504
|
+
#####################################################
|
1505
|
+
# @!group Promo codes
|
1506
|
+
#####################################################
|
1507
|
+
def app_promocodes(app_id: nil)
|
1508
|
+
r = request(:get, "ra/apps/#{app_id}/promocodes/versions")
|
1509
|
+
parse_response(r, 'data')['versions']
|
1510
|
+
end
|
1511
|
+
|
1512
|
+
def generate_app_version_promocodes!(app_id: nil, version_id: nil, quantity: nil)
|
1513
|
+
data = [{
|
1514
|
+
numberOfCodes: quantity,
|
1515
|
+
agreedToContract: true,
|
1516
|
+
versionId: version_id
|
1517
|
+
}]
|
1518
|
+
url = "ra/apps/#{app_id}/promocodes/versions"
|
1519
|
+
r = request(:post) do |req|
|
1520
|
+
req.url(url)
|
1521
|
+
req.body = data.to_json
|
1522
|
+
req.headers['Content-Type'] = 'application/json'
|
1523
|
+
end
|
1524
|
+
parse_response(r, 'data')
|
1525
|
+
end
|
1526
|
+
|
1527
|
+
def app_promocodes_history(app_id: nil)
|
1528
|
+
r = request(:get, "ra/apps/#{app_id}/promocodes/history")
|
1529
|
+
parse_response(r, 'data')['requests']
|
1530
|
+
end
|
1531
|
+
|
1532
|
+
#####################################################
|
1533
|
+
# @!group reject
|
1534
|
+
#####################################################
|
1535
|
+
|
1536
|
+
def reject!(app_id, version)
|
1537
|
+
raise "app_id is required" unless app_id
|
1538
|
+
raise "version is required" unless version
|
1539
|
+
|
1540
|
+
r = request(:post) do |req|
|
1541
|
+
req.url("ra/apps/#{app_id}/versions/#{version}/reject")
|
1542
|
+
req.headers['Content-Type'] = 'application/json'
|
1543
|
+
req.body = app_id.to_s
|
1544
|
+
end
|
1545
|
+
|
1546
|
+
handle_itc_response(r.body)
|
1547
|
+
parse_response(r, 'data')
|
1548
|
+
end
|
1549
|
+
|
1550
|
+
private
|
1551
|
+
|
1552
|
+
def with_tunes_retry(tries = 5, potential_server_error_tries = 3, &_block)
|
1553
|
+
return yield
|
1554
|
+
rescue Spaceship::TunesClient::ITunesConnectTemporaryError => ex
|
1555
|
+
seconds_to_sleep = 60
|
1556
|
+
unless (tries -= 1).zero?
|
1557
|
+
msg = "App Store Connect temporary error received: '#{ex.message}'. Retrying after #{seconds_to_sleep} seconds (remaining: #{tries})..."
|
1558
|
+
puts(msg)
|
1559
|
+
logger.warn(msg)
|
1560
|
+
sleep(seconds_to_sleep) unless Object.const_defined?("SpecHelper")
|
1561
|
+
retry
|
1562
|
+
end
|
1563
|
+
raise ex # re-raise the exception
|
1564
|
+
rescue Spaceship::TunesClient::ITunesConnectPotentialServerError => ex
|
1565
|
+
seconds_to_sleep = 10
|
1566
|
+
unless (potential_server_error_tries -= 1).zero?
|
1567
|
+
msg = "Potential server error received: '#{ex.message}'. Retrying after 10 seconds (remaining: #{potential_server_error_tries})..."
|
1568
|
+
puts(msg)
|
1569
|
+
logger.warn(msg)
|
1570
|
+
sleep(seconds_to_sleep) unless Object.const_defined?("SpecHelper")
|
1571
|
+
retry
|
1572
|
+
end
|
1573
|
+
raise ex
|
1574
|
+
end
|
1575
|
+
|
1576
|
+
def clear_user_cached_data
|
1577
|
+
@content_provider_id = nil
|
1578
|
+
@sso_token_for_image = nil
|
1579
|
+
@sso_token_for_video = nil
|
1580
|
+
end
|
1581
|
+
|
1582
|
+
# the contentProviderIr found in the UserDetail instance
|
1583
|
+
def content_provider_id
|
1584
|
+
@content_provider_id ||= user_detail_data.content_provider_id
|
1585
|
+
end
|
1586
|
+
|
1587
|
+
# the ssoTokenForImage found in the AppVersionRef instance
|
1588
|
+
def sso_token_for_image
|
1589
|
+
@sso_token_for_image ||= ref_data.sso_token_for_image
|
1590
|
+
end
|
1591
|
+
|
1592
|
+
# the ssoTokenForVideo found in the AppVersionRef instance
|
1593
|
+
def sso_token_for_video
|
1594
|
+
@sso_token_for_video ||= ref_data.sso_token_for_video
|
1595
|
+
end
|
1596
|
+
|
1597
|
+
# generates group hash used in the analytics time_series API.
|
1598
|
+
# Using rank=DESCENDING and limit=3 as this is what the App Store Connect analytics dashboard uses.
|
1599
|
+
def group_for_view_by(view_by, measures)
|
1600
|
+
if view_by.nil? || measures.nil?
|
1601
|
+
return nil
|
1602
|
+
else
|
1603
|
+
return {
|
1604
|
+
metric: measures.first,
|
1605
|
+
dimension: view_by,
|
1606
|
+
rank: "DESCENDING",
|
1607
|
+
limit: 3
|
1608
|
+
}
|
1609
|
+
end
|
1610
|
+
end
|
1611
|
+
|
1612
|
+
def update_tester_from_app!(tester, app_id, testing)
|
1613
|
+
url = tester.class.url(app_id)[:update_by_app]
|
1614
|
+
data = {
|
1615
|
+
users: [
|
1616
|
+
{
|
1617
|
+
emailAddress: {
|
1618
|
+
value: tester.email
|
1619
|
+
},
|
1620
|
+
firstName: {
|
1621
|
+
value: tester.first_name
|
1622
|
+
},
|
1623
|
+
lastName: {
|
1624
|
+
value: tester.last_name
|
1625
|
+
},
|
1626
|
+
testing: {
|
1627
|
+
value: testing
|
1628
|
+
}
|
1629
|
+
}
|
1630
|
+
]
|
1631
|
+
}
|
1632
|
+
|
1633
|
+
r = request(:post) do |req|
|
1634
|
+
req.url(url)
|
1635
|
+
req.body = data.to_json
|
1636
|
+
req.headers['Content-Type'] = 'application/json'
|
1637
|
+
end
|
1638
|
+
|
1639
|
+
data = parse_response(r, 'data')
|
1640
|
+
handle_itc_response(data)
|
1641
|
+
end
|
1642
|
+
end
|
1643
|
+
# rubocop:enable Metrics/ClassLength
|
1644
|
+
end
|