block (hidden by default)',
+ type: Boolean,
+ default_value: false
+ ),
+ FastlaneCore::ConfigItem.new(
+ key: :metadata,
+ env_name: 'FL_PROTOTYPE_BUILD_DETAILS_COMMENT_METADATA',
+ description: 'All additional metadata (as key/value pairs) you want to include in the HTML table of the comment. ' \
+ + 'If you are running this action after `appcenter_upload`, some metadata will automatically be added to this list too',
+ type: Hash,
+ optional: true,
+ default_value_dynamic: true # As some metadata will be auto-filled if you used `appcenter_upload`
+ ),
+ FastlaneCore::ConfigItem.new(
+ key: :footnote,
+ env_name: 'FL_PROTOTYPE_BUILD_DETAILS_COMMENT_FOOTNOTE',
+ description: 'Optional footnote to add below the HTML table of the comment. ' \
+ + 'If you are running this action after `appcenter_upload`, a default footnote for Automatticians will be used unless you provide an explicit value',
+ type: String,
+ optional: true,
+ default_value_dynamic: true # We have a default footnote for the case when you used App Center
+ ),
+ ]
+ end
+
+ def self.return_type
+ :string
+ end
+
+ def self.return_value
+ 'The HTML comment containing all the relevant info about a Prototype build and links to install it'
+ end
+
+ def self.authors
+ ['Automattic']
+ end
+
+ def self.is_supported?(platform)
+ true
+ end
+ end
+ end
+end
diff --git a/spec/prototype_build_details_comment_action_spec.rb b/spec/prototype_build_details_comment_action_spec.rb
new file mode 100644
index 000000000..9a0a89bd2
--- /dev/null
+++ b/spec/prototype_build_details_comment_action_spec.rb
@@ -0,0 +1,574 @@
+require_relative './spec_helper'
+
+describe Fastlane::Actions::PrototypeBuildDetailsCommentAction do
+ before do
+ ENV['BUILDKITE_COMMIT'] = 'a1b2c3f'
+ end
+
+ describe 'cases common to all operating modes' do
+ describe 'app_display_name' do
+ it 'includes the app display name as part of the intro text' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My Cool App',
+ download_url: 'https://localhost/foo.apk'
+ )
+ expect(comment).to include '📲 You can test the changes from this Pull Request in My Cool App'
+ end
+
+ it 'includes the app display name as part of implicit metadata' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My Cool App',
+ download_url: 'https://localhost/foo.apk'
+ )
+ expect(comment).to include '| App Name | My Cool App | '
+ end
+ end
+
+ describe 'app_icon' do
+ context 'when providing an URL' do
+ it 'includes the icon in the intro text' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My Cool App',
+ app_icon: 'https://localhost/foo.png',
+ download_url: 'https://localhost/foo.apk'
+ )
+ expect(comment).to include "
📲 "
+ end
+
+ it 'includes the icon next to the App Name in metadata' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My Cool App',
+ app_icon: 'https://localhost/foo.png',
+ download_url: 'https://localhost/foo.apk'
+ )
+ expect(comment).to include "App Name | My Cool App | "
+ end
+ end
+
+ context 'when providing an emoji code' do
+ it 'includes the icon in the intro text' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My Cool App',
+ app_icon: ':jetpack:',
+ download_url: 'https://localhost/foo.apk'
+ )
+ expect(comment).to include "
📲 "
+ end
+
+ it 'includes the icon next to the App Name in metadata' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My Cool App',
+ app_icon: ':jetpack:',
+ download_url: 'https://localhost/foo.apk'
+ )
+ expect(comment).to include "App Name | My Cool App | "
+ end
+ end
+ end
+
+ it 'includes the commit as part of the default rows' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My App',
+ download_url: 'https://localhost/foo.apk'
+ )
+ expect(comment).to include 'Commit | a1b2c3f | '
+ end
+
+ it 'includes the provided footnote if one was provided explicitly' do
+ custom_footnote = 'Note that Google Sign-In in not available in those builds'
+ comment = run_described_fastlane_action(
+ app_display_name: 'My App',
+ download_url: 'https://localhost/foo.apk',
+ footnote: custom_footnote
+ )
+ expect(comment).to include custom_footnote
+ end
+ end
+
+ context 'when using App Center with explicit parameters' do
+ it 'raises an error if neither `app_center_app_name` nor `download_url` is provided' do
+ expect do
+ run_described_fastlane_action(
+ app_display_name: 'My App',
+ app_center_org_name: 'BestOrg'
+ )
+ end.to raise_error(FastlaneCore::Interface::FastlaneError, described_class::NO_INSTALL_URL_ERROR_MESSAGE)
+ end
+
+ describe 'checking specific content is present' do
+ it 'generates the proper App Center link and QR code given an org, app name and release ID' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My App',
+ app_center_org_name: 'My-Org',
+ app_center_app_name: 'My-App',
+ app_center_release_id: '1337'
+ )
+ expect(comment).to include "My-App #1337"
+ expect(comment).to include 'https://chart.googleapis.com/chart?chs=500x500&cht=qr&chl=https%3A%2F%2Finstall.appcenter.ms%2Forgs%2FMy-Org%2Fapps%2FMy-App%2Freleases%2F1337&choe=UTF-8'
+ end
+
+ it 'uses the App Center link for the QR code even if a `download_url` is provided' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My App',
+ app_center_org_name: 'My-Org',
+ app_center_app_name: 'My-App',
+ app_center_release_id: '1337',
+ download_url: 'https://foo.cloudfront.net/someuuid/myapp-prototype-build-pr1337-a1b2c3f.apk'
+ )
+ expect(comment).to include "Direct Download | myapp-prototype-build-pr1337-a1b2c3f.apk | "
+ expect(comment).to include 'https://chart.googleapis.com/chart?chs=500x500&cht=qr&chl=https%3A%2F%2Finstall.appcenter.ms%2Forgs%2FMy-Org%2Fapps%2FMy-App%2Freleases%2F1337&choe=UTF-8'
+ # Inferred metadata rows: App Name, Commit, Direct Download, App Center Build
+ expect(comment).to include "App Name | My App | '
+ expect(comment).to include 'Version:Short | 28.1 | '
+ expect(comment).to include 'Version:Long | 281003 | '
+ expect(comment).to include 'Build Config | Prototype | '
+ expect(comment).to include 'Commit | a1b2c3f | '
+ expect(comment).to include "| App Center Build | My-App \#1337 |
"
+ # Additional inferred metadata rows: App Name, Commit, App Center Build
+ expect(comment).to include "Note: Google Sign-In in not available in those builds'
+ )
+
+ expect(comment).to eq <<~EXPECTED_COMMENT
+ 📲 You can test the changes from this Pull Request in The Best App by scanning the QR code below to install the corresponding build.
+
+
+  |
+ App Name | The Best App |
+
+ | Version:Short | 28.2 |
+ | Version:Long | 28.2.0.108 |
+ | Flavor | Celray |
+ | Commit | a1b2c3f |
+ | App Center Build | BestApp \#8888 |
+
+ Note: Google Sign-In in not available in those builds
+ EXPECTED_COMMENT
+ end
+
+ it 'generates a HTML table comment including the direct link if provided' do
+ metadata = {
+ 'Version:Short': '28.2',
+ 'Version:Long': '28.2.0.108'
+ }
+
+ comment = run_described_fastlane_action(
+ app_display_name: 'The Best App',
+ app_center_org_name: 'BestOrg',
+ app_center_app_name: 'BestApp',
+ app_center_release_id: '8888',
+ download_url: 'https://bestfront.cloudfront.net/feed42/bestapp-pr1357-a1b2c3f.apk',
+ metadata: metadata
+ )
+
+ expect(comment).to eq <<~EXPECTED_COMMENT
+ 📲 You can test the changes from this Pull Request in The Best App by scanning the QR code below to install the corresponding build.
+
+ Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.
+ EXPECTED_COMMENT
+ end
+
+ it 'generates a HTML table in a spoiler block if fold is true' do
+ metadata = {
+ 'Version:Short': '28.2',
+ 'Version:Long': '28.2.0.108',
+ Flavor: 'Celray',
+ Configuration: 'Debug'
+ }
+
+ comment = run_described_fastlane_action(
+ app_display_name: 'The Best App',
+ app_center_org_name: 'BestOrg',
+ app_center_app_name: 'BestApp',
+ app_center_release_id: '1234',
+ fold: true,
+ metadata: metadata,
+ footnote: 'Note: Google Sign-In in not available in those builds'
+ )
+
+ expect(comment).to eq <<~EXPECTED_COMMENT
+ 📲 You can test the changes from this Pull Request in The Best App by scanning the QR code below to install the corresponding build.
+
+
+  |
+ App Name | The Best App |
+
+ | Version:Short | 28.2 |
+ | Version:Long | 28.2.0.108 |
+ | Flavor | Celray |
+ | Configuration | Debug |
+ | Commit | a1b2c3f |
+ | App Center Build | BestApp \#1234 |
+
+ Note: Google Sign-In in not available in those builds
+
+ EXPECTED_COMMENT
+ end
+ end
+ end
+
+ context 'when using App Center and relying on implicit info from `lane_context`' do
+ let(:fake_lane_context) do |example|
+ {
+ app_name: 'My-App-Alpha',
+ app_display_name: 'My App (Alpha)',
+ id: '1337',
+ version: '1287003',
+ short_version: '28.7',
+ app_os: example.metadata[:app_os] || 'Android',
+ bundle_identifier: 'com.stubfactory.myapp',
+ app_icon_url: 'https://assets.appcenter.ms/My-App-Alpha/1337/icon.png'
+ }.transform_keys(&:to_s)
+ end
+
+ before do
+ stub_const('Fastlane::Actions::SharedValues::APPCENTER_BUILD_INFORMATION', :fake_app_center_build_info)
+ allow(Fastlane::Actions).to receive(:lane_context).and_return({ fake_app_center_build_info: fake_lane_context })
+ end
+
+ describe 'checking specific content is present' do
+ it 'generates the proper App Center link and QR code given just an org' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My App',
+ app_center_org_name: 'My-Org'
+ )
+ expect(comment).to include "My App (Alpha) #1337"
+ expect(comment).to include 'https://chart.googleapis.com/chart?chs=500x500&cht=qr&chl=https%3A%2F%2Finstall.appcenter.ms%2Forgs%2FMy-Org%2Fapps%2FMy-App-Alpha%2Freleases%2F1337&choe=UTF-8'
+ end
+
+ it 'uses the App Center link for the QR code even if a `download_url` is provided' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My App',
+ app_center_org_name: 'My-Org',
+ download_url: 'https://foo.cloudfront.net/someuuid/myapp-prototype-build-pr1337-a1b2c3f.apk'
+ )
+ expect(comment).to include 'https://chart.googleapis.com/chart?chs=500x500&cht=qr&chl=https%3A%2F%2Finstall.appcenter.ms%2Forgs%2FMy-Org%2Fapps%2FMy-App-Alpha%2Freleases%2F1337&choe=UTF-8'
+ # Inferred metadata rows: App Name, Build Number, Version, Application ID, Commit, Direct Download, App Center Build
+ expect(comment).to include " | Version | 42.3 | ' # explicitly provided, overriding the implicit value
+ expect(comment).not_to include 'Version | 28.7 | ' # otherwise implicitly added if it were not overridden
+ expect(comment).to include 'Build Number | 4203008 | ' # explicitly provided, overriding the implicit value
+ expect(comment).not_to include 'Build Number | 1287003 | ' # otherwise implicitly added if it were not overridden
+ expect(comment).to include 'Build Config | Prototype | ' # not overriding any implicit one
+ # Additional inferred metadata rows: App Name, Application ID, Commit, App Center Build
+ expect(comment).to include "Application ID | com.stubfactory.myapp | '
+ expect(comment).not_to include 'Bundle ID'
+ end
+
+ it 'uses "Bundle ID" as the name for the `bundle_identifier` value if using iOS', app_os: 'iOS' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My App',
+ app_center_org_name: 'My-Org'
+ )
+ expect(comment).to include 'Bundle ID | com.stubfactory.myapp | '
+ expect(comment).not_to include 'Application ID'
+ end
+
+ it 'includes the direct link if one is provided' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My App',
+ app_center_org_name: 'My-Org',
+ download_url: 'https://foo.cloudfront.net/someuuid/myapp-prototype-build-pr1337-a1b2c3f.apk'
+ )
+ expect(comment).to include "Direct Download | myapp-prototype-build-pr1337-a1b2c3f.apk | "
+ # Inferred metadata rows: App Name, Build Number, Version, Application ID, Commit, Direct Download, App Center Build
+ expect(comment).to include "Note: Google Sign-In in not available in those builds'
+ )
+
+ expect(comment).to eq <<~EXPECTED_COMMENT
+ 📲 You can test the changes from this Pull Request in The Best App by scanning the QR code below to install the corresponding build.
+
+
+  |
+ App Name | The Best App |
+
+ | Configuration | Debug |
+ | Build Number | 1287003 |
+ | Version | 28.7 |
+ | Application ID | com.stubfactory.myapp |
+ | Commit | a1b2c3f |
+ | App Center Build | My App (Alpha) \#1337 |
+
+ Note: Google Sign-In in not available in those builds
+ EXPECTED_COMMENT
+ end
+
+ it 'generates a HTML table comment including the direct link if provided' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'The Best App',
+ app_center_org_name: 'BestOrg',
+ download_url: 'https://bestfront.cloudfront.net/feed42/bestapp-pr1357-a1b2c3f.apk'
+ )
+
+ expect(comment).to eq <<~EXPECTED_COMMENT
+ 📲 You can test the changes from this Pull Request in The Best App by scanning the QR code below to install the corresponding build.
+
+ Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.
+ EXPECTED_COMMENT
+ end
+
+ it 'generates a HTML table in a spoiler block if fold is true' do
+ metadata = {
+ 'Google Login': 'Disabled'
+ }
+
+ comment = run_described_fastlane_action(
+ app_display_name: 'The Best App',
+ app_center_org_name: 'BestOrg',
+ fold: true,
+ metadata: metadata,
+ footnote: 'Note: Google Sign-In in not available in those builds'
+ )
+
+ expect(comment).to eq <<~EXPECTED_COMMENT
+ 📲 You can test the changes from this Pull Request in The Best App by scanning the QR code below to install the corresponding build.
+
+
+  |
+ App Name | The Best App |
+
+ | Google Login | Disabled |
+ | Build Number | 1287003 |
+ | Version | 28.7 |
+ | Application ID | com.stubfactory.myapp |
+ | Commit | a1b2c3f |
+ | App Center Build | My App (Alpha) \#1337 |
+
+ Note: Google Sign-In in not available in those builds
+
+ EXPECTED_COMMENT
+ end
+ end
+ end
+
+ context 'when not using App Center' do
+ it 'raises an error if no `download_url` is provided' do
+ expect do
+ run_described_fastlane_action(
+ app_display_name: 'My App'
+ )
+ end.to raise_error(FastlaneCore::Interface::FastlaneError, described_class::NO_INSTALL_URL_ERROR_MESSAGE)
+ end
+
+ describe 'checking specific content is present' do
+ it 'generates the proper QR code from the download url' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My App',
+ download_url: 'https://foo.cloudfront.net/someuuid/myapp-prototype-build-pr1337-a1b2c3f.apk'
+ )
+ expect(comment).to include 'https://chart.googleapis.com/chart?chs=500x500&cht=qr&chl=https%3A%2F%2Ffoo.cloudfront.net%2Fsomeuuid%2Fmyapp-prototype-build-pr1337-a1b2c3f.apk&choe=UTF-8'
+ end
+
+ it 'includes the direct link as metadata' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My App',
+ download_url: 'https://foo.cloudfront.net/someuuid/myapp-prototype-build-pr1337-a1b2c3f.apk'
+ )
+ expect(comment).to include " | Direct Download | myapp-prototype-build-pr1337-a1b2c3f.apk | "
+ end
+
+ it 'does not include the App Center default footnote if no explicit footnote is provided' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My App',
+ download_url: 'https://localhost/foo.apk'
+ )
+ expect(comment).not_to include described_class::DEFAULT_APP_CENTER_FOOTNOTE
+ end
+
+ it 'includes the provided footnote if one was provided explicitly' do
+ comment = run_described_fastlane_action(
+ app_display_name: 'My App',
+ download_url: 'https://localhost/foo.apk',
+ footnote: 'The link to this APK might stop working after a retention delay of 30 days.'
+ )
+ expect(comment).to include 'The link to this APK might stop working after a retention delay of 30 days.'
+ end
+ end
+
+ describe 'validating full comment' do
+ it 'generates a standard HTML table comment by default, with all the information provided' do
+ metadata = {
+ 'Version Name': '28.2',
+ 'Version Code': '1280200108',
+ Flavor: 'Celray'
+ }
+
+ comment = run_described_fastlane_action(
+ app_display_name: 'The Best App',
+ download_url: 'https://bestfront.cloudfront.net/feed42/bestapp-pr1357-a1b2c3f.apk',
+ metadata: metadata,
+ footnote: 'Note: Google Sign-In in not available in those builds'
+ )
+
+ expect(comment).to eq <<~EXPECTED_COMMENT
+ 📲 You can test the changes from this Pull Request in The Best App by scanning the QR code below to install the corresponding build.
+
+
+  |
+ App Name | The Best App |
+
+ | Version Name | 28.2 |
+ | Version Code | 1280200108 |
+ | Flavor | Celray |
+ | Commit | a1b2c3f |
+ | Direct Download | bestapp-pr1357-a1b2c3f.apk |
+
+ Note: Google Sign-In in not available in those builds
+ EXPECTED_COMMENT
+ end
+
+ it 'generates a HTML table in a spoiler block if fold is true' do
+ metadata = {
+ 'Version Name': '28.2',
+ 'Version Code': '1280200108',
+ Flavor: 'Celray',
+ Configuration: 'Debug'
+ }
+
+ comment = run_described_fastlane_action(
+ app_display_name: 'The Best App',
+ download_url: 'https://bestfront.cloudfront.net/feed42/bestapp-pr1357-a1b2c3f.apk',
+ fold: true,
+ metadata: metadata,
+ footnote: 'Note: Google Sign-In in not available in those builds'
+ )
+
+ expect(comment).to eq <<~EXPECTED_COMMENT
+ 📲 You can test the changes from this Pull Request in The Best App by scanning the QR code below to install the corresponding build.
+
+
+  |
+ App Name | The Best App |
+
+ | Version Name | 28.2 |
+ | Version Code | 1280200108 |
+ | Flavor | Celray |
+ | Configuration | Debug |
+ | Commit | a1b2c3f |
+ | Direct Download | bestapp-pr1357-a1b2c3f.apk |
+
+ Note: Google Sign-In in not available in those builds
+
+ EXPECTED_COMMENT
+ end
+ end
+ end
+end