fastlane-plugin-wpmreleasetoolkit 1.4.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_betabuild_prechecks.rb +19 -19
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_prechecks.rb +5 -10
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_beta.rb +9 -16
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_final_release.rb +8 -15
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_hotfix.rb +6 -12
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb +20 -20
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_codefreeze_prechecks.rb +13 -13
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_completecodefreeze_prechecks.rb +2 -8
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_current_branch_is_hotfix.rb +1 -7
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_download_file_by_version.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_finalize_prechecks.rb +2 -6
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_alpha_version.rb +1 -7
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_app_version.rb +1 -7
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_release_version.rb +1 -7
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_tag_build.rb +2 -8
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/check_translation_progress.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/comment_on_pr.rb +89 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb +3 -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_generate_strings_file_from_code.rb +115 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_localize_project.rb +5 -6
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/an_metadata_update_helper.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_git_helper.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb +33 -68
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb +5 -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/version.rb +1 -1
- metadata +13 -4
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'fastlane/action'
|
2
|
+
|
3
|
+
module Fastlane
|
4
|
+
module Actions
|
5
|
+
module SharedValues
|
6
|
+
PR_COMMENT_REUSE_IDENTIFIER = :PR_COMMENT_REUSE_IDENTIFIER
|
7
|
+
end
|
8
|
+
|
9
|
+
class CommentOnPrAction < Action
|
10
|
+
def self.run(params)
|
11
|
+
require_relative '../../helper/github_helper'
|
12
|
+
|
13
|
+
reuse_identifier = Fastlane::Helper::GithubHelper.comment_on_pr(
|
14
|
+
project_slug: params[:project],
|
15
|
+
pr_number: params[:pr_number],
|
16
|
+
body: params[:body],
|
17
|
+
reuse_identifier: params[:reuse_identifier]
|
18
|
+
)
|
19
|
+
|
20
|
+
Actions.lane_context[SharedValues::PR_COMMENT_REUSE_IDENTIFIER] = reuse_identifier
|
21
|
+
|
22
|
+
reuse_identifier
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.description
|
26
|
+
'Post a comment on a given PR number (optionally updating an existing one)'
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.authors
|
30
|
+
['Automattic']
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.details
|
34
|
+
<<~DETAILS
|
35
|
+
If used just once, this method makes it nice and easy to post a quick comment to a GitHub PR.
|
36
|
+
|
37
|
+
Subsequent runs will allow you to update an existing comment as many times as you need to
|
38
|
+
(e.g. across multiple CI runs), by using a `:reuse_identifier` to identify the comment to update.
|
39
|
+
DETAILS
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.available_options
|
43
|
+
[
|
44
|
+
FastlaneCore::ConfigItem.new(
|
45
|
+
key: :access_token,
|
46
|
+
env_name: 'GITHUB_TOKEN',
|
47
|
+
description: 'The GitHub token to use for posting the comment',
|
48
|
+
type: String
|
49
|
+
),
|
50
|
+
FastlaneCore::ConfigItem.new(
|
51
|
+
key: :reuse_identifier,
|
52
|
+
description: 'If provided, the reuse identifier can identify an existing comment to overwrite',
|
53
|
+
type: String,
|
54
|
+
default_value: nil
|
55
|
+
),
|
56
|
+
FastlaneCore::ConfigItem.new(
|
57
|
+
key: :project,
|
58
|
+
description: 'The project slug (ex: `wordpress-mobile/wordpress-ios`)',
|
59
|
+
type: String
|
60
|
+
),
|
61
|
+
FastlaneCore::ConfigItem.new(
|
62
|
+
key: :pr_number,
|
63
|
+
description: 'The PR number',
|
64
|
+
type: Integer
|
65
|
+
),
|
66
|
+
FastlaneCore::ConfigItem.new(
|
67
|
+
key: :body,
|
68
|
+
description: 'The content of the comment',
|
69
|
+
type: String
|
70
|
+
),
|
71
|
+
]
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.output
|
75
|
+
[
|
76
|
+
['PR_COMMENT_REUSE_IDENTIFIER', 'The `reuse_identifier` for the most recently posted comment'],
|
77
|
+
]
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.return_value
|
81
|
+
'The `reuse_identifier` for the posted comment (useful for updating it later, if needed)'
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.is_supported?(platform)
|
85
|
+
true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -10,7 +10,9 @@ module Fastlane
|
|
10
10
|
repository = params[:repository]
|
11
11
|
version = params[:version]
|
12
12
|
assets = params[:release_assets]
|
13
|
-
release_notes = params[:release_notes_file_path].nil? ? '' :
|
13
|
+
release_notes = params[:release_notes_file_path].nil? ? '' : File.read(params[:release_notes_file_path])
|
14
|
+
# Replace full URLS to PRs/Issues with shorthand, because GitHub does not render them properly otherwise.
|
15
|
+
release_notes.gsub!(%r{https://github.com/([^/]*/[^/]*)/(pulls?|issues?)/([0-9]*)}, '\1#\3')
|
14
16
|
prerelease = params[:prerelease]
|
15
17
|
|
16
18
|
UI.message("Creating draft release #{version} in #{repository}.")
|
@@ -8,8 +8,9 @@ module Fastlane
|
|
8
8
|
require_relative '../../helper/ios/ios_version_helper'
|
9
9
|
require_relative '../../helper/ios/ios_git_helper'
|
10
10
|
|
11
|
-
# Checkout
|
12
|
-
|
11
|
+
# Checkout default branch and update
|
12
|
+
default_branch = params[:default_branch]
|
13
|
+
Fastlane::Helper::GitHelper.checkout_and_pull(default_branch)
|
13
14
|
|
14
15
|
# Check versions
|
15
16
|
build_version = Fastlane::Helper::Ios::VersionHelper.get_build_version
|
@@ -69,6 +70,11 @@ module Fastlane
|
|
69
70
|
description: 'Skips confirmation',
|
70
71
|
is_string: false, # true: verifies the input is a string, false: every kind of value
|
71
72
|
default_value: false), # the default value if the user didn't provide one
|
73
|
+
FastlaneCore::ConfigItem.new(key: :default_branch,
|
74
|
+
env_name: 'FL_RELEASE_TOOLKIT_DEFAULT_BRANCH',
|
75
|
+
description: 'Default branch of the repository',
|
76
|
+
type: String,
|
77
|
+
default_value: Fastlane::Helper::GitHelper::DEFAULT_GIT_BRANCH),
|
72
78
|
]
|
73
79
|
end
|
74
80
|
|
@@ -8,16 +8,17 @@ module Fastlane
|
|
8
8
|
require_relative '../../helper/ios/ios_version_helper'
|
9
9
|
require_relative '../../helper/ios/ios_git_helper'
|
10
10
|
|
11
|
-
|
11
|
+
default_branch = params[:default_branch]
|
12
|
+
other_action.ensure_git_branch(branch: default_branch)
|
12
13
|
|
13
14
|
# Create new configuration
|
14
15
|
@new_version = Fastlane::Helper::Ios::VersionHelper.bump_version_release()
|
15
16
|
create_config()
|
16
17
|
show_config()
|
17
18
|
|
18
|
-
# Update local
|
19
|
-
Fastlane::Helper::GitHelper.checkout_and_pull(
|
20
|
-
Fastlane::Helper::GitHelper.create_branch(@new_release_branch, from:
|
19
|
+
# Update local default branch and create branch from it
|
20
|
+
Fastlane::Helper::GitHelper.checkout_and_pull(default_branch)
|
21
|
+
Fastlane::Helper::GitHelper.create_branch(@new_release_branch, from: default_branch)
|
21
22
|
UI.message 'Done!'
|
22
23
|
|
23
24
|
UI.message 'Updating glotPressKeys...' unless params[:skip_glotpress]
|
@@ -64,7 +65,11 @@ module Fastlane
|
|
64
65
|
description: 'Skips Deliver key update',
|
65
66
|
is_string: false, # true: verifies the input is a string, false: every kind of value
|
66
67
|
default_value: false), # the default value if the user didn't provide one
|
67
|
-
|
68
|
+
FastlaneCore::ConfigItem.new(key: :default_branch,
|
69
|
+
env_name: 'FL_RELEASE_TOOLKIT_DEFAULT_BRANCH',
|
70
|
+
description: 'Default branch of the repository',
|
71
|
+
type: String,
|
72
|
+
default_value: Fastlane::Helper::GitHelper::DEFAULT_GIT_BRANCH),
|
68
73
|
]
|
69
74
|
end
|
70
75
|
|
@@ -8,8 +8,9 @@ module Fastlane
|
|
8
8
|
require_relative '../../helper/ios/ios_version_helper'
|
9
9
|
require_relative '../../helper/ios/ios_git_helper'
|
10
10
|
|
11
|
-
# Checkout
|
12
|
-
|
11
|
+
# Checkout default branch and update
|
12
|
+
default_branch = params[:default_branch]
|
13
|
+
Fastlane::Helper::GitHelper.checkout_and_pull(default_branch)
|
13
14
|
|
14
15
|
# Create versions
|
15
16
|
current_version = Fastlane::Helper::Ios::VersionHelper.get_public_version
|
@@ -17,7 +18,7 @@ module Fastlane
|
|
17
18
|
next_version = Fastlane::Helper::Ios::VersionHelper.calc_next_release_version(current_version)
|
18
19
|
|
19
20
|
# Ask user confirmation
|
20
|
-
unless params[:skip_confirm] || UI.confirm("Building a new release branch starting from
|
21
|
+
unless params[:skip_confirm] || UI.confirm("Building a new release branch starting from #{default_branch}.\nCurrent version is #{current_version} (#{current_build_version}).\nAfter codefreeze the new version will be: #{next_version}.\nDo you want to continue?")
|
21
22
|
UI.user_error!('Aborted by user request')
|
22
23
|
end
|
23
24
|
|
@@ -37,7 +38,7 @@ module Fastlane
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def self.details
|
40
|
-
'Updates the
|
41
|
+
'Updates the default branch, checks the app version and ensure the branch is clean'
|
41
42
|
end
|
42
43
|
|
43
44
|
def self.available_options
|
@@ -48,6 +49,11 @@ module Fastlane
|
|
48
49
|
description: 'Skips confirmation before codefreeze',
|
49
50
|
is_string: false, # true: verifies the input is a string, false: every kind of value
|
50
51
|
default_value: false), # the default value if the user didn't provide one
|
52
|
+
FastlaneCore::ConfigItem.new(key: :default_branch,
|
53
|
+
env_name: 'FL_RELEASE_TOOLKIT_DEFAULT_BRANCH',
|
54
|
+
description: 'Default branch of the repository',
|
55
|
+
type: String,
|
56
|
+
default_value: Fastlane::Helper::GitHelper::DEFAULT_GIT_BRANCH),
|
51
57
|
]
|
52
58
|
end
|
53
59
|
|
@@ -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
|
@@ -20,16 +20,15 @@ module Fastlane
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.details
|
23
|
-
'Gathers the string to localise'
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.available_options
|
23
|
+
'Gathers the string to localise. Deprecated in favor of the new `ios_generate_strings_file_from_code`'
|
27
24
|
end
|
28
25
|
|
29
|
-
def self.
|
26
|
+
def self.category
|
27
|
+
:deprecated
|
30
28
|
end
|
31
29
|
|
32
|
-
def self.
|
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
|
@@ -50,7 +50,7 @@ module Fastlane
|
|
50
50
|
|
51
51
|
if line_count <= 1
|
52
52
|
# Single line output
|
53
|
-
fw.puts("msgid \"#{File.open(@content_file_path, 'r').read}\"")
|
53
|
+
fw.puts("msgid \"#{File.open(@content_file_path, 'r').read.rstrip}\"")
|
54
54
|
else
|
55
55
|
# Multiple line output
|
56
56
|
fw.puts('msgid ""')
|
@@ -13,7 +13,7 @@ module Fastlane
|
|
13
13
|
#
|
14
14
|
def self.commit_version_bump
|
15
15
|
require_relative './android_version_helper'
|
16
|
-
if Fastlane::Helper::Android::VersionHelper.
|
16
|
+
if File.exist?(Fastlane::Helper::Android::VersionHelper.version_properties_file)
|
17
17
|
Fastlane::Helper::GitHelper.commit(
|
18
18
|
message: 'Bump version number',
|
19
19
|
files: File.join(ENV['PROJECT_ROOT_FOLDER'], 'version.properties'),
|
@@ -26,14 +26,12 @@ module Fastlane
|
|
26
26
|
# "1.2" # Assuming build.gradle contains versionName "1.2.0"
|
27
27
|
# "1.2.3" # Assuming build.gradle contains versionName "1.2.3"
|
28
28
|
#
|
29
|
-
# @param [String] app The name of the app to be used for beta and alpha version update
|
30
|
-
#
|
31
29
|
# @return [String] The public-facing version number, extracted from the `versionName` of the `build.gradle` file.
|
32
30
|
# - If this version is a hotfix (more than 2 parts and 3rd part is non-zero), returns the "X.Y.Z" formatted string
|
33
31
|
# - Otherwise (not a hotfix / 3rd part of version is 0), returns "X.Y" formatted version number
|
34
32
|
#
|
35
|
-
def self.get_public_version
|
36
|
-
version = get_release_version
|
33
|
+
def self.get_public_version
|
34
|
+
version = get_release_version
|
37
35
|
vp = get_version_parts(version[VERSION_NAME])
|
38
36
|
return "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" unless is_hotfix?(version)
|
39
37
|
|
@@ -42,12 +40,10 @@ module Fastlane
|
|
42
40
|
|
43
41
|
# Extract the version name and code from the release version of the app from `version.properties file`
|
44
42
|
#
|
45
|
-
# @param [String] product_name The name of the app to be used for beta and alpha version update
|
46
|
-
#
|
47
43
|
# @return [Hash] A hash with 2 keys "name" and "code" containing the extracted version name and code, respectively
|
48
44
|
#
|
49
|
-
def self.get_release_version
|
50
|
-
return get_version_from_properties(
|
45
|
+
def self.get_release_version
|
46
|
+
return get_version_from_properties() if File.exist?(version_properties_file)
|
51
47
|
|
52
48
|
section = ENV['HAS_ALPHA_VERSION'].nil? ? 'defaultConfig' : 'vanilla {'
|
53
49
|
gradle_path = self.gradle_path
|
@@ -56,66 +52,36 @@ module Fastlane
|
|
56
52
|
return { VERSION_NAME => name, VERSION_CODE => code }
|
57
53
|
end
|
58
54
|
|
59
|
-
def self.
|
60
|
-
|
61
|
-
|
62
|
-
return File.exist?(properties_file_path)
|
55
|
+
def self.version_properties_file
|
56
|
+
File.join(ENV['PROJECT_ROOT_FOLDER'] || '.', 'version.properties')
|
63
57
|
end
|
64
58
|
|
65
59
|
# Extract the version name and code from the `version.properties` file in the project root
|
66
60
|
#
|
67
|
-
# @param [String] product_name The name of the app to extract the version from e.g. wordpress, simplenote
|
68
61
|
# @param [Boolean] is_alpha true if the alpha version should be returned, false otherwise
|
69
62
|
#
|
70
63
|
# @return [Hash] A hash with 2 keys "name" and "code" containing the extracted version name and code, respectively
|
71
64
|
#
|
72
|
-
def self.get_version_from_properties(
|
73
|
-
|
74
|
-
version_name_key = [product_name, alpha_variant, 'versionName'].compact.join('.')
|
75
|
-
version_code_key = [product_name, alpha_variant, 'versionCode'].compact.join('.')
|
65
|
+
def self.get_version_from_properties(is_alpha: false)
|
66
|
+
return nil unless File.exist?(version_properties_file)
|
76
67
|
|
77
|
-
|
68
|
+
version_name_key = is_alpha ? 'alpha.versionName' : 'versionName'
|
69
|
+
version_code_key = is_alpha ? 'alpha.versionCode' : 'versionCode'
|
78
70
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
text = f.read
|
83
|
-
name = text.match(/#{version_name_key}=(\S*)/m)&.captures&.first
|
84
|
-
code = text.match(/#{version_code_key}=(\S*)/m)&.captures&.first
|
71
|
+
text = File.read(version_properties_file)
|
72
|
+
name = text.match(/#{version_name_key}=(\S*)/m)&.captures&.first
|
73
|
+
code = text.match(/#{version_code_key}=(\S*)/m)&.captures&.first
|
85
74
|
|
86
|
-
|
87
|
-
|
88
|
-
return nil if name.nil? || code.nil?
|
89
|
-
|
90
|
-
return { VERSION_NAME => name, VERSION_CODE => code.to_i }
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
# Returns the name of the flavor used for alpha builds
|
95
|
-
#
|
96
|
-
# @env HAS_ALPHA_VERSION Should contain the name of the flavor used for alpha
|
97
|
-
#
|
98
|
-
# @return [String] The flavor name as provided by the env var, defaulting to `zalpha` if the env var
|
99
|
-
# is not set or is set to '1' ('boolean' value used in legacy call sites)
|
100
|
-
def self.alpha_flavor_name
|
101
|
-
# TODO: Have each fastlane action which depends on this take the alpha flavor name as ConfigItem/parameter
|
102
|
-
# explicitly instead (and get rid of the HAS_ALPHA_VERSION global / env var after that)
|
103
|
-
|
104
|
-
# For now we pass the alpha flavor name by reusing the HAS_ALPHA_VERSION env var.
|
105
|
-
return ENV['HAS_ALPHA_VERSION'] if ENV['HAS_ALPHA_VERSION'] && ENV['HAS_ALPHA_VERSION'] != '1'
|
106
|
-
|
107
|
-
'zalpha' # Default value if HAS_ALPHA_VERSION is not set or hasn't been updated at call site to the flavor name instead of '1'
|
75
|
+
return name.nil? || code.nil? ? nil : { VERSION_NAME => name, VERSION_CODE => code.to_i }
|
108
76
|
end
|
109
77
|
|
110
78
|
# Extract the version name and code from the `version.properties` file in the project root
|
111
79
|
#
|
112
|
-
# @param [String] app The name of the app to be used for beta and alpha version update
|
113
|
-
#
|
114
80
|
# @return [Hash] A hash with 2 keys `"name"` and `"code"` containing the extracted version name and code, respectively,
|
115
81
|
# or `nil` if `$HAS_ALPHA_VERSION` is not defined.
|
116
82
|
#
|
117
|
-
def self.get_alpha_version
|
118
|
-
return get_version_from_properties(
|
83
|
+
def self.get_alpha_version
|
84
|
+
return get_version_from_properties(is_alpha: true) if File.exist?(version_properties_file)
|
119
85
|
|
120
86
|
return nil if ENV['HAS_ALPHA_VERSION'].nil?
|
121
87
|
|
@@ -312,12 +278,11 @@ module Fastlane
|
|
312
278
|
|
313
279
|
# Prints the current and next release version names to stdout, then returns the next release version
|
314
280
|
#
|
315
|
-
# @param [String] app The name of the app to be used for beta and alpha version update
|
316
281
|
# @return [String] The next release version name to use after bumping the currently used release version.
|
317
282
|
#
|
318
|
-
def self.bump_version_release
|
283
|
+
def self.bump_version_release
|
319
284
|
# Bump release
|
320
|
-
current_version = get_release_version
|
285
|
+
current_version = self.get_release_version
|
321
286
|
UI.message("Current version: #{current_version[VERSION_NAME]}")
|
322
287
|
new_version = calc_next_release_base_version(current_version)
|
323
288
|
UI.message("New version: #{new_version[VERSION_NAME]}")
|
@@ -328,24 +293,24 @@ module Fastlane
|
|
328
293
|
|
329
294
|
# Update the `version.properties` file with new `versionName` and `versionCode` values
|
330
295
|
#
|
331
|
-
# @param [String] app The name of the app to be used for beta and alpha version update
|
332
296
|
# @param [Hash] new_version_beta The version hash for the beta, containing values for keys "name" and "code"
|
333
297
|
# @param [Hash] new_version_alpha The version hash for the alpha , containing values for keys "name" and "code"
|
334
298
|
#
|
335
|
-
def self.update_versions(
|
336
|
-
if
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
299
|
+
def self.update_versions(new_version_beta, new_version_alpha)
|
300
|
+
if File.exist?(version_properties_file)
|
301
|
+
replacements = {
|
302
|
+
versionName: (new_version_beta || {})[VERSION_NAME],
|
303
|
+
versionCode: (new_version_beta || {})[VERSION_CODE],
|
304
|
+
'alpha.versionName': (new_version_alpha || {})[VERSION_NAME],
|
305
|
+
'alpha.versionCode': (new_version_alpha || {})[VERSION_CODE]
|
306
|
+
}
|
307
|
+
content = File.read(version_properties_file)
|
308
|
+
content.gsub!(/^(.*) ?=.*$/) do |line|
|
309
|
+
key = Regexp.last_match(1).to_sym
|
310
|
+
value = replacements[key]
|
311
|
+
value.nil? ? line : "#{key}=#{value}"
|
348
312
|
end
|
313
|
+
File.write(version_properties_file, content)
|
349
314
|
else
|
350
315
|
self.update_version(new_version_beta, ENV['HAS_ALPHA_VERSION'].nil? ? 'defaultConfig' : 'vanilla {')
|
351
316
|
self.update_version(new_version_alpha, 'defaultConfig') unless new_version_alpha.nil?
|
@@ -434,7 +399,7 @@ module Fastlane
|
|
434
399
|
#
|
435
400
|
# @return [Bool] true if the string is representing an integer value, false if not
|
436
401
|
#
|
437
|
-
def self.is_int?
|
402
|
+
def self.is_int?(string)
|
438
403
|
true if Integer(string) rescue false
|
439
404
|
end
|
440
405
|
|
@@ -5,6 +5,11 @@ 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. It's currently set to 'develop' for
|
9
|
+
# backwards compatibility.
|
10
|
+
# TODO: Set to 'trunk' for the next major release.
|
11
|
+
DEFAULT_GIT_BRANCH = 'develop'.freeze
|
12
|
+
|
8
13
|
# Checks if the given path, or current directory if no path is given, is
|
9
14
|
# inside a Git repository
|
10
15
|
#
|
@@ -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
|