fastlane-plugin-wpmreleasetoolkit 4.0.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_localize_libs_action.rb +10 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_update_metadata_source_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_validate_lib_strings_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_betabuild_prechecks.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_prechecks.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_preflight.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_beta.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_final_release.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_hotfix.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_codefreeze_prechecks.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_completecodefreeze_prechecks.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_create_xml_release_notes.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_current_branch_is_hotfix.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_download_file_by_version.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_download_translations_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_finalize_prechecks.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_firebase_test.rb +187 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_alpha_version.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_app_version.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_release_version.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/{android_hotifx_prechecks.rb → android_hotfix_prechecks.rb} +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_send_app_size_metrics.rb +279 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_tag_build.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_release_notes.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/check_for_toolkit_updates_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/check_translation_progress.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/circleci_trigger_job_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/close_milestone_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_new_milestone_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/extract_release_notes_for_version_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/firebase_login.rb +44 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/get_prs_list_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_downloadmetadata_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_update_metadata_source.rb +1 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/promo_screenshots_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/removebranchprotection_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setbranchprotection_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setfrozentag_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_add_files_to_copy_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_apply_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_download_action.rb +2 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_setup_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_update_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_validate_action.rb +3 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_development_certificates_to_provisioning_profiles.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_devices_to_provisioning_profiles.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_betabuild_prechecks.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_build_prechecks.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_build_preflight.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_beta.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_hotfix.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_release.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_check_beta_deps.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_clear_intermediate_tags.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_codefreeze_prechecks.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_completecodefreeze_prechecks.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_current_branch_is_hotfix.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_final_tag.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_finalize_prechecks.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_app_version.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_build_version.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_store_app_sizes.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/{ios_hotifx_prechecks.rb → ios_hotfix_prechecks.rb} +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_lint_localizations.rb +48 -9
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_localize_project.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_merge_strings_files.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_send_app_size_metrics.rb +170 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_tag_build.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata_source.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_release_notes.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_validate_ci_build.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb +72 -49
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/app_size_metrics_helper.rb +95 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb +10 -18
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_helper.rb +7 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_linter_helper.rb +20 -34
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_strings_file_validation_helper.rb +107 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_download_helper.rb +3 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb +2 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/release_notes_helper.rb +4 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/user_agent.rb +5 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/models/file_reference.rb +2 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/models/firebase_account.rb +19 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/models/firebase_device.rb +62 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/models/firebase_test_lab_result.rb +36 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/models/firebase_test_runner.rb +104 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/version.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit.rb +2 -2
- metadata +122 -83
@@ -2,10 +2,20 @@ module Fastlane
|
|
2
2
|
module Actions
|
3
3
|
class IosLintLocalizationsAction < Action
|
4
4
|
def self.run(params)
|
5
|
-
violations =
|
5
|
+
violations = Hash.new([])
|
6
6
|
|
7
7
|
loop do
|
8
|
-
violations = self.
|
8
|
+
# If we did `violations = self.run...` we'd lose the default value for missing key being `[]` that we set above with `Hash.new`.
|
9
|
+
# We want that default value so that we can use `+=` when adding the duplicate keys violations below.
|
10
|
+
violations = violations.merge(self.run_linter(params))
|
11
|
+
|
12
|
+
if params[:check_duplicate_keys]
|
13
|
+
find_duplicated_keys(params).each do |language, duplicates|
|
14
|
+
violations[language] += duplicates
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
report(violations: violations, base_lang: params[:base_lang])
|
9
19
|
break unless !violations.empty? && params[:allow_retry] && UI.confirm(RETRY_MESSAGE)
|
10
20
|
end
|
11
21
|
|
@@ -22,17 +32,38 @@ module Fastlane
|
|
22
32
|
install_path: resolve_path(params[:install_path]),
|
23
33
|
version: params[:version]
|
24
34
|
)
|
25
|
-
|
35
|
+
|
36
|
+
helper.run(
|
26
37
|
input_dir: resolve_path(params[:input_dir]),
|
27
38
|
base_lang: params[:base_lang],
|
28
39
|
only_langs: params[:only_langs]
|
29
40
|
)
|
41
|
+
end
|
30
42
|
|
31
|
-
|
32
|
-
|
43
|
+
def self.report(violations:, base_lang:)
|
44
|
+
violations.each do |lang, lang_violations|
|
45
|
+
UI.error "Inconsistencies found between '#{base_lang}' and '#{lang}':\n\n#{lang_violations.join("\n")}\n"
|
33
46
|
end
|
47
|
+
end
|
34
48
|
|
35
|
-
|
49
|
+
def self.find_duplicated_keys(params)
|
50
|
+
duplicate_keys = {}
|
51
|
+
|
52
|
+
files_to_lint = Dir.chdir(params[:input_dir]) do
|
53
|
+
Dir.glob('*.lproj/Localizable.strings').map do |file|
|
54
|
+
{
|
55
|
+
language: File.basename(File.dirname(file), '.lproj'),
|
56
|
+
path: File.join(params[:input_dir], file)
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
files_to_lint.each do |file|
|
62
|
+
duplicates = Fastlane::Helper::Ios::StringsFileValidationHelper.find_duplicated_keys(file: file[:path])
|
63
|
+
duplicate_keys[file[:language]] = duplicates.map { |key, value| "`#{key}` was found at multiple lines: #{value.join(', ')}" } unless duplicates.empty?
|
64
|
+
end
|
65
|
+
|
66
|
+
duplicate_keys
|
36
67
|
end
|
37
68
|
|
38
69
|
RETRY_MESSAGE = <<~MSG
|
@@ -140,6 +171,14 @@ module Fastlane
|
|
140
171
|
default_value: false,
|
141
172
|
is_string: false # https://docs.fastlane.tools/advanced/actions/#boolean-parameters
|
142
173
|
),
|
174
|
+
FastlaneCore::ConfigItem.new(
|
175
|
+
key: :check_duplicate_keys,
|
176
|
+
env_name: 'FL_IOS_LINT_TRANSLATIONS_CHECK_DUPLICATE_KEYS',
|
177
|
+
description: 'Checks the input files for duplicate keys',
|
178
|
+
optional: true,
|
179
|
+
default_value: true,
|
180
|
+
is_string: false # https://docs.fastlane.tools/advanced/actions/#boolean-parameters
|
181
|
+
),
|
143
182
|
]
|
144
183
|
end
|
145
184
|
|
@@ -148,15 +187,15 @@ module Fastlane
|
|
148
187
|
end
|
149
188
|
|
150
189
|
def self.return_type
|
151
|
-
:
|
190
|
+
:hash
|
152
191
|
end
|
153
192
|
|
154
193
|
def self.return_value
|
155
|
-
'A hash, keyed by language code, whose values are
|
194
|
+
'A hash, keyed by language code, whose values are arrays of violations found for that language'
|
156
195
|
end
|
157
196
|
|
158
197
|
def self.authors
|
159
|
-
['
|
198
|
+
['Automattic']
|
160
199
|
end
|
161
200
|
|
162
201
|
def self.is_supported?(platform)
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'plist'
|
2
|
+
require_relative '../../helper/app_size_metrics_helper'
|
3
|
+
|
4
|
+
module Fastlane
|
5
|
+
module Actions
|
6
|
+
class IosSendAppSizeMetricsAction < Action
|
7
|
+
# Keys used by the metrics payload
|
8
|
+
IPA_FILE_SIZE_KEY = 'File Size'.freeze # value from `File.size` of the Universal `.ipa`
|
9
|
+
IPA_DOWNLOAD_SIZE_KEY = 'Download Size'.freeze # value from `app-thinning.plist`
|
10
|
+
IPA_INSTALL_SIZE_KEY = 'Install Size'.freeze # value from `app-thinning.plist`
|
11
|
+
|
12
|
+
def self.run(params)
|
13
|
+
# Check input parameters
|
14
|
+
api_url = URI(params[:api_url])
|
15
|
+
api_token = params[:api_token]
|
16
|
+
if (api_token.nil? || api_token.empty?) && !api_url.is_a?(URI::File)
|
17
|
+
UI.user_error!('An API token is required when using an `api_url` with a scheme other than `file://`')
|
18
|
+
end
|
19
|
+
|
20
|
+
# Build the payload base
|
21
|
+
metrics_helper = Fastlane::Helper::AppSizeMetricsHelper.new(
|
22
|
+
Platform: 'iOS',
|
23
|
+
'App Name': params[:app_name],
|
24
|
+
'App Version': params[:app_version],
|
25
|
+
'Build Type': params[:build_type],
|
26
|
+
Source: params[:source]
|
27
|
+
)
|
28
|
+
metrics_helper.add_metric(name: IPA_FILE_SIZE_KEY, value: File.size(params[:ipa_path]))
|
29
|
+
|
30
|
+
# Add app-thinning metrics to the payload if a `.plist` is provided
|
31
|
+
app_thinning_plist_path = params[:app_thinning_plist_path] || File.join(File.dirname(params[:ipa_path]), 'app-thinning.plist')
|
32
|
+
if File.exist?(app_thinning_plist_path)
|
33
|
+
plist = Plist.parse_xml(app_thinning_plist_path)
|
34
|
+
plist['variants'].each do |_key, variant|
|
35
|
+
variant_descriptors = variant['variantDescriptors'] || [{ 'device' => 'Universal' }]
|
36
|
+
variant_descriptors.each do |desc|
|
37
|
+
variant_metadata = { device: desc['device'], 'OS Version': desc['os-version'] }
|
38
|
+
metrics_helper.add_metric(name: IPA_DOWNLOAD_SIZE_KEY, value: variant['sizeCompressedApp'], metadata: variant_metadata)
|
39
|
+
metrics_helper.add_metric(name: IPA_INSTALL_SIZE_KEY, value: variant['sizeUncompressedApp'], metadata: variant_metadata)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Send the payload
|
45
|
+
metrics_helper.send_metrics(
|
46
|
+
to: api_url,
|
47
|
+
api_token: api_token,
|
48
|
+
use_gzip: params[:use_gzip_content_encoding]
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
#####################################################
|
53
|
+
# @!group Documentation
|
54
|
+
#####################################################
|
55
|
+
|
56
|
+
def self.description
|
57
|
+
'Send iOS app size metrics to our metrics server'
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.details
|
61
|
+
<<~DETAILS
|
62
|
+
Send iOS app size metrics to our metrics server.
|
63
|
+
|
64
|
+
In order to get Xcode generate the `app-thinning.plist` file (during `gym` and the export of the `.xcarchive`), you need to:
|
65
|
+
(1) Use either `ad-hoc`, `enterprise` or `development` export method (in particular, won't work with `app-store`),
|
66
|
+
(2) Provide `thinning: '<thin-for-all-variants>'` as part of your `export_options` of `gym` (or in your `options.plist` file if you use raw `xcodebuild`)
|
67
|
+
See https://help.apple.com/xcode/mac/11.0/index.html#/devde46df08a
|
68
|
+
|
69
|
+
For builds exported with the `app-store` method, `xcodebuild` won't generate an `app-thinning.plist` file; so you will only be able to get
|
70
|
+
the Universal `.ipa` file size as a metric, but won't get the per-device, broken-down install and download sizes for each thinned variant.
|
71
|
+
|
72
|
+
See https://github.com/Automattic/apps-metrics for the API contract expected by the Metrics server you are expected to send those metrics to.
|
73
|
+
|
74
|
+
Tip: If you provide a `file://` URL for the `api_url`, the action will write the payload on disk at the specified path instead of sending
|
75
|
+
the data to a endpoint over network. This can be useful e.g. to inspect the payload and debug it, or to store the metrics data as CI artefacts.
|
76
|
+
DETAILS
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.available_options
|
80
|
+
[
|
81
|
+
FastlaneCore::ConfigItem.new(
|
82
|
+
key: :api_url,
|
83
|
+
env_name: 'FL_IOS_SEND_APP_SIZE_METRICS_API_URL',
|
84
|
+
description: 'The endpoint API URL to publish metrics to. (Note: you can also point to a `file://` URL to write the payload to a file instead)',
|
85
|
+
type: String,
|
86
|
+
optional: false
|
87
|
+
),
|
88
|
+
FastlaneCore::ConfigItem.new(
|
89
|
+
key: :api_token,
|
90
|
+
env_name: 'FL_IOS_SEND_APP_SIZE_METRICS_API_TOKEN',
|
91
|
+
description: 'The bearer token to call the API. Required, unless `api_url` is a `file://` URL',
|
92
|
+
type: String,
|
93
|
+
optional: true
|
94
|
+
),
|
95
|
+
FastlaneCore::ConfigItem.new(
|
96
|
+
key: :use_gzip_content_encoding,
|
97
|
+
env_name: 'FL_IOS_SEND_APP_SIZE_METRICS_USE_GZIP_CONTENT_ENCODING',
|
98
|
+
description: 'Specify that we should use `Content-Encoding: gzip` and gzip the body when sending the request',
|
99
|
+
type: FastlaneCore::Boolean,
|
100
|
+
default_value: true
|
101
|
+
),
|
102
|
+
FastlaneCore::ConfigItem.new(
|
103
|
+
key: :app_name,
|
104
|
+
env_name: 'FL_IOS_SEND_APP_SIZE_METRICS_APP_NAME',
|
105
|
+
description: 'The name of the app for which we are publishing metrics, to help with filtering and grouping',
|
106
|
+
type: String,
|
107
|
+
optional: false
|
108
|
+
),
|
109
|
+
FastlaneCore::ConfigItem.new(
|
110
|
+
key: :app_version,
|
111
|
+
env_name: 'FL_IOS_SEND_APP_SIZE_METRICS_APP_VERSION',
|
112
|
+
description: 'The version of the app for which we are publishing metrics, to help with filtering and grouping',
|
113
|
+
type: String,
|
114
|
+
optional: false
|
115
|
+
),
|
116
|
+
FastlaneCore::ConfigItem.new(
|
117
|
+
key: :build_type,
|
118
|
+
env_name: 'FL_IOS_SEND_APP_SIZE_METRICS_BUILD_TYPE',
|
119
|
+
description: 'The build configuration for which we are publishing metrics, to help with filtering and grouping. E.g. `Debug`, `Release`',
|
120
|
+
type: String,
|
121
|
+
optional: true
|
122
|
+
),
|
123
|
+
FastlaneCore::ConfigItem.new(
|
124
|
+
key: :source,
|
125
|
+
env_name: 'FL_IOS_SEND_APP_SIZE_METRICS_SOURCE',
|
126
|
+
description: 'The type of event at the origin of that build, to help with filtering and grouping. E.g. `pr`, `beta`, `final-release`',
|
127
|
+
type: String,
|
128
|
+
optional: true
|
129
|
+
),
|
130
|
+
FastlaneCore::ConfigItem.new(
|
131
|
+
key: :ipa_path,
|
132
|
+
env_name: 'FL_IOS_SEND_APP_SIZE_METRICS_IPA_PATH',
|
133
|
+
description: 'The path to the `.ipa` to extract size information from',
|
134
|
+
type: String,
|
135
|
+
optional: false,
|
136
|
+
default_value: Actions.lane_context[SharedValues::IPA_OUTPUT_PATH],
|
137
|
+
verify_block: proc do |value|
|
138
|
+
UI.user_error!('You must provide an path to an existing `.ipa` file') unless File.exist?(value)
|
139
|
+
end
|
140
|
+
),
|
141
|
+
FastlaneCore::ConfigItem.new(
|
142
|
+
key: :app_thinning_plist_path,
|
143
|
+
env_name: 'FL_IOS_SEND_APP_SIZE_METRICS_APP_THINNING_PLIST_PATH',
|
144
|
+
description: 'The path to the `app-thinning.plist` file to extract thinning size information from. ' \
|
145
|
+
+ 'By default, will try to use the `app-thinning.plist` file next to the `ipa_path`, if that file exists',
|
146
|
+
type: String,
|
147
|
+
optional: true,
|
148
|
+
default_value_dynamic: true
|
149
|
+
),
|
150
|
+
]
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.return_type
|
154
|
+
:integer
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.return_value
|
158
|
+
'The HTTP return code from the call. Expect a 201 when new metrics were received successfully and entries created in the database'
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.authors
|
162
|
+
['Automattic']
|
163
|
+
end
|
164
|
+
|
165
|
+
def self.is_supported?(platform)
|
166
|
+
platform == :ios
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -9,86 +9,99 @@ module Fastlane
|
|
9
9
|
module Helper
|
10
10
|
module Android
|
11
11
|
module LocalizeHelper
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
LIB_SOURCE_XML_ATTR = 'a8c-src-lib'.freeze
|
13
|
+
|
14
|
+
# Checks if `string_node` has the `content_override` flag set
|
15
|
+
def self.skip_string_by_tag?(string_node)
|
16
|
+
skip = string_node.attr('content_override') == 'true' unless string_node.attr('content_override').nil?
|
15
17
|
if skip
|
16
|
-
|
18
|
+
UI.message " - Skipping #{string_node.attr('name')} string"
|
17
19
|
return true
|
18
20
|
end
|
19
21
|
|
20
22
|
return false
|
21
23
|
end
|
22
24
|
|
23
|
-
# Checks if string_name is in the
|
24
|
-
def self.skip_string_by_exclusion_list(library, string_name)
|
25
|
-
return false
|
25
|
+
# Checks if `string_name` is in the exclusion list
|
26
|
+
def self.skip_string_by_exclusion_list?(library, string_name)
|
27
|
+
return false if library[:exclusions].nil?
|
26
28
|
|
27
29
|
skip = library[:exclusions].include?(string_name)
|
28
30
|
if skip
|
29
|
-
|
31
|
+
UI.message " - Skipping #{string_name} string"
|
30
32
|
return true
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
#
|
35
|
-
def self.
|
36
|
-
|
37
|
-
|
36
|
+
# Adds the appropriate XML attributes to an XML `<string>` node according to library configuration
|
37
|
+
def self.add_xml_attributes!(string_node, library)
|
38
|
+
if library[:add_ignore_attr] == true
|
39
|
+
existing_ignores = (string_node['tools:ignore'] || '').split(',')
|
40
|
+
existing_ignores.append('UnusedResources') unless existing_ignores.include?('UnusedResources')
|
41
|
+
string_node['tools:ignore'] = existing_ignores.join(',')
|
42
|
+
end
|
43
|
+
string_node[LIB_SOURCE_XML_ATTR] = library[:source_id] unless library[:source_id].nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
# Merge a single `lib_string_node` XML node into the `main_strings_xml``
|
47
|
+
def self.merge_string_node(main_strings_xml, library, lib_string_node)
|
48
|
+
string_name = lib_string_node.attr('name')
|
49
|
+
string_content = lib_string_node.content
|
38
50
|
|
39
51
|
# Skip strings in the exclusions list
|
40
|
-
return :skipped if skip_string_by_exclusion_list(library, string_name)
|
52
|
+
return :skipped if skip_string_by_exclusion_list?(library, string_name)
|
41
53
|
|
42
54
|
# Search for the string in the main file
|
43
55
|
result = :added
|
44
|
-
|
45
|
-
if
|
56
|
+
main_strings_xml.xpath('//string').each do |main_string_node|
|
57
|
+
if main_string_node.attr('name') == string_name
|
46
58
|
# Skip if the string has the content_override tag
|
47
|
-
return :skipped if skip_string_by_tag(
|
59
|
+
return :skipped if skip_string_by_tag?(main_string_node)
|
48
60
|
|
49
61
|
# If nodes are equivalent, skip
|
50
|
-
return :found if
|
62
|
+
return :found if lib_string_node =~ main_string_node
|
51
63
|
|
52
64
|
# The string needs an update
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
break
|
65
|
+
if main_string_node.attr('tools:ignore').nil?
|
66
|
+
# No `tools:ignore` attribute; completely replace existing main string node with lib's one
|
67
|
+
add_xml_attributes!(lib_string_node, library)
|
68
|
+
main_string_node.replace lib_string_node
|
58
69
|
else
|
59
|
-
#
|
60
|
-
|
61
|
-
|
70
|
+
# Has the `tools:ignore` flag; update the content without touching the other existing attributes
|
71
|
+
add_xml_attributes!(main_string_node, library)
|
72
|
+
main_string_node.content = string_content
|
62
73
|
end
|
74
|
+
return :updated
|
63
75
|
end
|
64
76
|
end
|
65
77
|
|
66
78
|
# String not found, or removed because needing update and not in the exclusion list: add to the main file
|
67
|
-
|
79
|
+
add_xml_attributes!(lib_string_node, library)
|
80
|
+
main_strings_xml.xpath('//string').last().add_next_sibling("\n#{' ' * 4}#{lib_string_node.to_xml().strip}")
|
68
81
|
return result
|
69
82
|
end
|
70
83
|
|
71
|
-
# Verify a string
|
72
|
-
def self.verify_string(
|
73
|
-
string_name =
|
74
|
-
string_content =
|
84
|
+
# Verify a string node from a library has properly been merged into the main one
|
85
|
+
def self.verify_string(main_strings_xml, library, lib_string_node)
|
86
|
+
string_name = lib_string_node.attr('name')
|
87
|
+
string_content = lib_string_node.content
|
75
88
|
|
76
89
|
# Skip strings in the exclusions list
|
77
|
-
return if skip_string_by_exclusion_list(library, string_name)
|
90
|
+
return if skip_string_by_exclusion_list?(library, string_name)
|
78
91
|
|
79
92
|
# Search for the string in the main file
|
80
|
-
|
81
|
-
if
|
93
|
+
main_strings_xml.xpath('//string').each do |main_string_node|
|
94
|
+
if main_string_node.attr('name') == string_name
|
82
95
|
# Skip if the string has the content_override tag
|
83
|
-
return if skip_string_by_tag(
|
96
|
+
return if skip_string_by_tag?(main_string_node)
|
84
97
|
|
85
|
-
#
|
86
|
-
UI.user_error!("String #{string_name} [#{string_content}] has been updated in the main file but not in the library #{library[:library]}.") if
|
98
|
+
# Check if up-to-date
|
99
|
+
UI.user_error!("String #{string_name} [#{string_content}] has been updated in the main file but not in the library #{library[:library]}.") if main_string_node.content != string_content
|
87
100
|
return
|
88
101
|
end
|
89
102
|
end
|
90
103
|
|
91
|
-
# String not found and not in the exclusion list
|
104
|
+
# String not found and not in the exclusion list
|
92
105
|
UI.user_error!("String #{string_name} [#{string_content}] was found in library #{library[:library]} but not in the main file.")
|
93
106
|
end
|
94
107
|
|
@@ -98,27 +111,33 @@ module Fastlane
|
|
98
111
|
# @param [Hash] library Hash describing the library to merge. The Hash should contain the following keys:
|
99
112
|
# - `:library`: The human readable name of the library, used to display in console messages
|
100
113
|
# - `:strings_path`: The path to the strings.xml file of the library to merge into the main one
|
101
|
-
# - `:exclusions`: An array of strings keys to exclude during merge. Any of those keys from the
|
114
|
+
# - `:exclusions`: An array of strings keys to exclude during merge. Any of those keys from the
|
115
|
+
# library's `strings.xml` will be skipped and won't be merged into the main one.
|
116
|
+
# - `:source_id`: An optional `String` which will be added as the `a8c-src-lib` XML attribute
|
117
|
+
# to strings coming from this library, to help identify their source in the merged file.
|
118
|
+
# - `:add_ignore_attr`: If set to `true`, will add `tools:ignore="UnusedResources"` to merged strings.
|
119
|
+
#
|
102
120
|
# @return [Boolean] True if at least one string from the library has been added to (or has updated) the main strings file.
|
121
|
+
#
|
103
122
|
def self.merge_lib(main, library)
|
104
123
|
UI.message("Merging #{library[:library]} strings into #{main}")
|
105
|
-
|
106
|
-
|
124
|
+
main_strings_xml = File.open(main) { |f| Nokogiri::XML(f, nil, Encoding::UTF_8.to_s) }
|
125
|
+
lib_strings_xml = File.open(library[:strings_path]) { |f| Nokogiri::XML(f, nil, Encoding::UTF_8.to_s) }
|
107
126
|
|
108
127
|
updated_count = 0
|
109
128
|
untouched_count = 0
|
110
129
|
added_count = 0
|
111
130
|
skipped_count = 0
|
112
|
-
|
113
|
-
res =
|
131
|
+
lib_strings_xml.xpath('//string').each do |string_node|
|
132
|
+
res = merge_string_node(main_strings_xml, library, string_node)
|
114
133
|
case res
|
115
134
|
when :updated
|
116
|
-
|
135
|
+
UI.verbose "#{string_node.attr('name')} updated."
|
117
136
|
updated_count = updated_count + 1
|
118
137
|
when :found
|
119
138
|
untouched_count = untouched_count + 1
|
120
139
|
when :added
|
121
|
-
|
140
|
+
UI.verbose "#{string_node.attr('name')} added."
|
122
141
|
added_count = added_count + 1
|
123
142
|
when :skipped
|
124
143
|
skipped_count = skipped_count + 1
|
@@ -128,7 +147,7 @@ module Fastlane
|
|
128
147
|
end
|
129
148
|
|
130
149
|
File.open(main, 'w:UTF-8') do |f|
|
131
|
-
f.write(
|
150
|
+
f.write(main_strings_xml.to_xml(indent: 4))
|
132
151
|
end
|
133
152
|
|
134
153
|
UI.message("Done (#{added_count} added, #{updated_count} updated, #{untouched_count} untouched, #{skipped_count} skipped).")
|
@@ -144,8 +163,8 @@ module Fastlane
|
|
144
163
|
|
145
164
|
diff_string = diff_string.slice(0..(end_index - 1))
|
146
165
|
|
147
|
-
lib_strings.xpath('//string').each do |
|
148
|
-
res = verify_string(main_strings, library,
|
166
|
+
lib_strings.xpath('//string').each do |string_node|
|
167
|
+
res = verify_string(main_strings, library, string_node) if string_node.attr('name') == diff_string
|
149
168
|
end
|
150
169
|
end
|
151
170
|
end
|
@@ -263,9 +282,13 @@ module Fastlane
|
|
263
282
|
#
|
264
283
|
def self.download_glotpress_export_file(project_url:, locale:, filters:)
|
265
284
|
query_params = filters.transform_keys { |k| "filters[#{k}]" }.merge(format: 'android')
|
266
|
-
uri = URI.parse("#{project_url.chomp('/')}/#{locale}/default/export-translations
|
285
|
+
uri = URI.parse("#{project_url.chomp('/')}/#{locale}/default/export-translations/?#{URI.encode_www_form(query_params)}")
|
286
|
+
|
287
|
+
# Set an unambiguous User Agent so GlotPress won't rate-limit us
|
288
|
+
options = { 'User-Agent' => Wpmreleasetoolkit::USER_AGENT }
|
289
|
+
|
267
290
|
begin
|
268
|
-
uri.open { |f| Nokogiri::XML(f.read.gsub("\t", ' '), nil, Encoding::UTF_8.to_s) }
|
291
|
+
uri.open(options) { |f| Nokogiri::XML(f.read.gsub("\t", ' '), nil, Encoding::UTF_8.to_s) }
|
269
292
|
rescue StandardError => e
|
270
293
|
UI.error "Error downloading #{locale} - #{e.message}"
|
271
294
|
return nil
|