fastlane-plugin-wpmreleasetoolkit 3.0.0 → 3.1.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: d2f92b2b90c9f077ad4ea0ae25c5c84f0345ca2fb5e186d1c0cdfab70ea40770
4
- data.tar.gz: 0c919f8e9ca2af18c3488898efe2fe48f4ca5a3a4c0464991e000681cc6c9546
3
+ metadata.gz: 87b7167d8eeecefac13e31850447419c88d3e2ceca851a89782df561846f4b7b
4
+ data.tar.gz: 72b18c319cfbac6d39ea939c33cd801f1e777b79996ee617ea0649c0c3bfb420
5
5
  SHA512:
6
- metadata.gz: f0c0797c28da54495d995d856edb238631b70bf0126ae1516638a75e300717dd51a7f97f6fedd5cc3f9e7eef4e9cf328043c9fffcd34233a057338da8055307d
7
- data.tar.gz: 17c8536dc94ab2ea0f3b394d3d9768c248683ba78fa4558d7c10ed1cc7fe81fc0aebd1390691282db601297b6f48e67af2dbd546daa3b0a13d16ffacd8c34f4c
6
+ metadata.gz: 96c46a423eb4eaf0868bc5a6cecb6558a99dcf9f5f7b788bdc4255a2380aea4ed8adbd92d81476feaad00fc394182c70257aa140e7281920348b3ba8878bafba
7
+ data.tar.gz: 5329bbb8827fd617af2d43dd1c770e2cf9a23e6adce430bf658f2ee68fe11cda3ac1e5d52f76ced293c28f23df3a9315a882cce14ad7f7918c370ed1be07b2e0
@@ -0,0 +1,112 @@
1
+ require 'fastlane/action'
2
+ require 'digest/sha1'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ module SharedValues
7
+ S3_UPLOADED_FILE_PATH = :S3_UPLOADED_FILE_PATH
8
+ end
9
+
10
+ class UploadToS3Action < Action
11
+ def self.run(params)
12
+ file_path = params[:file]
13
+ file_name = File.basename(file_path)
14
+
15
+ bucket = params[:bucket]
16
+ key = params[:key] || file_name
17
+
18
+ if params[:auto_prefix] == true
19
+ file_name_hash = Digest::SHA1.hexdigest(file_name)
20
+ key = [file_name_hash, key].join('/')
21
+ end
22
+
23
+ UI.user_error!("File already exists in S3 bucket #{bucket} at #{key}") if file_is_already_uploaded?(bucket, key)
24
+
25
+ UI.message("Uploading #{file_path} to: #{key}")
26
+
27
+ File.open(file_path, 'rb') do |file|
28
+ Aws::S3::Client.new().put_object(
29
+ body: file,
30
+ bucket: bucket,
31
+ key: key
32
+ )
33
+ rescue Aws::S3::Errors::ServiceError => e
34
+ UI.crash!("Unable to upload file to S3: #{e.message}")
35
+ end
36
+
37
+ UI.success('Upload Complete')
38
+
39
+ Actions.lane_context[SharedValues::S3_UPLOADED_FILE_PATH] = key
40
+
41
+ return key
42
+ end
43
+
44
+ def self.file_is_already_uploaded?(bucket, key)
45
+ response = Aws::S3::Client.new().head_object(
46
+ bucket: bucket,
47
+ key: key
48
+ )
49
+ return response[:content_length].positive?
50
+ rescue Aws::S3::Errors::NotFound
51
+ return false
52
+ end
53
+
54
+ def self.description
55
+ 'Uploads a given file to S3'
56
+ end
57
+
58
+ def self.authors
59
+ ['Automattic']
60
+ end
61
+
62
+ def self.return_value
63
+ 'Returns the object\'s derived S3 key'
64
+ end
65
+
66
+ def self.details
67
+ 'Uploads a file to S3, and makes a pre-signed URL available in the lane context'
68
+ end
69
+
70
+ def self.available_options
71
+ [
72
+ FastlaneCore::ConfigItem.new(
73
+ key: :bucket,
74
+ description: 'The bucket that will store the file',
75
+ optional: false,
76
+ type: String,
77
+ verify_block: proc { |bucket| UI.user_error!('You must provide a valid bucket name') if bucket.empty? }
78
+ ),
79
+ FastlaneCore::ConfigItem.new(
80
+ key: :key,
81
+ description: 'The path to the file within the bucket. If `nil`, will default to the `file\'s basename',
82
+ optional: true,
83
+ type: String,
84
+ verify_block: proc { |key|
85
+ next if key.is_a?(String) && !key.empty?
86
+
87
+ UI.user_error!('The provided key must not be empty. Use nil instead if you want to default to the file basename')
88
+ }
89
+ ),
90
+ FastlaneCore::ConfigItem.new(
91
+ key: :file,
92
+ description: 'The path to the local file on disk',
93
+ optional: false,
94
+ type: String,
95
+ verify_block: proc { |f| UI.user_error!("Path `#{f}` does not exist.") unless File.file?(f) }
96
+ ),
97
+ FastlaneCore::ConfigItem.new(
98
+ key: :auto_prefix,
99
+ description: 'Generate a derived prefix based on the filename that makes it harder to guess the URL of the uploaded object',
100
+ optional: true,
101
+ default_value: true,
102
+ type: Boolean
103
+ ),
104
+ ]
105
+ end
106
+
107
+ def self.is_supported?(platform)
108
+ true
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,118 @@
1
+ module Fastlane
2
+ module Actions
3
+ class IosExtractKeysFromStringsFilesAction < Action
4
+ def self.run(params)
5
+ source_parent_dir = params[:source_parent_dir]
6
+ target_original_files = params[:target_original_files]
7
+ keys_to_extract_per_target_file = keys_list_per_target_file(target_original_files)
8
+
9
+ # For each locale, extract the right translations from `<source_tablename>.strings` into each target `.strings` file
10
+ Dir.glob('*.lproj', base: source_parent_dir).each do |lproj_dir_name|
11
+ source_strings_file = File.join(source_parent_dir, lproj_dir_name, "#{params[:source_tablename]}.strings")
12
+ translations = Fastlane::Helper::Ios::L10nHelper.read_strings_file_as_hash(path: source_strings_file)
13
+
14
+ target_original_files.each do |target_original_file|
15
+ target_strings_file = File.join(File.dirname(File.dirname(target_original_file)), lproj_dir_name, File.basename(target_original_file))
16
+ next if target_strings_file == target_original_file # do not generate/overwrite the original locale itself
17
+
18
+ keys_to_extract = keys_to_extract_per_target_file[target_original_file]
19
+ UI.message("Extracting #{keys_to_extract.count} keys into #{target_strings_file}...")
20
+
21
+ extracted_translations = translations.slice(*keys_to_extract)
22
+ FileUtils.mkdir_p(File.dirname(target_strings_file)) # Ensure path up to parent dir exists, create it if not.
23
+ Fastlane::Helper::Ios::L10nHelper.generate_strings_file_from_hash(translations: extracted_translations, output_path: target_strings_file)
24
+ rescue StandardError => e
25
+ UI.user_error!("Error while writing extracted translations to `#{target_strings_file}`: #{e.message}")
26
+ end
27
+ rescue StandardError => e
28
+ UI.user_error!("Error while reading the translations from source file `#{source_strings_file}`: #{e.message}")
29
+ end
30
+ end
31
+
32
+ # Pre-load the list of keys to extract for each target file.
33
+ #
34
+ # @param [Array<String>] original_files array of paths to the originals of target files
35
+ # @return [Hash<String, Array<String>>] The hash listing the keys to extract for each target file
36
+ #
37
+ def self.keys_list_per_target_file(original_files)
38
+ original_files.map do |original_file|
39
+ keys = Fastlane::Helper::Ios::L10nHelper.read_strings_file_as_hash(path: original_file).keys
40
+ [original_file, keys]
41
+ end.to_h
42
+ rescue StandardError => e
43
+ UI.user_error!("Failed to read the keys to extract from originals file: #{e.message}")
44
+ end
45
+
46
+ #####################################################
47
+ # @!group Documentation
48
+ #####################################################
49
+
50
+ def self.description
51
+ 'Extracts a subset of keys from a `.strings` file into separate `.strings` file(s)'
52
+ end
53
+
54
+ def self.details
55
+ <<~DETAILS
56
+ Extracts a subset of keys from a `.strings` file into separate `.strings` file(s), for each `*.lproj` subdirectory.
57
+
58
+ This is especially useful to extract, for each locale, the translations for files like `InfoPlist.strings` or
59
+ `<SomeIntentDefinitionFile>.strings` from the `Localizable.strings` file that we exported/downloaded back from GlotPress.
60
+
61
+ Since we typically merge all `*.strings` original files (e.g. `en.lproj/Localizable.strings` + `en.lproj/InfoPlist.strings` + …)
62
+ via `ios_merge_strings_file` before sending the originals to translations, we then need to extract the relevant keys and
63
+ translations back into the `*.lproj/InfoPlist.strings` after we pull those translations back from GlotPress
64
+ (`ios_download_strings_files_from_glotpress`). This is what this `ios_extract_keys_from_strings_files` action is for.
65
+ DETAILS
66
+ end
67
+
68
+ def self.available_options
69
+ [
70
+ FastlaneCore::ConfigItem.new(key: :source_parent_dir,
71
+ env_name: 'FL_IOS_EXTRACT_KEYS_FROM_STRINGS_FILES_SOURCE_PARENT_DIR',
72
+ description: 'The parent directory containing all the `*.lproj` subdirectories in which the source `.strings` files reside',
73
+ type: String,
74
+ verify_block: proc do |value|
75
+ UI.user_error!("`source_parent_dir` should be a path to an existing directory, but found `#{value}`.") unless File.directory?(value)
76
+ UI.user_error!("`source_parent_dir` should contain at least one `.lproj` subdirectory, but `#{value}` does not contain any.") if Dir.glob('*.lproj', base: value).empty?
77
+ end),
78
+ FastlaneCore::ConfigItem.new(key: :source_tablename,
79
+ env_name: 'FL_IOS_EXTRACT_KEYS_FROM_STRINGS_FILES_SOURCE_TABLENAME',
80
+ description: 'The basename of the `.strings` file (without the extension) to extract the keys and translations from for each locale',
81
+ type: String,
82
+ default_value: 'Localizable'),
83
+ FastlaneCore::ConfigItem.new(key: :target_original_files,
84
+ env_name: 'FL_IOS_EXTRACT_KEYS_FROM_STRINGS_FILES_TARGET_ORIGINAL_FILES',
85
+ description: 'The path(s) to the `<base-locale>.lproj/<target-tablename>.strings` file(s) for which we want to extract the keys to. ' \
86
+ + 'Each of those files should containing the original strings (typically `en` or `Base` locale) and will be used to determine which keys to extract from the `source_tablename`. ' \
87
+ + 'For each of those, the path(s) in which the translations will be extracted will be the files with the same basename in each of the other `*.lproj` sibling folders',
88
+ type: Array,
89
+ verify_block: proc do |values|
90
+ UI.user_error!('`target_original_files` must contain at least one path to an original `.strings` file.') if values.empty?
91
+ values.each do |v|
92
+ UI.user_error!("Path `#{v}` (found in `target_original_files`) does not exist.") unless File.exist?(v)
93
+ UI.user_error! "Expected `#{v}` (found in `target_original_files`) to be a path ending in a `*.lproj/*.strings`." unless File.extname(v) == '.strings' && File.extname(File.dirname(v)) == '.lproj'
94
+ end
95
+ end),
96
+ ]
97
+ end
98
+
99
+ def self.return_type
100
+ # Describes what type of data is expected to be returned
101
+ # see RETURN_TYPES in https://github.com/fastlane/fastlane/blob/master/fastlane/lib/fastlane/action.rb
102
+ nil
103
+ end
104
+
105
+ def self.return_value
106
+ # Freeform textual description of the return value
107
+ end
108
+
109
+ def self.authors
110
+ ['Automattic']
111
+ end
112
+
113
+ def self.is_supported?(platform)
114
+ [:ios, :mac].include?(platform)
115
+ end
116
+ end
117
+ end
118
+ end
@@ -36,7 +36,7 @@ module Fastlane
36
36
  #####################################################
37
37
 
38
38
  def self.description
39
- 'Generate the .strings files from your Objective-C and Swift code'
39
+ 'Generate the `.strings` files from your Objective-C and Swift code'
40
40
  end
41
41
 
42
42
  def self.details
@@ -108,7 +108,7 @@ module Fastlane
108
108
  xml.comment('Warning: Auto-generated file, do not edit.')
109
109
  xml.plist(version: '1.0') do
110
110
  xml.dict do
111
- translations.each do |k, v|
111
+ translations.sort.each do |k, v| # NOTE: use `sort` just in order to be deterministic over various runs
112
112
  xml.key(k.to_s)
113
113
  xml.string(v.to_s)
114
114
  end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module Wpmreleasetoolkit
3
- VERSION = '3.0.0'
3
+ VERSION = '3.1.0'
4
4
  end
5
5
  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: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorenzo Mattei
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-09 00:00:00.000000000 Z
11
+ date: 2022-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: diffy
@@ -401,6 +401,7 @@ files:
401
401
  - lib/fastlane/plugin/wpmreleasetoolkit/actions/common/removebranchprotection_action.rb
402
402
  - lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setbranchprotection_action.rb
403
403
  - lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setfrozentag_action.rb
404
+ - lib/fastlane/plugin/wpmreleasetoolkit/actions/common/upload_to_s3.rb
404
405
  - lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_add_files_to_copy_action.rb
405
406
  - lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_apply_action.rb
406
407
  - lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_download_action.rb
@@ -421,6 +422,7 @@ files:
421
422
  - lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_completecodefreeze_prechecks.rb
422
423
  - lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_current_branch_is_hotfix.rb
423
424
  - lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_download_strings_files_from_glotpress.rb
425
+ - lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_extract_keys_from_strings_files.rb
424
426
  - lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_final_tag.rb
425
427
  - lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_finalize_prechecks.rb
426
428
  - lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_generate_strings_file_from_code.rb