187 lines
5.2 KiB
Swift
187 lines
5.2 KiB
Swift
import ArgumentParser
|
|
import CliClient
|
|
import ConfigurationClient
|
|
import Dependencies
|
|
import Foundation
|
|
import Logging
|
|
|
|
struct CreateCommand: AsyncParsableCommand {
|
|
|
|
static let commandName = "create"
|
|
|
|
static let configuration = CommandConfiguration.playbook(
|
|
commandName: commandName,
|
|
abstract: "Create a home performance assesment project.",
|
|
examples: (
|
|
label: "Create Assesment",
|
|
example: "\(commandName) /new/assement/path"
|
|
)
|
|
)
|
|
|
|
@OptionGroup var globals: GlobalOptions
|
|
|
|
@Option(
|
|
name: .shortAndLong,
|
|
help: "The template repository to use."
|
|
)
|
|
var repo: String?
|
|
|
|
@Option(
|
|
name: .shortAndLong,
|
|
help: "The repo branch or version to use."
|
|
)
|
|
var branch: String?
|
|
|
|
@Option(
|
|
name: .shortAndLong,
|
|
help: "Path to local template directory to use.",
|
|
completion: .directory
|
|
)
|
|
var templateDir: String?
|
|
|
|
@Flag(
|
|
name: .shortAndLong,
|
|
help: "Force using a local template directory."
|
|
)
|
|
var localTemplateDir = false
|
|
|
|
@Argument(
|
|
help: "Path to the project directory.",
|
|
completion: .directory
|
|
)
|
|
var projectDir: String
|
|
|
|
@Argument(
|
|
help: "Extra arguments passed to the playbook."
|
|
)
|
|
var extraArgs: [String] = []
|
|
|
|
mutating func run() async throws {
|
|
try await _run()
|
|
}
|
|
|
|
private func _run() async throws {
|
|
try await withSetupLogger(commandName: Self.commandName, globals: globals) {
|
|
@Dependency(\.coders) var coders
|
|
@Dependency(\.cliClient) var cliClient
|
|
@Dependency(\.configurationClient) var configurationClient
|
|
@Dependency(\.logger) var logger
|
|
|
|
let encoder = coders.jsonEncoder()
|
|
|
|
let configuration = try await configurationClient.findAndLoad()
|
|
|
|
logger.debug("Configuration: \(configuration)")
|
|
|
|
let jsonData = try parseOptions(
|
|
command: self,
|
|
configuration: configuration,
|
|
logger: logger,
|
|
encoder: encoder
|
|
)
|
|
|
|
guard let jsonString = String(data: jsonData, encoding: .utf8) else {
|
|
throw CreateError.encodingError
|
|
}
|
|
|
|
logger.debug("JSON string: \(jsonString)")
|
|
|
|
let arguments = [
|
|
"--tags", "setup-project",
|
|
"--extra-vars", "project_dir=\(self.projectDir)",
|
|
"--extra-vars", "'\(jsonString)'"
|
|
] + extraArgs
|
|
|
|
try await cliClient.runPlaybookCommand(
|
|
globals.playbookOptions(
|
|
arguments: arguments,
|
|
configuration: configuration
|
|
)
|
|
)
|
|
|
|
// try await runPlaybook(
|
|
// commandName: Self.commandName,
|
|
// globals: self.globals,
|
|
// configuration: configuration,
|
|
// extraArgs: extraArgs,
|
|
// "--tags", "setup-project",
|
|
// "--extra-vars", "project_dir=\(self.projectDir)",
|
|
// "--extra-vars", "'\(jsonString)'"
|
|
// )
|
|
}
|
|
}
|
|
}
|
|
|
|
private func parseOptions(
|
|
command: CreateCommand,
|
|
configuration: Configuration,
|
|
logger: Logger,
|
|
encoder: JSONEncoder
|
|
) throws -> Data {
|
|
let templateDir = command.templateDir ?? configuration.template.directory
|
|
let templateRepo = command.repo ?? configuration.template.url
|
|
let version = (command.branch ?? configuration.template.version) ?? "main"
|
|
|
|
logger.debug("""
|
|
(\(command.localTemplateDir), \(String(describing: templateDir)), \(String(describing: templateRepo)))
|
|
""")
|
|
|
|
switch (command.localTemplateDir, templateDir, templateRepo) {
|
|
case (true, .none, _):
|
|
// User supplied they wanted to use a local template directory, but we could not find
|
|
// the path set from command line or in configuration.
|
|
throw CreateError.templateDirNotFound
|
|
case let (false, _, .some(repo)):
|
|
// User did not supply they wanted to use a local template directory, and we found a repo url that was
|
|
// either set by the command line or found in the configuration.
|
|
logger.debug("Using repo.")
|
|
return try encoder.encode(TemplateRepo(repo: repo, version: version))
|
|
case let (true, .some(templateDir), _):
|
|
// User supplied they wanted to use a local template directory, and we found the template directory
|
|
// either set by the command line or in the configuration.
|
|
logger.debug("Using template directory.")
|
|
return try encoder.encode(TemplateDirJson(path: templateDir))
|
|
case let (false, .some(templateDir), _):
|
|
// User supplied they did not wanted to use a local template directory, and we found the template directory
|
|
// either set by the command line or in the configuration, and no repo was found / handled previously.
|
|
logger.debug("Using template directory.")
|
|
return try encoder.encode(TemplateDirJson(path: templateDir))
|
|
case (_, .none, .none):
|
|
// We could not find a repo or template directory.
|
|
throw CreateError.templateDirOrRepoNotSpecified
|
|
}
|
|
}
|
|
|
|
private struct TemplateDirJson: Encodable {
|
|
|
|
let template: Template
|
|
|
|
init(path: String) {
|
|
self.template = .init(path: path)
|
|
}
|
|
|
|
struct Template: Encodable {
|
|
let path: String
|
|
}
|
|
}
|
|
|
|
private struct TemplateRepo: Encodable {
|
|
|
|
let template: Template
|
|
|
|
init(repo: String, version: String?) {
|
|
self.template = .init(repo: repo, version: version ?? "main")
|
|
}
|
|
|
|
struct Template: Encodable {
|
|
let repo: String
|
|
let version: String
|
|
}
|
|
}
|
|
|
|
enum CreateError: Error {
|
|
case encodingError
|
|
case templateDirNotFound
|
|
case templateDirOrRepoNotSpecified
|
|
}
|