fastlane-plugin-wpmreleasetoolkit 13.3.1 → 13.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ee60c5f0a3e9884bf810f436b0a2480805c7e54aa95ac65f7b38e971ab6340e
4
- data.tar.gz: 12718cd798a67c45d3f056f38aa9f69fa6dff65860936fda4d8d20dfba1e2737
3
+ metadata.gz: d022bdc136add014c305e7d06dee672e4cd9bb34bcac77ccef7a876f54597c9d
4
+ data.tar.gz: 92bee8e4989223907a6f2e8c8e733219ffba191c49a756e01e60dbbe95a3c913
5
5
  SHA512:
6
- metadata.gz: befe8e1e789fd36d8c4ddf1501c8bcc9e29d33cbe6c2b1541557f2d9e8c1ceadf1f1806673621643692a9d648eeabe69a7575d5fa01c1bce39645bac1b236715
7
- data.tar.gz: 692c4ad19f812174ebca4322610689539c25c1c973ebbb6b788de5c518145209d9f8a635a5552135b9cbe5f35deb319ba3c731c11115def13cf3c40f9317db43
6
+ metadata.gz: 690c4f8a452cceda096e4dc9f3667e9a2fbb44c67f7377a58ba1267f1aa7753c3403cabc279e6f28cc2d4b9ba4da43162433dd14034f944001e6b4038d164595
7
+ data.tar.gz: 669a524c570d9704139a297c54469acfdd86c41da83b1e6754b693e98b27afd24805328199cbe8f449d71e10c7588db12df636c8b08bad8bb86da3b1527a832e
@@ -15,11 +15,35 @@ module Fastlane
15
15
  end
16
16
 
17
17
  class UploadBuildToAppsCdnAction < Action
18
+ # See https://github.a8c.com/Automattic/wpcom/blob/trunk/wp-content/lib/a8c/cdn/src/enums/enum-resource-type.php
18
19
  RESOURCE_TYPE = 'Build'
20
+ # These are from the WordPress.com API, not the Apps CDN plugin
19
21
  VALID_POST_STATUS = %w[publish draft].freeze
20
- VALID_BUILD_TYPES = %w[Alpha Beta Nightly Production Prototype].freeze
21
- VALID_PLATFORMS = ['Android', 'iOS', 'Mac - Silicon', 'Mac - Intel', 'Mac - Any', 'Windows'].freeze
22
- VALID_INSTALL_TYPES = ['Full Install', 'Update'].freeze
22
+ # See https://github.a8c.com/Automattic/wpcom/blob/trunk/wp-content/lib/a8c/cdn/src/enums/enum-build-type.php
23
+ VALID_BUILD_TYPES = %w[
24
+ Alpha
25
+ Beta
26
+ Nightly
27
+ Production
28
+ Prototype
29
+ ].freeze
30
+ # See https://github.a8c.com/Automattic/wpcom/blob/trunk/wp-content/lib/a8c/cdn/src/enums/enum-platform.php
31
+ VALID_PLATFORMS = [
32
+ 'Android',
33
+ 'iOS',
34
+ 'Mac - Silicon',
35
+ 'Mac - Intel',
36
+ 'Mac - Any',
37
+ 'Windows',
38
+ 'Microsoft Store',
39
+ ].freeze
40
+ # See https://github.a8c.com/Automattic/wpcom/blob/trunk/wp-content/lib/a8c/cdn/src/enums/enum-install-type.php
41
+ VALID_INSTALL_TYPES = [
42
+ 'Full Install',
43
+ 'Update',
44
+ ].freeze
45
+ # See https://github.a8c.com/Automattic/wpcom/blob/trunk/wp-content/lib/a8c/cdn/src/enums/enum-visibility.php
46
+ VALID_VISIBILITIES = %i[internal external].freeze
23
47
 
24
48
  def self.run(params)
25
49
  UI.message('Uploading build to Apps CDN...')
@@ -179,6 +203,8 @@ module Fastlane
179
203
  type: String,
180
204
  verify_block: proc do |value|
181
205
  UI.user_error!('Product cannot be empty') if value.to_s.empty?
206
+ # Unlike for other parameters, we don't validate the product value against a list of valid values because we expect this list of
207
+ # supported products to be updated on the backend from time to time and we don't want to have to update the toolkit every time for it.
182
208
  end
183
209
  ),
184
210
  FastlaneCore::ConfigItem.new(
@@ -228,7 +254,7 @@ module Fastlane
228
254
  optional: false,
229
255
  type: Symbol,
230
256
  verify_block: proc do |value|
231
- UI.user_error!('Visibility must be either :internal or :external') unless %i[internal external].include?(value)
257
+ UI.user_error!("Visibility must be one of: #{VALID_VISIBILITIES.map { "`:#{_1}`" }.join(', ')}") unless VALID_VISIBILITIES.include?(value.to_s.downcase.to_sym)
232
258
  end
233
259
  ),
234
260
  FastlaneCore::ConfigItem.new(
@@ -33,6 +33,14 @@ module Fastlane
33
33
  def to_s
34
34
  "#{@major}.#{@minor}.#{@patch}.#{@build_number}"
35
35
  end
36
+
37
+ # Returns an array of the version components.
38
+ #
39
+ # @return [Array<Integer>] an array of the version components.
40
+ #
41
+ def components
42
+ [@major, @minor, @patch, @build_number]
43
+ end
36
44
  end
37
45
  end
38
46
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Fastlane
4
4
  module Wpmreleasetoolkit
5
- VERSION = '13.3.1'
5
+ VERSION = '13.5.0'
6
6
  end
7
7
  end
@@ -3,13 +3,35 @@
3
3
  module Fastlane
4
4
  module Wpmreleasetoolkit
5
5
  module Versioning
6
+ # Max total for `*_digits` params, not counting prefix
7
+ MAX_TOTAL_DIGITS = 8
8
+ MIN_DIGIT_COUNT = 1
9
+ MAX_DIGIT_COUNT = 3
10
+
6
11
  # The `DerivedBuildCodeFormatter` class is a specialized build code formatter for derived build codes.
7
12
  # It takes in an AppVersion object and derives a build code from it.
8
13
  class DerivedBuildCodeFormatter
14
+ # Initialize the formatter with configurable prefix and digit counts.
15
+ #
16
+ # @param [String] prefix The prefix to use for the build code. Must be a single digit (0-9), or empty string / nil.
17
+ # @param [Integer] major_digits Number of digits for major version. Must be between 1–3. Defaults to 2.
18
+ # @param [Integer] minor_digits Number of digits for minor version. Must be between 1–3. Defaults to 2.
19
+ # @param [Integer] patch_digits Number of digits for patch version. Must be between 1–3. Defaults to 2.
20
+ # @param [Integer] build_digits Number of digits for build number. Must be between 1–3. Defaults to 2.
21
+ #
22
+ def initialize(prefix: nil, major_digits: 2, minor_digits: 2, patch_digits: 2, build_digits: 2)
23
+ validate_prefix!(prefix)
24
+ @prefix = prefix.to_s
25
+
26
+ @digit_counts = [major_digits, minor_digits, patch_digits, build_digits]
27
+ @digit_counts.each { |d| validate_digit_count!(d) }
28
+ validate_total_digits!(@digit_counts)
29
+ end
30
+
9
31
  # Calculate the next derived build code.
10
32
  #
11
- # This method derives a new build code from the given AppVersion object by concatenating the digit 1,
12
- # the major version, the minor version, the patch version, and the build number.
33
+ # This method derives a new build code from the given AppVersion object by concatenating the configured prefix,
34
+ # the major version, the minor version, the patch version, and the build number with configurable digit counts.
13
35
  #
14
36
  # @param [AppVersion] version The AppVersion object to derive the next build code from.
15
37
  #
@@ -18,16 +40,76 @@ module Fastlane
18
40
  #
19
41
  # @return [String] The formatted build code string.
20
42
  #
21
- def build_code(build_code = nil, version:)
22
- format(
23
- # 1 is appended to the beginning of the string in case there needs to be additional platforms or
24
- # extensions that could then use a different digit prefix such as 2, etc.
25
- '1%<major>.2i%<minor>.2i%<patch>.2i%<build_number>.2i',
26
- major: version.major,
27
- minor: version.minor,
28
- patch: version.patch,
29
- build_number: version.build_number
30
- )
43
+ def build_code(_build_code = nil, version:)
44
+ formatted_components = version.components.zip(@digit_counts).map do |value, width|
45
+ comp = value.to_s.rjust(width, '0')
46
+ if comp.length > width
47
+ UI.user_error!("Version component value (#{value}) exceeds maximum allowed width of #{width} characters. " \
48
+ "Consider increasing the corresponding `*_digits` parameter of your `#{self.class.name}`")
49
+ end
50
+ comp
51
+ end
52
+ [@prefix, *formatted_components].join.gsub(/^0+/, '')
53
+ end
54
+
55
+ private
56
+
57
+ # Validates that the prefix is a valid single digit (0-9) or empty string.
58
+ #
59
+ # @param [String] prefix The prefix to validate
60
+ #
61
+ # @raise [StandardError] If the prefix is invalid
62
+ #
63
+ def validate_prefix!(prefix)
64
+ unless prefix.nil? || prefix.is_a?(String) || prefix.is_a?(Integer)
65
+ UI.user_error!("Prefix must be a string or integer, got: #{prefix.class}")
66
+ end
67
+
68
+ prefix_str = prefix.to_s
69
+
70
+ # Allow empty string
71
+ return if prefix_str.empty?
72
+
73
+ # Check if it's longer than 1 character
74
+ if prefix_str.length > 1
75
+ UI.user_error!("Prefix must be a single digit or empty string, got: '#{prefix_str}' (length: #{prefix_str.length})")
76
+ end
77
+
78
+ # Check if it's a valid integer
79
+ return if ('0'..'9').include?(prefix_str)
80
+
81
+ UI.user_error!("Prefix must be an integer digit (0-9) or empty string, got: '#{prefix_str}'")
82
+ end
83
+
84
+ # Validates that the digit count is a valid positive integer within reasonable limits.
85
+ #
86
+ # @param [Integer] digit_count The digit count to validate
87
+ #
88
+ # @raise [StandardError] If the digit count is invalid
89
+ #
90
+ def validate_digit_count!(digit_count)
91
+ # Check if it's an integer
92
+ unless digit_count.is_a?(Integer)
93
+ UI.user_error!("Digit count must be an integer, got: #{digit_count.class}")
94
+ end
95
+
96
+ return if digit_count.between?(MIN_DIGIT_COUNT, MAX_DIGIT_COUNT)
97
+
98
+ UI.user_error!("Digit count must be between #{MIN_DIGIT_COUNT} and #{MAX_DIGIT_COUNT} digits, got: #{digit_count}")
99
+ end
100
+
101
+ # Validates that the total number of digits (excluding prefix) doesn't exceed the maximum for multiplatform compatibility.
102
+ #
103
+ # Since Google Play's max versionCode is ≈ 2_000_000_000, we want to avoid being too close to the limit
104
+ # as this would then block us from submitting any updates for that app if we reached it.
105
+ def validate_total_digits!(digits_list)
106
+ total_digits = digits_list.sum
107
+
108
+ # Limit total digits to 8 (excluding prefix)
109
+ return if total_digits <= MAX_TOTAL_DIGITS
110
+
111
+ UI.user_error!("Total digit count (#{total_digits}) exceeds maximum allowed (#{MAX_TOTAL_DIGITS}). " \
112
+ "Current config: major(#{digits_list[0]}) + minor(#{digits_list[1]}) + patch(#{digits_list[2]}) + build(#{digits_list[3]}) digits")
31
113
  end
32
114
  end
33
115
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-wpmreleasetoolkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 13.3.1
4
+ version: 13.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Automattic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-06-26 00:00:00.000000000 Z
11
+ date: 2025-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport