Files
2022-03-14 11:07:08 +03:00

200 lines
8.2 KiB
Swift
Executable File

#!/usr/bin/env swift
import Foundation
protocol TemplateResolverType {
static var defaultConfig: String { get }
static var developmentTeam: String { get }
static var codeSignIdentity: String { get }
static var swiftActiveCompilationConditions: String { get }
static var applicationIdentifier: String { get }
static var targetPrivadoName: String { get }
static var cfBundleDisplayName: String { get }
static var provisionProfileSpecifier: String { get }
static var provisionProfileSpecifierOVPN: String { get }
static var provisionProfileSpecifierWireGuard: String { get }
}
final class YamlGenerator {
enum SchemeType: RawRepresentable {
case develop
case production
case beta
init?(rawValue: String) {
switch rawValue.uppercased() {
case "DEV": self = .develop
case "PROD": self = .production
case "BETA": self = .beta
default: return nil
}
}
var rawValue: String {
switch self {
case .develop: return "DEV"
case .production: return "PROD"
case .beta: return "BETA"
}
}
}
private enum Constants {
enum Templates {
static let defaultConfig = "{{defaultConfig}}"
static let developmentTeam = "{{DEVELOPMENT_TEAM}}"
static let codeSignIdentity = "{{CODE_SIGN_IDENTITY}}"
static let swiftActiveCompilationConditions = "{{SWIFT_ACTIVE_COMPILATION_CONDITIONS}}"
static let applicationIdentifier = "{{APPLICATION_IDENTIFIER}}"
static let targetPrivadoName = "{{TARGET_PRIVADO_NAME}}"
static let cfBundleDisplayName = "{{CFBundleDisplayName}}"
static let provisionProfileSpecifier = "{{PROVISIONING_PROFILE_SPECIFIER}}"
static let provisionProfileSpecifierOVPN = "{{PROVISIONING_PROFILE_SPECIFIER_OVPN}}"
static let provisionProfileSpecifierWireGuard = "{{PROVISIONING_PROFILE_SPECIFIER_WIREGUARD}}"
// static let developmentTeam = ""
}
enum Develop: TemplateResolverType {
static let defaultConfig = "Debug"
static let developmentTeam = "4D7YV49724"
static let codeSignIdentity = "Apple Development: Yuriy Shikin (S9D2XZUZH2)"
static let swiftActiveCompilationConditions = "BETA"
static let applicationIdentifier = "io.privado.ios"
static let targetPrivadoName = "PrivadoVPN"
static let cfBundleDisplayName = "PrivadoVPN"
static let provisionProfileSpecifier = "Privado iOS"
static let provisionProfileSpecifierOVPN = "Privado iOS OpenVPN Extension"
static let provisionProfileSpecifierWireGuard = "Privado iOS Wireguard Extension"
// static let developmentTeam = ""
}
enum Production: TemplateResolverType {
static let defaultConfig = "Release"
static let developmentTeam = "4D7YV49724"
static let codeSignIdentity = "Apple Distribution: PRIVADO NETWORKS LLC (4D7YV49724)"
static let swiftActiveCompilationConditions = "PRODUCTION"
static let applicationIdentifier = "io.privado.ios"
static let targetPrivadoName = "PrivadoVPN"
static let cfBundleDisplayName = "PrivadoVPN"
static let provisionProfileSpecifier = "Privado iOS AppStore"
static let provisionProfileSpecifierOVPN = "Privado iOS OpenVPN Extension AppStore"
static let provisionProfileSpecifierWireGuard = "Privado iOS Wireguard Extension AppStore"
// static let developmentTeam = ""
}
enum Beta: TemplateResolverType {
static let defaultConfig = "Release"
static let developmentTeam = "4D7YV49724"
static let codeSignIdentity = "Apple Distribution: PRIVADO NETWORKS LLC (4D7YV49724)"
static let swiftActiveCompilationConditions = "BETA"
static let applicationIdentifier = "io.privado.beta.ios"
static let targetPrivadoName = "PrivadoVPN"
static let cfBundleDisplayName = "PrivadoVPN Beta"
static let provisionProfileSpecifier = "Privado Beta iOS AppStore"
static let provisionProfileSpecifierOVPN = "Privado Beta iOS OpenVPN Extension AppStore"
static let provisionProfileSpecifierWireGuard = "Privado Beta iOS Wireguard Extension AppStore"
// static let developmentTeam = ""
}
}
@discardableResult
static func backup(yaml path: String, data: Data? = nil) -> Data? {
if let data = data {
try! data.write(to: URL(string: "file://\(path)")!)
return data
} else {
return try! Data(contentsOf: URL(string: "file://\(path)")!)
}
}
static func prepare(yaml path: String, type: SchemeType) {
let data = try! Data(contentsOf: URL(string: "file://\(path)")!)
let content = String(decoding: data, as: UTF8.self)
let resolver: TemplateResolverType.Type
switch type {
case .develop: resolver = Constants.Develop.self
case .production: resolver = Constants.Production.self
case .beta: resolver = Constants.Beta.self
}
let resultContent = content
.replacingOccurrences(of: Constants.Templates.applicationIdentifier, with: resolver.applicationIdentifier)
.replacingOccurrences(of: Constants.Templates.cfBundleDisplayName, with: resolver.cfBundleDisplayName)
.replacingOccurrences(of: Constants.Templates.codeSignIdentity, with: resolver.codeSignIdentity)
.replacingOccurrences(of: Constants.Templates.defaultConfig, with: resolver.defaultConfig)
.replacingOccurrences(of: Constants.Templates.developmentTeam, with: resolver.developmentTeam)
.replacingOccurrences(of: Constants.Templates.provisionProfileSpecifier, with: resolver.provisionProfileSpecifier)
.replacingOccurrences(of: Constants.Templates.provisionProfileSpecifierOVPN, with: resolver.provisionProfileSpecifierOVPN)
.replacingOccurrences(of: Constants.Templates.provisionProfileSpecifierWireGuard, with: resolver.provisionProfileSpecifierWireGuard)
.replacingOccurrences(of: Constants.Templates.swiftActiveCompilationConditions, with: resolver.swiftActiveCompilationConditions)
.replacingOccurrences(of: Constants.Templates.targetPrivadoName, with: resolver.targetPrivadoName)
let resultData = resultContent.data(using: .utf8)!
try! resultData.write(to: URL(string: "file://\(path)")!)
}
// MARK: - Private
}
func showHelp() {
print("How to use:")
print("--path=[PATH TO YAML]")
print("--type=[DEV|BETA|PROD] default value is DEV")
}
guard let pathArguments = CommandLine.arguments.first(where: { $0.contains("path") })
, let path = pathArguments.split(separator: "=").last else {
showHelp()
exit(1)
}
guard let xcodegenPath = ["/usr/local/bin/xcodegen", "/opt/homebrew/bin/xcodegen"].first(where: { FileManager.default.fileExists(atPath: $0) }) else {
print("Error 🍄 Can't find xcodegen")
exit(1)
}
let type: YamlGenerator.SchemeType
if let typeArguments = CommandLine.arguments.first(where: { $0.contains("type") })
, let arg = typeArguments.split(separator: "=").last
, let scheme = YamlGenerator.SchemeType(rawValue: String(arg)) {
type = scheme
} else {
type = .develop
}
// Replace templates
let yamlPath = "\(FileManager.default.currentDirectoryPath)/\(String(path))"
let data = YamlGenerator.backup(yaml: yamlPath)
YamlGenerator.prepare(yaml: yamlPath, type: type)
print("Generate xcodeproj 🥃")
let projectDirectory = yamlPath
.split(separator: "/")
.dropLast(1)
.map(String.init)
.joined(separator: "/")
print("PATH: \(yamlPath)")
let xcodegenProcess = Process()
xcodegenProcess.executableURL = URL(fileURLWithPath: xcodegenPath)
xcodegenProcess.arguments = ["generate",
"--spec", "\(yamlPath)"]
do {
try xcodegenProcess.run()
xcodegenProcess.waitUntilExit()
} catch {
print(error)
}
YamlGenerator.backup(yaml: yamlPath, data: data)
exit(0)