fastlane-plugin-wpmreleasetoolkit 1.1.0 → 1.4.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.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_betabuild_prechecks.rb +17 -11
  3. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_prechecks.rb +11 -5
  4. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_beta.rb +24 -24
  5. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_final_release.rb +25 -22
  6. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_hotfix.rb +23 -28
  7. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb +29 -38
  8. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_codefreeze_prechecks.rb +14 -7
  9. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_completecodefreeze_prechecks.rb +8 -2
  10. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_current_branch_is_hotfix.rb +9 -1
  11. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_finalize_prechecks.rb +6 -2
  12. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_alpha_version.rb +7 -1
  13. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_app_version.rb +7 -1
  14. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_release_version.rb +7 -1
  15. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_hotifx_prechecks.rb +4 -4
  16. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_tag_build.rb +9 -3
  17. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/check_translation_progress.rb +147 -0
  18. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_hotfix.rb +30 -15
  19. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_git_helper.rb +14 -5
  20. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb +124 -46
  21. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/filesystem_helper.rb +3 -1
  22. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/glotpress_helper.rb +79 -0
  23. data/lib/fastlane/plugin/wpmreleasetoolkit/version.rb +1 -1
  24. metadata +18 -2
@@ -9,8 +9,10 @@ module Fastlane
9
9
 
10
10
  UI.user_error!('This is not a release branch. Abort.') unless other_action.git_branch.start_with?('release/')
11
11
 
12
- version = Fastlane::Helper::Android::VersionHelper.get_public_version
13
- message = "Completing code freeze for: #{version}\n"
12
+ app = params[:app]
13
+
14
+ version = Fastlane::Helper::Android::VersionHelper.get_public_version(app)
15
+ message = "Completing code freeze for: [#{app}]#{version}\n"
14
16
  unless params[:skip_confirm]
15
17
  UI.user_error!('Aborted by user request') unless UI.confirm("#{message}Do you want to continue?")
16
18
  else
@@ -42,6 +44,10 @@ module Fastlane
42
44
  description: 'Skips confirmation',
43
45
  is_string: false, # true: verifies the input is a string, false: every kind of value
44
46
  default_value: false), # the default value if the user didn't provide one
47
+ FastlaneCore::ConfigItem.new(key: :app,
48
+ env_name: 'PROJECT_NAME',
49
+ description: 'The name of the app to get the release version for',
50
+ is_string: true), # true: verifies the input is a string, false: every kind of value
45
51
  ]
46
52
  end
47
53
 
@@ -7,7 +7,8 @@ module Fastlane
7
7
  class AndroidCurrentBranchIsHotfixAction < Action
8
8
  def self.run(params)
9
9
  require_relative '../../helper/android/android_version_helper'
10
- Fastlane::Helper::Android::VersionHelper.is_hotfix?(Fastlane::Helper::Android::VersionHelper.get_release_version)
10
+ version = Fastlane::Helper::Android::VersionHelper.get_release_version(product_name: params[:app])
11
+ Fastlane::Helper::Android::VersionHelper.is_hotfix?(version)
11
12
  end
12
13
 
13
14
  #####################################################
@@ -23,6 +24,13 @@ module Fastlane
23
24
  end
24
25
 
25
26
  def self.available_options
27
+ # Define all options your action supports.
28
+ [
29
+ FastlaneCore::ConfigItem.new(key: :app,
30
+ env_name: 'PROJECT_NAME',
31
+ description: 'The name of the app to get the release version for',
32
+ is_string: true), # true: verifies the input is a string, false: every kind of value
33
+ ]
26
34
  end
27
35
 
28
36
  def self.output
@@ -13,8 +13,8 @@ module Fastlane
13
13
 
14
14
  UI.user_error!('This is not a release branch. Abort.') unless other_action.git_branch.start_with?('release/')
15
15
 
16
- version = Fastlane::Helper::Android::VersionHelper.get_public_version
17
- message = "Finalizing release: #{version}\n"
16
+ version = Fastlane::Helper::Android::VersionHelper.get_public_version(params[:app])
17
+ message = "Finalizing #{params[:app]} release: #{version}\n"
18
18
  if params[:skip_confirm]
19
19
  UI.message(message)
20
20
  else
@@ -49,6 +49,10 @@ module Fastlane
49
49
  description: 'Skips confirmation',
50
50
  is_string: false, # true: verifies the input is a string, false: every kind of value
51
51
  default_value: false), # the default value if the user didn't provide one
52
+ FastlaneCore::ConfigItem.new(key: :app,
53
+ env_name: 'PROJECT_NAME',
54
+ description: 'The name of the app to get the release version for',
55
+ is_string: true), # true: verifies the input is a string, false: every kind of value
52
56
  ]
53
57
  end
54
58
 
@@ -3,7 +3,7 @@ module Fastlane
3
3
  class AndroidGetAlphaVersionAction < Action
4
4
  def self.run(params)
5
5
  require_relative '../../helper/android/android_version_helper'
6
- Fastlane::Helper::Android::VersionHelper.get_alpha_version()
6
+ Fastlane::Helper::Android::VersionHelper.get_alpha_version(params[:app])
7
7
  end
8
8
 
9
9
  #####################################################
@@ -20,6 +20,12 @@ module Fastlane
20
20
 
21
21
  def self.available_options
22
22
  # Define all options your action supports.
23
+ [
24
+ FastlaneCore::ConfigItem.new(key: :app,
25
+ env_name: 'PROJECT_NAME',
26
+ description: 'The name of the app to get the release version for',
27
+ is_string: true), # true: verifies the input is a string, false: every kind of value
28
+ ]
23
29
  end
24
30
 
25
31
  def self.output
@@ -3,7 +3,7 @@ module Fastlane
3
3
  class AndroidGetAppVersionAction < Action
4
4
  def self.run(params)
5
5
  require_relative '../../helper/android/android_version_helper'
6
- Fastlane::Helper::Android::VersionHelper.get_public_version
6
+ Fastlane::Helper::Android::VersionHelper.get_public_version(params[:app])
7
7
  end
8
8
 
9
9
  #####################################################
@@ -20,6 +20,12 @@ module Fastlane
20
20
 
21
21
  def self.available_options
22
22
  # Define all options your action supports.
23
+ [
24
+ FastlaneCore::ConfigItem.new(key: :app,
25
+ env_name: 'PROJECT_NAME',
26
+ description: 'The name of the app to get the release version for',
27
+ is_string: true), # true: verifies the input is a string, false: every kind of value
28
+ ]
23
29
  end
24
30
 
25
31
  def self.output
@@ -3,7 +3,7 @@ module Fastlane
3
3
  class AndroidGetReleaseVersionAction < Action
4
4
  def self.run(params)
5
5
  require_relative '../../helper/android/android_version_helper'
6
- Fastlane::Helper::Android::VersionHelper.get_release_version()
6
+ Fastlane::Helper::Android::VersionHelper.get_release_version(product_name: params[:app])
7
7
  end
8
8
 
9
9
  #####################################################
@@ -20,6 +20,12 @@ module Fastlane
20
20
 
21
21
  def self.available_options
22
22
  # Define all options your action supports.
23
+ [
24
+ FastlaneCore::ConfigItem.new(key: :app,
25
+ env_name: 'PROJECT_NAME',
26
+ description: 'The name of the app to get the release version for',
27
+ is_string: true), # true: verifies the input is a string, false: every kind of value
28
+ ]
23
29
  end
24
30
 
25
31
  def self.output
@@ -14,7 +14,7 @@ module Fastlane
14
14
 
15
15
  # Confirm
16
16
  message = "Requested Hotfix version: #{new_ver}\n"
17
- message << "Branching from: #{prev_ver}\n"
17
+ message << "Branching from tag: #{prev_ver}\n"
18
18
 
19
19
  if params[:skip_confirm]
20
20
  UI.message(message)
@@ -50,13 +50,13 @@ module Fastlane
50
50
  [
51
51
  FastlaneCore::ConfigItem.new(key: :version_name,
52
52
  env_name: 'FL_ANDROID_HOTFIX_PRECHECKS_VERSION',
53
- description: 'The version to work on', # a short description of this parameter
53
+ description: 'The hotfix version number to create',
54
54
  is_string: true),
55
55
  FastlaneCore::ConfigItem.new(key: :skip_confirm,
56
56
  env_name: 'FL_ANDROID_HOTFIX_PRECHECKS_SKIPCONFIRM',
57
57
  description: 'Skips confirmation',
58
- is_string: false, # true: verifies the input is a string, false: every kind of value
59
- default_value: false), # the default value if the user didn't provide one
58
+ is_string: false, # Boolean
59
+ default_value: false),
60
60
  ]
61
61
  end
62
62
 
@@ -5,10 +5,12 @@ module Fastlane
5
5
  require_relative '../../helper/android/android_version_helper'
6
6
  require_relative '../../helper/android/android_git_helper'
7
7
 
8
- release_ver = Fastlane::Helper::Android::VersionHelper.get_release_version()
9
- alpha_ver = Fastlane::Helper::Android::VersionHelper.get_alpha_version() unless ENV['HAS_ALPHA_VERSION'].nil?
8
+ app = ENV['PROJECT_NAME'].nil? ? params[:app] : ENV['PROJECT_NAME']
9
+
10
+ release_ver = Fastlane::Helper::Android::VersionHelper.get_release_version(product_name: app)
11
+ alpha_ver = Fastlane::Helper::Android::VersionHelper.get_alpha_version(app)
10
12
  Fastlane::Helper::GitHelper.create_tag(release_ver[Fastlane::Helper::Android::VersionHelper::VERSION_NAME])
11
- Fastlane::Helper::GitHelper.create_tag(alpha_ver[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]) unless ENV['HAS_ALPHA_VERSION'].nil? || (params[:tag_alpha] == false)
13
+ Fastlane::Helper::GitHelper.create_tag(alpha_ver[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]) unless alpha_ver.nil? || (params[:tag_alpha] == false)
12
14
  end
13
15
 
14
16
  #####################################################
@@ -30,6 +32,10 @@ module Fastlane
30
32
  description: 'True to skip tagging the alpha version',
31
33
  is_string: false,
32
34
  default_value: true),
35
+ FastlaneCore::ConfigItem.new(key: :app,
36
+ env_name: 'PROJECT_NAME',
37
+ description: 'The name of the app to get the release version for',
38
+ is_string: true), # true: verifies the input is a string, false: every kind of value
33
39
  ]
34
40
  end
35
41
 
@@ -0,0 +1,147 @@
1
+ module Fastlane
2
+ module Actions
3
+ class CheckTranslationProgressAction < Action
4
+ def self.run(params)
5
+ require_relative '../../helper/glotpress_helper'
6
+
7
+ UI.message('Checking translations status...')
8
+
9
+ under_threshold_langs = check_translations(
10
+ glotpress_url: params[:glotpress_url],
11
+ language_codes: params[:language_codes],
12
+ abort_on_violations: params[:abort_on_violations],
13
+ threshold: params[:min_acceptable_translation_percentage]
14
+ )
15
+
16
+ unless under_threshold_langs.empty?
17
+ check_results(
18
+ under_threshold_langs: under_threshold_langs,
19
+ threshold: params[:min_acceptable_translation_percentage],
20
+ skip_confirm: params[:skip_confirm]
21
+ )
22
+ end
23
+
24
+ UI.success('Done')
25
+ end
26
+
27
+ # Check the status of the translations and returns the list of violations
28
+ #
29
+ # @param [String] URL to the GlotPress project.
30
+ # @param [String] The list of codes (in GlotPress format) of the languages to check.
31
+ # @param [Bool] Whether to abort on the first found violation or not.
32
+ # @param [Integer] The minimum acceptable percentage of translated strings.
33
+ #
34
+ # @return [Array] The list of violations (array of hashes of "language code" and "current percentage")
35
+ #
36
+ def self.check_translations(glotpress_url:, language_codes:, abort_on_violations:, threshold:)
37
+ under_threshold_langs = []
38
+
39
+ data = begin
40
+ Fastlane::Helper::GlotPressHelper.get_translation_status_data(glotpress_url: glotpress_url)
41
+ rescue StandardError
42
+ nil
43
+ end
44
+ UI.abort_with_message!("Can't retrieve data from #{glotpress_url}") if data.nil? || data.empty?
45
+
46
+ language_codes.each do |language_code|
47
+ UI.message("> Getting translation status for #{language_code}")
48
+ progress = begin
49
+ Fastlane::Helper::GlotPressHelper.get_translation_status(
50
+ data: data,
51
+ language_code: language_code
52
+ )
53
+ rescue StandardError
54
+ -1
55
+ end
56
+
57
+ if abort_on_violations
58
+ UI.abort_with_message!("Can't get data for language #{language_code}") if progress == -1
59
+ UI.abort_with_message!("#{language_code} is translated #{progress}% which is under the required #{threshold}%.") if progress < threshold
60
+ end
61
+
62
+ UI.message("Language #{language_code} is #{progress}% translated.")
63
+ under_threshold_langs.push({ lang: language_code, progress: progress }) if progress < threshold
64
+ end
65
+
66
+ under_threshold_langs
67
+ end
68
+
69
+ # Report the status of the translations and verify whether to abort or not
70
+ #
71
+ # @param [Array] The list of violations (array of hashes of "language code" and "current percentage")
72
+ # @param [Integer] The minimum acceptable percentage of translated strings.
73
+ # @param [Bool] If true, continue after the report without asking the user.
74
+ #
75
+ def self.check_results(under_threshold_langs:, threshold:, skip_confirm:)
76
+ message = "The translations for the following languages are below the #{threshold}% threshold:\n"
77
+
78
+ under_threshold_langs.each do |lang|
79
+ message << " - #{lang[:lang]} is at #{lang[:progress]}%.\n"
80
+ end
81
+
82
+ if skip_confirm
83
+ UI.important(message)
84
+ elsif UI.interactive?
85
+ UI.abort_with_message!('Aborted by user!') unless UI.confirm("#{message}Do you want to continue?")
86
+ else
87
+ UI.abort_with_message!(message)
88
+ end
89
+ end
90
+
91
+ #####################################################
92
+ # @!group Documentation
93
+ #####################################################
94
+
95
+ def self.description
96
+ 'Raises an error if the translation percentage is lower than the provided threshold'
97
+ end
98
+
99
+ def self.details
100
+ 'This actions checks the current status of the translations on GlotPress ' \
101
+ 'and raises an error if it\'s below the provided threshold'
102
+ end
103
+
104
+ def self.available_options
105
+ [
106
+ FastlaneCore::ConfigItem.new(key: :glotpress_url,
107
+ env_name: 'FL_CHECK_TRANSLATION_PROGRESS_GLOTPRESS_URL',
108
+ description: 'URL to the GlotPress project',
109
+ type: String),
110
+ FastlaneCore::ConfigItem.new(key: :language_codes,
111
+ env_name: 'FL_CHECK_TRANSLATION_PROGRESS_LANGUAGE_CODES',
112
+ description: 'The list of the codes of the languages to check',
113
+ type: Array,
114
+ optional: true,
115
+ # Default to Mag16.
116
+ default_value: 'ar de es fr he id it ja ko nl pt-br ru sv tr zh-cn zh-tw'.split()),
117
+ FastlaneCore::ConfigItem.new(key: :min_acceptable_translation_percentage,
118
+ env_name: 'FL_CHECK_TRANSLATION_PROGRESS_MIN_ACCEPTABLE_TRANSLATION_PERCENTAGE',
119
+ description: 'The threshold under which an error is raised',
120
+ type: Integer,
121
+ optional: true,
122
+ default_value: 100),
123
+ FastlaneCore::ConfigItem.new(key: :abort_on_violations,
124
+ env_name: 'FL_CHECK_TRANSLATION_ABORT_ON_VIOLATIONS',
125
+ description: 'Should we abort with a global error if any violations are found?',
126
+ optional: true,
127
+ default_value: true,
128
+ is_string: false),
129
+ FastlaneCore::ConfigItem.new(key: :skip_confirm,
130
+ env_name: 'FL_CHECK_TRANSLATION_SKIP_CONFIRM',
131
+ description: 'Move ahead without requesting confirmation if violations are found. Only works if "abort_on_violations" is disabled',
132
+ optional: true,
133
+ default_value: false,
134
+ is_string: false),
135
+ ]
136
+ end
137
+
138
+ def self.authors
139
+ ['loremattei']
140
+ end
141
+
142
+ def self.is_supported?(platform)
143
+ true
144
+ end
145
+ end
146
+ end
147
+ end
@@ -9,14 +9,18 @@ module Fastlane
9
9
  create_config(params[:previous_version], params[:version])
10
10
  show_config()
11
11
 
12
- UI.message 'Updating Fastlane deliver file...'
13
- Fastlane::Helper::Ios::VersionHelper.update_fastlane_deliver(@new_short_version)
14
- UI.message 'Done!'
12
+ update_deliverfile = params[:skip_deliver] == false
13
+ if update_deliverfile
14
+ UI.message 'Updating Fastlane deliver file...'
15
+ Fastlane::Helper::Ios::VersionHelper.update_fastlane_deliver(@new_short_version)
16
+ UI.message 'Done!'
17
+ end
18
+
15
19
  UI.message 'Updating XcConfig...'
16
20
  Fastlane::Helper::Ios::VersionHelper.update_xc_configs(@new_version, @new_short_version, @new_version_internal)
17
21
  UI.message 'Done!'
18
22
 
19
- Fastlane::Helper::Ios::GitHelper.commit_version_bump(include_deliverfile: true, include_metadata: false)
23
+ Fastlane::Helper::Ios::GitHelper.commit_version_bump(include_deliverfile: update_deliverfile, include_metadata: false)
20
24
 
21
25
  UI.message 'Done.'
22
26
  end
@@ -34,18 +38,29 @@ module Fastlane
34
38
  end
35
39
 
36
40
  def self.available_options
37
- # Define all options your action supports.
38
-
39
- # Below a few examples
40
41
  [
41
- FastlaneCore::ConfigItem.new(key: :version,
42
- env_name: 'FL_IOS_BUMP_VERSION_HOTFIX_VERSION',
43
- description: 'The version of the hotfix',
44
- is_string: true),
45
- FastlaneCore::ConfigItem.new(key: :previous_version,
46
- env_name: 'FL_IOS_BUMP_VERSION_HOTFIX_PREVIOUS_VERSION',
47
- description: 'The version to branch from',
48
- is_string: true), # the default value if the user didn't provide one
42
+ FastlaneCore::ConfigItem.new(
43
+ key: :version,
44
+ env_name: 'FL_IOS_BUMP_VERSION_HOTFIX_VERSION',
45
+ description: 'The version of the hotfix',
46
+ is_string: true
47
+ ),
48
+ FastlaneCore::ConfigItem.new(
49
+ key: :previous_version,
50
+ env_name: 'FL_IOS_BUMP_VERSION_HOTFIX_PREVIOUS_VERSION',
51
+ description: 'The version to branch from',
52
+ is_string: true
53
+ ),
54
+ FastlaneCore::ConfigItem.new(
55
+ key: :skip_deliver,
56
+ env_name: 'FL_IOS_BUMP_VERSION_HOTFIX_SKIP_DELIVER',
57
+ description: 'Skips Deliverfile key update',
58
+ is_string: false, # Boolean parameter
59
+ optional: true,
60
+ # Don't skip the Deliverfile by default. At the time of writing, 2 out of 3 consumers
61
+ # still have a Deliverfile.
62
+ default_value: false
63
+ ),
49
64
  ]
50
65
  end
51
66
 
@@ -12,11 +12,20 @@ module Fastlane
12
12
  # @env PROJECT_NAME The name of the directory containing the project code (especially containing the `build.gradle` file)
13
13
  #
14
14
  def self.commit_version_bump
15
- Fastlane::Helper::GitHelper.commit(
16
- message: 'Bump version number',
17
- files: File.join(ENV['PROJECT_ROOT_FOLDER'], ENV['PROJECT_NAME'], 'build.gradle'),
18
- push: true
19
- )
15
+ require_relative './android_version_helper'
16
+ if Fastlane::Helper::Android::VersionHelper.properties_file_exists
17
+ Fastlane::Helper::GitHelper.commit(
18
+ message: 'Bump version number',
19
+ files: File.join(ENV['PROJECT_ROOT_FOLDER'], 'version.properties'),
20
+ push: true
21
+ )
22
+ else
23
+ Fastlane::Helper::GitHelper.commit(
24
+ message: 'Bump version number',
25
+ files: File.join(ENV['PROJECT_ROOT_FOLDER'], ENV['PROJECT_NAME'], 'build.gradle'),
26
+ push: true
27
+ )
28
+ end
20
29
  end
21
30
 
22
31
  # Calls the `tools/update-translations.sh` script from the project repo, then lint them using the provided gradle task
@@ -26,26 +26,29 @@ module Fastlane
26
26
  # "1.2" # Assuming build.gradle contains versionName "1.2.0"
27
27
  # "1.2.3" # Assuming build.gradle contains versionName "1.2.3"
28
28
  #
29
+ # @param [String] app The name of the app to be used for beta and alpha version update
30
+ #
29
31
  # @return [String] The public-facing version number, extracted from the `versionName` of the `build.gradle` file.
30
32
  # - If this version is a hotfix (more than 2 parts and 3rd part is non-zero), returns the "X.Y.Z" formatted string
31
33
  # - Otherwise (not a hotfix / 3rd part of version is 0), returns "X.Y" formatted version number
32
34
  #
33
- def self.get_public_version
34
- version = get_release_version
35
+ def self.get_public_version(app)
36
+ version = get_release_version(product_name: app)
35
37
  vp = get_version_parts(version[VERSION_NAME])
36
38
  return "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" unless is_hotfix?(version)
37
39
 
38
40
  "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}.#{vp[HOTFIX_NUMBER]}"
39
41
  end
40
42
 
41
- # Extract the version name and code from the `vanilla` flavor of the `$PROJECT_NAME/build.gradle file`
42
- # or for the defaultConfig if `HAS_ALPHA_VERSION` is not defined.
43
+ # Extract the version name and code from the release version of the app from `version.properties file`
43
44
  #
44
- # @env HAS_ALPHA_VERSION If set (with any value), indicates that the project uses `vanilla` flavor.
45
+ # @param [String] product_name The name of the app to be used for beta and alpha version update
45
46
  #
46
47
  # @return [Hash] A hash with 2 keys "name" and "code" containing the extracted version name and code, respectively
47
48
  #
48
- def self.get_release_version
49
+ def self.get_release_version(product_name:)
50
+ return get_version_from_properties(product_name: product_name) if properties_file_exists
51
+
49
52
  section = ENV['HAS_ALPHA_VERSION'].nil? ? 'defaultConfig' : 'vanilla {'
50
53
  gradle_path = self.gradle_path
51
54
  name = get_version_name_from_gradle_file(gradle_path, section)
@@ -53,12 +56,67 @@ module Fastlane
53
56
  return { VERSION_NAME => name, VERSION_CODE => code }
54
57
  end
55
58
 
56
- # Extract the version name and code from the `defaultConfig` of the `$PROJECT_NAME/build.gradle` file
59
+ def self.properties_file_exists
60
+ properties_file_path = File.join(ENV['PROJECT_ROOT_FOLDER'] || '.', 'version.properties')
61
+
62
+ return File.exist?(properties_file_path)
63
+ end
64
+
65
+ # Extract the version name and code from the `version.properties` file in the project root
66
+ #
67
+ # @param [String] product_name The name of the app to extract the version from e.g. wordpress, simplenote
68
+ # @param [Boolean] is_alpha true if the alpha version should be returned, false otherwise
69
+ #
70
+ # @return [Hash] A hash with 2 keys "name" and "code" containing the extracted version name and code, respectively
71
+ #
72
+ def self.get_version_from_properties(product_name:, is_alpha: false)
73
+ alpha_variant = is_alpha ? alpha_flavor_name : nil
74
+ version_name_key = [product_name, alpha_variant, 'versionName'].compact.join('.')
75
+ version_code_key = [product_name, alpha_variant, 'versionCode'].compact.join('.')
76
+
77
+ properties_file_path = File.join(ENV['PROJECT_ROOT_FOLDER'] || '.', 'version.properties')
78
+
79
+ return nil unless File.exist?(properties_file_path)
80
+
81
+ File.open(properties_file_path, 'r') do |f|
82
+ text = f.read
83
+ name = text.match(/#{version_name_key}=(\S*)/m)&.captures&.first
84
+ code = text.match(/#{version_code_key}=(\S*)/m)&.captures&.first
85
+
86
+ f.close
87
+
88
+ return nil if name.nil? || code.nil?
89
+
90
+ return { VERSION_NAME => name, VERSION_CODE => code.to_i }
91
+ end
92
+ end
93
+
94
+ # Returns the name of the flavor used for alpha builds
95
+ #
96
+ # @env HAS_ALPHA_VERSION Should contain the name of the flavor used for alpha
97
+ #
98
+ # @return [String] The flavor name as provided by the env var, defaulting to `zalpha` if the env var
99
+ # is not set or is set to '1' ('boolean' value used in legacy call sites)
100
+ def self.alpha_flavor_name
101
+ # TODO: Have each fastlane action which depends on this take the alpha flavor name as ConfigItem/parameter
102
+ # explicitly instead (and get rid of the HAS_ALPHA_VERSION global / env var after that)
103
+
104
+ # For now we pass the alpha flavor name by reusing the HAS_ALPHA_VERSION env var.
105
+ return ENV['HAS_ALPHA_VERSION'] if ENV['HAS_ALPHA_VERSION'] && ENV['HAS_ALPHA_VERSION'] != '1'
106
+
107
+ 'zalpha' # Default value if HAS_ALPHA_VERSION is not set or hasn't been updated at call site to the flavor name instead of '1'
108
+ end
109
+
110
+ # Extract the version name and code from the `version.properties` file in the project root
111
+ #
112
+ # @param [String] app The name of the app to be used for beta and alpha version update
57
113
  #
58
114
  # @return [Hash] A hash with 2 keys `"name"` and `"code"` containing the extracted version name and code, respectively,
59
115
  # or `nil` if `$HAS_ALPHA_VERSION` is not defined.
60
116
  #
61
- def self.get_alpha_version
117
+ def self.get_alpha_version(app)
118
+ return get_version_from_properties(product_name: app, is_alpha: true) if properties_file_exists
119
+
62
120
  return nil if ENV['HAS_ALPHA_VERSION'].nil?
63
121
 
64
122
  section = 'defaultConfig'
@@ -95,8 +153,8 @@ module Fastlane
95
153
  # - The final version name corresponds to the beta's versionName, without the `-rc` suffix
96
154
  # - The final version code corresponds to the versionCode for the alpha (or for the beta if alpha_version is nil) incremented by one.
97
155
  #
98
- # @param [Hash] beta_version The version hash for the beta (vanilla flavor), containing values for keys "name" and "code"
99
- # @param [Hash] alpha_version The version hash for the alpha (defaultConfig), containing values for keys "name" and "code",
156
+ # @param [Hash] beta_version The version hash for the beta, containing values for keys "name" and "code"
157
+ # @param [Hash] alpha_version The version hash for the alpha, containing values for keys "name" and "code",
100
158
  # or `nil` if no alpha version to consider.
101
159
  #
102
160
  # @return [Hash] A version hash with keys "name" and "code", containing the version name and code to use for final release.
@@ -254,11 +312,12 @@ module Fastlane
254
312
 
255
313
  # Prints the current and next release version names to stdout, then returns the next release version
256
314
  #
315
+ # @param [String] app The name of the app to be used for beta and alpha version update
257
316
  # @return [String] The next release version name to use after bumping the currently used release version.
258
317
  #
259
- def self.bump_version_release
318
+ def self.bump_version_release(app)
260
319
  # Bump release
261
- current_version = get_release_version()
320
+ current_version = get_release_version(product_name: app)
262
321
  UI.message("Current version: #{current_version[VERSION_NAME]}")
263
322
  new_version = calc_next_release_base_version(current_version)
264
323
  UI.message("New version: #{new_version[VERSION_NAME]}")
@@ -267,15 +326,30 @@ module Fastlane
267
326
  return verified_version
268
327
  end
269
328
 
270
- # Update the `build.gradle` file with new `versionName` and `versionCode` values, both or the `defaultConfig` and `vanilla` flavors
329
+ # Update the `version.properties` file with new `versionName` and `versionCode` values
271
330
  #
272
- # @param [Hash] new_version_beta The version hash for the beta (vanilla flavor), containing values for keys "name" and "code"
273
- # @param [Hash] new_version_alpha The version hash for the alpha (defaultConfig), containing values for keys "name" and "code"
274
- # @env HAS_ALPHA_VERSION If set (with any value), indicates that the project uses `vanilla` flavor.
331
+ # @param [String] app The name of the app to be used for beta and alpha version update
332
+ # @param [Hash] new_version_beta The version hash for the beta, containing values for keys "name" and "code"
333
+ # @param [Hash] new_version_alpha The version hash for the alpha , containing values for keys "name" and "code"
275
334
  #
276
- def self.update_versions(new_version_beta, new_version_alpha)
277
- self.update_version(new_version_beta, ENV['HAS_ALPHA_VERSION'].nil? ? 'defaultConfig' : 'vanilla {')
278
- self.update_version(new_version_alpha, 'defaultConfig') unless new_version_alpha.nil?
335
+ def self.update_versions(app, new_version_beta, new_version_alpha)
336
+ if properties_file_exists
337
+ new_version_name_beta_key = "#{app}.versionName"
338
+ new_version_code_beta_key = "#{app}.versionCode"
339
+ Action.sh('./gradlew', 'updateVersionProperties', "-Pkey=#{new_version_name_beta_key}", "-Pvalue=#{new_version_beta[VERSION_NAME]}")
340
+ Action.sh('./gradlew', 'updateVersionProperties', "-Pkey=#{new_version_code_beta_key}", "-Pvalue=#{new_version_beta[VERSION_CODE]}")
341
+
342
+ unless new_version_alpha.nil?
343
+ new_version_name_alpha_key = "#{app}.#{alpha_flavor_name}.versionName"
344
+ new_version_code_alpha_key = "#{app}.#{alpha_flavor_name}.versionCode"
345
+
346
+ Action.sh('./gradlew', 'updateVersionProperties', "-Pkey=#{new_version_name_alpha_key}", "-Pvalue=#{new_version_alpha[VERSION_NAME]}") unless new_version_alpha.nil?
347
+ Action.sh('./gradlew', 'updateVersionProperties', "-Pkey=#{new_version_code_alpha_key}", "-Pvalue=#{new_version_alpha[VERSION_CODE]}") unless new_version_alpha.nil?
348
+ end
349
+ else
350
+ self.update_version(new_version_beta, ENV['HAS_ALPHA_VERSION'].nil? ? 'defaultConfig' : 'vanilla {')
351
+ self.update_version(new_version_alpha, 'defaultConfig') unless new_version_alpha.nil?
352
+ end
279
353
  end
280
354
 
281
355
  # Compute the name of the previous hotfix version.
@@ -337,6 +411,37 @@ module Fastlane
337
411
  return parts
338
412
  end
339
413
 
414
+ # Ensure that a version string is correctly formatted (that is, each of its parts is a number) and returns the 2-parts version number
415
+ #
416
+ # @param [String] version The version string to verify
417
+ #
418
+ # @return [String] The "major.minor" version string, only with the first 2 components
419
+ # @raise [UserError] If any of the parts of the version string is not a number
420
+ #
421
+ def self.verify_version(version)
422
+ v_parts = get_version_parts(version)
423
+
424
+ v_parts.each do |part|
425
+ UI.user_error!('Version value can only contains numbers.') unless is_int?(part)
426
+ end
427
+
428
+ "#{v_parts[MAJOR_NUMBER]}.#{v_parts[MINOR_NUMBER]}"
429
+ end
430
+
431
+ # Check if a string is an integer.
432
+ #
433
+ # @param [String] string The string to test
434
+ #
435
+ # @return [Bool] true if the string is representing an integer value, false if not
436
+ #
437
+ def self.is_int? string
438
+ true if Integer(string) rescue false
439
+ end
440
+
441
+ #########
442
+ # Functions to support versioning through build.gradle - can be removed once all projects adopt version.properties
443
+ ########
444
+
340
445
  # Extract the versionName from a build.gradle file
341
446
  #
342
447
  # @param [String] file_path The path to the `.gradle` file
@@ -387,33 +492,6 @@ module Fastlane
387
492
  return nil
388
493
  end
389
494
 
390
- # Ensure that a version string is correctly formatted (that is, each of its parts is a number) and returns the 2-parts version number
391
- #
392
- # @param [String] version The version string to verify
393
- #
394
- # @return [String] The "major.minor" version string, only with the first 2 components
395
- # @raise [UserError] If any of the parts of the version string is not a number
396
- #
397
- def self.verify_version(version)
398
- v_parts = get_version_parts(version)
399
-
400
- v_parts.each do |part|
401
- UI.user_error!('Version value can only contains numbers.') unless is_int?(part)
402
- end
403
-
404
- "#{v_parts[MAJOR_NUMBER]}.#{v_parts[MINOR_NUMBER]}"
405
- end
406
-
407
- # Check if a string is an integer.
408
- #
409
- # @param [String] string The string to test
410
- #
411
- # @return [Bool] true if the string is representing an integer value, false if not
412
- #
413
- def self.is_int? string
414
- true if Integer(string) rescue false
415
- end
416
-
417
495
  # The path to the build.gradle file for the project.
418
496
  #
419
497
  # @env PROJECT_ROOT_FOLDER The path to the root of the project (the folder containing the `.git` directory).