@@ -2,37 +2,49 @@ module Fastlane
22 module Actions
33 class PrototypeBuildDetailsCommentAction < Action
44 def self . run ( params )
5- # Get Input Parameters
6- appcenter_org_name = params [ :appcenter_org_name ]
7- appcenter_app_name = params [ :appcenter_app_name ]
8- appcenter_release_id = params [ :appcenter_release_id ]
9- commit = params [ :commit ] || other_action . last_git_commit [ :abbreviated_commit_hash ]
10-
11- metadata = params [ :metadata ] # e.g. {'Build Config':… , 'Version': …, 'Short Version': …}
12- direct_link = params [ :download_url ]
13- unless direct_link . nil?
14- metadata [ 'Direct Link' ] = "<a href='#{ direct_link } '><code>#{ File . basename ( direct_link ) } </code></a>"
15- end
5+ app_display_name = params [ :app_display_name ]
166
17- # Build the comment parts
18- install_url = "https://install.appcenter.ms/orgs/#{ appcenter_org_name } /apps/#{ appcenter_app_name } /releases/#{ appcenter_release_id } "
19- qr_code_url = "https://chart.googleapis.com/chart?chs=500x500&cht=qr&chl=#{ CGI . escape ( install_url ) } &choe=UTF-8"
20- metadata_rows = metadata . compact . map do |key , value |
21- "<tr><td><b>#{ key } </b></td><td>#{ value } </td></tr>"
7+ app_center_org_name = params [ :app_center_org_name ]
8+ app_center_info = app_center_org_name . nil? ? { } : lane_context [ SharedValues ::APPCENTER_BUILD_INFORMATION ] || { }
9+ app_center_app_name = params [ :app_center_app_name ] || app_center_info [ 'app_name' ]
10+ app_center_app_display_name = app_center_info [ 'app_display_name' ] || app_center_app_name
11+ app_center_release_id = params [ :app_center_release_id ] || app_center_info [ 'id' ]
12+
13+ # Consolidate the list of Metadata to display with some implicit metadata if available
14+ metadata = params [ :metadata ] || { }
15+ metadata [ 'Build Number' ] ||= app_center_info [ 'version' ]
16+ metadata [ 'Version' ] ||= app_center_info [ 'short_version' ]
17+ metadata [ app_center_info [ 'app_os' ] == 'Android' ? 'Application ID' : 'Bundle ID' ] = app_center_info [ 'bundle_identifier' ]
18+ # (Feel free to add more CI-specific env vars in the line below to support other CI providers if you need)
19+ metadata [ 'Commit' ] ||= ENV . fetch ( 'BUILDKITE_COMMIT' , nil ) || other_action . last_git_commit [ :abbreviated_commit_hash ]
20+
21+ # Installation Link(s) -- either download_url param, or App Center Build link, or both
22+ install_url = nil
23+ if params [ :download_url ]
24+ install_url = params [ :download_url ]
25+ metadata [ 'Direct Download' ] = "<a href='#{ install_url } '><code>#{ File . basename ( install_url ) } </code></a>"
2226 end
27+ if app_center_org_name && app_center_app_name
28+ install_url = "https://install.appcenter.ms/orgs/#{ app_center_org_name } /apps/#{ app_center_app_name } /releases/#{ app_center_release_id } "
29+ metadata [ 'App Center Build' ] = "<a href='#{ install_url } '>#{ app_center_app_display_name } \# #{ app_center_release_id } </a>"
30+ end
31+ UI . user_error! ( NO_INSTALL_URL_ERROR_MESSAGE ) if install_url . nil?
32+ qr_code_url = "https://chart.googleapis.com/chart?chs=500x500&cht=qr&chl=#{ CGI . escape ( install_url ) } &choe=UTF-8"
2333
24- intro = "📲 You can test the changes from this Pull Request in <b>#{ appcenter_app_name } </b> by scanning the QR code below to install the corresponding build via App Center."
34+ # Build the comment parts
35+ icon_img_tag = img_tag ( params [ :app_icon ] || app_center_info [ 'app_icon_url' ] , alt : app_display_name )
36+ metadata_rows = metadata . compact . map { |key , value | "<tr><td><b>#{ key } </b></td><td>#{ value } </td></tr>" }
37+ intro = "#{ icon_img_tag } 📲 You can test the changes from this Pull Request in <b>#{ app_display_name } </b> by scanning the QR code below to install the corresponding build."
38+ footnote = params [ :footnote ] || ( app_center_info . nil? ? '' : '<em>Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.</em>' )
2539 body = <<~COMMENT_BODY
2640 <table>
2741 <tr>
28- <td rowspan='#{ metadata . count + 3 } '><img src='#{ qr_code_url } ' width='250' height='250' /></td>
29- <td width='150px'><b>App Name</b></td><td>#{ appcenter_app_name } </td>
42+ <td rowspan='#{ metadata . count + 1 } ' width='260px '><img src='#{ qr_code_url } ' width='250' height='250' /></td>
43+ <td width='150px'><b>App Name</b></td><td>#{ icon_img_tag } #{ app_display_name } </td>
3044 </tr>
3145 #{ metadata_rows . join ( "\n " ) }
32- <tr><td><b>App Center Build</b></td><td><a href='#{ install_url } '>Build \# #{ appcenter_release_id } </a></td></tr>
33- <tr><td><b>Commit</b></td><td>#{ commit } </td></tr>
3446 </table>
35- #{ params [ : footnote] }
47+ #{ footnote }
3648 COMMENT_BODY
3749
3850 if params [ :fold ]
@@ -42,6 +54,28 @@ def self.run(params)
4254 end
4355 end
4456
57+ #####################################################
58+ # @!group Helpers
59+ #####################################################
60+
61+ NO_INSTALL_URL_ERROR_MESSAGE = <<~NO_URL_ERROR . freeze
62+ No URL provided to download or install the app.
63+ - Either use this action right after using `appcenter_upload` and provide an `app_center_org_name` (so that this action can use the link to the App Center build)
64+ - Or provide an explicit value for the `download_url` parameter
65+ NO_URL_ERROR
66+
67+ def self . img_tag ( url_or_emoji , alt : '' )
68+ return nil if url_or_emoji . nil?
69+
70+ emoji = url_or_emoji . match ( /:(.*):/ ) &.captures &.first
71+ app_icon_url = if emoji
72+ "https://raw.githubusercontent.com/buildkite/emojis/main/img-buildkite-64/#{ emoji } .png"
73+ elsif URI ( url_or_emoji )
74+ url_or_emoji
75+ end
76+ app_icon_url ? "<img alt='#{ alt } ' align='top' src='#{ app_icon_url } ' width='20px' />" : ''
77+ end
78+
4579 #####################################################
4680 # @!group Documentation
4781 #####################################################
@@ -50,30 +84,75 @@ def self.description
5084 'Generates a string providing all the details of a prototype build, nicely-formatted and ready to be used as a PR comment (e.g. via `comment_on_pr`).'
5185 end
5286
87+ def self . details
88+ <<~DESC
89+ Generates a string providing all the details of a prototype build, nicely-formatted as HTML.
90+ The returned string will typically be subsequently used by the `comment_on_pr` action to post that HTML as comment on a PR.
91+
92+ If you used the `appcenter_upload` lane (to upload the Prototype build to App Center) before calling this action, and pass
93+ a value to the `app_center_org_name` parameter, then many of the parameters and metadata will be automatically extracted
94+ from the `lane_context` provided by `appcenter_upload`, including:
95+
96+ - The `app_center_app_name`, `app_center_release_id` and installation URL to use for the QR code to point to that release in App Center
97+ - The `app_icon`
98+ - The app's Build Number / versionCode
99+ - The app's Version / versionName
100+ - The app's Bundle ID / Application ID
101+ - A `footnote` mentioning the MC tool for Automatticians to add themselves to App Center
102+
103+ This means that if you are using App Center to distribute your Prototype Build, the only parameters you *have* to provide
104+ to this action are `app_display_name` and `app_center_org_name`; plus, for `metadata` most of the interesting values will already be pre-filled.
105+
106+ Any of those implicit default values/metadata can of course be overridden by passing an explicit value to the appropriate parameter(s).
107+ DESC
108+ end
109+
53110 def self . available_options
111+ app_center_auto = '(will be automatically extracted from `lane_context if you used `appcenter_upload` to distribute your Prototype build)'
54112 [
55113 FastlaneCore ::ConfigItem . new (
56- key : :appcenter_org_name ,
57- env_name : 'APPCENTER_OWNER_NAME' , # Same as the one used by the `appcenter_upload` action
58- description : 'The name of the organization in App Center' ,
114+ key : :app_display_name ,
115+ env_name : 'FL_PROTOTYPE_BUILD_DETAILS_COMMENT_APP_DISPLAY_NAME' ,
116+ description : 'The display name to use for the app in the comment message' ,
117+ optional : false ,
59118 type : String
60119 ) ,
61120 FastlaneCore ::ConfigItem . new (
62- key : :appcenter_app_name ,
63- env_name : 'APPCENTER_APP_NAME' , # Same as the one used by the `appcenter_upload` action
64- description : 'The name of the app in App Center' ,
65- type : String
121+ key : :app_center_org_name ,
122+ env_name : 'APPCENTER_OWNER_NAME' , # Intentionally the same as the one used by the `appcenter_upload` action
123+ description : 'The name of the organization in App Center (if you used `appcenter_upload` to distribute your Prototype build)' ,
124+ type : String ,
125+ optional : true
126+ ) ,
127+ FastlaneCore ::ConfigItem . new (
128+ key : :app_center_app_name ,
129+ env_name : 'APPCENTER_APP_NAME' , # Intentionally the same as the one used by the `appcenter_upload` action
130+ description : "The name of the app in App Center #{ app_center_auto } " ,
131+ type : String ,
132+ optional : true ,
133+ default_value_dynamic : true # As it will be extracted from the `lane_context`` if you used `appcenter_upload``
66134 ) ,
67135 FastlaneCore ::ConfigItem . new (
68- key : :appcenter_release_id ,
69- env_name : 'FL_PROTOTYPE_BUILD_APPCENTER_RELEASE_ID' ,
70- description : "The release ID/Number in App Center; can be obtained using `lane_context[SharedValues::APPCENTER_BUILD_INFORMATION]['id']`" ,
71- type : Integer
136+ key : :app_center_release_id ,
137+ env_name : 'APPCENTER_RELEASE_ID' ,
138+ description : "The release ID/Number in App Center #{ app_center_auto } " ,
139+ type : String ,
140+ optional : true ,
141+ default_value_dynamic : true # As it will be extracted from the `lane_context`` if you used `appcenter_upload``
142+ ) ,
143+ FastlaneCore ::ConfigItem . new (
144+ key : :app_icon ,
145+ env_name : 'FL_PROTOTYPE_BUILD_DETAILS_COMMENT_APP_ICON' ,
146+ description : "An `:emojicode:` or URL to use for the icon of the app in the message. #{ app_center_auto } " ,
147+ type : String ,
148+ optional : true ,
149+ default_value_dynamic : true # As it will be extracted from the `lane_context`` if you used `appcenter_upload``
72150 ) ,
73151 FastlaneCore ::ConfigItem . new (
74152 key : :download_url ,
75- env_name : 'FL_PROTOTYPE_BUILD_DOWNLOAD_URL' ,
76- description : 'The URL to download the build directly; e.g. a public link to the `.apk` file; you might use `lane_context[SharedValues::APPCENTER_DOWNLOAD_LINK]` for this for example' ,
153+ env_name : 'FL_PROTOTYPE_BUILD_DETAILS_COMMENT_DOWNLOAD_URL' ,
154+ description : 'The URL to download the build as a direct download. ' \
155+ + 'If you uploaded the build to App Center, we recommend leaving this nil (the comment will use the URL to the App Center build for the QR code)' ,
77156 type : String ,
78157 optional : true ,
79158 default_value : nil
@@ -88,25 +167,20 @@ def self.available_options
88167 FastlaneCore ::ConfigItem . new (
89168 key : :metadata ,
90169 env_name : 'FL_PROTOTYPE_BUILD_DETAILS_COMMENT_METADATA' ,
91- description : 'All additional metadata (as key/value pairs) you want to include in the HTML table of the comment' ,
170+ description : 'All additional metadata (as key/value pairs) you want to include in the HTML table of the comment. ' \
171+ + 'If you are running this action after `appcenter_upload`, some metadata will automatically be added to this list too' ,
92172 type : Hash ,
93173 optional : true ,
94- default_value : { }
174+ default_value_dynamic : true # As some metadata will be auto-filled if you used `appcenter_upload`
95175 ) ,
96176 FastlaneCore ::ConfigItem . new (
97177 key : :footnote ,
98178 env_name : 'FL_PROTOTYPE_BUILD_DETAILS_COMMENT_FOOTNOTE' ,
99- description : 'Optional footnote to add below the HTML table of the comment' ,
179+ description : 'Optional footnote to add below the HTML table of the comment. ' \
180+ + 'If you are running this action after `appcenter_upload`, a default footnote for Automatticians will be used unless you provide an explicit value' ,
100181 type : String ,
101- default_value : '<em>Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.</em>'
102- ) ,
103- FastlaneCore ::ConfigItem . new (
104- key : :commit ,
105- # Buildkite ENV var: https://buildkite.com/docs/pipelines/environment-variables#BUILDKITE_COMMIT
106- env_names : [ 'BUILDKITE_COMMIT' ] , # Feel free to add more CI-specific env vars for other CI providers
107- description : 'The commit this prototype build was build from; usually not passed explicitly, but derived from the environment variable instead' ,
108- type : String ,
109- optional : true
182+ optional : true ,
183+ default_value_dynamic : true # We have a default footnote for the case when you used App Center
110184 ) ,
111185 ]
112186 end
@@ -116,7 +190,7 @@ def self.return_type
116190 end
117191
118192 def self . return_value
119- 'The HTML comment containing all the relevant info about a Prototype build published to App Center '
193+ 'The HTML comment containing all the relevant info about a Prototype build and links to install it '
120194 end
121195
122196 def self . authors
0 commit comments