diff --git a/Package.swift b/Package.swift index 6e662d67..d812b5a5 100644 --- a/Package.swift +++ b/Package.swift @@ -22,8 +22,8 @@ import PackageDescription let releaseVersion = ProcessInfo.processInfo.environment["RELEASE_VERSION"] ?? "0.0.0" let gitCommit = ProcessInfo.processInfo.environment["GIT_COMMIT"] ?? "unspecified" -let scVersion = "0.5.0" let builderShimVersion = "0.6.0" +let scVersion = "0.5.0" let package = Package( name: "container", @@ -37,6 +37,7 @@ let package = Package( .library(name: "ContainerLog", targets: ["ContainerLog"]), .library(name: "ContainerPersistence", targets: ["ContainerPersistence"]), .library(name: "ContainerPlugin", targets: ["ContainerPlugin"]), + .library(name: "ContainerVersion", targets: ["ContainerVersion"]), .library(name: "ContainerXPC", targets: ["ContainerXPC"]), .library(name: "SocketForwarder", targets: ["SocketForwarder"]), .library(name: "ContainerBuildReporting", targets: ["ContainerBuildReporting"]), @@ -70,13 +71,13 @@ let package = Package( .product(name: "Containerization", package: "containerization"), .product(name: "ContainerizationOCI", package: "containerization"), .product(name: "ContainerizationOS", package: "containerization"), - "CVersion", - "TerminalProgress", "ContainerBuild", "ContainerClient", + "ContainerLog", "ContainerPersistence", "ContainerPlugin", - "ContainerLog", + "ContainerVersion", + "TerminalProgress", ], path: "Sources/CLI" ), @@ -90,14 +91,14 @@ let package = Package( .product(name: "Containerization", package: "containerization"), .product(name: "ContainerizationExtras", package: "containerization"), .product(name: "ContainerizationOS", package: "containerization"), - "CVersion", - "DNSServer", - "ContainerNetworkService", - "ContainerSandboxService", "ContainerClient", "ContainerLog", + "ContainerNetworkService", "ContainerPersistence", "ContainerPlugin", + "ContainerSandboxService", + "ContainerVersion", + "DNSServer", ], path: "Sources/APIServer" ), @@ -108,10 +109,10 @@ let package = Package( .product(name: "Logging", package: "swift-log"), .product(name: "GRPC", package: "grpc-swift"), .product(name: "Containerization", package: "containerization"), - "CVersion", + "ContainerLog", "ContainerNetworkService", "ContainerSandboxService", - "ContainerLog", + "ContainerVersion", "ContainerXPC", ], path: "Sources/Helpers/RuntimeLinux" @@ -140,9 +141,9 @@ let package = Package( .product(name: "ContainerizationExtras", package: "containerization"), .product(name: "ContainerizationIO", package: "containerization"), .product(name: "ContainerizationOS", package: "containerization"), - "CVersion", - "ContainerNetworkService", "ContainerLog", + "ContainerNetworkService", + "ContainerVersion", "ContainerXPC", ], path: "Sources/Helpers/NetworkVmnet" @@ -164,11 +165,11 @@ let package = Package( .product(name: "ArgumentParser", package: "swift-argument-parser"), .product(name: "Logging", package: "swift-log"), .product(name: "Containerization", package: "containerization"), - "CVersion", + "ContainerImagesService", "ContainerLog", "ContainerPlugin", + "ContainerVersion", "ContainerXPC", - "ContainerImagesService", ], path: "Sources/Helpers/Images" ), @@ -414,6 +415,12 @@ let package = Package( ], path: "Tests/CLITests" ), + .target( + name: "ContainerVersion", + dependencies: [ + "CVersion" + ], + ), .target( name: "CVersion", dependencies: [], diff --git a/Sources/APIServer/APIServer.swift b/Sources/APIServer/APIServer.swift index e1efbe23..67d7d3c3 100644 --- a/Sources/APIServer/APIServer.swift +++ b/Sources/APIServer/APIServer.swift @@ -15,11 +15,11 @@ //===----------------------------------------------------------------------===// import ArgumentParser -import CVersion import ContainerClient import ContainerLog import ContainerNetworkService import ContainerPlugin +import ContainerVersion import ContainerXPC import ContainerizationError import ContainerizationExtras @@ -37,7 +37,7 @@ struct APIServer: AsyncParsableCommand { static let configuration = CommandConfiguration( commandName: "container-apiserver", abstract: "Container management API server", - version: releaseVersion() + version: ReleaseVersion.singleLine(appName: "container-apiserver") ) @Flag(name: .long, help: "Enable debug logging") @@ -47,10 +47,6 @@ struct APIServer: AsyncParsableCommand { var installRoot = InstallRoot.url - static func releaseVersion() -> String { - (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? get_release_version().map { String(cString: $0) } ?? "0.0.0" - } - func run() async throws { let commandName = Self.configuration.commandName ?? "container-apiserver" let log = setupLogger() diff --git a/Sources/APIServer/HealthCheck/HealthCheckHarness.swift b/Sources/APIServer/HealthCheck/HealthCheckHarness.swift index a6c2738c..06374fd0 100644 --- a/Sources/APIServer/HealthCheck/HealthCheckHarness.swift +++ b/Sources/APIServer/HealthCheck/HealthCheckHarness.swift @@ -16,6 +16,7 @@ import CVersion import ContainerClient +import ContainerVersion import ContainerXPC import Containerization import Foundation @@ -37,8 +38,8 @@ actor HealthCheckHarness { let reply = message.reply() reply.set(key: .appRoot, value: appRoot.absoluteString) reply.set(key: .installRoot, value: installRoot.absoluteString) - reply.set(key: .apiServerVersion, value: APIServer.releaseVersion()) - reply.set(key: .apiServerCommit, value: get_git_commit().map { String(cString: $0) } ?? "unknown") + reply.set(key: .apiServerVersion, value: ReleaseVersion.singleLine(appName: "container-apiserver")) + reply.set(key: .apiServerCommit, value: get_git_commit().map { String(cString: $0) } ?? "unspecified") return reply } } diff --git a/Sources/CLI/Application.swift b/Sources/CLI/Application.swift index 66730370..b9b228a4 100644 --- a/Sources/CLI/Application.swift +++ b/Sources/CLI/Application.swift @@ -17,10 +17,10 @@ // import ArgumentParser -import CVersion import ContainerClient import ContainerLog import ContainerPlugin +import ContainerVersion import ContainerizationError import ContainerizationOS import Foundation @@ -48,7 +48,7 @@ struct Application: AsyncParsableCommand { static let configuration = CommandConfiguration( commandName: "container", abstract: "A container platform for macOS", - version: releaseVersion(), + version: ReleaseVersion.singleLine(appName: "container CLI"), subcommands: [ DefaultCommand.self ], @@ -336,25 +336,4 @@ extension Application { throw posixErr } } - - private static func releaseVersion() -> String { - var versionDetails: [String: String] = ["build": "release"] - #if DEBUG - versionDetails["build"] = "debug" - #endif - let gitCommit = { - let sha = get_git_commit().map { String(cString: $0) } - guard let sha else { - return "unspecified" - } - return String(sha.prefix(7)) - }() - versionDetails["commit"] = gitCommit - let extras: String = versionDetails.map { "\($0): \($1)" }.sorted().joined(separator: ", ") - - let bundleVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) - let releaseVersion = bundleVersion ?? get_release_version().map { String(cString: $0) } ?? "0.0.0" - - return "container CLI version \(releaseVersion) (\(extras))" - } } diff --git a/Sources/ContainerVersion/ReleaseVersion.swift b/Sources/ContainerVersion/ReleaseVersion.swift new file mode 100644 index 00000000..39925c32 --- /dev/null +++ b/Sources/ContainerVersion/ReleaseVersion.swift @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// Copyright © 2025 Apple Inc. and the container project authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//===----------------------------------------------------------------------===// + +import CVersion +import Foundation + +public struct ReleaseVersion { + public static func singleLine(appName: String) -> String { + var versionDetails: [String: String] = ["build": "release"] + #if DEBUG + versionDetails["build"] = "debug" + #endif + versionDetails["commit"] = gitCommit().map { String($0.prefix(7)) } ?? "unspecified" + let extras: String = versionDetails.map { "\($0): \($1)" }.sorted().joined(separator: ", ") + + return "\(appName) version \(version()) (\(extras))" + } + + public static func version() -> String { + let bundleVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) + return bundleVersion ?? get_release_version().map { String(cString: $0) } ?? "0.0.0" + } + + public static func gitCommit() -> String? { + get_git_commit().map { String(cString: $0) } + } +} diff --git a/Sources/Helpers/Images/ImagesHelper.swift b/Sources/Helpers/Images/ImagesHelper.swift index 95523ec4..f35d4f48 100644 --- a/Sources/Helpers/Images/ImagesHelper.swift +++ b/Sources/Helpers/Images/ImagesHelper.swift @@ -15,11 +15,11 @@ //===----------------------------------------------------------------------===// import ArgumentParser -import CVersion import ContainerImagesService import ContainerImagesServiceClient import ContainerLog import ContainerPlugin +import ContainerVersion import ContainerXPC import Containerization import Foundation @@ -30,7 +30,7 @@ struct ImagesHelper: AsyncParsableCommand { static let configuration = CommandConfiguration( commandName: "container-core-images", abstract: "XPC service for managing OCI images", - version: releaseVersion(), + version: ReleaseVersion.singleLine(appName: "container-core-images"), subcommands: [ Start.self ] @@ -129,8 +129,4 @@ extension ImagesHelper { return log } } - - private static func releaseVersion() -> String { - (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? get_release_version().map { String(cString: $0) } ?? "0.0.0" - } } diff --git a/Sources/Helpers/NetworkVmnet/NetworkVmnetHelper.swift b/Sources/Helpers/NetworkVmnet/NetworkVmnetHelper.swift index acbfb7af..96629b0c 100644 --- a/Sources/Helpers/NetworkVmnet/NetworkVmnetHelper.swift +++ b/Sources/Helpers/NetworkVmnet/NetworkVmnetHelper.swift @@ -15,9 +15,9 @@ //===----------------------------------------------------------------------===// import ArgumentParser -import CVersion import ContainerLog import ContainerNetworkService +import ContainerVersion import ContainerXPC import ContainerizationExtras import Foundation @@ -28,7 +28,7 @@ struct NetworkVmnetHelper: AsyncParsableCommand { static let configuration = CommandConfiguration( commandName: "container-network-vmnet", abstract: "XPC service for managing a vmnet network", - version: releaseVersion(), + version: ReleaseVersion.singleLine(appName: "container-network-vmnet"), subcommands: [ Start.self ] @@ -112,8 +112,4 @@ extension NetworkVmnetHelper { return try ReservedVmnetNetwork(configuration: configuration, log: log) } } - - private static func releaseVersion() -> String { - (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? get_release_version().map { String(cString: $0) } ?? "0.0.0" - } } diff --git a/Sources/Helpers/RuntimeLinux/RuntimeLinuxHelper.swift b/Sources/Helpers/RuntimeLinux/RuntimeLinuxHelper.swift index 554a9146..4be61429 100644 --- a/Sources/Helpers/RuntimeLinux/RuntimeLinuxHelper.swift +++ b/Sources/Helpers/RuntimeLinux/RuntimeLinuxHelper.swift @@ -15,11 +15,11 @@ //===----------------------------------------------------------------------===// import ArgumentParser -import CVersion import ContainerClient import ContainerLog import ContainerNetworkService import ContainerSandboxService +import ContainerVersion import ContainerXPC import Containerization import ContainerizationError @@ -34,7 +34,7 @@ struct RuntimeLinuxHelper: AsyncParsableCommand { static let configuration = CommandConfiguration( commandName: "container-runtime-linux", abstract: "XPC Service for managing a Linux sandbox", - version: releaseVersion() + version: ReleaseVersion.singleLine(appName: "container-runtime-linux") ) @Flag(name: .long, help: "Enable debug logging") @@ -122,8 +122,4 @@ struct RuntimeLinuxHelper: AsyncParsableCommand { throw POSIXError(.init(rawValue: errno)!) } } - - private static func releaseVersion() -> String { - (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? get_release_version().map { String(cString: $0) } ?? "0.0.0" - } }