Skip to content
This repository was archived by the owner on Feb 24, 2025. It is now read-only.

Commit b4d3a3e

Browse files
authored
Unify build number between App Store and DMG releases (#1929)
Task/Issue URL: https://app.asana.com/0/1201037661562251/1206111130949152/f Description: * DMG target now uses the same build number as App Store target. * To support internal releases using the same marketing version, DMG filenames now include build number. * appcastManager and archive.sh were updated to support it. * set_version.sh has been deleted and replaced by fastlane lane: bundle exec fastlane mac set_version version:1.70.0 * New fastlane lane was added for creating subsequent internal releases: bundle exec fastlane mac bump_internal_release
1 parent fb52a9c commit b4d3a3e

17 files changed

+220
-372
lines changed

.swiftlint.yml

+1
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,4 @@ excluded:
7676
- UITests
7777
- vendor
7878
- DerivedData
79+
- .ruby-lsp

Configuration/App/AppTargetsBase.xcconfig

-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES
2828
CODE_SIGN_STYLE[sdk=*] = Manual
2929
CODE_SIGN_STYLE[config=Debug][sdk=*] = Automatic
3030

31-
CURRENT_PROJECT_VERSION = $(MARKETING_VERSION)
32-
3331
ENABLE_HARDENED_RUNTIME = YES
3432

3533
INFOPLIST_FILE = DuckDuckGo/Info.plist

Configuration/AppStore.xcconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// limitations under the License.
1515
//
1616

17-
#include "AppStoreBuildNumber.xcconfig"
17+
#include "BuildNumber.xcconfig"
1818

1919
MAIN_BUNDLE_IDENTIFIER_PREFIX = com.duckduckgo.mobile.ios
2020

File renamed without changes.

Configuration/Common.xcconfig

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
//
1515

1616
#include "Version.xcconfig"
17+
#include "BuildNumber.xcconfig"
1718

1819
COMBINE_HIDPI_IMAGES = YES
1920

Configuration/Extensions/ExtensionBase.xcconfig

-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES
2020

2121
CODE_SIGN_STYLE[sdk=*] = Manual
2222

23-
CURRENT_PROJECT_VERSION = $(MARKETING_VERSION)
24-
2523
ENABLE_HARDENED_RUNTIME = YES
2624

2725
PRODUCT_BUNDLE_IDENTIFIER[sdk=*] = $(BUNDLE_IDENTIFIER_PREFIX)

DuckDuckGo.xcodeproj/project.pbxproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -3214,7 +3214,7 @@
32143214
3767190128E724B2003A2A15 /* DuckPlayerURLExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DuckPlayerURLExtension.swift; sourceTree = "<group>"; };
32153215
376C4DB828A1A48A00CC0F5B /* FirePopoverViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirePopoverViewModelTests.swift; sourceTree = "<group>"; };
32163216
376CC8B4296EB630006B63A7 /* AppStore.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppStore.xcconfig; sourceTree = "<group>"; };
3217-
376CC8B5296EBA8F006B63A7 /* AppStoreBuildNumber.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppStoreBuildNumber.xcconfig; sourceTree = "<group>"; };
3217+
376CC8B5296EBA8F006B63A7 /* BuildNumber.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = BuildNumber.xcconfig; sourceTree = "<group>"; };
32183218
37717E66296B5A20002FAEDF /* Global.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Global.xcconfig; sourceTree = "<group>"; };
32193219
3775912C29AAC72700E26367 /* SyncPreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncPreferences.swift; sourceTree = "<group>"; };
32203220
3775913529AB9A1C00E26367 /* SyncManagementDialogViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncManagementDialogViewController.swift; sourceTree = "<group>"; };
@@ -4757,8 +4757,8 @@
47574757
37717E66296B5A20002FAEDF /* Global.xcconfig */,
47584758
378B5888295CF2A4002C0CC0 /* Common.xcconfig */,
47594759
378B5887295CF2A4002C0CC0 /* Version.xcconfig */,
4760+
376CC8B5296EBA8F006B63A7 /* BuildNumber.xcconfig */,
47604761
376CC8B4296EB630006B63A7 /* AppStore.xcconfig */,
4761-
376CC8B5296EBA8F006B63A7 /* AppStoreBuildNumber.xcconfig */,
47624762
7B5291892A169BC90022E406 /* DeveloperID.xcconfig */,
47634763
378C76D8296842FD0092E949 /* App */,
47644764
4B4D604E2A0B293C00BCD287 /* Extensions */,

Gemfile

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
source 'https://rubygems.org'
22

33
gem 'fastlane', '2.217.0'
4+
gem 'httparty'

Gemfile.lock

+5
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,17 @@ GEM
146146
highline (2.0.3)
147147
http-cookie (1.0.5)
148148
domain_name (~> 0.5)
149+
httparty (0.21.0)
150+
mini_mime (>= 1.0.0)
151+
multi_xml (>= 0.5.2)
149152
httpclient (2.8.3)
150153
jmespath (1.6.2)
151154
json (2.6.3)
152155
jwt (2.7.1)
153156
mini_magick (4.12.0)
154157
mini_mime (1.1.5)
155158
multi_json (1.15.0)
159+
multi_xml (0.6.0)
156160
multipart-post (2.3.0)
157161
nanaimo (0.3.0)
158162
naturally (2.2.1)
@@ -208,6 +212,7 @@ PLATFORMS
208212

209213
DEPENDENCIES
210214
fastlane (= 2.217.0)
215+
httparty
211216

212217
BUNDLED WITH
213218
2.3.26

fastlane/Fastfile

+117-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# frozen_string_literal: true
22

3+
fastlane_require 'httparty'
4+
fastlane_require 'rexml/document'
5+
36
UI.abort_with_message!('Please run fastlane via `bundle exec`') unless FastlaneCore::Helper.bundler?
47

58
########################################################################
@@ -8,8 +11,9 @@ UI.abort_with_message!('Please run fastlane via `bundle exec`') unless FastlaneC
811
DEFAULT_BRANCH = 'main'
912
RELEASE_BRANCH = 'release'
1013
PROJECT_ROOT_FOLDER = File.dirname(File.expand_path(__dir__))
14+
INFO_PLIST = File.join(PROJECT_ROOT_FOLDER, 'DuckDuckGo/Info.plist')
1115
VERSION_CONFIG_PATH = File.join(PROJECT_ROOT_FOLDER, 'Configuration/Version.xcconfig')
12-
APP_STORE_BUILD_NUMBER_CONFIG_PATH = File.join(PROJECT_ROOT_FOLDER, 'Configuration/AppStoreBuildNumber.xcconfig')
16+
BUILD_NUMBER_CONFIG_PATH = File.join(PROJECT_ROOT_FOLDER, 'Configuration/BuildNumber.xcconfig')
1317
VERSION_CONFIG_DEFINITION = 'MARKETING_VERSION'
1418
BUILD_NUMBER_CONFIG_DEFINITION = 'CURRENT_PROJECT_VERSION'
1519
UPGRADABLE_EMBEDDED_FILES = [
@@ -99,23 +103,27 @@ platform :mac do
99103
#
100104
# - Cuts a new release branch
101105
# - Updates submodules and embedded files
106+
# - Pushes changes to remote
102107
#
103108
# @option [String] version (default: nil) Marketing version string
104-
# @option [Boolean] skip_confirm (default: false) If true, avoids any interactive prompt
105109
# @option [Boolean] resume (default: false) If true, the lane can run from a release/ branch and will run dedicated prechecks.
110+
# @option [Boolean] force (default: false) Don't ask for confirmation.
106111
#
107112
desc 'Executes the release preparation work in the repository'
108113
lane :code_freeze do |options|
109114
begin
110115
options[:resume]? macos_codefreeze_resume_prechecks : macos_codefreeze_prechecks
111116
new_version = validate_new_version(options)
112-
app_store_build_number = increment_app_store_build_number(options)
117+
build_number = increment_current_build_number(options)
113118
macos_create_release_branch(version: new_version) unless options[:resume]
114119
macos_update_embedded_files
115120
macos_update_version_and_build_number_config(
116121
version: new_version,
117-
build_number: app_store_build_number
122+
build_number: build_number,
123+
force: options[:force]
118124
)
125+
sh('git', 'push')
126+
119127
rescue => exception
120128
if exception.message == "Tests have failed"
121129
UI.user_error! %{Tests have failed.
@@ -131,6 +139,75 @@ platform :mac do
131139
end
132140
end
133141

142+
# Bumps build number for the current version and updates embedded files.
143+
# Pushes changes to remote.
144+
#
145+
# - Should be called on an existing internal release branch.
146+
# - Also runs unit tests after updating embedded files.
147+
#
148+
# @option [Boolean] force (default: false) Don't ask for confirmation.
149+
#
150+
desc 'Prepares new internal release on top of an existing one'
151+
lane :bump_internal_release do |options|
152+
begin
153+
unless git_branch.start_with?(RELEASE_BRANCH)
154+
UI.abort_with_message!("Incorrect branch. Branch name must start with '#{RELEASE_BRANCH}/'.")
155+
end
156+
157+
force = options[:force].nil? ? false : options[:force]
158+
current_version = macos_current_version
159+
current_build_number = macos_current_build_number
160+
build_number = increment_current_build_number(options)
161+
162+
UI.important("Current version is #{current_version} (#{current_build_number}).")
163+
UI.important("Will update to #{current_version} (#{build_number}).")
164+
165+
unless force
166+
unless UI.confirm("Do you want to continue?")
167+
UI.abort_with_message!('Aborted by user.')
168+
end
169+
end
170+
171+
macos_update_embedded_files
172+
macos_update_version_and_build_number_config(
173+
version: current_version,
174+
build_number: build_number,
175+
force: true
176+
)
177+
sh('git', 'push')
178+
179+
rescue => exception
180+
if exception.message == "Tests have failed"
181+
UI.user_error! %{Tests have failed.
182+
* If you believe the failing test is flaky, please retry the same fastlane command.
183+
* If the failure looks legitimate, try to fix it, commit the fix (be sure to only
184+
include the files you've changed while making a fix and leave other changed files
185+
unmodified), and run the command again appending `resume:true`.
186+
}
187+
else
188+
raise exception
189+
end
190+
end
191+
end
192+
193+
# Updates marketing version to the specified one and increments build number by 1.
194+
#
195+
# @option [String] version Marketing version string.
196+
# @option [Boolean] force (default: false) Don't ask for confirmation.
197+
#
198+
desc 'Executes the release preparation work in the repository'
199+
lane :set_version do |options|
200+
unless options[:version]
201+
UI.user_error! 'You must provide a version.'
202+
end
203+
new_version = validate_new_version(options)
204+
build_number = increment_current_build_number(options)
205+
macos_update_version_and_build_number_config(
206+
version: new_version,
207+
build_number: build_number
208+
)
209+
end
210+
134211
#################################################
135212
# Helper functions
136213
#################################################
@@ -229,30 +306,52 @@ platform :mac do
229306
end
230307
end
231308

232-
# Calculates the new version or validate the provided one, if it exists
309+
# Calculates the new version or validates the provided one, if it exists
233310
# and prompts the user to confirm
234311
#
235312
# @option [String] version (default: nil) Marketing version string
313+
# @option [Boolean] force (default: false) Don't ask for confirmation.
236314
#
237315
private_lane :validate_new_version do |options|
238316
current_version = macos_current_version
239317
user_version = format_user_version(options[:version])
240318
new_version = user_version.nil? ? macos_bump_minor_version(current_version) : user_version
241-
unless UI.confirm(
242-
"Current version is #{current_version}.\nNew version is #{new_version}.\nDo you want to continue?"
243-
)
244-
UI.abort_with_message!('Aborted by user.')
319+
force = options[:force].nil? ? false : options[:force]
320+
unless force
321+
unless UI.confirm(
322+
"Current version is #{current_version}.\nNew version is #{new_version}.\nDo you want to continue?"
323+
)
324+
UI.abort_with_message!('Aborted by user.')
325+
end
245326
end
246327
new_version
247328
end
248329

249330
# Checks current build number and increments it by 1.
250331
#
251-
desc 'Increment App Store build number'
252-
private_lane :increment_app_store_build_number do
332+
desc 'Increment build number'
333+
private_lane :increment_current_build_number do
334+
macos_current_build_number = [fetch_testflight_build_number, fetch_appcast_build_number].max
253335
macos_current_build_number + 1
254336
end
255337

338+
private_lane :fetch_testflight_build_number do |options|
339+
build_number = latest_testflight_build_number(
340+
api_key: get_api_key,
341+
username: get_username(options),
342+
platform: 'osx'
343+
)
344+
build_number
345+
end
346+
347+
private_lane :fetch_appcast_build_number do |options|
348+
url = sh("plutil -extract SUFeedURL raw #{INFO_PLIST}").chomp
349+
xml = HTTParty.get(url).body
350+
xml_data = REXML::Document.new(xml)
351+
versions = xml_data.get_elements('//rss/channel/item/sparkle:version').map { |e| e.text.split('.')[0].to_i }
352+
versions.max
353+
end
354+
256355
# Checks out a new branch from the current commit and pushes it
257356
#
258357
# @option [String] version (default: nil) Marketing version string
@@ -279,7 +378,7 @@ platform :mac do
279378
# - Runs automated tests
280379
# - Commits and pushes
281380
#
282-
private_lane :macos_update_embedded_files do
381+
private_lane :macos_update_embedded_files do |options|
283382
sh("cd #{PROJECT_ROOT_FOLDER} && ./scripts/update_embedded.sh")
284383

285384
# Verify no unexpected files were modified
@@ -300,36 +399,35 @@ platform :mac do
300399
modified_files.each { |modified_file| sh('git', 'add', modified_file.to_s) }
301400
sh('git', 'commit', '-m', 'Update embedded files')
302401
ensure_git_status_clean
303-
sh('git', 'push')
304402
end
305403

306404
# Updates version in the config file
307405
#
308-
# @option [String] version (default: nil) Marketing version string
406+
# @option [String] version Marketing version string
407+
# @option [String] build_number Build number
309408
#
310409
private_lane :macos_update_version_and_build_number_config do |options|
311410
version = options[:version]
312411
build_number = options[:build_number]
313412
File.write(VERSION_CONFIG_PATH, "#{VERSION_CONFIG_DEFINITION} = #{version}\n")
314-
File.write(APP_STORE_BUILD_NUMBER_CONFIG_PATH, "#{BUILD_NUMBER_CONFIG_DEFINITION} = #{build_number}\n")
413+
File.write(BUILD_NUMBER_CONFIG_PATH, "#{BUILD_NUMBER_CONFIG_DEFINITION} = #{build_number}\n")
315414
git_commit(
316415
path: [
317416
VERSION_CONFIG_PATH,
318-
APP_STORE_BUILD_NUMBER_CONFIG_PATH
417+
BUILD_NUMBER_CONFIG_PATH
319418
],
320419
message: "Bump version to #{version} (#{build_number})"
321420
)
322-
sh('git', 'push')
323421
end
324422

325-
# Reads App Store build number from the config file
423+
# Reads build number from the config file
326424
#
327425
# @return [String] build number read from the file, or nil in case of failure
328426
#
329427
def macos_current_build_number
330428
current_build_number = 0
331429

332-
file_data = File.read(APP_STORE_BUILD_NUMBER_CONFIG_PATH).split("\n")
430+
file_data = File.read(BUILD_NUMBER_CONFIG_PATH).split("\n")
333431
file_data.each do |line|
334432
current_build_number = line.split('=')[1].strip.to_i if line.start_with?(BUILD_NUMBER_CONFIG_DEFINITION)
335433
end

fastlane/README.md

+16
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,22 @@ Updates App Store metadata
5555

5656
Executes the release preparation work in the repository
5757

58+
### mac bump_internal_release
59+
60+
```sh
61+
[bundle exec] fastlane mac bump_internal_release
62+
```
63+
64+
Prepares new internal release on top of an existing one
65+
66+
### mac set_version
67+
68+
```sh
69+
[bundle exec] fastlane mac set_version
70+
```
71+
72+
Executes the release preparation work in the repository
73+
5874
----
5975

6076
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.

0 commit comments

Comments
 (0)