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.
- checksums.yaml +4 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_localize_libs_action.rb +8 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_betabuild_prechecks.rb +8 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb +11 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_codefreeze_prechecks.rb +10 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/buildkite_trigger_build_action.rb +90 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/comment_on_pr.rb +89 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb +2 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_downloadmetadata_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_betabuild_prechecks.rb +8 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_release.rb +10 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_codefreeze_prechecks.rb +10 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_download_strings_files_from_glotpress.rb +113 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_generate_strings_file_from_code.rb +115 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_lint_localizations.rb +5 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_localize_project.rb +6 -7
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_merge_strings_files.rb +75 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_git_helper.rb +0 -20
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb +8 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb +3 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb +48 -8
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/interactive_prompt_reminder.rb +93 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_git_helper.rb +3 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_helper.rb +108 -173
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_linter_helper.rb +207 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb +3 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/models/file_reference.rb +1 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/version.rb +1 -1
- metadata +26 -39
- data/bin/drawText +0 -20
- data/ext/drawText/drawText/Assets/style.css +0 -1
- data/ext/drawText/drawText/CoreTextStack.swift +0 -113
- data/ext/drawText/drawText/Helpers/CommandLineHelpers.swift +0 -36
- data/ext/drawText/drawText/Helpers/Extensions.swift +0 -27
- data/ext/drawText/drawText/Helpers/FileSystemHelper.swift +0 -24
- data/ext/drawText/drawText/Stylesheet.swift +0 -48
- data/ext/drawText/drawText/TextImage.swift +0 -100
- data/ext/drawText/drawText/main.swift +0 -61
- data/ext/drawText/drawText Tests/DigitParsingTests.swift +0 -21
- data/ext/drawText/drawText Tests/ExtensionsTests.swift +0 -5
- data/ext/drawText/drawText Tests/Info.plist +0 -22
- data/ext/drawText/drawText Tests/StylesheetTests.swift +0 -31
- data/ext/drawText/drawText Tests/Test Cases/default-stylesheet.txt +0 -10
- data/ext/drawText/drawText Tests/Test Cases/external-styles-sample.css +0 -3
- data/ext/drawText/drawText Tests/Test Cases/external-styles-test.txt +0 -13
- data/ext/drawText/drawText Tests/Test Cases/large-text-block.txt +0 -1
- data/ext/drawText/drawText Tests/Test Cases/regular-text-block.txt +0 -2
- data/ext/drawText/drawText Tests/Test Cases/rtl-text-block.txt +0 -2
- data/ext/drawText/drawText Tests/Test Cases/text-size-adjustment-test.txt +0 -10
- data/ext/drawText/drawText Tests/TextImageTests.swift +0 -99
- data/ext/drawText/drawText Tests/drawText_Tests.swift +0 -14
- data/ext/drawText/drawText.xcodeproj/project.pbxproj +0 -508
- data/ext/drawText/drawText.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- data/ext/drawText/drawText.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- data/ext/drawText/drawText.xcodeproj/xcshareddata/xcschemes/drawText Tests.xcscheme +0 -57
- data/ext/drawText/drawText.xcodeproj/xcshareddata/xcschemes/drawText.xcscheme +0 -109
- data/ext/drawText/extconf.rb +0 -36
- data/ext/drawText/makefile.example +0 -8
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_merge_translators_strings.rb +0 -106
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_metadata.rb +0 -52
- 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/
|
21
|
-
helper = Fastlane::Helper::Ios::
|
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::
|
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::
|
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::
|
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
|
19
|
+
'Gathers the strings to localise. Deprecated'
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.details
|
23
|
-
'Gathers the
|
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.
|
26
|
+
def self.category
|
27
|
+
:deprecated
|
27
28
|
end
|
28
29
|
|
29
|
-
def self.
|
30
|
-
|
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
|
23
|
+
@@client ||= begin
|
24
|
+
client = Octokit::Client.new(access_token: github_token!)
|
12
25
|
|
13
|
-
|
14
|
-
|
15
|
-
|
26
|
+
# Fetch the current user
|
27
|
+
user = client.user
|
28
|
+
UI.message("Logged in as: #{user.name}")
|
16
29
|
|
17
|
-
|
18
|
-
|
30
|
+
# Auto-paginate to ensure we're not missing data
|
31
|
+
client.auto_paginate = true
|
19
32
|
|
20
|
-
|
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(
|
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
|
-
# @
|
39
|
-
#
|
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")
|