feat: Adds generate-config command.
This commit is contained in:
170
Sources/hpa/CreateCommand.swift
Normal file
170
Sources/hpa/CreateCommand.swift
Normal file
@@ -0,0 +1,170 @@
|
||||
import ArgumentParser
|
||||
import CliClient
|
||||
import Dependencies
|
||||
import Foundation
|
||||
import Logging
|
||||
|
||||
struct CreateCommand: AsyncParsableCommand {
|
||||
|
||||
static let commandName = "create"
|
||||
|
||||
static let configuration = CommandConfiguration.playbookCommandConfiguration(
|
||||
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(\.cliClient) var cliClient
|
||||
@Dependency(\.logger) var logger
|
||||
|
||||
let encoder = cliClient.encoder()
|
||||
|
||||
let configuration = try cliClient.loadConfiguration()
|
||||
|
||||
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)")
|
||||
|
||||
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.templateDir
|
||||
let templateRepo = command.repo ?? configuration.templateRepo
|
||||
let version = (command.branch ?? configuration.templateRepoVersion) ?? "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
|
||||
}
|
||||
Reference in New Issue
Block a user