fastlane-plugin-wpmreleasetoolkit 2.0.0 → 3.0.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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_localize_libs_action.rb +8 -3
  3. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_betabuild_prechecks.rb +8 -2
  4. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb +11 -4
  5. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_codefreeze_prechecks.rb +10 -4
  6. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/buildkite_trigger_build_action.rb +90 -0
  7. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/comment_on_pr.rb +89 -0
  8. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb +2 -0
  9. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_downloadmetadata_action.rb +1 -1
  10. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_betabuild_prechecks.rb +8 -2
  11. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_release.rb +10 -5
  12. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_codefreeze_prechecks.rb +10 -4
  13. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_download_strings_files_from_glotpress.rb +113 -0
  14. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_generate_strings_file_from_code.rb +115 -0
  15. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_lint_localizations.rb +5 -5
  16. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_localize_project.rb +6 -7
  17. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_merge_strings_files.rb +75 -0
  18. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_git_helper.rb +0 -20
  19. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb +8 -0
  20. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb +3 -0
  21. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb +48 -8
  22. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/interactive_prompt_reminder.rb +93 -0
  23. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_git_helper.rb +3 -2
  24. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_helper.rb +108 -173
  25. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_linter_helper.rb +207 -0
  26. data/lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb +3 -3
  27. data/lib/fastlane/plugin/wpmreleasetoolkit/models/file_reference.rb +1 -4
  28. data/lib/fastlane/plugin/wpmreleasetoolkit/version.rb +1 -1
  29. metadata +26 -39
  30. data/bin/drawText +0 -20
  31. data/ext/drawText/drawText/Assets/style.css +0 -1
  32. data/ext/drawText/drawText/CoreTextStack.swift +0 -113
  33. data/ext/drawText/drawText/Helpers/CommandLineHelpers.swift +0 -36
  34. data/ext/drawText/drawText/Helpers/Extensions.swift +0 -27
  35. data/ext/drawText/drawText/Helpers/FileSystemHelper.swift +0 -24
  36. data/ext/drawText/drawText/Stylesheet.swift +0 -48
  37. data/ext/drawText/drawText/TextImage.swift +0 -100
  38. data/ext/drawText/drawText/main.swift +0 -61
  39. data/ext/drawText/drawText Tests/DigitParsingTests.swift +0 -21
  40. data/ext/drawText/drawText Tests/ExtensionsTests.swift +0 -5
  41. data/ext/drawText/drawText Tests/Info.plist +0 -22
  42. data/ext/drawText/drawText Tests/StylesheetTests.swift +0 -31
  43. data/ext/drawText/drawText Tests/Test Cases/default-stylesheet.txt +0 -10
  44. data/ext/drawText/drawText Tests/Test Cases/external-styles-sample.css +0 -3
  45. data/ext/drawText/drawText Tests/Test Cases/external-styles-test.txt +0 -13
  46. data/ext/drawText/drawText Tests/Test Cases/large-text-block.txt +0 -1
  47. data/ext/drawText/drawText Tests/Test Cases/regular-text-block.txt +0 -2
  48. data/ext/drawText/drawText Tests/Test Cases/rtl-text-block.txt +0 -2
  49. data/ext/drawText/drawText Tests/Test Cases/text-size-adjustment-test.txt +0 -10
  50. data/ext/drawText/drawText Tests/TextImageTests.swift +0 -99
  51. data/ext/drawText/drawText Tests/drawText_Tests.swift +0 -14
  52. data/ext/drawText/drawText.xcodeproj/project.pbxproj +0 -508
  53. data/ext/drawText/drawText.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  54. data/ext/drawText/drawText.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  55. data/ext/drawText/drawText.xcodeproj/xcshareddata/xcschemes/drawText Tests.xcscheme +0 -57
  56. data/ext/drawText/drawText.xcodeproj/xcshareddata/xcschemes/drawText.xcscheme +0 -109
  57. data/ext/drawText/extconf.rb +0 -36
  58. data/ext/drawText/makefile.example +0 -8
  59. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_merge_translators_strings.rb +0 -106
  60. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_metadata.rb +0 -52
  61. data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_merge_translators_strings.rb +0 -93
@@ -0,0 +1,115 @@
1
+ module Fastlane
2
+ module Actions
3
+ class IosGenerateStringsFileFromCodeAction < Action
4
+ def self.run(params)
5
+ files = files_matching(paths: params[:paths], exclude: params[:exclude])
6
+ flags = [('-q' if params[:quiet]), ('-SwiftUI' if params[:swiftui])].compact
7
+ flags += Array(params[:routines]).flat_map { |routine| ['-s', routine] }
8
+ cmd = ['genstrings', '-o', params[:output_dir], *flags, *files]
9
+ out = Actions.sh_control_output(*cmd, print_command: FastlaneCore::Globals.verbose?, print_command_output: true)
10
+ out = out.scrub.strip.split("\n")
11
+ errors = out.select { |line| line.include?('genstrings: error: ') }
12
+ UI.user_error!(errors.join("\n")) unless !params[:fail_on_error] || errors.empty?
13
+ out
14
+ end
15
+
16
+ # Adds the proper `**/*.{m,swift}` to the list of paths
17
+ def self.glob_pattern(path)
18
+ if path.end_with?('**') || path.end_with?('**/')
19
+ File.join(path, '*.{m,swift}')
20
+ elsif File.directory?(path) || path.end_with?('/')
21
+ File.join(path, '**', '*.{m,swift}')
22
+ else
23
+ path
24
+ end
25
+ end
26
+
27
+ def self.files_matching(paths:, exclude:)
28
+ globbed_paths = paths.map { |p| glob_pattern(p) }
29
+ Dir.glob(globbed_paths).reject do |file|
30
+ exclude&.any? { |ex| File.fnmatch?(ex, file) }
31
+ end
32
+ end
33
+
34
+ #####################################################
35
+ # @!group Documentation
36
+ #####################################################
37
+
38
+ def self.description
39
+ 'Generate the .strings files from your Objective-C and Swift code'
40
+ end
41
+
42
+ def self.details
43
+ <<~DETAILS
44
+ Uses `genstrings` to generate the `.strings` files from your Objective-C and Swift code.
45
+ (especially `Localizable.strings` but it could generate more if the code uses custom tables).
46
+
47
+ You can provide a list of paths to scan but also paths to exclude. Both supports glob patterns.
48
+ You can also optionally provide a list of custom "routines" (aka macros or functions) that
49
+ `genstrings` should parse in addition to the usual `NSLocalizedString`. (see `-s` option of `genstrings`).
50
+
51
+ Tip: support for custom routines is useful if some of your targets define a helper function e.g.
52
+ `PodLocalizedString` to wrap calls to `Bundle.localizedString(forKey: key, value: value, table: nil)`,
53
+ just like the build-in `NSLocalizedString` does, but providing a custom bundle to look up the strings from.
54
+ DETAILS
55
+ end
56
+
57
+ def self.available_options
58
+ [
59
+ FastlaneCore::ConfigItem.new(key: :paths,
60
+ env_name: 'FL_IOS_GENERATE_STRINGS_FILE_FROM_CODE_PATHS',
61
+ description: 'Array of paths to scan for `.m` and `.swift` files. The entries can also contain glob patterns',
62
+ type: Array,
63
+ default_value: ['.']),
64
+ FastlaneCore::ConfigItem.new(key: :exclude,
65
+ env_name: 'FL_IOS_GENERATE_STRINGS_FILE_FROM_CODE_EXCLUDE',
66
+ description: 'Array of paths or glob patterns to exclude from scanning',
67
+ type: Array,
68
+ default_value: []),
69
+ FastlaneCore::ConfigItem.new(key: :routines,
70
+ env_name: 'FL_IOS_GENERATE_STRINGS_FILE_FROM_CODE_ROUTINES',
71
+ description: 'Base name of the alternate methods to be parsed in addition to the standard `NSLocalizedString()` one. See the `-s` option in `man genstrings`',
72
+ type: Array,
73
+ default_value: []),
74
+ FastlaneCore::ConfigItem.new(key: :quiet,
75
+ env_name: 'FL_IOS_GENERATE_STRINGS_FILE_FROM_CODE_QUIET',
76
+ description: 'In quiet mode, `genstrings` will log warnings about duplicate values, but not about duplicate comments',
77
+ is_string: false, # Boolean
78
+ default_value: true),
79
+ FastlaneCore::ConfigItem.new(key: :swiftui,
80
+ env_name: 'FL_IOS_GENERATE_STRINGS_FILE_FROM_CODE_SWIFTUI',
81
+ description: "Should we include SwiftUI's `Text()` when parsing code with `genstrings`",
82
+ is_string: false, # Boolean
83
+ default_value: false),
84
+ FastlaneCore::ConfigItem.new(key: :output_dir,
85
+ env_name: 'FL_IOS_GENERATE_STRINGS_FILE_FROM_CODE_OUTPUT_DIR',
86
+ description: 'The path to the directory where the generated `.strings` files should be created',
87
+ type: String),
88
+ FastlaneCore::ConfigItem.new(key: :fail_on_error,
89
+ env_name: 'FL_IOS_GENERATE_STRINGS_FILE_FROM_CODE_FAIL_ON_ERROR',
90
+ description: 'If true, will fail with user_error! if `genstrings` printed any error while parsing',
91
+ is_string: false, # Boolean
92
+ default_value: true),
93
+ ]
94
+ end
95
+
96
+ def self.return_type
97
+ # Describes what type of data is expected to be returned
98
+ # see RETURN_TYPES in https://github.com/fastlane/fastlane/blob/master/fastlane/lib/fastlane/action.rb
99
+ :array_of_strings
100
+ end
101
+
102
+ def self.return_value
103
+ 'List of warning lines generated by genstrings on stdout'
104
+ end
105
+
106
+ def self.authors
107
+ ['Automattic']
108
+ end
109
+
110
+ def self.is_supported?(platform)
111
+ [:ios, :mac].include?(platform)
112
+ end
113
+ end
114
+ end
115
+ end
@@ -17,8 +17,8 @@ module Fastlane
17
17
  def self.run_linter(params)
18
18
  UI.message 'Linting localizations for parameter placeholders consistency...'
19
19
 
20
- require_relative '../../helper/ios/ios_l10n_helper'
21
- helper = Fastlane::Helper::Ios::L10nHelper.new(
20
+ require_relative '../../helper/ios/ios_l10n_linter_helper'
21
+ helper = Fastlane::Helper::Ios::L10nLinterHelper.new(
22
22
  install_path: resolve_path(params[:install_path]),
23
23
  version: params[:version]
24
24
  )
@@ -92,7 +92,7 @@ module Fastlane
92
92
  description: 'The path where to install the SwiftGen tooling needed to run the linting process. If a relative path, should be relative to your repo_root',
93
93
  type: String,
94
94
  optional: true,
95
- default_value: "vendor/swiftgen/#{Fastlane::Helper::Ios::L10nHelper::SWIFTGEN_VERSION}"
95
+ default_value: "vendor/swiftgen/#{Fastlane::Helper::Ios::L10nLinterHelper::SWIFTGEN_VERSION}"
96
96
  ),
97
97
  FastlaneCore::ConfigItem.new(
98
98
  key: :version,
@@ -100,7 +100,7 @@ module Fastlane
100
100
  description: 'The version of SwiftGen to install and use for linting',
101
101
  type: String,
102
102
  optional: true,
103
- default_value: Fastlane::Helper::Ios::L10nHelper::SWIFTGEN_VERSION
103
+ default_value: Fastlane::Helper::Ios::L10nLinterHelper::SWIFTGEN_VERSION
104
104
  ),
105
105
  FastlaneCore::ConfigItem.new(
106
106
  key: :input_dir,
@@ -115,7 +115,7 @@ module Fastlane
115
115
  description: 'The language that should be used as the base language that every other language will be compared against',
116
116
  type: String,
117
117
  optional: true,
118
- default_value: Fastlane::Helper::Ios::L10nHelper::DEFAULT_BASE_LANG
118
+ default_value: Fastlane::Helper::Ios::L10nLinterHelper::DEFAULT_BASE_LANG
119
119
  ),
120
120
  FastlaneCore::ConfigItem.new(
121
121
  key: :only_langs,
@@ -16,20 +16,19 @@ module Fastlane
16
16
  #####################################################
17
17
 
18
18
  def self.description
19
- 'Gathers the string to localise'
19
+ 'Gathers the strings to localise. Deprecated'
20
20
  end
21
21
 
22
22
  def self.details
23
- 'Gathers the string to localise'
23
+ 'Gathers the strings to localise. Deprecated in favor of the new `ios_generate_strings_file_from_code`'
24
24
  end
25
25
 
26
- def self.available_options
26
+ def self.category
27
+ :deprecated
27
28
  end
28
29
 
29
- def self.output
30
- end
31
-
32
- def self.return_value
30
+ def self.deprecated_notes
31
+ 'This action is deprecated in favor of `ios_generate_strings_file_from_code`'
33
32
  end
34
33
 
35
34
  def self.authors
@@ -0,0 +1,75 @@
1
+ module Fastlane
2
+ module Actions
3
+ class IosMergeStringsFilesAction < Action
4
+ def self.run(params)
5
+ UI.message "Merging strings files: #{params[:paths].inspect}"
6
+
7
+ duplicates = Fastlane::Helper::Ios::L10nHelper.merge_strings(paths: params[:paths], output_path: params[:destination])
8
+ duplicates.each do |dup_key|
9
+ UI.important "Duplicate key found while merging the `.strings` files: `#{dup_key}`"
10
+ end
11
+ duplicates
12
+ end
13
+
14
+ #####################################################
15
+ # @!group Documentation
16
+ #####################################################
17
+
18
+ def self.description
19
+ 'Merge multiple `.strings` files into one'
20
+ end
21
+
22
+ def self.details
23
+ <<~DETAILS
24
+ Merge multiple `.strings` files into one.
25
+
26
+ Especially useful to prepare a single `.strings` file merging strings from both `Localizable.strings` from
27
+ the app code — typically previously extracted from `ios_generate_strings_file_from_code` —
28
+ and string files like `InfoPlist.strings` — which values may not be generated from the codebase but
29
+ manually maintained by developers.
30
+
31
+ The action only supports merging files which are in the OpenStep (`"key" = "value";`) text format (which is
32
+ the most common format for `.strings` files, and the one generated by `genstrings`), but can handle the case
33
+ of different files using different encodings (UTF8 vs UTF16) and is able to detect and report duplicates.
34
+ It does not handle `.strings` files in XML or binary-plist formats (which are valid but more rare)
35
+ DETAILS
36
+ end
37
+
38
+ def self.available_options
39
+ [
40
+ FastlaneCore::ConfigItem.new(
41
+ key: :paths,
42
+ env_name: 'FL_IOS_MERGE_STRINGS_FILES_PATHS',
43
+ description: 'The paths of all the `.strings` files to merge together',
44
+ type: Array,
45
+ optional: false
46
+ ),
47
+ FastlaneCore::ConfigItem.new(
48
+ key: :destination,
49
+ env_name: 'FL_IOS_MERGE_STRINGS_FILES_DESTINATION',
50
+ description: 'The path of the merged `.strings` file to generate. If nil, the merge will happen in-place in the first file in the `paths:` list',
51
+ type: String,
52
+ optional: true,
53
+ default_value: nil
54
+ ),
55
+ ]
56
+ end
57
+
58
+ def self.return_type
59
+ :array_of_strings
60
+ end
61
+
62
+ def self.return_value
63
+ 'The list of duplicate keys found while merging the various `.strings` files'
64
+ end
65
+
66
+ def self.authors
67
+ ['automattic']
68
+ end
69
+
70
+ def self.is_supported?(platform)
71
+ [:ios, :mac].include? platform
72
+ end
73
+ end
74
+ end
75
+ end
@@ -27,26 +27,6 @@ module Fastlane
27
27
  )
28
28
  end
29
29
  end
30
-
31
- # Calls the `tools/update-translations.sh` script from the project repo, then lint them using the provided gradle task
32
- #
33
- # Deprecated. Use the `android_download_translations` action instead.
34
- #
35
- # @env PROJECT_ROOT_FOLDER The path to the git root of the project
36
- # @env PROJECT_NAME The name of the directory containing the project code (especially containing the `build.gradle` file)
37
- #
38
- # @param [String] validate_translation_command The name of the gradle task to run to validate the translations
39
- #
40
- # @todo Remove this once every client has migrated to `android_download_translations` and we got rid of that legacy action.
41
- #
42
- def self.update_metadata(validate_translation_command)
43
- Action.sh('./tools/update-translations.sh')
44
- Action.sh('git', 'submodule', 'update', '--init', '--recursive')
45
- Action.sh('./gradlew', validate_translation_command)
46
-
47
- res_dir = File.join(ENV['PROJECT_ROOT_FOLDER'], ENV['PROJECT_NAME'], 'src', 'main', 'res')
48
- Fastlane::Helper::GitHelper.commit(message: 'Update translations', files: res_dir, push: true)
49
- end
50
30
  end
51
31
  end
52
32
  end
@@ -92,6 +92,14 @@ module Fastlane
92
92
  UI.user_error!("String #{string_name} [#{string_content}] was found in library #{library[:library]} but not in the main file.")
93
93
  end
94
94
 
95
+ # Merge strings from a library into the strings.xml of the main app
96
+ #
97
+ # @param [String] main Path to the main strings.xml file (something like `…/res/values/strings.xml`)
98
+ # @param [Hash] library Hash describing the library to merge. The Hash should contain the following keys:
99
+ # - `:library`: The human readable name of the library, used to display in console messages
100
+ # - `: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 library's `strings.xml` will be skipped and won't be merged into the main one.
102
+ # @return [Boolean] True if at least one string from the library has been added to (or has updated) the main strings file.
95
103
  def self.merge_lib(main, library)
96
104
  UI.message("Merging #{library[:library]} strings into #{main}")
97
105
  main_strings = File.open(main) { |f| Nokogiri::XML(f, nil, Encoding::UTF_8.to_s) }
@@ -5,6 +5,9 @@ module Fastlane
5
5
  # Helper methods to execute git-related operations
6
6
  #
7
7
  module GitHelper
8
+ # Fallback default branch of the client repository.
9
+ DEFAULT_GIT_BRANCH = 'trunk'.freeze
10
+
8
11
  # Checks if the given path, or current directory if no path is given, is
9
12
  # inside a Git repository
10
13
  #
@@ -1,23 +1,37 @@
1
1
  require 'fastlane_core/ui/ui'
2
2
  require 'octokit'
3
3
  require 'open-uri'
4
+ require 'securerandom'
4
5
 
5
6
  module Fastlane
6
7
  UI = FastlaneCore::UI unless Fastlane.const_defined?('UI')
7
8
 
8
9
  module Helper
9
10
  class GithubHelper
11
+ def self.github_token!
12
+ token = [
13
+ 'GHHELPER_ACCESS', # For historical reasons / backward compatibility
14
+ 'GITHUB_TOKEN', # Used by the `gh` CLI tool
15
+ ].map { |key| ENV[key] }
16
+ .compact
17
+ .first
18
+
19
+ token || UI.user_error!('Please provide a GitHub authentication token via the `GITHUB_TOKEN` environment variable')
20
+ end
21
+
10
22
  def self.github_client
11
- client = Octokit::Client.new(access_token: ENV['GHHELPER_ACCESS'])
23
+ @@client ||= begin
24
+ client = Octokit::Client.new(access_token: github_token!)
12
25
 
13
- # Fetch the current user
14
- user = client.user
15
- UI.message("Logged in as: #{user.name}")
26
+ # Fetch the current user
27
+ user = client.user
28
+ UI.message("Logged in as: #{user.name}")
16
29
 
17
- # Auto-paginate to ensure we're not missing data
18
- client.auto_paginate = true
30
+ # Auto-paginate to ensure we're not missing data
31
+ client.auto_paginate = true
19
32
 
20
- client
33
+ client
34
+ end
21
35
  end
22
36
 
23
37
  def self.get_milestone(repository, release)
@@ -117,8 +131,11 @@ module Fastlane
117
131
  file_name = File.basename(file_path)
118
132
  download_path = File.join(download_folder, file_name)
119
133
 
134
+ download_url = github_client.contents(repository,
135
+ path: file_path,
136
+ ref: tag).download_url
120
137
  begin
121
- uri = URI.parse("https://raw.githubusercontent.com/#{repository}/#{tag}/#{file_path}")
138
+ uri = URI.parse(download_url)
122
139
  uri.open do |remote_file|
123
140
  File.write(download_path, remote_file.read)
124
141
  end
@@ -128,6 +145,29 @@ module Fastlane
128
145
 
129
146
  download_path
130
147
  end
148
+
149
+ # Creates (or updates an existing) GitHub PR Comment
150
+ def self.comment_on_pr(project_slug:, pr_number:, body:, reuse_identifier: SecureRandom.uuid)
151
+ client = github_client
152
+ comments = client.issue_comments(project_slug, pr_number)
153
+
154
+ reuse_marker = "<!-- REUSE_ID: #{reuse_identifier} -->"
155
+
156
+ existing_comment = comments.find do |comment|
157
+ # Only match comments posted by the owner of the GitHub Token, and with the given reuse ID
158
+ comment.user.id == client.user.id and comment.body.include?(reuse_marker)
159
+ end
160
+
161
+ comment_body = reuse_marker + body
162
+
163
+ if existing_comment.nil?
164
+ client.add_comment(project_slug, pr_number, comment_body)
165
+ else
166
+ client.update_comment(project_slug, existing_comment.id, comment_body)
167
+ end
168
+
169
+ reuse_identifier
170
+ end
131
171
  end
132
172
  end
133
173
  end
@@ -0,0 +1,93 @@
1
+ require 'fastlane_core'
2
+
3
+ # The features in this file are controlled by the following ENV vars:
4
+ #
5
+ # @env `FASTLANE_PROMPT_REMINDER_DISABLE_AUTO_PATCH`
6
+ # If this variable is set, it will disable the auto-application of the monkey patch. In such case,
7
+ # `UI.input`, `UI.confirm`, `UI.select` and `UI.password` methods won't be automatically patched
8
+ # unless you explicitly call `monkey_patch_interactive_prompts_with_reminder` yourself.
9
+ #
10
+ # @env `FASTLANE_PROMPT_REMINDER_MESSAGE`
11
+ # - If not set, then while auto-patching the `UI.…` methods, it will NOT make the patched methods
12
+ # speak any vocal message – and instead will only emit a beep and make your Terminal icon jump in the Dock.
13
+ # - If set to `default`, `true`, `yes` or `1`, then while auto-patching the `UI.…` methods, it will
14
+ # make the patched methods announce the default message.
15
+ # - If set to any other string, it will make the patched methods use that string as the message to announce
16
+ # during the reminders
17
+ # - NOTE: This env var only has an effect if the other `FASTLANE_PROMPT_REMINDER_DISABLE_AUTO_PATCH` env var
18
+ # is _not_ set (and thus the `UI.…` methods _are_ auto-patched), because it only affects how auto-patching is done.
19
+ #
20
+ # @env `FASTLANE_PROMPT_REMINDER_DELAYS`
21
+ # The delays (in seconds) to use when monkey-patching the `UI.…` methods to wrap them around `with_reminder`,
22
+ # separated by a comma (e.g. `60,300,900`). If unset, will use the default delays of `30,180,600`.
23
+
24
+ module FastlaneCore
25
+ # NOTE: FastlaneCore::UI delegates to the FastlaneCore::Shell implementation when output is the terminal
26
+ class Shell
27
+ DEFAULT_PROMPT_REMINDER_MESSAGE = 'An interactive prompt is waiting for you in the Terminal!'.freeze
28
+ DEFAULT_PROMPT_REMINDER_DELAYS = [30, 180, 600].freeze
29
+
30
+ # Calls the block given and remind the user with a vocal message if the block does not return after specific delays.
31
+ #
32
+ # Especially useful when using a block which calls methods that are interactive, in order to remind the user
33
+ # to answer the interactive prompt if they forgot about it after some delays.
34
+ #
35
+ # Example usage:
36
+ #
37
+ # text = with_reminder do
38
+ # puts "Enter some text:"
39
+ # $stdout.getch
40
+ # end
41
+ #
42
+ # @param [Double,Array<Double>] after
43
+ # Delay or list of delays to wait for before pronouncing the reminder message.
44
+ # If an array of values is passed, the message will be pronounced multiple times, after having waited for the subsequent delays in turn.
45
+ # Defaults to reminding after 30s, then 3mn, then 10mn.
46
+ # @param [String] message
47
+ # The message to pronounce out loud after the delay has passed, if the block hasn't returned beforehand.
48
+ # @return The same value that the blocks might return
49
+ #
50
+ def self.with_reminder(after: DEFAULT_PROMPT_REMINDER_DELAYS, message: DEFAULT_PROMPT_REMINDER_MESSAGE)
51
+ delays_list = Array(after.dup)
52
+ thread = Thread.new do
53
+ until delays_list.empty?
54
+ sleep(delays_list.shift)
55
+ $stdout.beep
56
+ system('say', message) unless message.nil?
57
+ end
58
+ end
59
+ # execute the interactive code
60
+ res = yield
61
+ # if we replied before the timeout, kill the thread so message won't be triggered
62
+ thread.kill
63
+ # If the block given returned a value, pass it
64
+ return res
65
+ end
66
+
67
+ # Monkey-Patch fastlane's `UI.input`, `UI.confirm`, `UI.select` and `UI.password` interactive methods
68
+ # (which delegate to `FastlaneCore::Shell` when output is the terminal)
69
+ #
70
+ # Once you call this method, any invocation of `UI.input`, `UI.confirm`, `UI.select` or `UI.password`
71
+ # anywhere in Fastlane (by your Fastfile, an action, …) will be wrapped in a call to with_reminder automatically.
72
+ #
73
+ def self.monkey_patch_interactive_prompts_with_reminder(after: DEFAULT_PROMPT_REMINDER_DELAYS, message: DEFAULT_PROMPT_REMINDER_MESSAGE)
74
+ %i[input confirm select password].each do |method_name|
75
+ old_method = instance_method(method_name)
76
+
77
+ define_method(method_name) do |*args|
78
+ FastlaneCore::Shell.with_reminder(after: after, message: message) { old_method.bind(self).call(*args) }
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ # Apply Monkey patch
86
+ unless ENV['FASTLANE_PROMPT_REMINDER_DISABLE_AUTO_PATCH']
87
+ message = ENV['FASTLANE_PROMPT_REMINDER_MESSAGE']
88
+ message = FastlaneCore::Shell::DEFAULT_PROMPT_REMINDER_MESSAGE if %w[default true yes 1].include?(message&.downcase)
89
+ delays = ENV['FASTLANE_PROMPT_REMINDER_DELAYS']&.split(',')&.map(&:to_i) || FastlaneCore::Shell::DEFAULT_PROMPT_REMINDER_DELAYS
90
+
91
+ FastlaneCore::UI.verbose("Monkey-patching the UI interactive methods to add a reminder (#{delays.inspect}, #{message.inspect})")
92
+ FastlaneCore::Shell.monkey_patch_interactive_prompts_with_reminder(after: delays, message: message)
93
+ end
@@ -35,8 +35,9 @@ module Fastlane
35
35
  # @env PROJECT_ROOT_FOLDER The path to the git root of the project
36
36
  # @env PROJECT_NAME The name of the directory containing the project code (especially containing the `build.gradle` file)
37
37
  #
38
- # @todo Migrate the scripts, currently in each host repo and called by this method, to be helpers and actions
39
- # in the release-toolkit instead, and move this code away from `ios_git_helper`.
38
+ # @deprecated This method is only used by the `ios_localize_project` action, which is itself deprecated
39
+ # in favor of the new `ios_generate_strings_file_from_code` action
40
+ # @todo [Next Major] Remove this method once we fully remove `ios_localize_project`
40
41
  #
41
42
  def self.localize_project
42
43
  Action.sh("cd #{get_from_env!(key: 'PROJECT_ROOT_FOLDER')} && ./Scripts/localize.py")