Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Packages/MenuBar/Sources/MenuBar/MenuBarItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,14 @@ private extension MenuBarItem {
) { action in
switch action {
case .startFleet:
fleet.start(numberOfMachines: settingsStore.numberOfVirtualMachines)
fleet.start(
numberOfMachines: settingsStore.numberOfVirtualMachines,
arguments: settingsStore.virtualMachineArguments
)
case .stopFleet:
fleet.stop()
case .startEditor:
editor.start()
editor.start(arguments: settingsStore.virtualMachineArguments)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public final class AppStorageSettingsStore: SettingsStore {
static let virtualMachine = "virtualMachine"
static let numberOfVirtualMachines = "numberOfVirtualMachines"
static let startVirtualMachinesOnLaunch = "startVirtualMachinesOnLaunch"
static let virtualMachineArguments = "virtualMachineArguments"
static let gitHubPrivateKeyName = "gitHubPrivateKeyName"
static let gitHubRunnerDisableUpdates = "gitHubRunnerDisableUpdates"
static let gitHubRunnerLabels = "gitHubRunnerLabels"
Expand Down Expand Up @@ -83,6 +84,17 @@ public final class AppStorageSettingsStore: SettingsStore {
}
}
}
public var virtualMachineArguments: [String] {
get {
access(keyPath: \.virtualMachineArguments)
return userDefaults.stringArray(forKey: AppStorageKey.virtualMachineArguments) ?? []
}
set {
withMutation(keyPath: \.virtualMachineArguments) {
userDefaults.setValue(newValue, forKey: AppStorageKey.virtualMachineArguments)
}
}
}
public var gitHubPrivateKeyName: String? {
get {
access(keyPath: \.gitHubPrivateKeyName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public protocol SettingsStore: AnyObject {
var virtualMachine: VirtualMachine { get set }
var numberOfVirtualMachines: Int { get set }
var startVirtualMachinesOnLaunch: Bool { get set }
var virtualMachineArguments: [String] { get set }
var gitHubPrivateKeyName: String? { get set }
var gitHubRunnerDisableUpdates: Bool { get set }
var gitHubRunnerLabels: String { get set }
Expand Down
9 changes: 8 additions & 1 deletion Packages/Settings/Sources/SettingsUI/Internal/L10n.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ internal enum L10n {
}
}
internal enum GithubRunner {
/// Disable default labels
internal static let disableDefaultLabels = L10n.tr("Localizable", "settings.github_runner.disableDefaultLabels", fallback: "Disable default labels")
/// Disable runner auto-update
internal static let disableUpdates = L10n.tr("Localizable", "settings.github_runner.disableUpdates", fallback: "Disable runner auto-update")
/// Group
Expand All @@ -101,7 +103,6 @@ internal enum L10n {
/// acme
internal static let prompt = L10n.tr("Localizable", "settings.github_runner.group.prompt", fallback: "acme")
}
internal static let disableDefaultLabels = L10n.tr("Localizable", "settings.github_runner.disableDefaultLabels", fallback: "Disable default labels")
internal enum Labels {
/// Comma-separated list of labels.
internal static let footer = L10n.tr("Localizable", "settings.github_runner.labels.footer", fallback: "Comma-separated list of labels.")
Expand All @@ -122,6 +123,8 @@ internal enum L10n {
internal static let repository = L10n.tr("Localizable", "settings.runner_scope.repository", fallback: "Repository")
}
internal enum VirtualMachine {
/// Additional Arguments
internal static let additionalArguments = L10n.tr("Localizable", "settings.virtual_machine.additional_arguments", fallback: "Additional Arguments")
/// Number of Machines
internal static let count = L10n.tr("Localizable", "settings.virtual_machine.count", fallback: "Number of Machines")
/// Use the Tart CLI to create a virtual machine.
Expand All @@ -134,6 +137,10 @@ internal enum L10n {
internal static let tartHome = L10n.tr("Localizable", "settings.virtual_machine.tart_home", fallback: "Tart Home")
/// Unknown
internal static let unknown = L10n.tr("Localizable", "settings.virtual_machine.unknown", fallback: "Unknown")
internal enum AdditionalArguments {
/// Specify additional tart launch arguments.
internal static let prompt = L10n.tr("Localizable", "settings.virtual_machine.additional_arguments.prompt", fallback: "Specify additional tart launch arguments.")
}
internal enum Count {
/// One
internal static let one = L10n.tr("Localizable", "settings.virtual_machine.count.one", fallback: "One")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
"settings.virtual_machine.ssh.password" = "Password";
"settings.virtual_machine.ssh.footer" = "The credentials are used to SSH into the virtual machine to configure it to start the GitHub Actions runner. Make sure \"Remote Login\" is enabled in the virtual machine.";
"settings.virtual_machine.start_virtual_machines_on_app_launch" = "Start Virtual Machines on App Launch";
"settings.virtual_machine.additional_arguments" = "Additional Arguments";
"settings.virtual_machine.additional_arguments.prompt" = "Specify additional tart launch arguments.";

"settings.github" = "GitHub";
"settings.github.organization_name" = "Organization Name";
Expand All @@ -41,7 +43,7 @@
"settings.github.create_app" = "Create GitHub App";

"settings.github_runner" = "Runner";
"settings.github_runner.disableDefaultLabels" = "Disable default labels"
"settings.github_runner.disableDefaultLabels" = "Disable default labels";
"settings.github_runner.disableUpdates" = "Disable runner auto-update";
"settings.github_runner.disableUpdates.subtitle" = "This is meant to be used when a fixed version is pre-installed, otherwise Tartelet will install the latest version when the VM starts.";
"settings.github_runner.labels" = "Labels";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct VirtualMachineSettingsView<SettingsStoreType: SettingsStore & Observable>
@State private var isRefreshingVirtualMachines = false
@State private var sshUsername = ""
@State private var sshPassword = ""
@State private var additionalArguments = ""

var body: some View {
Form {
Expand All @@ -32,6 +33,12 @@ struct VirtualMachineSettingsView<SettingsStoreType: SettingsStore & Observable>
Toggle(isOn: $settingsStore.startVirtualMachinesOnLaunch) {
Text(L10n.Settings.VirtualMachine.startVirtualMachinesOnAppLaunch)
}
TextField(
L10n.Settings.VirtualMachine.additionalArguments,
text: $additionalArguments,
prompt: Text(L10n.Settings.VirtualMachine.AdditionalArguments.prompt)
)
.disabled(!isSettingsEnabled)
}
Section {
TextField(
Expand Down Expand Up @@ -71,6 +78,12 @@ struct VirtualMachineSettingsView<SettingsStoreType: SettingsStore & Observable>
await refreshVirtualMachines()
}
}
.onChange(of: settingsStore.virtualMachineArguments) { _, newValue in
additionalArguments = newValue.joined(separator: " ")
}
.onChange(of: additionalArguments) { _, newValue in
settingsStore.virtualMachineArguments = newValue.split(separator: " ").map(String.init)
}
.onChange(of: sshUsername) { _, newValue in
if !newValue.isEmpty {
credentialsStore.setUsername(newValue)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ public struct Tart {
try await executeCommand(withArguments: ["clone", sourceName, newName])
}

public func run(name: String) async throws {
public func run(name: String, additionalArguments: [String] = []) async throws {
let homeFolderURL = homeProvider.homeFolderURL ??
FileManager.default.homeDirectoryForCurrentUser.appending(component: ".tart")
let cacheFolder = homeFolderURL.appendingPathComponent("cache")
if !FileManager.default.fileExists(atPath: cacheFolder.path) {
try FileManager.default.createDirectory(atPath: cacheFolder.path, withIntermediateDirectories: true)
}
var runArgs = ["run", "--dir=cache:\(cacheFolder.path())"]
runArgs.append(contentsOf: additionalArguments)
if let tartRunOptions = ProcessInfo.processInfo.environment["TARTELET_RUN_OPTIONS"] {
runArgs.append(tartRunOptions)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public final class TartVirtualMachine: VirtualMachine {
self.vmName = vmName
}

public func start() async throws {
try await tart.run(name: vmName)
public func start(arguments: [String]) async throws {
try await tart.run(name: vmName, additionalArguments: arguments)
}

public func clone(named newName: String) async throws -> VirtualMachine {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ public final class SSHConnectingVirtualMachine<SSHClientType: SSHClient>: Virtua
self.sshClient = sshClient
}

public func start() async throws {
public func start(arguments: [String]) async throws {
try await withThrowingTaskGroup(of: StartVirtualMachineResult.self) { group in
group.addTask {
return try await self.startVirtualMachine()
return try await self.startVirtualMachine(arguments: arguments)
}
group.addTask {
return try await self.connect(to: self.virtualMachine)
Expand Down Expand Up @@ -108,9 +108,9 @@ public final class SSHConnectingVirtualMachine<SSHClientType: SSHClient>: Virtua
}

private extension SSHConnectingVirtualMachine {
private func startVirtualMachine() async throws -> StartVirtualMachineResult {
private func startVirtualMachine(arguments: [String]) async throws -> StartVirtualMachineResult {
do {
try await self.virtualMachine.start()
try await self.virtualMachine.start(arguments: arguments)
return .success(.virtualMachineTerminated)
} catch {
if error is CancellationError {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation
public protocol VirtualMachine {
var name: String { get }
var canStart: Bool { get }
func start() async throws
func start(arguments: [String]) async throws
func clone(named newName: String) async throws -> VirtualMachine
func delete() async throws
func getIPAddress() async throws -> String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public final class VirtualMachineEditor {
self.virtualMachine = virtualMachine
}

public func start() {
public func start(arguments: [String]) {
guard runTask == nil else {
return
}
Expand All @@ -29,7 +29,7 @@ public final class VirtualMachineEditor {
defer {
self.runTask = nil
}
try await virtualMachine.start()
try await virtualMachine.start(arguments: arguments)
} onCancel: {
self.stop()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public final class VirtualMachineFleet {
self.baseVirtualMachine = baseVirtualMachine
}

public func start(numberOfMachines: Int) {
public func start(numberOfMachines: Int, arguments: [String]) {
guard !isStarted else {
return
}
Expand All @@ -25,7 +25,7 @@ public final class VirtualMachineFleet {
isStarted = true
for index in 0 ..< numberOfMachines {
let name = baseVirtualMachine.name + "-\(index + 1)"
startSequentiallyRunningVirtualMachines(named: name)
startSequentiallyRunningVirtualMachines(named: name, arguments: arguments)
}
}

Expand All @@ -44,12 +44,12 @@ public final class VirtualMachineFleet {
}

private extension VirtualMachineFleet {
private func startSequentiallyRunningVirtualMachines(named name: String) {
private func startSequentiallyRunningVirtualMachines(named name: String, arguments: [String]) {
let task = Task {
while !Task.isCancelled {
do {
let virtualMachine = try await baseVirtualMachine.clone(named: name)
try await runVirtualMachine(virtualMachine)
try await runVirtualMachine(virtualMachine, arguments: arguments)
if isStopping {
activeTasks[name]?.cancel()
}
Expand All @@ -69,11 +69,11 @@ private extension VirtualMachineFleet {
activeTasks[name] = task
}

private func runVirtualMachine(_ virtualMachine: VirtualMachine) async throws {
private func runVirtualMachine(_ virtualMachine: VirtualMachine, arguments: [String]) async throws {
try await withTaskCancellationHandler {
logger.info("Start virtual machine named \(virtualMachine.name)")
do {
try await virtualMachine.start()
try await virtualMachine.start(arguments: arguments)
logger.info("Did stop virtual machine named \(virtualMachine.name)")
do {
try await virtualMachine.delete()
Expand Down
5 changes: 4 additions & 1 deletion Tartelet/Sources/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
beginObservingAppIconVisibility()
if Composers.settingsStore.startVirtualMachinesOnLaunch {
Composers.fleet.start(numberOfMachines: Composers.settingsStore.numberOfVirtualMachines)
Composers.fleet.start(
numberOfMachines: Composers.settingsStore.numberOfVirtualMachines,
arguments: Composers.settingsStore.virtualMachineArguments
)
}

// If Tartelet is launched as a login item, we can keep the window hidden
Expand Down
4 changes: 2 additions & 2 deletions Tartelet/Sources/SettingsVirtualMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ struct SettingsVirtualMachine<SettingsStoreType: SettingsStore>: VirtualMachineD
TartVirtualMachine(tart: tart, vmName: name)
}

func start() async throws {
try await virtualMachine.start()
func start(arguments: [String]) async throws {
try await virtualMachine.start(arguments: arguments)
}

func clone(named newName: String) async throws -> VirtualMachineDomain.VirtualMachine {
Expand Down