fastlane-plugin-wpmreleasetoolkit 9.0.1 → 9.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_betabuild_prechecks.rb +41 -5
  3. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_prechecks.rb +37 -6
  4. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_beta.rb +40 -5
  5. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_final_release.rb +40 -5
  6. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_hotfix.rb +35 -3
  7. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb +42 -5
  8. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_codefreeze_prechecks.rb +33 -3
  9. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_completecodefreeze_prechecks.rb +25 -1
  10. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_current_branch_is_hotfix.rb +28 -2
  11. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_download_file_by_version.rb +13 -1
  12. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_download_translations_action.rb +3 -1
  13. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_finalize_prechecks.rb +25 -1
  14. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_alpha_version.rb +28 -2
  15. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_app_version.rb +28 -2
  16. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_release_version.rb +28 -2
  17. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_tag_build.rb +29 -2
  18. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_release_notes.rb +2 -0
  19. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/copy_branch_protection_action.rb +80 -0
  20. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/{removebranchprotection_action.rb → remove_branch_protection_action.rb} +24 -17
  21. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/set_branch_protection_action.rb +153 -0
  22. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_release_notes.rb +2 -0
  23. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_git_helper.rb +8 -9
  24. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb +31 -47
  25. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/deprecated.rb +46 -0
  26. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb +49 -4
  27. data/lib/fastlane/plugin/wpmreleasetoolkit/models/app_version.rb +36 -0
  28. data/lib/fastlane/plugin/wpmreleasetoolkit/models/build_code.rb +27 -0
  29. data/lib/fastlane/plugin/wpmreleasetoolkit/version.rb +1 -1
  30. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/calculators/abstract_version_calculator.rb +85 -0
  31. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/calculators/date_build_code_calculator.rb +32 -0
  32. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/calculators/date_version_calculator.rb +37 -0
  33. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/calculators/marketing_version_calculator.rb +26 -0
  34. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/calculators/semantic_version_calculator.rb +21 -0
  35. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/calculators/simple_build_code_calculator.rb +22 -0
  36. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/files/android_version_file.rb +76 -0
  37. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/files/ios_version_file.rb +64 -0
  38. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/formatters/abstract_version_formatter.rb +27 -0
  39. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/formatters/derived_build_code_formatter.rb +33 -0
  40. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/formatters/four_part_build_code_formatter.rb +22 -0
  41. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/formatters/four_part_version_formatter.rb +35 -0
  42. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/formatters/rc_notation_version_formatter.rb +65 -0
  43. data/lib/fastlane/plugin/wpmreleasetoolkit/versioning/formatters/simple_build_code_formatter.rb +20 -0
  44. data/lib/fastlane/plugin/wpmreleasetoolkit.rb +1 -1
  45. metadata +36 -4
  46. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setbranchprotection_action.rb +0 -63
@@ -30,8 +30,11 @@ module Fastlane
30
30
  # - If this version is a hotfix (more than 2 parts and 3rd part is non-zero), returns the "X.Y.Z" formatted string
31
31
  # - Otherwise (not a hotfix / 3rd part of version is 0), returns "X.Y" formatted version number
32
32
  #
33
- def self.get_public_version
34
- version = get_release_version
33
+ def self.get_public_version(build_gradle_path:, version_properties_path:)
34
+ version = get_release_version(
35
+ build_gradle_path: build_gradle_path,
36
+ version_properties_path: version_properties_path
37
+ )
35
38
  vp = get_version_parts(version[VERSION_NAME])
36
39
  return "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" unless is_hotfix?(version)
37
40
 
@@ -42,33 +45,28 @@ module Fastlane
42
45
  #
43
46
  # @return [Hash] A hash with 2 keys "name" and "code" containing the extracted version name and code, respectively
44
47
  #
45
- def self.get_release_version
46
- return get_version_from_properties if File.exist?(version_properties_file)
48
+ def self.get_release_version(build_gradle_path:, version_properties_path:)
49
+ return get_version_from_properties(version_properties_path: version_properties_path) if File.exist?(version_properties_path)
47
50
 
48
51
  section = ENV['HAS_ALPHA_VERSION'].nil? ? 'defaultConfig' : 'vanilla {'
49
- gradle_path = self.gradle_path
50
- name = get_version_name_from_gradle_file(gradle_path, section)
51
- code = get_version_build_from_gradle_file(gradle_path, section)
52
+ name = get_version_name_from_gradle_file(build_gradle_path, section)
53
+ code = get_version_build_from_gradle_file(build_gradle_path, section)
52
54
  return { VERSION_NAME => name, VERSION_CODE => code }
53
55
  end
54
56
 
55
- def self.version_properties_file
56
- File.join(ENV['PROJECT_ROOT_FOLDER'] || '.', 'version.properties')
57
- end
58
-
59
57
  # Extract the version name and code from the `version.properties` file in the project root
60
58
  #
61
59
  # @param [Boolean] is_alpha true if the alpha version should be returned, false otherwise
62
60
  #
63
61
  # @return [Hash] A hash with 2 keys "name" and "code" containing the extracted version name and code, respectively
64
62
  #
65
- def self.get_version_from_properties(is_alpha: false)
66
- return nil unless File.exist?(version_properties_file)
63
+ def self.get_version_from_properties(version_properties_path:, is_alpha: false)
64
+ return nil unless File.exist?(version_properties_path)
67
65
 
68
66
  version_name_key = is_alpha ? 'alpha.versionName' : 'versionName'
69
67
  version_code_key = is_alpha ? 'alpha.versionCode' : 'versionCode'
70
68
 
71
- text = File.read(version_properties_file)
69
+ text = File.read(version_properties_path)
72
70
  name = text.match(/#{version_name_key}=(\S*)/m)&.captures&.first
73
71
  code = text.match(/#{version_code_key}=(\S*)/m)&.captures&.first
74
72
 
@@ -80,15 +78,14 @@ module Fastlane
80
78
  # @return [Hash] A hash with 2 keys `"name"` and `"code"` containing the extracted version name and code, respectively,
81
79
  # or `nil` if `$HAS_ALPHA_VERSION` is not defined.
82
80
  #
83
- def self.get_alpha_version
84
- return get_version_from_properties(is_alpha: true) if File.exist?(version_properties_file)
81
+ def self.get_alpha_version(build_gradle_path:, version_properties_path:)
82
+ return get_version_from_properties(version_properties_path: version_properties_path, is_alpha: true) if File.exist?(version_properties_path)
85
83
 
86
84
  return nil if ENV['HAS_ALPHA_VERSION'].nil?
87
85
 
88
86
  section = 'defaultConfig'
89
- gradle_path = self.gradle_path
90
- name = get_version_name_from_gradle_file(gradle_path, section)
91
- code = get_version_build_from_gradle_file(gradle_path, section)
87
+ name = get_version_name_from_gradle_file(build_gradle_path, section)
88
+ code = get_version_build_from_gradle_file(build_gradle_path, section)
92
89
  return { VERSION_NAME => name, VERSION_CODE => code }
93
90
  end
94
91
 
@@ -280,9 +277,12 @@ module Fastlane
280
277
  #
281
278
  # @return [String] The next release version name to use after bumping the currently used release version.
282
279
  #
283
- def self.bump_version_release
280
+ def self.bump_version_release(build_gradle_path:, version_properties_path:)
284
281
  # Bump release
285
- current_version = self.get_release_version
282
+ current_version = self.get_release_version(
283
+ build_gradle_path: build_gradle_path,
284
+ version_properties_path: version_properties_path
285
+ )
286
286
  UI.message("Current version: #{current_version[VERSION_NAME]}")
287
287
  new_version = calc_next_release_base_version(current_version)
288
288
  UI.message("New version: #{new_version[VERSION_NAME]}")
@@ -296,21 +296,21 @@ module Fastlane
296
296
  # @param [Hash] new_version_beta The version hash for the beta, containing values for keys "name" and "code"
297
297
  # @param [Hash] new_version_alpha The version hash for the alpha , containing values for keys "name" and "code"
298
298
  #
299
- def self.update_versions(new_version_beta, new_version_alpha)
300
- if File.exist?(version_properties_file)
299
+ def self.update_versions(new_version_beta, new_version_alpha, version_properties_path:)
300
+ if File.exist?(version_properties_path)
301
301
  replacements = {
302
302
  versionName: (new_version_beta || {})[VERSION_NAME],
303
303
  versionCode: (new_version_beta || {})[VERSION_CODE],
304
304
  'alpha.versionName': (new_version_alpha || {})[VERSION_NAME],
305
305
  'alpha.versionCode': (new_version_alpha || {})[VERSION_CODE]
306
306
  }
307
- content = File.read(version_properties_file)
307
+ content = File.read(version_properties_path)
308
308
  content.gsub!(/^(.*) ?=.*$/) do |line|
309
309
  key = Regexp.last_match(1).to_sym
310
310
  value = replacements[key]
311
311
  value.nil? ? line : "#{key}=#{value}"
312
312
  end
313
- File.write(version_properties_file, content)
313
+ File.write(version_properties_path, content)
314
314
  else
315
315
  self.update_version(new_version_beta, ENV['HAS_ALPHA_VERSION'].nil? ? 'defaultConfig' : 'vanilla {')
316
316
  self.update_version(new_version_alpha, 'defaultConfig') unless new_version_alpha.nil?
@@ -337,12 +337,10 @@ module Fastlane
337
337
  # @param [String] import_key The key to look for
338
338
  # @return [String] The value of the key, or nil if not found
339
339
  #
340
- def self.get_library_version_from_gradle_config(import_key:)
341
- gradle_file_path = File.join(ENV['PROJECT_ROOT_FOLDER'] || '.', 'build.gradle')
340
+ def self.get_library_version_from_gradle_config(build_gradle_path:, import_key:)
341
+ return nil unless File.exist?(build_gradle_path)
342
342
 
343
- return nil unless File.exist?(gradle_file_path)
344
-
345
- File.open(gradle_file_path, 'r') do |f|
343
+ File.open(build_gradle_path, 'r') do |f|
346
344
  text = f.read
347
345
  text.match(/^\s*(?:\w*\.)?#{Regexp.escape(import_key)}\s*=\s*['"](.*?)["']/m)&.captures&.first
348
346
  end
@@ -456,19 +454,6 @@ module Fastlane
456
454
  return nil
457
455
  end
458
456
 
459
- # The path to the build.gradle file for the project.
460
- #
461
- # @env PROJECT_ROOT_FOLDER The path to the root of the project (the folder containing the `.git` directory).
462
- # @env PROJECT_NAME The name of the project, i.e. the name of the subdirectory containing the project's `build.gradle` file.
463
- #
464
- # @return [String] The path of the `build.gradle` file inside the project subfolder in the project's repo
465
- #
466
- def self.gradle_path
467
- UI.user_error!("You need to set the `PROJECT_ROOT_FOLDER` environment variable to the path to the project's root") if ENV['PROJECT_ROOT_FOLDER'].nil?
468
- UI.user_error!('You need to set the `PROJECT_NAME` environment variable to the relative path to the project subfolder name') if ENV['PROJECT_NAME'].nil?
469
- File.join(ENV['PROJECT_ROOT_FOLDER'], ENV['PROJECT_NAME'], 'build.gradle')
470
- end
471
-
472
457
  # Update both the versionName and versionCode of the build.gradle file to the specified version.
473
458
  #
474
459
  # @param [Hash] version The version hash, containing values for keys "name" and "code"
@@ -477,12 +462,11 @@ module Fastlane
477
462
  # @todo This implementation is very fragile. This should be done parsing the file in a proper way.
478
463
  # Leveraging gradle itself is probably the easiest way.
479
464
  #
480
- def self.update_version(version, section)
481
- gradle_path = self.gradle_path
465
+ def self.update_version(version, section, build_gradle_path:)
482
466
  temp_file = Tempfile.new('fastlaneIncrementVersion')
483
467
  found_section = false
484
468
  version_updated = 0
485
- File.open(gradle_path, 'r') do |file|
469
+ File.open(build_gradle_path, 'r') do |file|
486
470
  file.each_line do |line|
487
471
  if found_section
488
472
  if version_updated < 2
@@ -508,7 +492,7 @@ module Fastlane
508
492
  end
509
493
  temp_file.rewind
510
494
  temp_file.close
511
- FileUtils.mv(temp_file.path, gradle_path)
495
+ FileUtils.mv(temp_file.path, build_gradle_path)
512
496
  temp_file.unlink
513
497
  end
514
498
  end
@@ -0,0 +1,46 @@
1
+ module Fastlane
2
+ module Helper
3
+ # A helper class to store deprecated methods and actions
4
+ class Deprecated
5
+ # Creates a project_root_folder Fastlane ConfigItem
6
+ #
7
+ # @return [FastlaneCore::ConfigItem] The Fastlane ConfigItem for the `PROJECT_ROOT_FOLDER` environment variable
8
+ #
9
+ def self.project_root_folder_config_item
10
+ verify_block = proc do
11
+ UI.deprecated('DEPRECATED: The PROJECT_ROOT_FOLDER environment variable and config item are deprecated and will be removed in a future version of the Release Toolkit. Please provide a full path instead.')
12
+ end
13
+
14
+ FastlaneCore::ConfigItem.new(
15
+ key: :project_root_folder,
16
+ env_name: 'PROJECT_ROOT_FOLDER',
17
+ description: 'The path to the project root folder',
18
+ deprecated: true,
19
+ optional: true,
20
+ verify_block: verify_block,
21
+ type: String
22
+ )
23
+ end
24
+
25
+ # Creates a project_root_folder Fastlane ConfigItem
26
+ #
27
+ # @return [FastlaneCore::ConfigItem] The Fastlane ConfigItem for the `PROJECT_ROOT_FOLDER` environment variable
28
+ #
29
+ def self.project_name_config_item
30
+ verify_block = proc do
31
+ UI.deprecated('DEPRECATED: The PROJECT_NAME environment variable and config item are deprecated and will be removed in a future version of the Release Toolkit. Please provide a full path instead.')
32
+ end
33
+
34
+ FastlaneCore::ConfigItem.new(
35
+ key: :project_name,
36
+ env_name: 'PROJECT_NAME',
37
+ description: 'The app project name',
38
+ deprecated: true,
39
+ optional: true,
40
+ verify_block: verify_block,
41
+ type: String
42
+ )
43
+ end
44
+ end
45
+ end
46
+ end
@@ -244,11 +244,20 @@ module Fastlane
244
244
  #
245
245
  # @param [String] repository The repository name (including the organization)
246
246
  # @param [String] branch The branch name
247
- # @param [Hash] options A customizable set of options.
248
- # @see https://docs.github.com/en/rest/branches/branch-protection#update-branch-protection
247
+ # @see https://docs.github.com/en/rest/branches/branch-protection#delete-branch-protection
248
+ #
249
+ def remove_branch_protection(repository:, branch:)
250
+ client.unprotect_branch(repository, branch)
251
+ end
252
+
253
+ # Get the list of branch protection settings for a given branch of a repository
249
254
  #
250
- def remove_branch_protection(repository:, branch:, **options)
251
- client.unprotect_branch(repository, branch, options)
255
+ # @param [String] repository The repository name (including the organization)
256
+ # @param [String] branch The branch name
257
+ # @see https://docs.github.com/en/rest/branches/branch-protection#get-branch-protection
258
+ #
259
+ def get_branch_protection(repository:, branch:, **options)
260
+ client.branch_protection(repository, branch)
252
261
  end
253
262
 
254
263
  # Protects a single branch from a repository
@@ -262,6 +271,42 @@ module Fastlane
262
271
  client.protect_branch(repository, branch, options)
263
272
  end
264
273
 
274
+ # Convert a response from the `/branch-protection` API endpoint into a Hash
275
+ # suitable to be returned and/or reused to pass to a subsequent `/branch-protection` API request
276
+ # @param [Sawyer::Resource] response The API response returned by `#get_branch_protection` or `#set_branch_protection`
277
+ # @return [Hash] A hash representation of the API response—or an empty Hash if `response` was `nil`—
278
+ # with Boolean values normalized to true/false, and any extra values that would be refused
279
+ # if used in a subsequent API request (like legacy vs new key) removed.
280
+ # @see https://docs.github.com/en/rest/branches/branch-protection
281
+ #
282
+ def self.branch_protection_api_response_to_normalized_hash(response)
283
+ return {} if response.nil?
284
+
285
+ normalize_values = lambda do |hash|
286
+ hash.each do |k, v|
287
+ # Boolean values appear as { "enabled" => true/false } in the Response, while they must appear as true/false in Request
288
+ hash[k] = v[:enabled] if v.is_a?(Hash) && v.key?(:enabled)
289
+ # References to :users, :teams and :apps are expanded as Objects in the Response, while they must just be the login or slug in Request
290
+ hash[k] = v.map { |item| item[:login] } if k == :users && v.is_a?(Array)
291
+ hash[k] = v.map { |item| item[:slug] } if %i[teams apps].include?(k) && v.is_a?(Array)
292
+ # Response contains lots of `*url` keys that are useless in practice and makes the returned hash harder to parse visually
293
+ hash.delete(k) if k.to_s == 'url' || k.to_s.end_with?('_url')
294
+
295
+ # Recurse into Hashes and Array of Hashes
296
+ normalize_values.call(v) if v.is_a?(Hash)
297
+ v.each { |item| normalize_values.call(item) if item.is_a?(Hash) } if v.is_a?(Array)
298
+ end
299
+ end
300
+
301
+ hash = response.to_hash
302
+ normalize_values.call(hash)
303
+
304
+ # Response contains both (legacy) `:contexts` key and new `:checks` key, but only one of the two should be passed in Request
305
+ hash[:required_status_checks].delete(:contexts) unless hash.dig(:required_status_checks, :checks).nil?
306
+
307
+ hash
308
+ end
309
+
265
310
  # Creates a GithubToken Fastlane ConfigItem
266
311
  #
267
312
  # @return [FastlaneCore::ConfigItem] The Fastlane ConfigItem for GitHub OAuth access token
@@ -0,0 +1,36 @@
1
+ module Fastlane
2
+ module Models
3
+ # The AppVersion model represents a version of an app with major, minor, patch, and build number components.
4
+ class AppVersion
5
+ attr_accessor :major, :minor, :patch, :build_number
6
+
7
+ # Initializes a new AppVersion instance.
8
+ #
9
+ # @param [Integer] major The major version number.
10
+ # @param [Integer] minor The minor version number.
11
+ # @param [Integer] patch The patch version number.
12
+ # @param [Integer] build_number The build number.
13
+ #
14
+ def initialize(major, minor, patch = 0, build_number = 0)
15
+ # Validate that the major and minor version numbers are not nil
16
+ UI.user_error!('Major version cannot be nil') if major.nil?
17
+ UI.user_error!('Minor version cannot be nil') if minor.nil?
18
+
19
+ @major = major
20
+ @minor = minor
21
+ @patch = patch
22
+ @build_number = build_number
23
+ end
24
+
25
+ # Converts the AppVersion object to a string representation.
26
+ # This should only be used for internal debugging/testing purposes, not to write versions in version files
27
+ # In order to format an `AppVersion` into a `String`, you should use the appropriate `VersionFormatter` for your project instead.
28
+ #
29
+ # @return [String] a string in the format "major.minor.patch.build_number".
30
+ #
31
+ def to_s
32
+ "#{@major}.#{@minor}.#{@patch}.#{@build_number}"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ module Fastlane
2
+ module Models
3
+ # The `BuildCode` model represents a build code for an app. This could be the Version Code for an Android app or
4
+ # the VERSION_LONG/BUILD_NUMBER for an iOS/Mac app.
5
+ class BuildCode
6
+ attr_accessor :build_code
7
+
8
+ # Initializes a new BuildCode instance with the provided build code value.
9
+ #
10
+ # @param build_code [String] The build code value.
11
+ #
12
+ def initialize(build_code)
13
+ UI.user_error!('Build code cannot be nil') if build_code.nil?
14
+
15
+ @build_code = build_code
16
+ end
17
+
18
+ # Returns the build code as a string.
19
+ #
20
+ # @return [String] The build code represented as a string.
21
+ #
22
+ def to_s
23
+ @build_code.to_s
24
+ end
25
+ end
26
+ end
27
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Fastlane
4
4
  module Wpmreleasetoolkit
5
- VERSION = '9.0.1'
5
+ VERSION = '9.2.0'
6
6
  end
7
7
  end
@@ -0,0 +1,85 @@
1
+ module Fastlane
2
+ module Wpmreleasetoolkit
3
+ module Versioning
4
+ # The `AbstractVersionCalculator` class is responsible for performing version calculations and transformations. It can be used
5
+ # as a base class for version calculations that use different versioning schemes. It contains calculation and
6
+ # transformation methods that are shared by all platforms. It has the abstract suffix because it should not be
7
+ # instantiated directly.
8
+ class AbstractVersionCalculator
9
+ # This method increments the major version component and resets minor, patch, and build number
10
+ # components to zero.
11
+ #
12
+ # @param version [AppVersion] The version to calculate the next major version for.
13
+ #
14
+ # @return [AppVersion] The next major version.
15
+ #
16
+ def next_major_version(version:)
17
+ new_version = version.dup
18
+ new_version.major += 1
19
+ new_version.minor = 0
20
+ new_version.patch = 0
21
+ new_version.build_number = 0
22
+
23
+ new_version
24
+ end
25
+
26
+ # This method increments the minor version component and resets patch and build number components
27
+ # to zero.
28
+ #
29
+ # @param version [AppVersion] The version to calculate the next minor version for.
30
+ #
31
+ # @return [AppVersion] The next minor version.
32
+ #
33
+ def next_minor_version(version:)
34
+ new_version = version.dup
35
+ new_version.minor += 1
36
+ new_version.patch = 0
37
+ new_version.build_number = 0
38
+
39
+ new_version
40
+ end
41
+
42
+ # This method increments the patch version component and resets the build number component to zero.
43
+ #
44
+ # @param version [AppVersion] The version to calculate the next patch version for.
45
+ #
46
+ # @return [AppVersion] The next patch version.
47
+ #
48
+ def next_patch_version(version:)
49
+ new_version = version.dup
50
+ new_version.patch += 1
51
+ new_version.build_number = 0
52
+
53
+ new_version
54
+ end
55
+
56
+ # This method increments the build number component.
57
+ #
58
+ # @param version [AppVersion] The version to calculate the next build number for.
59
+ #
60
+ # @return [AppVersion] The next version with an incremented build number.
61
+ #
62
+ def next_build_number(version:)
63
+ new_version = version.dup
64
+ new_version.build_number += 1
65
+
66
+ new_version
67
+ end
68
+
69
+ # Calculate the previous patch version by decrementing the patch version if it's not zero.
70
+ #
71
+ # @param [AppVersion] version The version to calculate the previous patch version for.
72
+ #
73
+ # @return [AppVersion] The previous patch version.
74
+ #
75
+ def previous_patch_version(version:)
76
+ new_version = version.dup
77
+ new_version.patch -= 1 unless version.patch.zero?
78
+ new_version.build_number = 0
79
+
80
+ new_version
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,32 @@
1
+ module Fastlane
2
+ module Wpmreleasetoolkit
3
+ module Versioning
4
+ # The `DateBuildCodeCalculator` class is a build code calculator for apps that use date-based
5
+ # build codes.
6
+ class DateBuildCodeCalculator
7
+ # Calculate the next internal build code by setting the build number to the current date.
8
+ #
9
+ # @param [AppVersion] version The version to calculate the next internal version for.
10
+ #
11
+ # @return [AppVersion] The next version with the build number set to the current date.
12
+ #
13
+ def next_build_code(version:)
14
+ new_version = version.dup
15
+ new_version.build_number = today_date
16
+
17
+ new_version
18
+ end
19
+
20
+ private
21
+
22
+ # Get the current date in the format 'YYYYMMDD'.
23
+ #
24
+ # @return [String] The current date in 'YYYYMMDD' format.
25
+ #
26
+ def today_date
27
+ DateTime.now.strftime('%Y%m%d')
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'abstract_version_calculator'
2
+
3
+ module Fastlane
4
+ module Wpmreleasetoolkit
5
+ module Versioning
6
+ # The `DateVersionCalculator` class is a specialized version calculator for date-based versions
7
+ # of an app, extending the `AbstractVersionCalculator` class.
8
+ class DateVersionCalculator < AbstractVersionCalculator
9
+ # Calculate the next date-based release version.
10
+ #
11
+ # If the current month is December, the method prompts the user to determine if the next
12
+ # release will be the first release of the next year. If so, it increments the major version
13
+ # and sets the minor version to 1, resetting the patch and build number components to zero.
14
+ # Otherwise, it calculates the next minor version.
15
+ #
16
+ # @param [AppVersion] version The version to calculate the next date-based release version for.
17
+ #
18
+ # @return [AppVersion] The next date-based release version.
19
+ #
20
+ def next_release_version(version:)
21
+ new_version = version.dup
22
+ first_release_of_year = FastlaneCore::UI.confirm('Is this release the first release of next year?') if Time.now.month == 12
23
+ if first_release_of_year
24
+ new_version.major += 1
25
+ new_version.minor = 1
26
+ new_version.patch = 0
27
+ new_version.build_number = 0
28
+
29
+ new_version
30
+ else
31
+ next_minor_version(version: version)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'abstract_version_calculator'
2
+
3
+ module Fastlane
4
+ module Wpmreleasetoolkit
5
+ module Versioning
6
+ # The `MarketingVersionCalculator` class is a specialized version calculator for marketing versions
7
+ # of an app, extending the `AbstractVersionCalculator` class.
8
+ class MarketingVersionCalculator < AbstractVersionCalculator
9
+ # Calculate the next marketing release version.
10
+ #
11
+ # This method checks if the minor version is 9. If it is, it calculates the next major version.
12
+ # Otherwise, it calculates the next minor version. The patch and build number components are reset to zero.
13
+ #
14
+ # @param [AppVersion] version The version to calculate the next marketing release version for.
15
+ #
16
+ # @return [AppVersion] The next marketing release version.
17
+ #
18
+ def next_release_version(version:)
19
+ UI.user_error!('Marketing Versioning: The minor version cannot be greater than 9') if version.minor > 9
20
+
21
+ version.minor == 9 ? next_major_version(version: version) : next_minor_version(version: version)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ require_relative 'abstract_version_calculator'
2
+
3
+ module Fastlane
4
+ module Wpmreleasetoolkit
5
+ module Versioning
6
+ # The `SemanticVersionCalculator` class is a specialized version calculator for semantic versions
7
+ # of an app, extending the `AbstractVersionCalculator` class.
8
+ class SemanticVersionCalculator < AbstractVersionCalculator
9
+ # Calculate the next semantic release version.
10
+ #
11
+ # @param [AppVersion] version The version to calculate the next semantic release version from.
12
+ #
13
+ # @return [AppVersion] The next semantic release version.
14
+ #
15
+ def next_release_version(version:)
16
+ next_minor_version(version: version)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ module Fastlane
2
+ module Wpmreleasetoolkit
3
+ module Versioning
4
+ # The `SimpleBuildCodeCalculator` class is a build code calculator for apps that use simple integer
5
+ # build codes.
6
+ class SimpleBuildCodeCalculator
7
+ # Calculate the next build code.
8
+ #
9
+ # This method increments the build code value by 1.
10
+ #
11
+ # @param [BuildCode] version The build code to increment.
12
+ #
13
+ # @return [BuildCode] The next build code.
14
+ #
15
+ def next_build_code(build_code:)
16
+ new_build_code = build_code.dup
17
+ new_build_code.build_code += 1
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,76 @@
1
+ require 'java-properties'
2
+
3
+ module Fastlane
4
+ module Wpmreleasetoolkit
5
+ module Versioning
6
+ # The `AndroidVersionFile` class takes in a version.properties file path and reads/writes values to/from the file.
7
+ class AndroidVersionFile
8
+ attr_reader :version_properties_path
9
+
10
+ # Initializes a new instance of AndroidVersionFile with the specified version.properties file path.
11
+ #
12
+ # @param [String] version_properties_path The path to the version.properties file.
13
+ #
14
+ def initialize(version_properties_path: 'version.properties')
15
+ UI.user_error!("version.properties not found at this path: #{version_properties_path}") unless File.exist?(version_properties_path)
16
+
17
+ @version_properties_path = version_properties_path
18
+ end
19
+
20
+ # Reads the version name from a version.properties file.
21
+ #
22
+ # @return [String] The version name read from the file.
23
+ #
24
+ # @raise [UI::Error] If the file_path is nil or the version name is not found.
25
+ #
26
+ def read_version_name
27
+ # Read the version name from the version.properties file
28
+ file_content = JavaProperties.load(version_properties_path)
29
+ version_name = file_content[:versionName]
30
+ UI.user_error!('Version name not found in version.properties') if version_name.nil?
31
+
32
+ version_name
33
+ end
34
+
35
+ # Reads the version code from a version.properties file.
36
+ #
37
+ # @param [String] file_path The path to the version.properties file.
38
+ #
39
+ # @return [BuildCode] An instance of `BuildCode` representing the version code read from the file.
40
+ #
41
+ # @raise [UI::Error] If the file_path is nil or the version code is not found.
42
+ #
43
+ def read_version_code
44
+ # Read the version code from the version.properties file
45
+ file_content = JavaProperties.load(version_properties_path)
46
+ version_code = file_content[:versionCode]
47
+ UI.user_error!('Version code not found in version.properties') if version_code.nil?
48
+
49
+ # Create a BuildCode object
50
+ Fastlane::Models::BuildCode.new(version_code.to_i)
51
+ end
52
+
53
+ # Writes the provided version name and version code to the version.properties file.
54
+ #
55
+ # @param [String] version_name The version name to write to the file.
56
+ # @param [String] version_code The version code to write to the file.
57
+ #
58
+ # @raise [UI::Error] If the version name or version code is nil.
59
+ #
60
+ def write_version(version_name:, version_code:)
61
+ # Create the version name and version code hash
62
+ version = {
63
+ versionName: version_name,
64
+ versionCode: version_code
65
+ }
66
+
67
+ # Write the version name and version code hash to the version.properties file
68
+ JavaProperties.write(
69
+ version,
70
+ version_properties_path
71
+ )
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end