fastlane-plugin-wpmreleasetoolkit 11.0.2 → 11.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 +4 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_backmerge_pull_request_action.rb +215 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb +80 -21
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb +26 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f9d86b44058a8ff2f28f2c56bdb81230395e36eac41f6e4d0761140f9694177
|
4
|
+
data.tar.gz: cc234c6029919a63d4d9ed2114d390bb58ad79e67f7ae1650e94b23cfac92bc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2e86d40c624300445ddc600e19b8b16a560e86725c82344719bbbadb69ad0c1552fff4f951cdb5411d892973fa37b524b47bcc99b0d14a23bff56607d44f676
|
7
|
+
data.tar.gz: faf08e93483cced02d83d705b9cff2843e07244c708312bdf8dfb86131b2990d4e5ba94397aa71aadd8a3cb6d485da2007b5743950e15486ff81243f8a956b35
|
@@ -0,0 +1,215 @@
|
|
1
|
+
require 'fastlane/action'
|
2
|
+
require_relative '../../helper/github_helper'
|
3
|
+
|
4
|
+
module Fastlane
|
5
|
+
module Actions
|
6
|
+
class CreateReleaseBackmergePullRequestAction < Action
|
7
|
+
DEFAULT_BRANCH = 'trunk'.freeze
|
8
|
+
|
9
|
+
def self.run(params)
|
10
|
+
token = params[:github_token]
|
11
|
+
repository = params[:repository]
|
12
|
+
source_branch = params[:source_branch]
|
13
|
+
default_branch = params[:default_branch]
|
14
|
+
target_branches = params[:target_branches]
|
15
|
+
labels = params[:labels]
|
16
|
+
milestone_title = params[:milestone_title]
|
17
|
+
reviewers = params[:reviewers]
|
18
|
+
team_reviewers = params[:team_reviewers]
|
19
|
+
intermediate_branch_created_callback = params[:intermediate_branch_created_callback]
|
20
|
+
|
21
|
+
if target_branches.include?(source_branch)
|
22
|
+
UI.user_error!('`target_branches` must not contain `source_branch`')
|
23
|
+
end
|
24
|
+
|
25
|
+
github_helper = Fastlane::Helper::GithubHelper.new(github_token: params[:github_token])
|
26
|
+
target_milestone = milestone_title.nil? ? nil : github_helper.get_milestone(repository, milestone_title)
|
27
|
+
|
28
|
+
final_target_branches = if target_branches.empty?
|
29
|
+
unless source_branch.start_with?('release/')
|
30
|
+
UI.user_error!('`source_branch` must start with `release/`')
|
31
|
+
end
|
32
|
+
|
33
|
+
determine_target_branches(source_release_version: source_branch.delete('release/'), default_branch: default_branch)
|
34
|
+
else
|
35
|
+
target_branches
|
36
|
+
end
|
37
|
+
|
38
|
+
final_target_branches.map do |target_branch|
|
39
|
+
Fastlane::Helper::GitHelper.checkout_and_pull(source_branch)
|
40
|
+
|
41
|
+
create_backmerge_pr(
|
42
|
+
token: token,
|
43
|
+
repository: repository,
|
44
|
+
title: "Merge #{source_branch} into #{target_branch}",
|
45
|
+
head_branch: source_branch,
|
46
|
+
base_branch: target_branch,
|
47
|
+
labels: labels,
|
48
|
+
milestone: target_milestone&.number,
|
49
|
+
reviewers: reviewers,
|
50
|
+
team_reviewers: team_reviewers,
|
51
|
+
intermediate_branch_created_callback: intermediate_branch_created_callback
|
52
|
+
)
|
53
|
+
end.compact
|
54
|
+
end
|
55
|
+
|
56
|
+
# Determines the target branches for a release version.
|
57
|
+
#
|
58
|
+
# @param source_release_version [String] the source release version to compare against other release branches.
|
59
|
+
# @param default_branch [String] the default branch to use if no target branches are found.
|
60
|
+
# @return [Array<String>] the list of target branches greater than the release version.
|
61
|
+
def self.determine_target_branches(source_release_version:, default_branch:)
|
62
|
+
release_branches = Actions.sh('git', 'branch', '-r', '-l', 'origin/release/*').strip.split("\n")
|
63
|
+
|
64
|
+
all_release_branches_versions = release_branches
|
65
|
+
.map { |branch| branch.match(%r{origin/release/([0-9.]*)})&.captures&.first }
|
66
|
+
.compact
|
67
|
+
|
68
|
+
target_branches = all_release_branches_versions.select { |branch| Gem::Version.new(branch) > Gem::Version.new(source_release_version) }
|
69
|
+
.map { |v| "release/#{v}" }
|
70
|
+
target_branches = [default_branch] if target_branches.empty?
|
71
|
+
|
72
|
+
target_branches
|
73
|
+
end
|
74
|
+
|
75
|
+
# Creates a backmerge pull request using the `create_pull_request` Fastlane Action.
|
76
|
+
#
|
77
|
+
# @param token [String] the GitHub token for authentication.
|
78
|
+
# @param repository [String] the repository where the pull request will be created.
|
79
|
+
# @param title [String] the title of the pull request.
|
80
|
+
# @param head_branch [String] the source branch for the pull request.
|
81
|
+
# @param base_branch [String] the target branch for the pull request.
|
82
|
+
# @param labels [Array<String>] the labels to add to the pull request.
|
83
|
+
# @param milestone [String] the milestone to associate with the pull request.
|
84
|
+
# @param reviewers [Array<String>] the individual reviewers for the pull request.
|
85
|
+
# @param team_reviewers [Array<String>] the team reviewers for the pull request.
|
86
|
+
# @param intermediate_branch_created_callback [Proc] A callback to call after having created the intermediate branch
|
87
|
+
# to allow the caller to e.g. add new commits on it before the PR is created. The callback takes two parameters: the base branch and the intermediate branch
|
88
|
+
#
|
89
|
+
# @return [String] The URL of the created Pull Request, or `nil` if no PR was created.
|
90
|
+
#
|
91
|
+
def self.create_backmerge_pr(token:, repository:, title:, head_branch:, base_branch:, labels:, milestone:, reviewers:, team_reviewers:, intermediate_branch_created_callback:)
|
92
|
+
intermediate_branch = "merge/#{head_branch.gsub('/', '-')}-into-#{base_branch.gsub('/', '-')}"
|
93
|
+
|
94
|
+
if Fastlane::Helper::GitHelper.branch_exists_on_remote?(branch_name: intermediate_branch)
|
95
|
+
UI.user_error!("The intermediate branch `#{intermediate_branch}` already exists. Please check if there is an existing Pull Request that needs to be merged or closed first, or delete the branch.")
|
96
|
+
return nil
|
97
|
+
end
|
98
|
+
|
99
|
+
Fastlane::Helper::GitHelper.create_branch(intermediate_branch)
|
100
|
+
|
101
|
+
intermediate_branch_created_callback&.call(base_branch, intermediate_branch)
|
102
|
+
|
103
|
+
# if there's a callback, make sure it didn't switch branches
|
104
|
+
other_action.ensure_git_branch(branch: "^#{intermediate_branch}/") unless intermediate_branch_created_callback.nil?
|
105
|
+
|
106
|
+
if Fastlane::Helper::GitHelper.point_to_same_commit?(base_branch, head_branch)
|
107
|
+
UI.error("No differences between #{head_branch} and #{base_branch}. Skipping PR creation.")
|
108
|
+
return nil
|
109
|
+
end
|
110
|
+
|
111
|
+
other_action.push_to_git_remote(tags: false)
|
112
|
+
|
113
|
+
pr_body = <<~BODY
|
114
|
+
Merging `#{head_branch}` into `#{base_branch}`.
|
115
|
+
|
116
|
+
Via intermediate branch `#{intermediate_branch}`, to help fix conflicts if any:
|
117
|
+
```
|
118
|
+
#{head_branch.rjust(40)} ----o-- - - -
|
119
|
+
#{' ' * 40} \\
|
120
|
+
#{intermediate_branch.rjust(40)} `---.
|
121
|
+
#{' ' * 40} \\
|
122
|
+
#{base_branch.rjust(40)} ------------x- - -
|
123
|
+
```
|
124
|
+
BODY
|
125
|
+
|
126
|
+
other_action.create_pull_request(
|
127
|
+
api_token: token,
|
128
|
+
repo: repository,
|
129
|
+
title: title,
|
130
|
+
body: pr_body,
|
131
|
+
head: intermediate_branch,
|
132
|
+
base: base_branch,
|
133
|
+
labels: labels,
|
134
|
+
milestone: milestone,
|
135
|
+
reviewers: reviewers,
|
136
|
+
team_reviewers: team_reviewers
|
137
|
+
)
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.description
|
141
|
+
'Creates backmerge PRs for a release branch into target branches'
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.authors
|
145
|
+
['Automattic']
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.return_type
|
149
|
+
:array_of_strings
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.return_value
|
153
|
+
'The list of the created backmerge Pull Request URLs'
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.details
|
157
|
+
<<~DETAILS
|
158
|
+
This action creates backmerge Pull Requests from a release branch into one or more target branches.
|
159
|
+
|
160
|
+
It can be used to ensure that changes from a release branch are merged back into other branches, such as newer release branches or the main development branch (e.g., `trunk`).
|
161
|
+
DETAILS
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.available_options
|
165
|
+
[
|
166
|
+
FastlaneCore::ConfigItem.new(key: :repository,
|
167
|
+
env_name: 'GHHELPER_REPOSITORY',
|
168
|
+
description: 'The remote path of the GH repository on which we work',
|
169
|
+
optional: false,
|
170
|
+
type: String),
|
171
|
+
FastlaneCore::ConfigItem.new(key: :source_branch,
|
172
|
+
description: 'The source branch to create a backmerge PR from, in the format `release/x.y.z`',
|
173
|
+
optional: false,
|
174
|
+
type: String),
|
175
|
+
FastlaneCore::ConfigItem.new(key: :default_branch,
|
176
|
+
description: 'The default branch to target if no newer release branches exist',
|
177
|
+
optional: true,
|
178
|
+
default_value: DEFAULT_BRANCH,
|
179
|
+
type: String),
|
180
|
+
FastlaneCore::ConfigItem.new(key: :target_branches,
|
181
|
+
description: 'Array of target branches for the backmerge. If empty, the action will determine target branches by finding all `release/x.y.z` branches with a `x.y.z` version greater than the version in source branch\'s name. If none are found, it will target `default_branch`', # rubocop:disable Layout/LineLength
|
182
|
+
optional: true,
|
183
|
+
default_value: [],
|
184
|
+
type: Array),
|
185
|
+
FastlaneCore::ConfigItem.new(key: :labels,
|
186
|
+
description: 'The labels that should be assigned to the backmerge PRs',
|
187
|
+
optional: true,
|
188
|
+
default_value: [],
|
189
|
+
type: Array),
|
190
|
+
FastlaneCore::ConfigItem.new(key: :milestone_title,
|
191
|
+
description: 'The title of the milestone to assign to the created PRs',
|
192
|
+
optional: true,
|
193
|
+
type: String),
|
194
|
+
FastlaneCore::ConfigItem.new(key: :reviewers,
|
195
|
+
description: 'An array of GitHub users that will be assigned to the pull request',
|
196
|
+
optional: true,
|
197
|
+
type: Array),
|
198
|
+
FastlaneCore::ConfigItem.new(key: :team_reviewers,
|
199
|
+
description: 'An array of GitHub team slugs that will be assigned to the pull request',
|
200
|
+
optional: true,
|
201
|
+
type: Array),
|
202
|
+
FastlaneCore::ConfigItem.new(key: :intermediate_branch_created_callback,
|
203
|
+
description: 'Callback to allow for the caller to perform operations on the intermediate branch before pushing. The call back receives two parameters: the base (target) branch for the PR and the intermediate branch name',
|
204
|
+
optional: true,
|
205
|
+
type: Proc),
|
206
|
+
Fastlane::Helper::GithubHelper.github_token_config_item,
|
207
|
+
]
|
208
|
+
end
|
209
|
+
|
210
|
+
def self.is_supported?(platform)
|
211
|
+
true
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
@@ -152,6 +152,13 @@ module Fastlane
|
|
152
152
|
(added_count + updated_count) != 0
|
153
153
|
end
|
154
154
|
|
155
|
+
########
|
156
|
+
# @!group Verify diff of library vs main strings matches
|
157
|
+
#
|
158
|
+
# @note This set of methods is used by `an_validate_lib_strings_action`
|
159
|
+
# (which doesn't seem to be used by any of our Android projects nowadays?)
|
160
|
+
########
|
161
|
+
|
155
162
|
def self.verify_diff(diff_string, main_strings, lib_strings, library)
|
156
163
|
return unless diff_string.start_with?('name=')
|
157
164
|
|
@@ -198,6 +205,8 @@ module Fastlane
|
|
198
205
|
end
|
199
206
|
end
|
200
207
|
|
208
|
+
# @!endgroup
|
209
|
+
|
201
210
|
########
|
202
211
|
# @!group Downloading translations from GlotPress
|
203
212
|
########
|
@@ -223,7 +232,7 @@ module Fastlane
|
|
223
232
|
#
|
224
233
|
# @param [String] res_dir The relative path to the `…/src/main/res` directory.
|
225
234
|
# @param [String] glotpress_project_url The base URL to the glotpress project to download the strings from.
|
226
|
-
# @param [Hash{
|
235
|
+
# @param [Hash{Symbol=>String}, Array] glotpress_filters
|
227
236
|
# The filters to apply when exporting strings from GlotPress.
|
228
237
|
# Typical examples include `{ status: 'current' }` or `{ status: 'review' }`.
|
229
238
|
# If an array of Hashes is provided instead of a single Hash, this method will perform as many
|
@@ -235,10 +244,8 @@ module Fastlane
|
|
235
244
|
def self.download_from_glotpress(res_dir:, glotpress_project_url:, locales_map:, glotpress_filters: { status: 'current' })
|
236
245
|
glotpress_filters = [glotpress_filters] unless glotpress_filters.is_a?(Array)
|
237
246
|
|
238
|
-
attributes_to_copy = %w[formatted] # Attributes that we want to replicate into translated `string.xml` files
|
239
247
|
orig_file = File.join(res_dir, 'values', 'strings.xml')
|
240
248
|
orig_xml = File.open(orig_file) { |f| Nokogiri::XML(f, nil, Encoding::UTF_8.to_s) }
|
241
|
-
orig_attributes = orig_xml.xpath('//string').to_h { |tag| [tag['name'], tag.attributes.select { |k, _| attributes_to_copy.include?(k) }] }
|
242
249
|
|
243
250
|
locales_map.each do |lang_codes|
|
244
251
|
all_xml_documents = glotpress_filters.map do |filters|
|
@@ -250,13 +257,7 @@ module Fastlane
|
|
250
257
|
# Merge all XMLs together
|
251
258
|
merged_xml = merge_xml_documents(all_xml_documents)
|
252
259
|
|
253
|
-
|
254
|
-
merged_xml.xpath('//string').each do |string_tag|
|
255
|
-
apply_substitutions(string_tag)
|
256
|
-
orig_attributes[string_tag['name']]&.each { |k, v| string_tag[k] = v }
|
257
|
-
quick_lint(string_tag, lang_codes[:android])
|
258
|
-
end
|
259
|
-
merged_xml.xpath('//string-array/item').each { |item_tag| apply_substitutions(item_tag) }
|
260
|
+
post_process_xml!(merged_xml, locale_code: lang_codes[:android], original_xml: orig_xml)
|
260
261
|
|
261
262
|
# Save
|
262
263
|
lang_dir = File.join(res_dir, "values-#{lang_codes[:android]}")
|
@@ -266,8 +267,10 @@ module Fastlane
|
|
266
267
|
end
|
267
268
|
end
|
268
269
|
|
270
|
+
# @!endgroup
|
271
|
+
|
269
272
|
#####################
|
270
|
-
# Private Helpers
|
273
|
+
# @!group Private Helpers
|
271
274
|
#####################
|
272
275
|
|
273
276
|
# Downloads the export from GlotPress for a given locale and given filters
|
@@ -276,7 +279,7 @@ module Fastlane
|
|
276
279
|
# @param [String] locale The GlotPress locale code to download strings for.
|
277
280
|
# @param [Hash{Symbol=>String}] filters The hash of filters to apply when exporting from GlotPress.
|
278
281
|
# Typical examples include `{ status: 'current' }` or `{ status: 'review' }`.
|
279
|
-
# @return [Nokogiri::XML] the download XML document, parsed as a Nokogiri::XML object
|
282
|
+
# @return [Nokogiri::XML::Document] the download XML document, parsed as a Nokogiri::XML object
|
280
283
|
#
|
281
284
|
def self.download_glotpress_export_file(project_url:, locale:, filters:)
|
282
285
|
query_params = filters.transform_keys { |k| "filters[#{k}]" }.merge(format: 'android')
|
@@ -297,6 +300,9 @@ module Fastlane
|
|
297
300
|
|
298
301
|
# Merge multiple Nokogiri::XML `strings.xml` documents together
|
299
302
|
#
|
303
|
+
# Used especially when we provided multiple GlotPress filters to `download_from_glotpress`,
|
304
|
+
# as in this case we'd trigger one export per filter, then merge the result in a single XML
|
305
|
+
#
|
300
306
|
# @param [Array<Nokogiri::XML::Document>] all_xmls Array of the Nokogiri XML documents to merge together
|
301
307
|
# @return [Nokogiri::XML::Document] The merged document.
|
302
308
|
#
|
@@ -323,11 +329,53 @@ module Fastlane
|
|
323
329
|
end
|
324
330
|
private_class_method :merge_xml_documents
|
325
331
|
|
326
|
-
#
|
332
|
+
# Process a downloaded XML (in-place), to apply the following
|
333
|
+
# - replicate attributes from the nodes of the original XML (`translatable`, `tools:ignore`, …) to the translated XML
|
334
|
+
# - text substitutions for common special characters
|
335
|
+
# - quick-lint string by searching for common issue patterns (using `%%` in a `formatted=false` string, etc)
|
336
|
+
#
|
337
|
+
# @param [Nokogiri::XML::Document] translated_xml The downloaded XML to post-process
|
338
|
+
# @param [String] locale_code The android locale code associated with the translated_xml
|
339
|
+
# @param [Nokogiri::XML::Document] original_xml The original `values/strings.xml` to use as reference
|
340
|
+
#
|
341
|
+
def self.post_process_xml!(translated_xml, locale_code:, original_xml:)
|
342
|
+
copy_orig_attributes = lambda do |node, xpath|
|
343
|
+
orig_attributes = original_xml.xpath(xpath)&.first&.attribute_nodes&.to_h do |attr|
|
344
|
+
[[attr.namespace&.prefix, attr.name].compact.join(':'), attr.value]
|
345
|
+
end
|
346
|
+
orig_attributes&.each { |k, v| node[k] = v unless k == 'name' }
|
347
|
+
end
|
348
|
+
|
349
|
+
# 1. Replicate namespaces on the document (especially `xmlns:tools` if present)
|
350
|
+
original_xml.namespaces.each { |k, v| translated_xml.root&.add_namespace(k.delete_prefix('xmlns:'), v) }
|
351
|
+
# 2. Replicate attributes on any node with `@name` attribute (`string`, `string-array`, `plurals`)
|
352
|
+
translated_xml.xpath('//*[@name]').each do |node|
|
353
|
+
copy_orig_attributes.call(node, "//#{node.name}[@name = '#{node['name']}']")
|
354
|
+
end
|
355
|
+
# 3. Process copies for `string` nodes
|
356
|
+
translated_xml.xpath('//string[@name]').each do |string_node|
|
357
|
+
apply_substitutions!(string_node)
|
358
|
+
quick_lint(string_node, locale_code)
|
359
|
+
end
|
360
|
+
# 4. Process copies for `string-array/item` nodes
|
361
|
+
translated_xml.xpath('//string-array[@name]/item').each do |item_node|
|
362
|
+
apply_substitutions!(item_node)
|
363
|
+
quick_lint(item_node, locale_code)
|
364
|
+
end
|
365
|
+
# 5. Replicate attributes + Process copies for `plurals/item` nodes
|
366
|
+
translated_xml.xpath('//plurals[@name]/item[@quantity]').each do |item_node|
|
367
|
+
copy_orig_attributes.call(item_node, "//plurals[@name = '#{item_node.parent['name']}']/item[@quantity = '#{item_node['quantity']}']")
|
368
|
+
apply_substitutions!(item_node)
|
369
|
+
quick_lint(item_node, locale_code)
|
370
|
+
end
|
371
|
+
end
|
372
|
+
private_class_method :post_process_xml!
|
373
|
+
|
374
|
+
# Apply some common text substitutions to tag contents, like `... => …` or en-dash instead of regular dash for ranges of numbers
|
327
375
|
#
|
328
376
|
# @param [Nokogiri::XML::Node] tag The XML tag/node to apply substitutions to
|
329
377
|
#
|
330
|
-
def self.apply_substitutions(tag)
|
378
|
+
def self.apply_substitutions!(tag)
|
331
379
|
tag.content = tag.content.gsub('...', '…')
|
332
380
|
|
333
381
|
# Typography en-dash
|
@@ -339,17 +387,28 @@ module Fastlane
|
|
339
387
|
is_negative_number ? str : "#{match[1]}\u{2013}#{match[2]}"
|
340
388
|
end
|
341
389
|
end
|
342
|
-
private_class_method :apply_substitutions
|
390
|
+
private_class_method :apply_substitutions!
|
343
391
|
|
344
|
-
# Perform some quick basic checks about an individual `<string>` tag and print warnings accordingly
|
392
|
+
# Perform some quick basic checks about an individual `<string>` tag and print warnings accordingly:
|
393
|
+
# - detect the use of `%%` in the string even if `formatted=false` is set
|
394
|
+
# - detect the presence of `\@string/` in translated XML, which suggests the original key that referenced `@string/…` did not set `translatable=false`
|
395
|
+
# and thus that `@string/…` copy was sent to GlotPress for translation, then escaped during exporting it back.
|
345
396
|
#
|
346
|
-
# @param [Nokogiri::XML::Node]
|
397
|
+
# @param [Nokogiri::XML::Node] node The XML tag/node to check the content of
|
347
398
|
# @param [String] lang The language we are currently processing. Used for providing context during logging / warning message
|
348
399
|
#
|
349
|
-
def self.quick_lint(
|
350
|
-
|
351
|
-
|
352
|
-
|
400
|
+
def self.quick_lint(node, lang)
|
401
|
+
named_node = node.has_attribute?('name') ? node : node.parent
|
402
|
+
if named_node['formatted'] == 'false' && node.content.include?('%%')
|
403
|
+
UI.important "Warning: [#{lang}] translation for '#{named_node['name']}' has attribute formatted=false, but still contains escaped '%%' in translation."
|
404
|
+
end
|
405
|
+
# rubocop:disable Style/GuardClause
|
406
|
+
if node.content.include?('\\@string/')
|
407
|
+
UI.important "Warning: [#{lang}] exported translation for '#{named_node['name']}' contains `\\@string/`. This is a sign that this entry was not marked as `translatable=false` " \
|
408
|
+
+ 'in the original `values/strings.xml`, and was thus sent to GlotPress, which added the backslash when exporting it back.'
|
409
|
+
node.content = node.content.gsub('\\@string/', '@string/')
|
410
|
+
end
|
411
|
+
# rubocop:enable Style/GuardClause
|
353
412
|
end
|
354
413
|
private_class_method :quick_lint
|
355
414
|
|
@@ -179,6 +179,21 @@ module Fastlane
|
|
179
179
|
Action.sh('git', 'fetch', '--tags')
|
180
180
|
end
|
181
181
|
|
182
|
+
# Checks if two git references point to the same commit.
|
183
|
+
#
|
184
|
+
# @param ref1 [String] the first git reference to check.
|
185
|
+
# @param ref2 [String] the second git reference to check.
|
186
|
+
#
|
187
|
+
# @return [Boolean] true if the two references point to the same commit, false otherwise.
|
188
|
+
#
|
189
|
+
def self.point_to_same_commit?(ref1, ref2)
|
190
|
+
git_repo = Git.open(Dir.pwd)
|
191
|
+
ref1_commit = git_repo.gcommit(ref1)
|
192
|
+
ref2_commit = git_repo.gcommit(ref2)
|
193
|
+
|
194
|
+
ref1_commit.sha == ref2_commit.sha
|
195
|
+
end
|
196
|
+
|
182
197
|
# Returns the current git branch, or "HEAD" if it's not checked out to any branch
|
183
198
|
# Can NOT be replaced using the environment variables such as `GIT_BRANCH` or `BUILDKITE_BRANCH`
|
184
199
|
#
|
@@ -206,6 +221,17 @@ module Fastlane
|
|
206
221
|
!Action.sh('git', 'branch', '--list', branch_name).empty?
|
207
222
|
end
|
208
223
|
|
224
|
+
# Checks if a branch exists on the repository's remote.
|
225
|
+
#
|
226
|
+
# @param branch_name [String] the name of the branch to check.
|
227
|
+
# @param remote_name [String] the name of the remote repository (default is 'origin').
|
228
|
+
#
|
229
|
+
# @return [Boolean] true if the branch exists on remote, false otherwise.
|
230
|
+
#
|
231
|
+
def self.branch_exists_on_remote?(branch_name:, remote_name: 'origin')
|
232
|
+
!Action.sh('git', 'ls-remote', '--heads', remote_name, branch_name).empty?
|
233
|
+
end
|
234
|
+
|
209
235
|
# Ensure that we are on the expected branch, and abort if not.
|
210
236
|
#
|
211
237
|
# @param [String] branch_name The name of the branch we expect to be on
|
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: 11.0
|
4
|
+
version: 11.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Automattic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -449,6 +449,7 @@ files:
|
|
449
449
|
- lib/fastlane/plugin/wpmreleasetoolkit/actions/common/copy_branch_protection_action.rb
|
450
450
|
- lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_new_milestone_action.rb
|
451
451
|
- lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb
|
452
|
+
- lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_backmerge_pull_request_action.rb
|
452
453
|
- lib/fastlane/plugin/wpmreleasetoolkit/actions/common/extract_release_notes_for_version_action.rb
|
453
454
|
- lib/fastlane/plugin/wpmreleasetoolkit/actions/common/find_previous_tag.rb
|
454
455
|
- lib/fastlane/plugin/wpmreleasetoolkit/actions/common/firebase_login.rb
|