mirror of
https://github.com/bitwarden/ios.git
synced 2026-02-04 02:14:09 -06:00
[PM-18404] Add SDK version to About screen version copy-paste (#2250)
This commit is contained in:
parent
04c9952ce7
commit
a65b92732b
3
.gitignore
vendored
3
.gitignore
vendored
@ -87,3 +87,6 @@ Authenticator/Application/Support/Settings.bundle/Acknowledgements.latest_result
|
||||
# AI
|
||||
.claude/settings.local.json
|
||||
review-*.md
|
||||
|
||||
# Generated files
|
||||
BitwardenKit/Core/Platform/Utilities/SDKVersionInfo.swift
|
||||
|
||||
@ -8,6 +8,9 @@ import UIKit
|
||||
public protocol AppAdditionalInfo {
|
||||
/// CI Build information.
|
||||
var ciBuildInfo: KeyValuePairs<String, String> { get }
|
||||
|
||||
/// SDK version information.
|
||||
var sdkVersion: String { get }
|
||||
}
|
||||
|
||||
// MARK: - DefaultAppAdditionalInfo
|
||||
@ -19,6 +22,10 @@ public struct DefaultAppAdditionalInfo: AppAdditionalInfo {
|
||||
CIBuildInfo.info
|
||||
}
|
||||
|
||||
public var sdkVersion: String {
|
||||
SDKVersionInfo.version
|
||||
}
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
@ -102,11 +109,11 @@ public extension DefaultAppInfoService {
|
||||
"",
|
||||
appNameAndVersionString,
|
||||
bundleString,
|
||||
// TODO: PM-18404 - Include server and SDK version
|
||||
// sdkString,
|
||||
// TODO: PM-18404 - Include server version
|
||||
// serverString,
|
||||
deviceString,
|
||||
systemOSString,
|
||||
sdkString,
|
||||
additionalInfoString,
|
||||
]
|
||||
.compactMap(\.self)
|
||||
@ -118,11 +125,11 @@ public extension DefaultAppInfoService {
|
||||
[
|
||||
appNameAndVersionString,
|
||||
bundleString,
|
||||
// TODO: PM-18404 - Include server and SDK version
|
||||
// sdkString,
|
||||
// TODO: PM-18404 - Include server version
|
||||
// serverString,
|
||||
deviceString,
|
||||
systemOSString,
|
||||
sdkString,
|
||||
additionalInfoString,
|
||||
]
|
||||
.compactMap(\.self)
|
||||
@ -167,6 +174,13 @@ public extension DefaultAppInfoService {
|
||||
"📱 Device: \(systemDevice.modelIdentifier)"
|
||||
}
|
||||
|
||||
/// A string containing the SDK version info.
|
||||
private var sdkString: String? {
|
||||
let version = appAdditionalInfo.sdkVersion
|
||||
guard version != "Unknown", !version.isEmpty else { return nil }
|
||||
return "🦀 SDK: \(version)"
|
||||
}
|
||||
|
||||
/// A string containing the OS info.
|
||||
private var systemOSString: String {
|
||||
"🍏 System: \(systemDevice.systemName) \(systemDevice.systemVersion)"
|
||||
|
||||
@ -124,6 +124,67 @@ class AppInfoServiceTests: BitwardenTestCase {
|
||||
)
|
||||
}
|
||||
|
||||
/// `appInfoString` includes SDK version when available.
|
||||
func test_appInfoString_withSDKVersion() {
|
||||
appAdditionalInfo.sdkVersion = "1.0.0-1234-abc1234"
|
||||
|
||||
XCTAssertEqual(
|
||||
subject.appInfoString,
|
||||
"""
|
||||
© Bitwarden Inc. 2015–2025
|
||||
|
||||
📝 Bitwarden 1.0 (1)
|
||||
📦 Bundle: com.8bit.bitwarden
|
||||
📱 Device: iPhone14,2
|
||||
🍏 System: iOS 16.4
|
||||
🦀 SDK: 1.0.0-1234-abc1234
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
/// `appInfoString` excludes SDK version when unknown.
|
||||
func test_appInfoString_withUnknownSDKVersion() {
|
||||
appAdditionalInfo.sdkVersion = "Unknown"
|
||||
|
||||
XCTAssertEqual(
|
||||
subject.appInfoString,
|
||||
"""
|
||||
© Bitwarden Inc. 2015–2025
|
||||
|
||||
📝 Bitwarden 1.0 (1)
|
||||
📦 Bundle: com.8bit.bitwarden
|
||||
📱 Device: iPhone14,2
|
||||
🍏 System: iOS 16.4
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
/// `appInfoString` includes both SDK version and CI build info when both available.
|
||||
func test_appInfoString_withSDKVersionAndCIBuildInfo() {
|
||||
appAdditionalInfo.sdkVersion = "1.0.0-1234-abc1234"
|
||||
appAdditionalInfo.ciBuildInfo = [
|
||||
"🧱 Commit": "bitwarden/ios/main@abc123",
|
||||
"💻 Build Source": "bitwarden/ios/actions/runs/123/attempts/123",
|
||||
"🛠️ Compiler Flags": "DEBUG_MENU",
|
||||
]
|
||||
|
||||
XCTAssertEqual(
|
||||
subject.appInfoString,
|
||||
"""
|
||||
© Bitwarden Inc. 2015–2025
|
||||
|
||||
📝 Bitwarden 1.0 (1)
|
||||
📦 Bundle: com.8bit.bitwarden
|
||||
📱 Device: iPhone14,2
|
||||
🍏 System: iOS 16.4
|
||||
🦀 SDK: 1.0.0-1234-abc1234
|
||||
🧱 Commit: bitwarden/ios/main@abc123
|
||||
💻 Build Source: bitwarden/ios/actions/runs/123/attempts/123
|
||||
🛠️ Compiler Flags: DEBUG_MENU
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
/// `debugAppInfoString` returns the app info string without copyright info.
|
||||
func test_appInfoWithoutCopyrightString() {
|
||||
appAdditionalInfo.ciBuildInfo = [
|
||||
@ -169,8 +230,17 @@ class AppInfoServiceTests: BitwardenTestCase {
|
||||
func test_appAdditionalInfo_ciBuildInfo() {
|
||||
XCTAssertTrue(DefaultAppAdditionalInfo().ciBuildInfo.isEmpty)
|
||||
}
|
||||
|
||||
/// `sdkVersion` returns the SDK version from SDKVersionInfo.
|
||||
func test_appAdditionalInfo_sdkVersion() {
|
||||
let info = DefaultAppAdditionalInfo()
|
||||
XCTAssertNotNil(info.sdkVersion)
|
||||
XCTAssertFalse(info.sdkVersion.isEmpty)
|
||||
XCTAssertEqual(info.sdkVersion, SDKVersionInfo.version)
|
||||
}
|
||||
}
|
||||
|
||||
class MockAppAdditionalInfo: AppAdditionalInfo {
|
||||
var ciBuildInfo: KeyValuePairs<String, String> = [:]
|
||||
var sdkVersion: String = "Unknown"
|
||||
}
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
import BitwardenKit
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
/// Tests for `SDKVersionInfo`.
|
||||
struct SDKVersionInfoTests {
|
||||
/// `version` is not "Unknown" since the build script should have generated it.
|
||||
@Test
|
||||
func versionIsNotUnknown() {
|
||||
#expect(
|
||||
SDKVersionInfo.version != "Unknown",
|
||||
"SDK version should be generated by build script, not 'Unknown'",
|
||||
)
|
||||
}
|
||||
|
||||
/// `version` is not empty.
|
||||
@Test
|
||||
func versionIsNotEmpty() {
|
||||
#expect(!SDKVersionInfo.version.isEmpty)
|
||||
}
|
||||
|
||||
/// `version` matches the expected semantic version format from project-common.yml.
|
||||
/// Expected format: "MAJOR.MINOR.PATCH-BUILD_NUMBER-COMMIT_HASH"
|
||||
/// Example: "2.0.0-3659-948b207"
|
||||
@Test
|
||||
func versionMatchesSemanticVersionFormat() {
|
||||
let version = SDKVersionInfo.version
|
||||
|
||||
// Regex pattern for semantic version with build number and commit hash
|
||||
// Format: X.Y.Z-BUILD-HASH where:
|
||||
// - X.Y.Z is the semantic version (e.g., 2.0.0)
|
||||
// - BUILD is the build number (e.g., 3659)
|
||||
// - HASH is the short git commit hash (e.g., 948b207)
|
||||
let pattern = #"^\d+\.\d+\.\d+-\d+-[a-f0-9]+$"#
|
||||
|
||||
let regex = try? NSRegularExpression(pattern: pattern, options: [])
|
||||
let range = NSRange(version.startIndex..., in: version)
|
||||
let matches = regex?.firstMatch(in: version, options: [], range: range)
|
||||
|
||||
#expect(
|
||||
matches != nil,
|
||||
"SDK version '\(version)' should match format 'X.Y.Z-BUILD-HASH' (e.g., '2.0.0-3659-948b207')",
|
||||
)
|
||||
}
|
||||
}
|
||||
49
Scripts/generate-sdk-version-info.sh
Executable file
49
Scripts/generate-sdk-version-info.sh
Executable file
@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# SDK Version Info Generator
|
||||
#
|
||||
# Extracts SDK version from project-common.yml and generates SDKVersionInfo.swift
|
||||
# Works in ALL builds (local + CI), not just CI builds
|
||||
#
|
||||
# Prerequisites:
|
||||
# - project-common.yml exists with BitwardenSdk revision comment
|
||||
# - Write access to BitwardenKit/Core/Platform/Utilities/
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_FILE="${SRCROOT:-$(pwd)}/project-common.yml"
|
||||
OUTPUT_FILE="${SRCROOT:-$(pwd)}/BitwardenKit/Core/Platform/Utilities/SDKVersionInfo.swift"
|
||||
|
||||
# Extract SDK version from YAML comment
|
||||
# Format: revision: <hash> # <version>
|
||||
SDK_VERSION=$(grep -A5 "BitwardenSdk:" "$PROJECT_FILE" | \
|
||||
grep "revision:" | \
|
||||
sed 's/.*# //' | \
|
||||
tr -d '\n' || echo "Unknown")
|
||||
|
||||
# If extraction failed or returned the full line (no # comment), provide fallback
|
||||
if [ -z "$SDK_VERSION" ] || [ "$SDK_VERSION" = "Unknown" ] || [[ "$SDK_VERSION" == *"revision:"* ]]; then
|
||||
echo "❌ ERROR: Could not extract SDK version from $PROJECT_FILE"
|
||||
echo "Expected format: 'revision: <hash> # <version>'"
|
||||
echo "Example: 'revision: 70f9530... # 2.0.0-3659-948b207'"
|
||||
echo "Tests will fail with 'Unknown' version"
|
||||
SDK_VERSION="Unknown"
|
||||
fi
|
||||
|
||||
echo "🔧 Generating SDK Version Info..."
|
||||
echo "🔧 SDK Version: $SDK_VERSION"
|
||||
|
||||
# Generate Swift file
|
||||
cat << EOF > "$OUTPUT_FILE"
|
||||
/// SDK version information extracted from project-common.yml at build time.
|
||||
/// WARNING: This file is automatically generated by Scripts/generate-sdk-version-info.sh
|
||||
/// and should not be modified manually.
|
||||
///
|
||||
public enum SDKVersionInfo {
|
||||
/// The BitwardenSDK version string (e.g., "2.0.0-3659-948b207").
|
||||
/// Extracted from the revision comment in project-common.yml.
|
||||
public static let version: String = "$SDK_VERSION"
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "✅ SDK Version Info generated successfully."
|
||||
@ -122,6 +122,15 @@ targets:
|
||||
- SourceryTarget
|
||||
templateAttributes:
|
||||
sourcesPath: BitwardenKit
|
||||
sources:
|
||||
- path: BitwardenKit/Core/Platform/Utilities/SDKVersionInfo.swift
|
||||
optional: true
|
||||
preBuildScripts:
|
||||
- name: Generate SDK Version Info
|
||||
path: Scripts/generate-sdk-version-info.sh
|
||||
basedOnDependencyAnalysis: false
|
||||
outputFiles:
|
||||
- $(SRCROOT)/BitwardenKit/Core/Platform/Utilities/SDKVersionInfo.swift
|
||||
dependencies:
|
||||
- package: BitwardenSdk
|
||||
- package: SwiftUIIntrospect
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user