feat: Updating configuration.

This commit is contained in:
2024-12-23 22:46:20 -05:00
parent 11ec829a90
commit 7d23172c71
5 changed files with 230 additions and 4 deletions

25
.bump-version.json Normal file
View File

@@ -0,0 +1,25 @@
{
"strategy" : {
"semvar" : {
"preRelease" : {
"strategy" : {
"command" : {
"arguments" : [
"git",
"describe",
"--tags"
]
}
}
},
"requireExistingFile" : true,
"requireExistingSemVar" : true
}
},
"target" : {
"module" : {
"fileName" : "Version.swift",
"name" : "cli-version"
}
}
}

View File

@@ -2,6 +2,12 @@
requireExistingFile = true
requireExistingSemVar = true
[strategy.semvar.preRelease]
style = 'branch'
[strategy.semvar.preRelease.branch]
includeCommitSha = true
[target.module]
fileName = 'Version.swift'
name = 'cli-version'

View File

@@ -48,6 +48,7 @@ let package = Package(
name: "ConfigurationClient",
dependencies: [
"FileClient",
.product(name: "CustomDump", package: "swift-custom-dump"),
.product(name: "Dependencies", package: "swift-dependencies"),
.product(name: "DependenciesMacros", package: "swift-dependencies"),
.product(name: "TOMLKit", package: "TOMLKit")

View File

@@ -1,6 +1,9 @@
import CustomDump
import Foundation
import TOMLKit
// TODO: Just use json for configuration ??
/// Represents configuration that can be set via a file, generally in the root of the
/// project directory.
///
@@ -38,6 +41,19 @@ public struct Configuration: Codable, Equatable, Sendable {
}
}
public struct Configuration2: Codable, Equatable, Sendable {
public let target: Configuration.Target?
public let strategy: Configuration.VersionStrategy2?
public static let mock = Self(
target: .init(module: .init("cli-version")),
strategy: .semvar(value: .init(preRelease: .init(
strategy: .branch()
)))
// strategy: .branch()
)
}
public extension Configuration {
/// Represents a branch version or pre-release strategy.
@@ -58,12 +74,32 @@ public extension Configuration {
}
}
struct PreRelease2: Codable, Equatable, Sendable {
public let prefix: String?
public let strategy: Strategy
public init(
prefix: String? = nil,
strategy: Strategy
) {
self.prefix = prefix
self.strategy = strategy
}
public enum Strategy: Codable, Equatable, Sendable {
case branch(includeCommitSha: Bool = true)
case command(arguments: [String])
case gitTag
}
}
/// Represents version strategy for pre-release.
///
/// This appends a suffix to the version that get's generated from the version strategy.
/// For example: `1.0.0-rc-1`
///
struct PreReleaseStrategy: Codable, Equatable, Sendable {
struct PreReleaseStrategy: Codable, Equatable, Sendable, CustomDumpReflectable {
/// Use branch and commit sha as pre-release suffix.
public let branch: Branch?
@@ -76,7 +112,7 @@ public extension Configuration {
/// Whether we use `git describe --tags` for part of the suffix, this is only used
/// if we have a custom style.
public let usesGitTag: Bool
public let usesGitTag: Bool?
init(
style: StyleId,
@@ -90,6 +126,30 @@ public extension Configuration {
self.usesGitTag = usesGitTag
}
public var customDumpMirror: Mirror {
guard let branch else {
return .init(
self,
children: [
"style": style,
"prefix": prefix as Any,
"usesGitTag": style == .gitTag ? true : (usesGitTag ?? false)
],
displayStyle: .struct
)
// return .init(reflecting: self)
}
return .init(
self,
children: [
"style": style,
"branch": branch,
"prefix": prefix as Any
],
displayStyle: .struct
)
}
/// Represents a pre-release strategy that is derived from calling
/// `git describe --tags`.
public static let gitTag = Self(style: StyleId.gitTag)
@@ -154,11 +214,34 @@ public extension Configuration {
}
struct SemVar2: Codable, Equatable, Sendable {
/// Optional pre-releas suffix strategy.
public let preRelease: PreRelease2?
/// Fail if an existing version file does not exist in the target.
public let requireExistingFile: Bool
/// Fail if an existing semvar is not parsed from the file or version generation strategy.
public let requireExistingSemVar: Bool
public init(
preRelease: PreRelease2? = nil,
requireExistingFile: Bool = true,
requireExistingSemVar: Bool = true
) {
self.preRelease = preRelease
self.requireExistingFile = requireExistingFile
self.requireExistingSemVar = requireExistingSemVar
}
}
/// Represents the target where we will bump the version in.
///
/// This can either be a path to a version file or a module used to
/// locate the version file.
struct Target: Codable, Equatable, Sendable {
struct Target: Codable, Equatable, Sendable, CustomDumpReflectable {
/// The path to a version file.
public let path: String?
@@ -206,6 +289,44 @@ public extension Configuration {
self.name = name
self.fileName = fileName
}
}
public var customDumpMirror: Mirror {
guard let module else {
guard let path else { return .init(reflecting: self) }
return .init(
self,
children: [
"path": path
],
displayStyle: .struct
)
}
return .init(
self,
children: [
"module": module
],
displayStyle: .struct
)
}
}
enum VersionStrategy2: Codable, Equatable, Sendable {
case branch(includeCommitSha: Bool = true)
case semvar(
preRelease: PreRelease2? = nil,
requireExistingFile: Bool? = nil,
requireExistingSemVar: Bool? = nil
)
static func semvar(value: SemVar2) -> Self {
.semvar(
preRelease: value.preRelease,
requireExistingFile: value.requireExistingFile,
requireExistingSemVar: value.requireExistingSemVar
)
}
}
@@ -214,7 +335,7 @@ public extension Configuration {
/// Typically a `SemVar` strategy or `Branch`.
///
///
struct VersionStrategy: Codable, Equatable, Sendable {
struct VersionStrategy: Codable, Equatable, Sendable, CustomDumpReflectable {
/// Set if we're using the branch and commit sha to derive the version.
public let branch: Branch?
@@ -240,5 +361,27 @@ public extension Configuration {
self.semvar = semvar
}
public var customDumpMirror: Mirror {
if let branch {
return .init(
self,
children: [
"branch": branch
],
displayStyle: .struct
)
} else if let semvar {
return .init(
self,
children: [
"semvar": semvar
],
displayStyle: .struct
)
} else {
return .init(reflecting: self)
}
}
}
}

View File

@@ -3,6 +3,7 @@ import Dependencies
import Foundation
import Testing
import TestSupport
import TOMLKit
@Suite("ConfigurationClientTests")
struct ConfigurationClientTests {
@@ -98,6 +99,56 @@ struct ConfigurationClientTests {
}
}
// @Test
// func writeDefault() async throws {
// try await run {
// @Dependency(\.coders) var coders
// @Dependency(\.configurationClient) var configurationClient
//
// // let configuration = Configuration.customPreRelease
// // try await configurationClient.write(configuration, .json(URL(filePath: ".bump-version.json")))
//
// // let target = Configuration.Target2.path("foo")
// // let target = Configuration.Target2.gitTag
// // let target = Configuration.Target2.branch()
// let target = Configuration2.mock
//
// let encoded = try coders.jsonEncoder().encode(target)
// let url = URL(filePath: ".bump-version.json")
// try encoded.write(to: url)
//
// let data = try Data(contentsOf: url)
// let decoded = try coders.jsonDecoder().decode(Configuration2.self, from: data)
// print(decoded)
// }
// }
// @Test
// func tomlPlayground() throws {
// let jsonEncoder = JSONEncoder()
// let encoder = TOMLEncoder()
// let decoder = TOMLDecoder()
//
// enum TestType: Codable {
// case one
// case hello(Hello)
//
// struct Hello: Codable {
// let value: String
// }
// }
//
// struct TestContainer: Codable {
// let testType: TestType
// }
//
// let sut = TestContainer(testType: .hello(.init(value: "world")))
// let encoded = try encoder.encode(sut)
// print(encoded)
// // let decoded = try decoder.decode(TestContainer.self, from: encoded)
// // #expect(decoded.testType == sut.testType)
// }
func run(
setupDependencies: @escaping (inout DependencyValues) -> Void = { _ in },
operation: () async throws -> Void