Skip to content

Commit 6ec3ee9

Browse files
authored
Merge branch '8-scheduled-job' into github-summary
2 parents 802c45a + 1b8c595 commit 6ec3ee9

File tree

77 files changed

+1139
-841
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+1139
-841
lines changed

LINTING_PROGRESS.md

Lines changed: 276 additions & 53 deletions
Large diffs are not rendered by default.

Sources/BushelCloudCLI/Commands/ExportCommand.swift

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,17 @@ internal enum ExportCommand {
3636
// MARK: - Export Types
3737

3838
private struct ExportData: Codable {
39-
internal let restoreImages: [RecordExport]
40-
internal let xcodeVersions: [RecordExport]
41-
internal let swiftVersions: [RecordExport]
39+
let restoreImages: [RecordExport]
40+
let xcodeVersions: [RecordExport]
41+
let swiftVersions: [RecordExport]
4242
}
4343

4444
private struct RecordExport: Codable {
45-
internal let recordName: String
46-
internal let recordType: String
47-
internal let fields: [String: String]
45+
let recordName: String
46+
let recordType: String
47+
let fields: [String: String]
4848

49-
internal init(from recordInfo: RecordInfo) {
49+
init(from recordInfo: RecordInfo) {
5050
self.recordName = recordInfo.recordName
5151
self.recordType = recordInfo.recordType
5252
self.fields = recordInfo.fields.mapValues { fieldValue in
@@ -193,5 +193,4 @@ internal enum ExportCommand {
193193
print(" • Ensure data has been synced to CloudKit")
194194
print(" • Run 'bushel-cloud sync' first if needed")
195195
}
196-
197196
}

Sources/BushelCloudKit/CloudKit/BushelCloudKitService.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ public import MistKit
4949
public struct BushelCloudKitService: Sendable, RecordManaging, CloudKitRecordCollection {
5050
public typealias RecordTypeSetType = RecordTypeSet
5151

52-
private let service: CloudKitService
53-
5452
// MARK: - CloudKitRecordCollection
5553

5654
/// All CloudKit record types managed by this service (using variadic generics)
@@ -61,6 +59,8 @@ public struct BushelCloudKitService: Sendable, RecordManaging, CloudKitRecordCol
6159
DataSourceMetadata.self
6260
)
6361

62+
private let service: CloudKitService
63+
6464
// MARK: - Initialization
6565

6666
/// Initialize CloudKit service with Server-to-Server authentication
@@ -180,7 +180,9 @@ public struct BushelCloudKitService: Sendable, RecordManaging, CloudKitRecordCol
180180
) async throws {
181181
// Create empty classification (no tracking)
182182
let classification = OperationClassification(proposedRecords: [], existingRecords: [])
183-
_ = try await executeBatchOperations(operations, recordType: recordType, classification: classification)
183+
_ = try await executeBatchOperations(
184+
operations, recordType: recordType, classification: classification
185+
)
184186
}
185187

186188
/// Execute operations in batches with detailed create/update tracking
@@ -203,7 +205,10 @@ public struct BushelCloudKitService: Sendable, RecordManaging, CloudKitRecordCol
203205

204206
ConsoleOutput.print("Syncing \(operations.count) \(recordType) record(s) in \(batches.count) batch(es)...")
205207
Self.logger.debug(
206-
"CloudKit batch limit: 200 operations/request. Using \(batches.count) batch(es) for \(operations.count) records."
208+
"""
209+
CloudKit batch limit: 200 operations/request. \
210+
Using \(batches.count) batch(es) for \(operations.count) records.
211+
"""
207212
)
208213
Self.logger.debug(
209214
"Classification: \(classification.creates.count) creates, \(classification.updates.count) updates"

Sources/BushelCloudKit/CloudKit/PEMValidator.swift

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import Foundation
3131

3232
/// Validates PEM format for CloudKit Server-to-Server private keys
33-
enum PEMValidator {
33+
internal enum PEMValidator {
3434
/// Validates a PEM string has proper structure and encoding
3535
///
3636
/// **Checks performed:**
@@ -46,24 +46,28 @@ enum PEMValidator {
4646
///
4747
/// - Parameter pemString: The PEM-formatted private key string
4848
/// - Throws: BushelCloudKitError.invalidPEMFormat with specific reason and recovery suggestion
49-
static func validate(_ pemString: String) throws {
49+
internal static func validate(_ pemString: String) throws {
5050
let trimmed = pemString.trimmingCharacters(in: .whitespacesAndNewlines)
5151

5252
// Check for BEGIN header
5353
guard trimmed.contains("-----BEGIN") && trimmed.contains("PRIVATE KEY-----") else {
5454
throw BushelCloudKitError.invalidPEMFormat(
5555
reason: "Missing '-----BEGIN PRIVATE KEY-----' header",
56-
suggestion:
57-
"Ensure you copied the entire PEM file including the header line. Re-download from CloudKit Dashboard if needed."
56+
suggestion: """
57+
Ensure you copied the entire PEM file including the header line. \
58+
Re-download from CloudKit Dashboard if needed.
59+
"""
5860
)
5961
}
6062

6163
// Check for END footer
6264
guard trimmed.contains("-----END") && trimmed.contains("PRIVATE KEY-----") else {
6365
throw BushelCloudKitError.invalidPEMFormat(
6466
reason: "Missing '-----END PRIVATE KEY-----' footer",
65-
suggestion:
66-
"The PEM file may have been truncated during copy/paste. Ensure you copied the entire file including the footer line."
67+
suggestion: """
68+
The PEM file may have been truncated during copy/paste. \
69+
Ensure you copied the entire file including the footer line.
70+
"""
6771
)
6872
}
6973

@@ -85,8 +89,10 @@ enum PEMValidator {
8589
guard Data(base64Encoded: base64Content) != nil else {
8690
throw BushelCloudKitError.invalidPEMFormat(
8791
reason: "PEM content is not valid base64 encoding",
88-
suggestion:
89-
"The key file may be corrupted. Ensure you used a text editor (not binary editor) and the file is UTF-8 encoded."
92+
suggestion: """
93+
The key file may be corrupted. \
94+
Ensure you used a text editor (not binary editor) and the file is UTF-8 encoded.
95+
"""
9096
)
9197
}
9298
}

Sources/BushelCloudKit/CloudKit/SyncEngine+Export.swift

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ public import MistKit
3939
// MARK: - Export Operations
4040

4141
extension SyncEngine {
42+
// MARK: - Export Result Type
43+
44+
public struct ExportResult {
45+
public let restoreImages: [RecordInfo]
46+
public let xcodeVersions: [RecordInfo]
47+
public let swiftVersions: [RecordInfo]
48+
49+
public init(
50+
restoreImages: [RecordInfo], xcodeVersions: [RecordInfo], swiftVersions: [RecordInfo]
51+
) {
52+
self.restoreImages = restoreImages
53+
self.xcodeVersions = xcodeVersions
54+
self.swiftVersions = swiftVersions
55+
}
56+
}
57+
4258
/// Export all records from CloudKit to a structured format
4359
public func export() async throws -> ExportResult {
4460
ConsoleOutput.print("\n" + String(repeating: "=", count: 60))
@@ -83,7 +99,10 @@ extension SyncEngine {
8399
ConsoleOutput.print("\(swiftVersions.count) Swift versions")
84100

85101
Self.logger.debug(
86-
"MistKit returns RecordInfo structs with record metadata. Use .fields to access CloudKit field values."
102+
"""
103+
MistKit returns RecordInfo structs with record metadata. \
104+
Use .fields to access CloudKit field values.
105+
"""
87106
)
88107

89108
return ExportResult(
@@ -92,20 +111,4 @@ extension SyncEngine {
92111
swiftVersions: swiftVersions
93112
)
94113
}
95-
96-
// MARK: - Export Result Type
97-
98-
public struct ExportResult {
99-
public let restoreImages: [RecordInfo]
100-
public let xcodeVersions: [RecordInfo]
101-
public let swiftVersions: [RecordInfo]
102-
103-
public init(
104-
restoreImages: [RecordInfo], xcodeVersions: [RecordInfo], swiftVersions: [RecordInfo]
105-
) {
106-
self.restoreImages = restoreImages
107-
self.xcodeVersions = xcodeVersions
108-
self.swiftVersions = swiftVersions
109-
}
110-
}
111114
}

Sources/BushelCloudKit/CloudKit/SyncEngine.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,6 @@ public struct SyncEngine: Sendable {
375375
ConsoleOutput.print(String(repeating: "=", count: 60))
376376
Self.logger.info("Clear completed successfully")
377377
}
378-
379378
}
380379

381380
// MARK: - Loggable Conformance

Sources/BushelCloudKit/Configuration/CloudKitConfiguration.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,10 @@ public struct ValidatedCloudKitConfiguration: Sendable {
107107

108108
guard let parsedEnvironment = MistKit.Environment(rawValue: environmentString) else {
109109
throw ConfigurationError(
110-
"Invalid CLOUDKIT_ENVIRONMENT: '\(config.environment ?? "")'. Must be 'development' or 'production'",
110+
"""
111+
Invalid CLOUDKIT_ENVIRONMENT: '\(config.environment ?? "")'. \
112+
Must be 'development' or 'production'
113+
""",
111114
key: "cloudkit.environment"
112115
)
113116
}

Sources/BushelCloudKit/Configuration/ConfigurationKeys.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ internal enum ConfigurationKeys {
9898
internal enum Sync {
9999
internal static let dryRun = ConfigKey<Bool>(bushelPrefixed: "sync.dry_run")
100100
internal static let restoreImagesOnly = ConfigKey<Bool>(
101-
bushelPrefixed: "sync.restore_images_only")
101+
bushelPrefixed: "sync.restore_images_only"
102+
)
102103
internal static let xcodeOnly = ConfigKey<Bool>(bushelPrefixed: "sync.xcode_only")
103104
internal static let swiftOnly = ConfigKey<Bool>(bushelPrefixed: "sync.swift_only")
104105
internal static let noBetas = ConfigKey<Bool>(bushelPrefixed: "sync.no_betas")

Sources/BushelCloudKit/Configuration/ConfigurationLoader.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,20 @@ public actor ConfigurationLoader {
7171
// MARK: - Helper Methods
7272

7373
/// Read a string value from configuration
74-
func readString(forKey key: String) -> String? {
74+
internal func readString(forKey key: String) -> String? {
7575
configReader.string(forKey: ConfigKey(key))
7676
}
7777

7878
/// Read an integer value from configuration
79-
func readInt(forKey key: String) -> Int? {
79+
internal func readInt(forKey key: String) -> Int? {
8080
guard let stringValue = configReader.string(forKey: ConfigKey(key)) else {
8181
return nil
8282
}
8383
return Int(stringValue)
8484
}
8585

8686
/// Read a double value from configuration
87-
func readDouble(forKey key: String) -> Double? {
87+
internal func readDouble(forKey key: String) -> Double? {
8888
guard let stringValue = configReader.string(forKey: ConfigKey(key)) else {
8989
return nil
9090
}
@@ -95,7 +95,7 @@ public actor ConfigurationLoader {
9595

9696
/// Read a string value with automatic CLI → ENV → default fallback
9797
/// Returns non-optional since ConfigKey has a required default
98-
func read(_ key: ConfigKeyKit.ConfigKey<String>) -> String {
98+
internal func read(_ key: ConfigKeyKit.ConfigKey<String>) -> String {
9999
for source in ConfigKeySource.allCases {
100100
guard let keyString = key.key(for: source) else { continue }
101101
if let value = readString(forKey: keyString) {
@@ -116,7 +116,7 @@ public actor ConfigurationLoader {
116116
///
117117
/// - Parameter key: Configuration key with boolean type
118118
/// - Returns: Boolean value from CLI/ENV or the key's default
119-
func read(_ key: ConfigKeyKit.ConfigKey<Bool>) -> Bool {
119+
internal func read(_ key: ConfigKeyKit.ConfigKey<Bool>) -> Bool {
120120
// Try CLI first (presence-based for flags)
121121
if let cliKey = key.key(for: .commandLine),
122122
configReader.string(forKey: ConfigKey(cliKey)) != nil
@@ -140,7 +140,7 @@ public actor ConfigurationLoader {
140140

141141
/// Read a string value with automatic CLI → ENV fallback
142142
/// Returns optional since OptionalConfigKey has no default
143-
func read(_ key: ConfigKeyKit.OptionalConfigKey<String>) -> String? {
143+
internal func read(_ key: ConfigKeyKit.OptionalConfigKey<String>) -> String? {
144144
for source in ConfigKeySource.allCases {
145145
guard let keyString = key.key(for: source) else { continue }
146146
if let value = readString(forKey: keyString) {
@@ -152,7 +152,7 @@ public actor ConfigurationLoader {
152152

153153
/// Read an integer value with automatic CLI → ENV fallback
154154
/// Returns optional since OptionalConfigKey has no default
155-
func read(_ key: ConfigKeyKit.OptionalConfigKey<Int>) -> Int? {
155+
internal func read(_ key: ConfigKeyKit.OptionalConfigKey<Int>) -> Int? {
156156
for source in ConfigKeySource.allCases {
157157
guard let keyString = key.key(for: source) else { continue }
158158
if let value = readInt(forKey: keyString) {
@@ -164,7 +164,7 @@ public actor ConfigurationLoader {
164164

165165
/// Read a double value with automatic CLI → ENV fallback
166166
/// Returns optional since OptionalConfigKey has no default
167-
func read(_ key: ConfigKeyKit.OptionalConfigKey<Double>) -> Double? {
167+
internal func read(_ key: ConfigKeyKit.OptionalConfigKey<Double>) -> Double? {
168168
for source in ConfigKeySource.allCases {
169169
guard let keyString = key.key(for: source) else { continue }
170170
if let value = readDouble(forKey: keyString) {

Sources/BushelCloudKit/DataSources/AppleDB/AppleDBEntry.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,21 @@
3030
import Foundation
3131

3232
/// Represents a single macOS build entry from AppleDB
33-
struct AppleDBEntry: Codable {
34-
let version: String
35-
let build: String? // Some entries may not have a build number
36-
let released: String // ISO date or empty string
37-
let beta: Bool?
38-
let rc: Bool?
39-
let `internal`: Bool?
40-
let deviceMap: [String]
41-
let signed: SignedStatus
42-
let sources: [AppleDBSource]?
43-
44-
enum CodingKeys: String, CodingKey {
33+
internal struct AppleDBEntry: Codable {
34+
internal enum CodingKeys: String, CodingKey {
4535
case version, build, released
4636
case beta, rc
4737
case `internal` = "internal"
4838
case deviceMap, signed, sources
4939
}
40+
41+
internal let version: String
42+
internal let build: String? // Some entries may not have a build number
43+
internal let released: String // ISO date or empty string
44+
internal let beta: Bool?
45+
internal let rc: Bool?
46+
internal let `internal`: Bool?
47+
internal let deviceMap: [String]
48+
internal let signed: SignedStatus
49+
internal let sources: [AppleDBSource]?
5050
}

0 commit comments

Comments
 (0)