From 001cfca5658f852c81f7cd3e71cc9f4b49d31b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Pi=C3=B1era=20Buend=C3=ADa?= Date: Tue, 16 Jun 2026 16:42:18 +0200 Subject: [PATCH] feat(tart): label virtual machines on macOS 27 --- Sources/tart/VM.swift | 19 ++++++++++++++++++- Tests/TartTests/VMTests.swift | 23 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 Tests/TartTests/VMTests.swift diff --git a/Sources/tart/VM.swift b/Sources/tart/VM.swift index 77ef457..c5cc89f 100644 --- a/Sources/tart/VM.swift +++ b/Sources/tart/VM.swift @@ -66,6 +66,7 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject { self.network = network configuration = try Self.craftConfiguration(diskURL: vmDir.diskURL, nvramURL: vmDir.nvramURL, vmConfig: config, + label: name, network: network, additionalStorageDevices: additionalStorageDevices, directorySharingDevices: directorySharingDevices, serialPorts: serialPorts, @@ -197,7 +198,7 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject { // Initialize the virtual machine and its configuration self.network = network configuration = try Self.craftConfiguration(diskURL: vmDir.diskURL, nvramURL: vmDir.nvramURL, - vmConfig: config, network: network, + vmConfig: config, label: name, network: network, additionalStorageDevices: additionalStorageDevices, directorySharingDevices: directorySharingDevices, serialPorts: serialPorts @@ -315,6 +316,7 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject { diskURL: URL, nvramURL: URL, vmConfig: VMConfig, + label: String? = nil, network: Network = NetworkShared(), additionalStorageDevices: [VZStorageDeviceConfiguration], directorySharingDevices: [VZDirectorySharingDeviceConfiguration], @@ -444,11 +446,26 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject { // Socket device configuration.socketDevices = [VZVirtioSocketDeviceConfiguration()] + #if compiler(>=6.4) + if #available(macOS 27, *), let label, let virtualMachineLabel = Self.virtualMachineLabel(for: label) { + configuration.label = virtualMachineLabel + } + #endif + try configuration.validate() return configuration } + static func virtualMachineLabel(for name: String) -> String? { + let trimmedName = name.trimmingCharacters(in: .whitespacesAndNewlines) + guard trimmedName.contains(where: { !$0.isWhitespace }) else { + return nil + } + + return String(trimmedName.prefix(64)) + } + func guestDidStop(_ virtualMachine: VZVirtualMachine) { print("guest has stopped the virtual machine") sema.signal() diff --git a/Tests/TartTests/VMTests.swift b/Tests/TartTests/VMTests.swift new file mode 100644 index 0000000..82407d2 --- /dev/null +++ b/Tests/TartTests/VMTests.swift @@ -0,0 +1,23 @@ +import XCTest +@testable import tart + +final class VMTests: XCTestCase { + func testVirtualMachineLabelUsesVMName() { + XCTAssertEqual(VM.virtualMachineLabel(for: "macos-runner"), "macos-runner") + } + + func testVirtualMachineLabelTrimsWhitespace() { + XCTAssertEqual(VM.virtualMachineLabel(for: " macos-runner "), "macos-runner") + } + + func testVirtualMachineLabelRejectsWhitespaceOnlyName() { + XCTAssertNil(VM.virtualMachineLabel(for: " ")) + } + + func testVirtualMachineLabelCapsAtSixtyFourCharacters() { + XCTAssertEqual( + VM.virtualMachineLabel(for: String(repeating: "a", count: 65)), + String(repeating: "a", count: 64) + ) + } +}