From dcf66f2547e59400bd51cb13c2542294438652bc Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Tue, 11 Mar 2025 17:25:02 +0100 Subject: [PATCH 1/5] Migrate from App Center to Firebase App Distribution --- Gemfile | 6 ++-- Gemfile.lock | 52 +++++++++++++++++------------ fastlane/Fastfile | 61 +++++++++++++---------------------- fastlane/env/user.env.example | 1 - 4 files changed, 57 insertions(+), 63 deletions(-) diff --git a/Gemfile b/Gemfile index b2251322020..5f33be6bf98 100644 --- a/Gemfile +++ b/Gemfile @@ -12,12 +12,12 @@ gem 'danger-dangermattic', '~> 1.2' gem 'dotenv' # 2.217.0 includes a fix for Xcode 15 test results parsing in CI gem 'fastlane', '~> 2.217' -gem 'fastlane-plugin-appcenter', '~> 2.0' +gem 'fastlane-plugin-firebase_app_distribution', '~> 0.10' gem 'fastlane-plugin-sentry', '~> 1.0' # This comment avoids typing to switch to a development version for testing. # -# gem 'fastlane-plugin-wpmreleasetoolkit', git: 'git@github.com:wordpress-mobile/release-toolkit', branch: '' -gem 'fastlane-plugin-wpmreleasetoolkit', '~> 12.5' +gem 'fastlane-plugin-wpmreleasetoolkit', git: 'git@github.com:wordpress-mobile/release-toolkit', ref: 'b1f7eb84ebffcbcf8a3a8ca3189cd00c8a5d3916' # release-toolkit#639 (FAD comment) +# gem 'fastlane-plugin-wpmreleasetoolkit', '~> 12.5' gem 'rake', '~> 12.3' gem 'rubocop', '~> 1.65' gem 'rubocop-rake', '~> 0.6' diff --git a/Gemfile.lock b/Gemfile.lock index c5fddd25f82..aa330035837 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,26 @@ +GIT + remote: git@github.com:wordpress-mobile/release-toolkit + revision: b1f7eb84ebffcbcf8a3a8ca3189cd00c8a5d3916 + ref: b1f7eb84ebffcbcf8a3a8ca3189cd00c8a5d3916 + specs: + fastlane-plugin-wpmreleasetoolkit (12.5.0) + activesupport (>= 6.1.7.1) + buildkit (~> 1.5) + chroma (= 0.2.0) + diffy (~> 3.3) + fastlane (~> 2.213) + git (~> 1.3) + google-cloud-storage (~> 1.31) + java-properties (~> 0.3.0) + nokogiri (~> 1.11) + octokit (~> 6.1) + parallel (~> 1.14) + plist (~> 3.1) + progress_bar (~> 1.3) + rake (>= 12.3, < 14.0) + rake-compiler (~> 1.0) + xcodeproj (~> 1.22) + GEM remote: https://rubygems.org/ specs: @@ -210,26 +233,11 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.4.0) xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) - fastlane-plugin-appcenter (2.1.2) + fastlane-plugin-firebase_app_distribution (0.10.0) + google-apis-firebaseappdistribution_v1 (~> 0.3.0) + google-apis-firebaseappdistribution_v1alpha (~> 0.2.0) fastlane-plugin-sentry (1.25.1) os (~> 1.1, >= 1.1.4) - fastlane-plugin-wpmreleasetoolkit (12.5.0) - activesupport (>= 6.1.7.1) - buildkit (~> 1.5) - chroma (= 0.2.0) - diffy (~> 3.3) - fastlane (~> 2.213) - git (~> 1.3) - google-cloud-storage (~> 1.31) - java-properties (~> 0.3.0) - nokogiri (~> 1.11) - octokit (~> 6.1) - parallel (~> 1.14) - plist (~> 3.1) - progress_bar (~> 1.3) - rake (>= 12.3, < 14.0) - rake-compiler (~> 1.0) - xcodeproj (~> 1.22) fastlane-sirp (1.0.0) sysrandom (~> 1.0) ffi (1.17.0) @@ -250,6 +258,10 @@ GEM representable (~> 3.0) retriable (>= 2.0, < 4.a) rexml + google-apis-firebaseappdistribution_v1 (0.3.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-firebaseappdistribution_v1alpha (0.2.0) + google-apis-core (>= 0.11.0, < 2.a) google-apis-iamcredentials_v1 (0.17.0) google-apis-core (>= 0.11.0, < 2.a) google-apis-playcustomapp_v1 (0.13.0) @@ -416,9 +428,9 @@ DEPENDENCIES danger-dangermattic (~> 1.2) dotenv fastlane (~> 2.217) - fastlane-plugin-appcenter (~> 2.0) + fastlane-plugin-firebase_app_distribution (~> 0.10) fastlane-plugin-sentry (~> 1.0) - fastlane-plugin-wpmreleasetoolkit (~> 12.5) + fastlane-plugin-wpmreleasetoolkit! rake (~> 12.3) rmagick (~> 4.1) rubocop (~> 1.65) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 4587e696208..85fae17e562 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -24,6 +24,11 @@ DERIVED_DATA_DIR = File.join(FASTLANE_DIR, 'DerivedData') SCREENSHOTS_DIR = File.join(FASTLANE_DIR, 'screenshots') FASTLANE_METADATA_FOLDER = File.join(FASTLANE_DIR, 'metadata') WORKSPACE_PATH = File.join(PROJECT_ROOT_FOLDER, 'WooCommerce.xcworkspace') + +# Firebase App Distribution +FIREBASE_APP_ID = '1:124902176124:ios:02259de1e7c42b291620f9' +FIREBASE_TESTERS_GROUP = 'woocommerce-ios---prototype-builds' + BUILDKITE_RELEASE_PIPELINE = 'release-builds.yml' IOS_LOCALES = %w[ar-SA de-DE en-US es-ES fr-FR he id it ja ko nl-NL pt-BR ru sv tr zh-Hans zh-Hant].freeze SIMULATOR_VERSION = '18.1' # For screenshots @@ -51,7 +56,7 @@ MAIN_BUNDLE_IDENTIFIERS = [ ].freeze ALPHA_VERSION_BUNDLE_IDENTIFIER = 'com.automattic.alpha.woocommerce' -# Registered in our Enterprise account, for App Center / Prototype Builds +# Registered in our Enterprise account, for Prototype Builds ALPHA_BUNDLE_IDENTIFIERS = MAIN_BUNDLE_IDENTIFIERS.map do |id| id.gsub(APP_STORE_VERSION_BUNDLE_IDENTIFIER, ALPHA_VERSION_BUNDLE_IDENTIFIER) end.freeze @@ -738,13 +743,17 @@ platform :ios do build_for_prototype_build - appcenter_upload( - api_token: get_required_env('APPCENTER_API_TOKEN'), - owner_name: 'automattic', - owner_type: 'organization', - app_name: 'WooCommerce-Installable-Builds', - destinations: 'Collaborators', - notify_testers: false + release_notes = <<~NOTES + Pull Request: ##{ENV.fetch('BUILDKITE_PULL_REQUEST', 'N/A')} + Branch: `#{ENV.fetch('BUILDKITE_BRANCH', 'N/A')}` + Commit: #{ENV.fetch('BUILDKITE_COMMIT', 'N/A')[0...7]} + NOTES + + firebase_app_distribution( + app: FIREBASE_APP_ID, + service_credentials_json_data: get_required_env('FIREBASE_APP_DISTRIBUTION_ACCOUNT_KEY'), + release_notes: release_notes, + groups: FIREBASE_TESTERS_GROUP ) sentry_upload_dsym( @@ -757,15 +766,12 @@ platform :ios do # The build code used in the Enterprise build has a different format that the App Store one. # We cannot use the standard build_code_current method but have to read it directly. build_code = Xcodeproj::Config.new(File.new(PUBLIC_CONFIG_FILE)).to_hash[BUILD_CODE_KEY] - UI.message("Successfully built and uploaded prototype build `#{build_code}` to App Center.") + UI.message("Successfully built and uploaded prototype build `#{build_code}` to Firebase App Distribution.") return if ENV['BUILDKITE_PULL_REQUEST'].nil? # PR Comment - comment_body = prototype_build_details_comment( - app_display_name: 'WooCommerce iOS', - app_center_org_name: 'automattic' - ) + comment_body = prototype_build_details_comment(app_display_name: 'WooCommerce iOS Prototype') comment_on_pr( project: GITHUB_REPO, pr_number: Integer(ENV.fetch('BUILDKITE_PULL_REQUEST')), @@ -778,19 +784,15 @@ platform :ios do lane :build_for_prototype_build do |fetch_code_signing: true| update_certs_and_profiles_enterprise if fetch_code_signing - # Get the current build version, and update it if needed - versions = Xcodeproj::Config.new(File.new(PUBLIC_CONFIG_FILE)).to_hash - build_number = generate_prototype_build_number - UI.message("Updating build version to #{build_number}") - versions[BUILD_CODE_KEY] = build_number - new_config = Xcodeproj::Config.new(versions) - new_config.save_as(Pathname.new(PUBLIC_CONFIG_FILE)) + build_number = ENV.fetch('BUILDKITE_BUILD_NUMBER', '0') + pr_or_branch = ENV.fetch('BUILDKITE_PULL_REQUEST', nil)&.then { |num| "PR ##{num}" } || ENV.fetch('BUILDKITE_BRANCH', nil) gym( scheme: 'WooCommerce Alpha', workspace: WORKSPACE_PATH, export_method: 'enterprise', clean: true, + xcargs: { BUILD_CODE_KEY => build_number, 'VERSION_SHORT' => pr_or_branch }.compact, output_directory: 'build', export_team_id: get_required_env('INT_EXPORT_TEAM_ID'), export_options: { @@ -1329,25 +1331,6 @@ lane :test_without_building do |options| UI.user_error!("Tests failed with #{tests_result[:number_of_failures_excluding_retries]} failures.") if tests_result[:number_of_failures_excluding_retries].positive? end -# ----------------------------------------------------------------------------------- -# Generates Prototype Build Version Numbers in a Buildkite-specific way -# ----------------------------------------------------------------------------------- -def generate_prototype_build_number - if ENV.key?('BUILDKITE') - commit = ENV.fetch('BUILDKITE_COMMIT')[0, 7] - branch = ENV.fetch('BUILDKITE_BRANCH') - pr_num = ENV.fetch('BUILDKITE_PULL_REQUEST') - - pr_num == 'false' ? "#{branch}-#{commit}" : "pr#{pr_num}-#{commit}" - else - repo = Git.open(PROJECT_ROOT_FOLDER) - commit = repo.current_branch - branch = repo.revparse('HEAD')[0, 7] - - "#{branch}-#{commit}" - end -end - # ----------------------------------------------------------------------------------- # Raises an error if Sentry is not installed # ----------------------------------------------------------------------------------- diff --git a/fastlane/env/user.env.example b/fastlane/env/user.env.example index f74b95dbf7f..5b54678281c 100644 --- a/fastlane/env/user.env.example +++ b/fastlane/env/user.env.example @@ -1,5 +1,4 @@ GHHELPER_ACCESS= SENTRY_AUTH_TOKEN= -APPCENTER_API_TOKEN= CIRCLE_CI_AUTH_TOKEN= From d3b8159c03ac09b4eb5656b2c56552f92cb0313e Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Tue, 11 Mar 2025 19:37:43 +0100 Subject: [PATCH 2/5] Point to official release-toolkit --- Gemfile | 4 ++-- Gemfile.lock | 42 ++++++++++++++++++------------------------ 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/Gemfile b/Gemfile index 5f33be6bf98..aa35044d0ef 100644 --- a/Gemfile +++ b/Gemfile @@ -16,8 +16,8 @@ gem 'fastlane-plugin-firebase_app_distribution', '~> 0.10' gem 'fastlane-plugin-sentry', '~> 1.0' # This comment avoids typing to switch to a development version for testing. # -gem 'fastlane-plugin-wpmreleasetoolkit', git: 'git@github.com:wordpress-mobile/release-toolkit', ref: 'b1f7eb84ebffcbcf8a3a8ca3189cd00c8a5d3916' # release-toolkit#639 (FAD comment) -# gem 'fastlane-plugin-wpmreleasetoolkit', '~> 12.5' +# gem 'fastlane-plugin-wpmreleasetoolkit', git: 'git@github.com:wordpress-mobile/release-toolkit', branch: '' +gem 'fastlane-plugin-wpmreleasetoolkit', '~> 13.0' gem 'rake', '~> 12.3' gem 'rubocop', '~> 1.65' gem 'rubocop-rake', '~> 0.6' diff --git a/Gemfile.lock b/Gemfile.lock index aa330035837..fb5190cb951 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,26 +1,3 @@ -GIT - remote: git@github.com:wordpress-mobile/release-toolkit - revision: b1f7eb84ebffcbcf8a3a8ca3189cd00c8a5d3916 - ref: b1f7eb84ebffcbcf8a3a8ca3189cd00c8a5d3916 - specs: - fastlane-plugin-wpmreleasetoolkit (12.5.0) - activesupport (>= 6.1.7.1) - buildkit (~> 1.5) - chroma (= 0.2.0) - diffy (~> 3.3) - fastlane (~> 2.213) - git (~> 1.3) - google-cloud-storage (~> 1.31) - java-properties (~> 0.3.0) - nokogiri (~> 1.11) - octokit (~> 6.1) - parallel (~> 1.14) - plist (~> 3.1) - progress_bar (~> 1.3) - rake (>= 12.3, < 14.0) - rake-compiler (~> 1.0) - xcodeproj (~> 1.22) - GEM remote: https://rubygems.org/ specs: @@ -238,6 +215,23 @@ GEM google-apis-firebaseappdistribution_v1alpha (~> 0.2.0) fastlane-plugin-sentry (1.25.1) os (~> 1.1, >= 1.1.4) + fastlane-plugin-wpmreleasetoolkit (13.0.0) + activesupport (>= 6.1.7.1) + buildkit (~> 1.5) + chroma (= 0.2.0) + diffy (~> 3.3) + fastlane (~> 2.213) + git (~> 1.3) + google-cloud-storage (~> 1.31) + java-properties (~> 0.3.0) + nokogiri (~> 1.11) + octokit (~> 6.1) + parallel (~> 1.14) + plist (~> 3.1) + progress_bar (~> 1.3) + rake (>= 12.3, < 14.0) + rake-compiler (~> 1.0) + xcodeproj (~> 1.22) fastlane-sirp (1.0.0) sysrandom (~> 1.0) ffi (1.17.0) @@ -430,7 +424,7 @@ DEPENDENCIES fastlane (~> 2.217) fastlane-plugin-firebase_app_distribution (~> 0.10) fastlane-plugin-sentry (~> 1.0) - fastlane-plugin-wpmreleasetoolkit! + fastlane-plugin-wpmreleasetoolkit (~> 13.0) rake (~> 12.3) rmagick (~> 4.1) rubocop (~> 1.65) From 5c8834074c3877a49dc5a2e95d9ab879030309eb Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Wed, 12 Mar 2025 17:06:44 +0100 Subject: [PATCH 3/5] Remove more unused code from Fastfile --- fastlane/Fastfile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 85fae17e562..2fd4c4d8e70 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -763,11 +763,6 @@ platform :ios do dsym_path: './build/WooCommerce.app.dSYM.zip' ) - # The build code used in the Enterprise build has a different format that the App Store one. - # We cannot use the standard build_code_current method but have to read it directly. - build_code = Xcodeproj::Config.new(File.new(PUBLIC_CONFIG_FILE)).to_hash[BUILD_CODE_KEY] - UI.message("Successfully built and uploaded prototype build `#{build_code}` to Firebase App Distribution.") - return if ENV['BUILDKITE_PULL_REQUEST'].nil? # PR Comment From fbd47bf99b19ef820b24631b237ba5abbce7486b Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Fri, 14 Mar 2025 17:59:02 +0100 Subject: [PATCH 4/5] Fix early return logic --- fastlane/Fastfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 2fd4c4d8e70..919fbbd8c96 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -763,7 +763,7 @@ platform :ios do dsym_path: './build/WooCommerce.app.dSYM.zip' ) - return if ENV['BUILDKITE_PULL_REQUEST'].nil? + next if ENV.fetch('BUILDKITE_PULL_REQUEST', 'false') == 'false' # PR Comment comment_body = prototype_build_details_comment(app_display_name: 'WooCommerce iOS Prototype') From e730f75f83abf39d411465582dda33f0b1628c33 Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Wed, 19 Mar 2025 21:13:18 +0100 Subject: [PATCH 5/5] Fix BUILDKITE_PULL_REQUEST being false not nil --- fastlane/Fastfile | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 919fbbd8c96..09293c96a0f 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -744,7 +744,7 @@ platform :ios do build_for_prototype_build release_notes = <<~NOTES - Pull Request: ##{ENV.fetch('BUILDKITE_PULL_REQUEST', 'N/A')} + Pull Request: ##{pull_request_number || 'N/A'} Branch: `#{ENV.fetch('BUILDKITE_BRANCH', 'N/A')}` Commit: #{ENV.fetch('BUILDKITE_COMMIT', 'N/A')[0...7]} NOTES @@ -763,13 +763,13 @@ platform :ios do dsym_path: './build/WooCommerce.app.dSYM.zip' ) - next if ENV.fetch('BUILDKITE_PULL_REQUEST', 'false') == 'false' + next if pull_request_number.nil? # PR Comment comment_body = prototype_build_details_comment(app_display_name: 'WooCommerce iOS Prototype') comment_on_pr( project: GITHUB_REPO, - pr_number: Integer(ENV.fetch('BUILDKITE_PULL_REQUEST')), + pr_number: pull_request_number, reuse_identifier: 'prototype-build-link', body: comment_body ) @@ -780,7 +780,7 @@ platform :ios do update_certs_and_profiles_enterprise if fetch_code_signing build_number = ENV.fetch('BUILDKITE_BUILD_NUMBER', '0') - pr_or_branch = ENV.fetch('BUILDKITE_PULL_REQUEST', nil)&.then { |num| "PR ##{num}" } || ENV.fetch('BUILDKITE_BRANCH', nil) + pr_or_branch = pull_request_number&.then { |num| "PR ##{num}" } || ENV.fetch('BUILDKITE_BRANCH', nil) gym( scheme: 'WooCommerce Alpha', @@ -1473,13 +1473,6 @@ def prompt_user_for_app_store_connect_credentials ENV['FASTLANE_USER'] = CredentialsManager::AccountManager.new.user end -def override_default_release_branch(version) - success = Fastlane::Helper::GitHelper.checkout_and_pull(release: version) - UI.user_error!("Release branch for version #{version} doesn't exist. Abort.") unless success - - UI.message("Checked out branch `#{git_branch}` as requested by user.\n") -end - # https://buildkite.com/docs/test-analytics/ci-environments TEST_ANALYTICS_ENVIRONMENT = %w[ BUILDKITE_ANALYTICS_TOKEN @@ -1495,6 +1488,13 @@ TEST_ANALYTICS_ENVIRONMENT = %w[ # ----------------------------------------------------------------------------------- # Release Management Utils # ----------------------------------------------------------------------------------- + +def pull_request_number + # Buildkite sets this env var to the PR number if on a PR, but to 'false' (and not nil) if not on a PR + pr_num = ENV.fetch('BUILDKITE_PULL_REQUEST', 'false') + pr_num == 'false' ? nil : Integer(pr_num) +end + def create_backmerge_pr version = release_version_current