Skip to content

Commit 64d411a

Browse files
authored
ci: Verify bumped version on CI (#5268)
* ci: Verify bumped version on CI * Print version found for each file * Collect all errors before exiting
1 parent 2cec785 commit 64d411a

File tree

3 files changed

+152
-18
lines changed

3 files changed

+152
-18
lines changed

.github/workflows/version-bump-util.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,10 @@ jobs:
1414
runs-on: ubuntu-latest
1515
steps:
1616
- uses: actions/checkout@v4
17+
- name: Generate Version Number
18+
run: |
19+
TIMESTAMP=$(date +%Y%m%d%H%M%S)
20+
echo "VERSION=100.0.$TIMESTAMP" >> $GITHUB_ENV
1721
# We don't care which version we bump to, as long as it's a valid semver
18-
- run: make bump-version TO=100.0.0
22+
- run: make bump-version TO=${{ env.VERSION }}
23+
- run: make verify-version TO=${{ env.VERSION }}

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,11 @@ build-xcframework-sample:
119119
# call this like `make bump-version TO=5.0.0-rc.0`
120120
bump-version: clean-version-bump
121121
@echo "--> Bumping version from ${TO}"
122-
./Utils/VersionBump/.build/debug/VersionBump ${TO}
122+
./Utils/VersionBump/.build/debug/VersionBump --update ${TO}
123+
124+
verify-version: clean-version-bump
125+
@echo "--> Verifying version from ${TO}"
126+
./Utils/VersionBump/.build/debug/VersionBump --verify ${TO}
123127

124128
clean-version-bump:
125129
@echo "--> Clean VersionBump"

Utils/VersionBump/main.swift

Lines changed: 141 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,38 @@ import Foundation
22
import Regex
33
import SwiftShell
44

5+
protocol ErrorHandling: Error {
6+
var message: String { get }
7+
}
8+
9+
enum FileError: Error, ErrorHandling {
10+
case fileNotFound(String)
11+
case unknownFile(String)
12+
13+
var message: String {
14+
switch self {
15+
case .fileNotFound(let file):
16+
return "File not found: \(file)"
17+
case .unknownFile(let file):
18+
return "Unknown file: \(file)"
19+
}
20+
}
21+
}
22+
23+
enum VersionError: Error, ErrorHandling {
24+
case versionNotFound(String)
25+
case versionMismatch(String, String)
26+
27+
var message: String {
28+
switch self {
29+
case .versionNotFound(let file):
30+
return "No version found for \(file)"
31+
case .versionMismatch(let file, let versionFound):
32+
return "Unexpected version \(versionFound) found for file \(file)"
33+
}
34+
}
35+
}
36+
537
let fromVersionFile = "./Sentry.podspec"
638

739
let files = [
@@ -17,7 +49,7 @@ let files = [
1749
// This will enable publishing apps with SDK beta version.
1850
let restrictFiles = [
1951
"./Sources/Configuration/SDK.xcconfig",
20-
"./Sources/Configuration/Versioning.xcconfig",
52+
"./Sources/Configuration/Versioning.xcconfig",
2153
"./Sources/Configuration/SentrySwiftUI.xcconfig",
2254
"./Samples/Shared/Config/Versioning.xcconfig"
2355
]
@@ -26,27 +58,37 @@ let args = CommandLine.arguments
2658

2759
let semver: StaticString = "([0-9]+)\\.([0-9]+)\\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?(?:\\+[0-9A-Za-z-]+)?"
2860
let regex = Regex(semver)
29-
if regex.firstMatch(in: args[1]) == nil {
61+
if regex.firstMatch(in: args[2]) == nil {
3062
exit(errormessage: "version number must fit x.x.x format" )
3163
}
3264

33-
let fromVersionFileHandler = try open(fromVersionFile)
34-
let fromFileContent: String = fromVersionFileHandler.read()
65+
if args[1] == "--verify" {
66+
let expectedVersion = args[2]
67+
try verifyVersionInFiles(expectedVersion)
68+
} else if args[1] == "--update" {
69+
try updateVersionInFiles()
70+
}
3571

36-
if let match = Regex(semver, options: [.dotMatchesLineSeparators]).firstMatch(in: fromFileContent) {
37-
var fromVersion = match.matchedString
38-
var toVersion = args[1]
72+
func updateVersionInFiles() throws {
73+
let fromVersionFileHandler = try open(fromVersionFile)
74+
let fromFileContent: String = fromVersionFileHandler.read()
3975

40-
for file in files {
41-
try updateVersion(file, fromVersion, toVersion)
42-
}
43-
44-
fromVersion = extractVersionOnly(fromVersion)
45-
toVersion = extractVersionOnly(toVersion)
46-
47-
for file in restrictFiles {
48-
try updateVersion(file, fromVersion, toVersion)
76+
if let match = Regex(semver, options: [.dotMatchesLineSeparators]).firstMatch(in: fromFileContent) {
77+
var fromVersion = match.matchedString
78+
var toVersion = args[2]
79+
80+
for file in files {
81+
try updateVersion(file, fromVersion, toVersion)
82+
}
83+
84+
fromVersion = extractVersionOnly(fromVersion)
85+
toVersion = extractVersionOnly(toVersion)
86+
87+
for file in restrictFiles {
88+
try updateVersion(file, fromVersion, toVersion)
89+
}
4990
}
91+
print("Successfuly updated version numbers")
5092
}
5193

5294
func updateVersion(_ file: String, _ fromVersion: String, _ toVersion: String) throws {
@@ -62,3 +104,86 @@ func extractVersionOnly(_ version: String) -> String {
62104
guard let indexOfHypen = version.firstIndex(of: "-") else { return version }
63105
return String(version.prefix(upTo: indexOfHypen))
64106
}
107+
108+
func verifyVersionInFiles(_ expectedVersion: String) throws {
109+
var errors: [String] = []
110+
let expectedVersion = args[2]
111+
112+
for file in files {
113+
do {
114+
try verifyFile(file, expectedVersion)
115+
} catch let error as ErrorHandling {
116+
errors.append(error.message)
117+
}
118+
}
119+
120+
let exactVersion = extractVersionOnly(expectedVersion)
121+
for file in restrictFiles {
122+
do {
123+
try verifyRestrictedFile(file, expectedVersion: exactVersion)
124+
} catch let error as ErrorHandling {
125+
errors.append(error.message)
126+
}
127+
}
128+
129+
if !errors.isEmpty {
130+
exit(errormessage: "Could not validate all files: \n\(errors.joined(separator: "\n"))")
131+
}
132+
133+
print("Successfully validated files version number")
134+
}
135+
136+
func verifyFile(_ file: String, _ expectedVersion: String) throws {
137+
guard let fileHandler = try? open(file) else {
138+
throw FileError.fileNotFound(file)
139+
}
140+
141+
let fileContent = fileHandler.read()
142+
let regexString = try getRegexString(for: file)
143+
let match = try? Regex(string: regexString, options: [.dotMatchesLineSeparators]).firstMatch(in: fileContent)
144+
145+
guard let version = match?.captures[0] else {
146+
throw VersionError.versionNotFound(file)
147+
}
148+
149+
guard version == expectedVersion else {
150+
throw VersionError.versionMismatch(file, version)
151+
}
152+
153+
print("\(file) validated to have the correct version: \(version)")
154+
}
155+
156+
func verifyRestrictedFile(_ file: String, expectedVersion: String) throws {
157+
guard let fileHandler = try? open(file) else {
158+
throw FileError.fileNotFound(file)
159+
}
160+
161+
let fileContent = fileHandler.read()
162+
let marketingRegex = try? Regex(string: "MARKETING_VERSION\\s=\\s(?<version>[a-zA-z0-9\\.\\-]+)", options: [.dotMatchesLineSeparators])
163+
let currentProjectRegex = try? Regex(string: "CURRENT_PROJECT_VERSION\\s=\\s(?<version>[a-zA-z0-9\\.\\-]+)", options: [.dotMatchesLineSeparators])
164+
let match = marketingRegex?.firstMatch(in: fileContent) ?? currentProjectRegex?.firstMatch(in: fileContent)
165+
166+
guard let version = match?.captures[0] else {
167+
throw VersionError.versionNotFound(file)
168+
}
169+
170+
guard version == expectedVersion else {
171+
throw VersionError.versionMismatch(file, version)
172+
}
173+
174+
print("\(file) validated to have the correct version: \(version)")
175+
}
176+
177+
func getRegexString(for file: String) throws -> String {
178+
if file.hasSuffix(".podspec") {
179+
if file == "./Tests/HybridSDKTest/HybridPod.podspec" {
180+
return "s\\.dependency\\s\"Sentry\\/HybridSDK\",\\s\"(?<version>[a-zA-z0-9\\.\\-]+)\""
181+
}
182+
return "\\ss\\.version\\s+=\\s\"(?<version>[a-zA-z0-9\\.\\-]+)\""
183+
} else if file == "./Package.swift" {
184+
return "https:\\/\\/github\\.com\\/getsentry\\/sentry-cocoa\\/releases\\/download\\/(?<version>[a-zA-z0-9\\.\\-]+)\\/Sentry"
185+
} else if file == "./Sources/Sentry/SentryMeta.m" {
186+
return "static NSString \\*versionString = @\"(?<version>[a-zA-z0-9\\.\\-]+)\""
187+
}
188+
throw FileError.unknownFile(file)
189+
}

0 commit comments

Comments
 (0)