Cloud to lab (#2993)

This commit is contained in:
Pedro Piñera Buendía 2021-05-22 09:58:02 +02:00 committed by GitHub
parent 49761cbd7c
commit 6e58ef29d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
66 changed files with 458 additions and 455 deletions

View File

@ -153,7 +153,7 @@ let package = Package(
"TuistSigning", "TuistSigning",
"TuistDependencies", "TuistDependencies",
"TuistLinting", "TuistLinting",
"TuistCloud", "TuistLab",
"TuistDoc", "TuistDoc",
"GraphViz", "GraphViz",
"TuistMigration", "TuistMigration",
@ -178,7 +178,7 @@ let package = Package(
"TuistCacheTesting", "TuistCacheTesting",
"TuistGeneratorTesting", "TuistGeneratorTesting",
"TuistScaffoldTesting", "TuistScaffoldTesting",
"TuistCloudTesting", "TuistLabTesting",
"TuistAutomationTesting", "TuistAutomationTesting",
"TuistSigningTesting", "TuistSigningTesting",
"TuistDependenciesTesting", "TuistDependenciesTesting",
@ -202,7 +202,7 @@ let package = Package(
"ProjectAutomation", "ProjectAutomation",
rxBlockingDependency, rxBlockingDependency,
"TuistLoaderTesting", "TuistLoaderTesting",
"TuistCloudTesting", "TuistLabTesting",
"TuistGraphTesting", "TuistGraphTesting",
] ]
), ),
@ -370,7 +370,7 @@ let package = Package(
] ]
), ),
.target( .target(
name: "TuistCloud", name: "TuistLab",
dependencies: [ dependencies: [
"XcodeProj", "XcodeProj",
swiftToolsSupportDependency, swiftToolsSupportDependency,
@ -381,9 +381,9 @@ let package = Package(
] ]
), ),
.testTarget( .testTarget(
name: "TuistCloudTests", name: "TuistLabTests",
dependencies: [ dependencies: [
"TuistCloud", "TuistLab",
"TuistSupportTesting", "TuistSupportTesting",
"TuistCoreTesting", "TuistCoreTesting",
rxBlockingDependency, rxBlockingDependency,
@ -391,9 +391,9 @@ let package = Package(
] ]
), ),
.target( .target(
name: "TuistCloudTesting", name: "TuistLabTesting",
dependencies: [ dependencies: [
"TuistCloud", "TuistLab",
swiftToolsSupportDependency, swiftToolsSupportDependency,
"TuistCore", "TuistCore",
rxTestDependency, rxTestDependency,

View File

@ -1,34 +0,0 @@
import Foundation
/// Cloud represents the configuration to connect to the server.
public struct Cloud: Codable, Equatable {
enum CodingKeys: String, CodingKey {
case url
case projectId = "project_id"
case options
}
/// Cloud option.
public enum Option: String, Codable, Equatable {
case insights
}
/// The base URL that points to the cloud server
public let url: String
/// The project unique identifier.
public let projectId: String
/// Cloud options.
public let options: [Option]
/// Initializes a new Cloud configuration instance.
/// - Parameters:
/// - projectId: Project unique identifier.
/// - url: Base URL to the cloud server.
/// - options: Cloud options.
/// - Returns: A Cloud instance.
public static func cloud(projectId: String, url: String, options: [Option] = []) -> Cloud {
Cloud(url: url, projectId: projectId, options: options)
}
}

View File

@ -45,8 +45,8 @@ public struct Config: Codable, Equatable {
/// List of `Plugin`s used to extend Tuist. /// List of `Plugin`s used to extend Tuist.
public let plugins: [PluginLocation] public let plugins: [PluginLocation]
/// Cloud configuration. /// Lab configuration.
public let cloud: Cloud? public let lab: Lab?
/// Cache configuration. /// Cache configuration.
public let cache: Cache? public let cache: Cache?
@ -55,13 +55,13 @@ public struct Config: Codable, Equatable {
/// ///
/// - Parameters: /// - Parameters:
/// - compatibleXcodeVersions: List of Xcode versions the project is compatible with. /// - compatibleXcodeVersions: List of Xcode versions the project is compatible with.
/// - cloud: Cloud configuration. /// - lab: Lab configuration.
/// - cache: Cache configuration. /// - cache: Cache configuration.
/// - plugins: A list of plugins to extend Tuist. /// - plugins: A list of plugins to extend Tuist.
/// - generationOptions: List of options to use when generating the project. /// - generationOptions: List of options to use when generating the project.
public init( public init(
compatibleXcodeVersions: CompatibleXcodeVersions = .all, compatibleXcodeVersions: CompatibleXcodeVersions = .all,
cloud: Cloud? = nil, lab: Lab? = nil,
cache: Cache? = nil, cache: Cache? = nil,
plugins: [PluginLocation] = [], plugins: [PluginLocation] = [],
generationOptions: [GenerationOptions] generationOptions: [GenerationOptions]
@ -69,7 +69,7 @@ public struct Config: Codable, Equatable {
self.compatibleXcodeVersions = compatibleXcodeVersions self.compatibleXcodeVersions = compatibleXcodeVersions
self.plugins = plugins self.plugins = plugins
self.generationOptions = generationOptions self.generationOptions = generationOptions
self.cloud = cloud self.lab = lab
self.cache = cache self.cache = cache
dumpIfNeeded(self) dumpIfNeeded(self)
} }

View File

@ -0,0 +1,34 @@
import Foundation
/// Lab represents the configuration to connect to the server.
public struct Lab: Codable, Equatable {
enum CodingKeys: String, CodingKey {
case url
case projectId = "project_id"
case options
}
/// Lab option.
public enum Option: String, Codable, Equatable {
case insights
}
/// The base URL that points to the Lab server
public let url: String
/// The project unique identifier.
public let projectId: String
/// Lab options.
public let options: [Option]
/// Initializes a new Lab configuration instance.
/// - Parameters:
/// - projectId: Project unique identifier.
/// - url: Base URL to the Lab server.
/// - options: Lab options.
/// - Returns: A Lab instance.
public static func lab(projectId: String, url: String, options: [Option] = []) -> Lab {
Lab(url: url, projectId: projectId, options: options)
}
}

View File

@ -26,34 +26,34 @@ enum CacheRemoteStorageError: FatalError, Equatable {
public final class CacheRemoteStorage: CacheStoring { public final class CacheRemoteStorage: CacheStoring {
// MARK: - Attributes // MARK: - Attributes
private let cloudClient: CloudClienting private let labClient: LabClienting
private let fileClient: FileClienting private let fileClient: FileClienting
private let fileArchiverFactory: FileArchivingFactorying private let fileArchiverFactory: FileArchivingFactorying
private let cloudCacheResponseFactory: CloudCacheResourceFactorying private let labCacheResourceFactory: LabCacheResourceFactorying
private let cacheDirectoriesProvider: CacheDirectoriesProviding private let cacheDirectoriesProvider: CacheDirectoriesProviding
// MARK: - Init // MARK: - Init
public convenience init(cloudConfig: Cloud, cloudClient: CloudClienting, cacheDirectoriesProvider: CacheDirectoriesProviding) { public convenience init(labConfig: Lab, labClient: LabClienting, cacheDirectoriesProvider: CacheDirectoriesProviding) {
self.init( self.init(
cloudClient: cloudClient, labClient: labClient,
fileArchiverFactory: FileArchivingFactory(), fileArchiverFactory: FileArchivingFactory(),
fileClient: FileClient(), fileClient: FileClient(),
cloudCacheResponseFactory: CloudCacheResourceFactory(cloudConfig: cloudConfig), labCacheResourceFactory: LabCacheResourceFactory(labConfig: labConfig),
cacheDirectoriesProvider: cacheDirectoriesProvider cacheDirectoriesProvider: cacheDirectoriesProvider
) )
} }
init(cloudClient: CloudClienting, init(labClient: LabClienting,
fileArchiverFactory: FileArchivingFactorying, fileArchiverFactory: FileArchivingFactorying,
fileClient: FileClienting, fileClient: FileClienting,
cloudCacheResponseFactory: CloudCacheResourceFactorying, labCacheResourceFactory: LabCacheResourceFactorying,
cacheDirectoriesProvider: CacheDirectoriesProviding) cacheDirectoriesProvider: CacheDirectoriesProviding)
{ {
self.cloudClient = cloudClient self.labClient = labClient
self.fileArchiverFactory = fileArchiverFactory self.fileArchiverFactory = fileArchiverFactory
self.fileClient = fileClient self.fileClient = fileClient
self.cloudCacheResponseFactory = cloudCacheResponseFactory self.labCacheResourceFactory = labCacheResourceFactory
self.cacheDirectoriesProvider = cacheDirectoriesProvider self.cacheDirectoriesProvider = cacheDirectoriesProvider
} }
@ -62,8 +62,8 @@ public final class CacheRemoteStorage: CacheStoring {
public func exists(hash: String) -> Single<Bool> { public func exists(hash: String) -> Single<Bool> {
do { do {
let successRange = 200 ..< 300 let successRange = 200 ..< 300
let resource = try cloudCacheResponseFactory.existsResource(hash: hash) let resource = try labCacheResourceFactory.existsResource(hash: hash)
return cloudClient.request(resource) return labClient.request(resource)
.flatMap { _, response in .flatMap { _, response in
.just(successRange.contains(response.statusCode)) .just(successRange.contains(response.statusCode))
} }
@ -81,8 +81,8 @@ public final class CacheRemoteStorage: CacheStoring {
public func fetch(hash: String) -> Single<AbsolutePath> { public func fetch(hash: String) -> Single<AbsolutePath> {
do { do {
let resource = try cloudCacheResponseFactory.fetchResource(hash: hash) let resource = try labCacheResourceFactory.fetchResource(hash: hash)
return cloudClient return labClient
.request(resource) .request(resource)
.map(\.object.data.url) .map(\.object.data.url)
.flatMap { (url: URL) in .flatMap { (url: URL) in
@ -107,12 +107,12 @@ public final class CacheRemoteStorage: CacheStoring {
let archiver = try fileArchiverFactory.makeFileArchiver(for: paths) let archiver = try fileArchiverFactory.makeFileArchiver(for: paths)
let destinationZipPath = try archiver.zip(name: hash) let destinationZipPath = try archiver.zip(name: hash)
let md5 = try FileHandler.shared.urlSafeBase64MD5(path: destinationZipPath) let md5 = try FileHandler.shared.urlSafeBase64MD5(path: destinationZipPath)
let storeResource = try cloudCacheResponseFactory.storeResource( let storeResource = try labCacheResourceFactory.storeResource(
hash: hash, hash: hash,
contentMD5: md5 contentMD5: md5
) )
return cloudClient return labClient
.request(storeResource) .request(storeResource)
.map { (responseTuple) -> URL in responseTuple.object.data.url } .map { (responseTuple) -> URL in responseTuple.object.data.url }
.flatMapCompletable { (url: URL) in .flatMapCompletable { (url: URL) in
@ -134,12 +134,12 @@ public final class CacheRemoteStorage: CacheStoring {
private func verify(hash: String, contentMD5: String) -> Completable { private func verify(hash: String, contentMD5: String) -> Completable {
do { do {
let verifyUploadResource = try cloudCacheResponseFactory.verifyUploadResource( let verifyUploadResource = try labCacheResourceFactory.verifyUploadResource(
hash: hash, hash: hash,
contentMD5: contentMD5 contentMD5: contentMD5
) )
return cloudClient return labClient
.request(verifyUploadResource).asCompletable() .request(verifyUploadResource).asCompletable()
} catch { } catch {
return Completable.error(error) return Completable.error(error)

View File

@ -3,62 +3,60 @@ import TuistCore
import TuistGraph import TuistGraph
import TuistSupport import TuistSupport
typealias CloudExistsResource = HTTPResource<CloudResponse<CloudHEADResponse>, CloudHEADResponseError> typealias LabExistsResource = HTTPResource<LabResponse<LabHEADResponse>, LabHEADResponseError>
typealias LabCacheResource = HTTPResource<LabResponse<LabCacheResponse>, LabResponseError>
typealias CloudCacheResource = HTTPResource<CloudResponse<CloudCacheResponse>, CloudResponseError> typealias LabVerifyUploadResource = HTTPResource<LabResponse<LabVerifyUploadResponse>, LabResponseError>
typealias CloudVerifyUploadResource = HTTPResource<CloudResponse<CloudVerifyUploadResponse>, CloudResponseError>
/// Entity responsible for providing cache-related resources /// Entity responsible for providing cache-related resources
protocol CloudCacheResourceFactorying { protocol LabCacheResourceFactorying {
func existsResource(hash: String) throws -> CloudExistsResource func existsResource(hash: String) throws -> LabExistsResource
func fetchResource(hash: String) throws -> CloudCacheResource func fetchResource(hash: String) throws -> LabCacheResource
func storeResource(hash: String, contentMD5: String) throws -> CloudCacheResource func storeResource(hash: String, contentMD5: String) throws -> LabCacheResource
func verifyUploadResource(hash: String, contentMD5: String) throws -> CloudVerifyUploadResource func verifyUploadResource(hash: String, contentMD5: String) throws -> LabVerifyUploadResource
} }
class CloudCacheResourceFactory: CloudCacheResourceFactorying { class LabCacheResourceFactory: LabCacheResourceFactorying {
private let cloudConfig: Cloud private let labConfig: Lab
init(cloudConfig: Cloud) { init(labConfig: Lab) {
self.cloudConfig = cloudConfig self.labConfig = labConfig
} }
func existsResource(hash: String) throws -> CloudExistsResource { func existsResource(hash: String) throws -> LabExistsResource {
let url = try apiCacheURL(hash: hash, cacheURL: cloudConfig.url, projectId: cloudConfig.projectId) let url = try apiCacheURL(hash: hash, cacheURL: labConfig.url, projectId: labConfig.projectId)
var request = URLRequest(url: url) var request = URLRequest(url: url)
request.httpMethod = "HEAD" request.httpMethod = "HEAD"
return HTTPResource( return HTTPResource(
request: { request }, request: { request },
parse: { _, _ in CloudResponse(status: "HEAD", data: CloudHEADResponse()) }, parse: { _, _ in LabResponse(status: "HEAD", data: LabHEADResponse()) },
parseError: { _, _ in CloudHEADResponseError() } parseError: { _, _ in LabHEADResponseError() }
) )
} }
func fetchResource(hash: String) throws -> CloudCacheResource { func fetchResource(hash: String) throws -> LabCacheResource {
let url = try apiCacheURL( let url = try apiCacheURL(
hash: hash, hash: hash,
cacheURL: cloudConfig.url, cacheURL: labConfig.url,
projectId: cloudConfig.projectId projectId: labConfig.projectId
) )
return HTTPResource.jsonResource(for: url, httpMethod: "GET") return HTTPResource.jsonResource(for: url, httpMethod: "GET")
} }
func storeResource(hash: String, contentMD5: String) throws -> CloudCacheResource { func storeResource(hash: String, contentMD5: String) throws -> LabCacheResource {
let url = try apiCacheURL( let url = try apiCacheURL(
hash: hash, hash: hash,
cacheURL: cloudConfig.url, cacheURL: labConfig.url,
projectId: cloudConfig.projectId, projectId: labConfig.projectId,
contentMD5: contentMD5 contentMD5: contentMD5
) )
return HTTPResource.jsonResource(for: url, httpMethod: "POST") return HTTPResource.jsonResource(for: url, httpMethod: "POST")
} }
func verifyUploadResource(hash: String, contentMD5: String) throws -> CloudVerifyUploadResource { func verifyUploadResource(hash: String, contentMD5: String) throws -> LabVerifyUploadResource {
let url = try apiCacheVerifyUploadURL( let url = try apiCacheVerifyUploadURL(
hash: hash, hash: hash,
cacheURL: cloudConfig.url, cacheURL: labConfig.url,
projectId: cloudConfig.projectId, projectId: labConfig.projectId,
contentMD5: contentMD5 contentMD5: contentMD5
) )
return HTTPResource.jsonResource(for: url, httpMethod: "POST") return HTTPResource.jsonResource(for: url, httpMethod: "POST")

View File

@ -1 +0,0 @@
struct CloudHEADResponse: Decodable {}

View File

@ -1,3 +0,0 @@
struct CloudVerifyUploadResponse: Decodable {
let uploadedSize: Int
}

View File

@ -1,6 +1,6 @@
import Foundation import Foundation
struct CloudCacheResponse: Decodable { struct LabCacheResponse: Decodable {
let url: URL let url: URL
let expiresAt: TimeInterval let expiresAt: TimeInterval

View File

@ -0,0 +1,3 @@
import Foundation
struct LabHEADResponse: Decodable {}

View File

@ -0,0 +1,5 @@
import Foundation
struct LabVerifyUploadResponse: Decodable {
let uploadedSize: Int
}

View File

@ -1,13 +1,13 @@
import Foundation import Foundation
import TuistCloud
import TuistCore import TuistCore
import TuistGraph import TuistGraph
import TuistLab
import TuistSupport import TuistSupport
import TuistSupportTesting import TuistSupportTesting
@testable import TuistCache @testable import TuistCache
@testable import TuistCoreTesting @testable import TuistCoreTesting
public class MockCloudCacheResourceFactory: CloudCacheResourceFactorying { public class MockLabCacheResourceFactory: LabCacheResourceFactorying {
public init() {} public init() {}
public var invokedExistsResource = false public var invokedExistsResource = false
@ -15,13 +15,13 @@ public class MockCloudCacheResourceFactory: CloudCacheResourceFactorying {
public var invokedExistsResourceParameters: (hash: String, Void)? public var invokedExistsResourceParameters: (hash: String, Void)?
public var invokedExistsResourceParametersList = [(hash: String, Void)]() public var invokedExistsResourceParametersList = [(hash: String, Void)]()
public var stubbedExistsResourceError: Error? public var stubbedExistsResourceError: Error?
public var stubbedExistsResourceResult: CloudExistsResource = HTTPResource( public var stubbedExistsResourceResult: LabExistsResource = HTTPResource(
request: { URLRequest.test() }, request: { URLRequest.test() },
parse: { _, _ in CloudResponse(status: "HEAD", data: CloudHEADResponse()) }, parse: { _, _ in LabResponse(status: "HEAD", data: LabHEADResponse()) },
parseError: { _, _ in CloudHEADResponseError() } parseError: { _, _ in LabHEADResponseError() }
) )
public func existsResource(hash: String) throws -> HTTPResource<CloudResponse<CloudHEADResponse>, CloudHEADResponseError> { public func existsResource(hash: String) throws -> HTTPResource<LabResponse<LabHEADResponse>, LabHEADResponseError> {
invokedExistsResource = true invokedExistsResource = true
invokedExistsResourceCount += 1 invokedExistsResourceCount += 1
invokedExistsResourceParameters = (hash, ()) invokedExistsResourceParameters = (hash, ())
@ -37,13 +37,13 @@ public class MockCloudCacheResourceFactory: CloudCacheResourceFactorying {
public var invokedFetchResourceParameters: (hash: String, Void)? public var invokedFetchResourceParameters: (hash: String, Void)?
public var invokedFetchResourceParametersList = [(hash: String, Void)]() public var invokedFetchResourceParametersList = [(hash: String, Void)]()
public var stubbedFetchResourceError: Error? public var stubbedFetchResourceError: Error?
public var stubbedFetchResourceResult: CloudCacheResource = HTTPResource( public var stubbedFetchResourceResult: LabCacheResource = HTTPResource(
request: { URLRequest.test() }, request: { URLRequest.test() },
parse: { _, _ in CloudResponse.test(data: CloudCacheResponse.test()) }, parse: { _, _ in LabResponse.test(data: LabCacheResponse.test()) },
parseError: { _, _ in CloudResponseError.test() } parseError: { _, _ in LabResponseError.test() }
) )
public func fetchResource(hash: String) throws -> CloudCacheResource { public func fetchResource(hash: String) throws -> LabCacheResource {
invokedFetchResource = true invokedFetchResource = true
invokedFetchResourceCount += 1 invokedFetchResourceCount += 1
invokedFetchResourceParameters = (hash, ()) invokedFetchResourceParameters = (hash, ())
@ -59,13 +59,13 @@ public class MockCloudCacheResourceFactory: CloudCacheResourceFactorying {
public var invokedStoreResourceParameters: (hash: String, contentMD5: String)? public var invokedStoreResourceParameters: (hash: String, contentMD5: String)?
public var invokedStoreResourceParametersList = [(hash: String, contentMD5: String)]() public var invokedStoreResourceParametersList = [(hash: String, contentMD5: String)]()
public var stubbedStoreResourceError: Error? public var stubbedStoreResourceError: Error?
public var stubbedStoreResourceResult: CloudCacheResource = HTTPResource( public var stubbedStoreResourceResult: LabCacheResource = HTTPResource(
request: { URLRequest.test() }, request: { URLRequest.test() },
parse: { _, _ in CloudResponse.test(data: CloudCacheResponse.test()) }, parse: { _, _ in LabResponse.test(data: LabCacheResponse.test()) },
parseError: { _, _ in CloudResponseError.test() } parseError: { _, _ in LabResponseError.test() }
) )
public func storeResource(hash: String, contentMD5: String) throws -> CloudCacheResource { public func storeResource(hash: String, contentMD5: String) throws -> LabCacheResource {
invokedStoreResource = true invokedStoreResource = true
invokedStoreResourceCount += 1 invokedStoreResourceCount += 1
invokedStoreResourceParameters = (hash, contentMD5) invokedStoreResourceParameters = (hash, contentMD5)
@ -81,13 +81,13 @@ public class MockCloudCacheResourceFactory: CloudCacheResourceFactorying {
public var invokedVerifyUploadResourceParameters: (hash: String, contentMD5: String)? public var invokedVerifyUploadResourceParameters: (hash: String, contentMD5: String)?
public var invokedVerifyUploadResourceParametersList = [(hash: String, contentMD5: String)]() // swiftlint:disable:this identifier_name public var invokedVerifyUploadResourceParametersList = [(hash: String, contentMD5: String)]() // swiftlint:disable:this identifier_name
public var stubbedVerifyUploadResourceError: Error? public var stubbedVerifyUploadResourceError: Error?
public var stubbedVerifyUploadResourceResult: CloudVerifyUploadResource = HTTPResource( public var stubbedVerifyUploadResourceResult: LabVerifyUploadResource = HTTPResource(
request: { URLRequest.test() }, request: { URLRequest.test() },
parse: { _, _ in CloudResponse.test(data: CloudVerifyUploadResponse.test()) }, parse: { _, _ in LabResponse.test(data: LabVerifyUploadResponse.test()) },
parseError: { _, _ in CloudResponseError.test() } parseError: { _, _ in LabResponseError.test() }
) )
public func verifyUploadResource(hash: String, contentMD5: String) throws -> CloudVerifyUploadResource { public func verifyUploadResource(hash: String, contentMD5: String) throws -> LabVerifyUploadResource {
invokedVerifyUploadResource = true invokedVerifyUploadResource = true
invokedVerifyUploadResourceCount += 1 invokedVerifyUploadResourceCount += 1
invokedVerifyUploadResourceParameters = (hash, contentMD5) invokedVerifyUploadResourceParameters = (hash, contentMD5)

View File

@ -1,7 +0,0 @@
@testable import TuistCache
extension CloudVerifyUploadResponse {
public static func test(uploadedSize: Int = 0) -> CloudVerifyUploadResponse {
CloudVerifyUploadResponse(uploadedSize: uploadedSize)
}
}

View File

@ -1,9 +1,9 @@
import Foundation import Foundation
@testable import TuistCache @testable import TuistCache
extension CloudCacheResponse { extension LabCacheResponse {
public static func test(url: URL = URL.test(), expiresAt: TimeInterval = 0) -> CloudCacheResponse { public static func test(url: URL = URL.test(), expiresAt: TimeInterval = 0) -> LabCacheResponse {
CloudCacheResponse( LabCacheResponse(
url: url, url: url,
expiresAt: expiresAt expiresAt: expiresAt
) )

View File

@ -0,0 +1,7 @@
@testable import TuistCache
extension LabVerifyUploadResponse {
public static func test(uploadedSize: Int = 0) -> LabVerifyUploadResponse {
LabVerifyUploadResponse(uploadedSize: uploadedSize)
}
}

View File

@ -1,2 +0,0 @@
import TuistSupport
let logger = Logger(label: "io.tuist.cloud")

View File

@ -2,6 +2,6 @@ import Foundation
import RxSwift import RxSwift
import TuistSupport import TuistSupport
public protocol CloudClienting { public protocol LabClienting {
func request<T, E>(_ resource: HTTPResource<T, E>) -> Single<(object: T, response: HTTPURLResponse)> func request<T, E>(_ resource: HTTPResource<T, E>) -> Single<(object: T, response: HTTPURLResponse)>
} }

View File

@ -1,6 +1,6 @@
import Foundation import Foundation
public struct CloudResponse<T: Decodable>: Decodable { public struct LabResponse<T: Decodable>: Decodable {
public let status: String public let status: String
public let data: T public let data: T

View File

@ -1,7 +1,7 @@
import Foundation import Foundation
import TuistSupport import TuistSupport
public struct CloudResponseError: Decodable, LocalizedError, Equatable { public struct LabResponseError: Decodable, LocalizedError, Equatable {
public var status: String public var status: String
public var errors: [Error]? public var errors: [Error]?
@ -15,6 +15,6 @@ public struct CloudResponseError: Decodable, LocalizedError, Equatable {
} }
} }
public struct CloudHEADResponseError: Decodable, LocalizedError, Equatable { public struct LabHEADResponseError: Decodable, LocalizedError, Equatable {
public init() {} public init() {}
} }

View File

@ -1,8 +0,0 @@
import Foundation
@testable import TuistCore
extension CloudResponse {
static func test(status: String = "status", data: T) -> CloudResponse<T> {
CloudResponse(status: status, data: data)
}
}

View File

@ -0,0 +1,8 @@
import Foundation
@testable import TuistCore
extension LabResponse {
static func test(status: String = "status", data: T) -> LabResponse<T> {
LabResponse(status: status, data: data)
}
}

View File

@ -1,14 +1,14 @@
import Foundation import Foundation
@testable import TuistCore @testable import TuistCore
public extension CloudResponseError.Error { public extension LabResponseError.Error {
static func test(code: String = "Code", message: String = "Message") -> CloudResponseError.Error { static func test(code: String = "Code", message: String = "Message") -> LabResponseError.Error {
.init(code: code, message: message) .init(code: code, message: message)
} }
} }
public extension CloudResponseError { public extension LabResponseError {
static func test(status: String = "Error status", errors: [Error]? = [.test()]) -> CloudResponseError { static func test(status: String = "Error status", errors: [Error]? = [.test()]) -> LabResponseError {
.init(status: status, errors: errors) .init(status: status, errors: errors)
} }
} }

View File

@ -4,11 +4,11 @@ import TuistSupport
@testable import TuistCore @testable import TuistCore
public enum MockCloudClientingError: Error { public enum MockLabClientingError: Error {
case mockedError case mockedError
} }
public final class MockCloudClient: CloudClienting { public final class MockLabClient: LabClienting {
// MARK: Factories // MARK: Factories
public var invokedRequest = false public var invokedRequest = false

View File

@ -18,7 +18,7 @@ public enum BinaryLinking: String, Codable {
public extension Sequence where Element == BinaryArchitecture { public extension Sequence where Element == BinaryArchitecture {
/// Returns true if all the architectures are only for simulator. /// Returns true if all the architectures are only for simulator.
var onlySimulator: Bool { var onlySimulator: Bool {
let simulatorArchitectures: [BinaryArchitecture] = [.x8664, .i386] let simulatorArchitectures: [BinaryArchitecture] = [.x8664, .i386, .arm64]
return allSatisfy { simulatorArchitectures.contains($0) } return allSatisfy { simulatorArchitectures.contains($0) }
} }
} }

View File

@ -29,8 +29,8 @@ public struct Config: Equatable, Hashable {
/// List of Xcode versions the project or set of projects is compatible with. /// List of Xcode versions the project or set of projects is compatible with.
public let compatibleXcodeVersions: CompatibleXcodeVersions public let compatibleXcodeVersions: CompatibleXcodeVersions
/// Cloud configuration. /// Lab configuration.
public let cloud: Cloud? public let lab: Lab?
/// Cache configuration. /// Cache configuration.
public let cache: Cache? public let cache: Cache?
@ -40,26 +40,26 @@ public struct Config: Equatable, Hashable {
/// Returns the default Tuist configuration. /// Returns the default Tuist configuration.
public static var `default`: Config { public static var `default`: Config {
Config(compatibleXcodeVersions: .all, cloud: nil, cache: nil, plugins: [], generationOptions: [], path: nil) Config(compatibleXcodeVersions: .all, lab: nil, cache: nil, plugins: [], generationOptions: [], path: nil)
} }
/// Initializes the tuist cofiguration. /// Initializes the tuist cofiguration.
/// ///
/// - Parameters: /// - Parameters:
/// - compatibleXcodeVersions: List of Xcode versions the project or set of projects is compatible with. /// - compatibleXcodeVersions: List of Xcode versions the project or set of projects is compatible with.
/// - cloud: Cloud configuration. /// - lab: Lab configuration.
/// - plugins: List of locations to a `Plugin` manifest. /// - plugins: List of locations to a `Plugin` manifest.
/// - generationOptions: Generation options. /// - generationOptions: Generation options.
/// - path: The path of the config file. /// - path: The path of the config file.
public init(compatibleXcodeVersions: CompatibleXcodeVersions, public init(compatibleXcodeVersions: CompatibleXcodeVersions,
cloud: Cloud?, lab: Lab?,
cache: Cache?, cache: Cache?,
plugins: [PluginLocation], plugins: [PluginLocation],
generationOptions: [GenerationOption], generationOptions: [GenerationOption],
path: AbsolutePath?) path: AbsolutePath?)
{ {
self.compatibleXcodeVersions = compatibleXcodeVersions self.compatibleXcodeVersions = compatibleXcodeVersions
self.cloud = cloud self.lab = lab
self.cache = cache self.cache = cache
self.plugins = plugins self.plugins = plugins
self.generationOptions = generationOptions self.generationOptions = generationOptions
@ -70,7 +70,7 @@ public struct Config: Equatable, Hashable {
public func hash(into hasher: inout Hasher) { public func hash(into hasher: inout Hasher) {
hasher.combine(generationOptions) hasher.combine(generationOptions)
hasher.combine(cloud) hasher.combine(lab)
hasher.combine(cache) hasher.combine(cache)
hasher.combine(compatibleXcodeVersions) hasher.combine(compatibleXcodeVersions)
} }

View File

@ -1,26 +1,26 @@
import Foundation import Foundation
/// Cloud represents the configuration to connect to the server. /// Lab represents the configuration to connect to the server.
public struct Cloud: Equatable, Hashable { public struct Lab: Equatable, Hashable {
/// Cloud option. /// Lab option.
public enum Option: String, Codable, Equatable { public enum Option: String, Codable, Equatable {
case insights case insights
} }
/// The base URL that points to the cloud server /// The base URL that points to the lab server
public let url: URL public let url: URL
/// The project unique identifier. /// The project unique identifier.
public let projectId: String public let projectId: String
/// Cloud options. /// Lab options.
public let options: [Option] public let options: [Option]
/// Initializes an instance of Cloud. /// Initializes an instance of Lab.
/// - Parameters: /// - Parameters:
/// - url: Cloud server base URL. /// - url: Lab server base URL.
/// - projectId: Project unique identifier. /// - projectId: Project unique identifier.
/// - options: Cloud options. /// - options: Lab options.
public init(url: URL, projectId: String, options: [Option]) { public init(url: URL, projectId: String, options: [Option]) {
self.url = url self.url = url
self.projectId = projectId self.projectId = projectId

View File

@ -4,7 +4,7 @@ import TSCBasic
public extension Config { public extension Config {
static func test(compatibleXcodeVersions: CompatibleXcodeVersions = .all, static func test(compatibleXcodeVersions: CompatibleXcodeVersions = .all,
cloud: Cloud? = Cloud.test(), lab: Lab? = Lab.test(),
cache: Cache? = Cache.test(), cache: Cache? = Cache.test(),
plugins: [PluginLocation] = [], plugins: [PluginLocation] = [],
generationOptions: [GenerationOption] = [], generationOptions: [GenerationOption] = [],
@ -12,7 +12,7 @@ public extension Config {
{ {
Config( Config(
compatibleXcodeVersions: compatibleXcodeVersions, compatibleXcodeVersions: compatibleXcodeVersions,
cloud: cloud, lab: lab,
cache: cache, cache: cache,
plugins: plugins, plugins: plugins,
generationOptions: generationOptions, generationOptions: generationOptions,

View File

@ -3,11 +3,11 @@ import TSCBasic
import TuistSupportTesting import TuistSupportTesting
@testable import TuistGraph @testable import TuistGraph
public extension Cloud { public extension Lab {
static func test(url: URL = URL.test(), static func test(url: URL = URL.test(),
projectId: String = "123", projectId: String = "123",
options: [Cloud.Option] = []) -> Cloud options: [Lab.Option] = []) -> Lab
{ {
Cloud(url: url, projectId: projectId, options: options) Lab(url: url, projectId: projectId, options: options)
} }
} }

View File

@ -4,10 +4,10 @@ import RxSwift
import TSCBasic import TSCBasic
import TuistAutomation import TuistAutomation
import TuistCache import TuistCache
import TuistCloud
import TuistCore import TuistCore
import TuistGenerator import TuistGenerator
import TuistGraph import TuistGraph
import TuistLab
import TuistLoader import TuistLoader
import TuistSupport import TuistSupport

View File

@ -1,8 +1,8 @@
import Foundation import Foundation
import TuistCache import TuistCache
import TuistCloud
import TuistCore import TuistCore
import TuistGraph import TuistGraph
import TuistLab
import TuistLoader import TuistLoader
final class CacheStorageProvider: CacheStorageProviding { final class CacheStorageProvider: CacheStorageProviding {
@ -17,8 +17,12 @@ final class CacheStorageProvider: CacheStorageProviding {
func storages() throws -> [CacheStoring] { func storages() throws -> [CacheStoring] {
let cacheDirectoriesProvider = try cacheDirectoryProviderFactory.cacheDirectories(config: config) let cacheDirectoriesProvider = try cacheDirectoryProviderFactory.cacheDirectories(config: config)
var storages: [CacheStoring] = [CacheLocalStorage(cacheDirectoriesProvider: cacheDirectoriesProvider)] var storages: [CacheStoring] = [CacheLocalStorage(cacheDirectoriesProvider: cacheDirectoriesProvider)]
if let cloudConfig = config.cloud { if let labConfig = config.lab {
let storage = CacheRemoteStorage(cloudConfig: cloudConfig, cloudClient: CloudClient(), cacheDirectoriesProvider: cacheDirectoriesProvider) let storage = CacheRemoteStorage(
labConfig: labConfig,
labClient: LabClient(),
cacheDirectoriesProvider: cacheDirectoriesProvider
)
storages.append(storage) storages.append(storage)
} }
return storages return storages

View File

@ -1,17 +0,0 @@
import ArgumentParser
import Foundation
import TSCBasic
struct CloudCommand: ParsableCommand {
static var configuration: CommandConfiguration {
CommandConfiguration(
commandName: "cloud",
abstract: "A set of commands for cloud features.",
subcommands: [
CloudAuthCommand.self,
CloudSessionCommand.self,
CloudLogoutCommand.self,
]
)
}
}

View File

@ -2,16 +2,16 @@ import ArgumentParser
import Foundation import Foundation
import TSCBasic import TSCBasic
struct CloudAuthCommand: ParsableCommand { struct LabAuthCommand: ParsableCommand {
static var configuration: CommandConfiguration { static var configuration: CommandConfiguration {
CommandConfiguration( CommandConfiguration(
commandName: "auth", commandName: "auth",
_superCommandName: "cloud", _superCommandName: "lab",
abstract: "Authenticates the user on the server with the URL defined in the Config.swift file" abstract: "Authenticates the user on the server with the URL defined in the Config.swift file"
) )
} }
func run() throws { func run() throws {
try CloudAuthService().authenticate() try LabAuthService().authenticate()
} }
} }

View File

@ -2,16 +2,16 @@ import ArgumentParser
import Foundation import Foundation
import TSCBasic import TSCBasic
struct CloudLogoutCommand: ParsableCommand { struct LabLogoutCommand: ParsableCommand {
static var configuration: CommandConfiguration { static var configuration: CommandConfiguration {
CommandConfiguration( CommandConfiguration(
commandName: "logout", commandName: "logout",
_superCommandName: "cloud", _superCommandName: "lab",
abstract: "Removes any existing session to authenticate on the server with the URL defined in the Config.swift file" abstract: "Removes any existing session to authenticate on the server with the URL defined in the Config.swift file"
) )
} }
func run() throws { func run() throws {
try CloudLogoutService().logout() try LabLogoutService().logout()
} }
} }

View File

@ -2,16 +2,16 @@ import ArgumentParser
import Foundation import Foundation
import TSCBasic import TSCBasic
struct CloudSessionCommand: ParsableCommand { struct LabSessionCommand: ParsableCommand {
static var configuration: CommandConfiguration { static var configuration: CommandConfiguration {
CommandConfiguration( CommandConfiguration(
commandName: "session", commandName: "session",
_superCommandName: "cloud", _superCommandName: "lab",
abstract: "Prints any existing session to authenticate on the server with the URL defined in the Config.swift file" abstract: "Prints any existing session to authenticate on the server with the URL defined in the Config.swift file"
) )
} }
func run() throws { func run() throws {
try CloudSessionService().printSession() try LabSessionService().printSession()
} }
} }

View File

@ -0,0 +1,17 @@
import ArgumentParser
import Foundation
import TSCBasic
struct LabCommand: ParsableCommand {
static var configuration: CommandConfiguration {
CommandConfiguration(
commandName: "lab",
abstract: "A set of commands for lab features.",
subcommands: [
LabAuthCommand.self,
LabSessionCommand.self,
LabLogoutCommand.self,
]
)
}
}

View File

@ -25,7 +25,7 @@ public struct TuistCommand: ParsableCommand {
CreateIssueCommand.self, CreateIssueCommand.self,
ScaffoldCommand.self, ScaffoldCommand.self,
InitCommand.self, InitCommand.self,
CloudCommand.self, LabCommand.self,
CacheCommand.self, CacheCommand.self,
SigningCommand.self, SigningCommand.self,
MigrationCommand.self, MigrationCommand.self,

View File

@ -1,10 +1,10 @@
import Foundation import Foundation
import TSCBasic import TSCBasic
import TuistCache import TuistCache
import TuistCloud
import TuistCore import TuistCore
import TuistGenerator import TuistGenerator
import TuistGraph import TuistGraph
import TuistLab
import TuistSigning import TuistSigning
/// It defines an interface for providing the mappers to be used for a specific configuration. /// It defines an interface for providing the mappers to be used for a specific configuration.

View File

@ -1,39 +1,38 @@
import Foundation import Foundation
import TuistCloud
import TuistCore import TuistCore
import TuistLab
import TuistLoader import TuistLoader
import TuistSupport import TuistSupport
protocol CloudAuthServicing: AnyObject { protocol LabAuthServicing: AnyObject {
/// It reads the cloud URL from the project's Config.swift and /// It reads the lab URL from the project's Config.swift and
/// authenticates the user on that server storing the credentials /// authenticates the user on that server storing the credentials
/// locally on the keychain /// locally on the keychain
func authenticate() throws func authenticate() throws
} }
enum CloudAuthServiceError: FatalError, Equatable { enum LabAuthServiceError: FatalError, Equatable {
case missingCloudURL case missingLabURL
/// Error description. /// Error description.
var description: String { var description: String {
switch self { switch self {
case .missingCloudURL: case .missingLabURL:
return "The cloud URL attribute is missing in your project's configuration." return "The lab URL attribute is missing in your project's configuration."
} }
} }
/// Error type. /// Error type.
var type: ErrorType { var type: ErrorType {
switch self { switch self {
case .missingCloudURL: case .missingLabURL:
return .abort return .abort
} }
} }
} }
final class CloudAuthService: CloudAuthServicing { final class LabAuthService: LabAuthServicing {
/// Cloud session controller. let labSessionController: LabSessionControlling
let cloudSessionController: CloudSessionControlling
let configLoader: ConfigLoading let configLoader: ConfigLoading
// MARK: - Init // MARK: - Init
@ -42,27 +41,27 @@ final class CloudAuthService: CloudAuthServicing {
let manifestLoader = ManifestLoader() let manifestLoader = ManifestLoader()
let configLoader = ConfigLoader(manifestLoader: manifestLoader) let configLoader = ConfigLoader(manifestLoader: manifestLoader)
self.init( self.init(
cloudSessionController: CloudSessionController(), labSessionController: LabSessionController(),
configLoader: configLoader configLoader: configLoader
) )
} }
init( init(
cloudSessionController: CloudSessionControlling, labSessionController: LabSessionControlling,
configLoader: ConfigLoading configLoader: ConfigLoading
) { ) {
self.cloudSessionController = cloudSessionController self.labSessionController = labSessionController
self.configLoader = configLoader self.configLoader = configLoader
} }
// MARK: - CloudAuthServicing // MARK: - LabAuthServicing
func authenticate() throws { func authenticate() throws {
let path = FileHandler.shared.currentPath let path = FileHandler.shared.currentPath
let config = try configLoader.loadConfig(path: path) let config = try configLoader.loadConfig(path: path)
guard let cloudURL = config.cloud?.url else { guard let labURL = config.lab?.url else {
throw CloudAuthServiceError.missingCloudURL throw LabAuthServiceError.missingLabURL
} }
try cloudSessionController.authenticate(serverURL: cloudURL) try labSessionController.authenticate(serverURL: labURL)
} }
} }

View File

@ -1,40 +1,38 @@
import Foundation import Foundation
import TuistCloud
import TuistCore import TuistCore
import TuistLab
import TuistLoader import TuistLoader
import TuistSupport import TuistSupport
protocol CloudLogoutServicing: AnyObject { protocol LabLogoutServicing: AnyObject {
/// It reads the cloud URL from the project's Config.swift and /// It reads the lab URL from the project's Config.swift and
/// and it removes any session associated to that domain from /// and it removes any session associated to that domain from
/// the keychain /// the keychain
func logout() throws func logout() throws
} }
enum CloudLogoutServiceError: FatalError, Equatable { enum LabLogoutServiceError: FatalError, Equatable {
case missingCloudURL case missingLabURL
/// Error description. /// Error description.
var description: String { var description: String {
switch self { switch self {
case .missingCloudURL: case .missingLabURL:
return "The cloud URL attribute is missing in your project's configuration." return "The lab URL attribute is missing in your project's configuration."
} }
} }
/// Error type. /// Error type.
var type: ErrorType { var type: ErrorType {
switch self { switch self {
case .missingCloudURL: case .missingLabURL:
return .abort return .abort
} }
} }
} }
final class CloudLogoutService: CloudLogoutServicing { final class LabLogoutService: LabLogoutServicing {
/// Cloud session controller. let labSessionController: LabSessionControlling
let cloudSessionController: CloudSessionControlling
let configLoader: ConfigLoading let configLoader: ConfigLoading
// MARK: - Init // MARK: - Init
@ -43,27 +41,27 @@ final class CloudLogoutService: CloudLogoutServicing {
let manifestLoader = ManifestLoader() let manifestLoader = ManifestLoader()
let configLoader = ConfigLoader(manifestLoader: manifestLoader) let configLoader = ConfigLoader(manifestLoader: manifestLoader)
self.init( self.init(
cloudSessionController: CloudSessionController(), labSessionController: LabSessionController(),
configLoader: configLoader configLoader: configLoader
) )
} }
init( init(
cloudSessionController: CloudSessionControlling, labSessionController: LabSessionControlling,
configLoader: ConfigLoading configLoader: ConfigLoading
) { ) {
self.cloudSessionController = cloudSessionController self.labSessionController = labSessionController
self.configLoader = configLoader self.configLoader = configLoader
} }
// MARK: - CloudAuthServicing // MARK: - LabAuthServicing
func logout() throws { func logout() throws {
let path = FileHandler.shared.currentPath let path = FileHandler.shared.currentPath
let config = try configLoader.loadConfig(path: path) let config = try configLoader.loadConfig(path: path)
guard let cloudURL = config.cloud?.url else { guard let labURL = config.lab?.url else {
throw CloudLogoutServiceError.missingCloudURL throw LabLogoutServiceError.missingLabURL
} }
try cloudSessionController.logout(serverURL: cloudURL) try labSessionController.logout(serverURL: labURL)
} }
} }

View File

@ -1,40 +1,38 @@
import Foundation import Foundation
import TuistCloud
import TuistCore import TuistCore
import TuistLab
import TuistLoader import TuistLoader
import TuistSupport import TuistSupport
protocol CloudSessionServicing: AnyObject { protocol LabSessionServicing: AnyObject {
/// It reads the cloud URL from the project's Config.swift and /// It reads the lab URL from the project's Config.swift and
/// prints any existing session in the keychain to authenticate /// prints any existing session in the keychain to authenticate
/// on a server identified by that URL. /// on a server identified by that URL.
func printSession() throws func printSession() throws
} }
enum CloudSessionServiceError: FatalError, Equatable { enum LabSessionServiceError: FatalError, Equatable {
case missingCloudURL case missingLabURL
/// Error description. /// Error description.
var description: String { var description: String {
switch self { switch self {
case .missingCloudURL: case .missingLabURL:
return "The cloud URL attribute is missing in your project's configuration." return "The lab URL attribute is missing in your project's configuration."
} }
} }
/// Error type. /// Error type.
var type: ErrorType { var type: ErrorType {
switch self { switch self {
case .missingCloudURL: case .missingLabURL:
return .abort return .abort
} }
} }
} }
final class CloudSessionService: CloudSessionServicing { final class LabSessionService: LabSessionServicing {
/// Cloud session controller. let labSessionController: LabSessionControlling
let cloudSessionController: CloudSessionControlling
let configLoader: ConfigLoading let configLoader: ConfigLoading
// MARK: - Init // MARK: - Init
@ -43,27 +41,27 @@ final class CloudSessionService: CloudSessionServicing {
let manifestLoader = ManifestLoader() let manifestLoader = ManifestLoader()
let configLoader = ConfigLoader(manifestLoader: manifestLoader) let configLoader = ConfigLoader(manifestLoader: manifestLoader)
self.init( self.init(
cloudSessionController: CloudSessionController(), labSessionController: LabSessionController(),
configLoader: configLoader configLoader: configLoader
) )
} }
init( init(
cloudSessionController: CloudSessionControlling, labSessionController: LabSessionControlling,
configLoader: ConfigLoading configLoader: ConfigLoading
) { ) {
self.cloudSessionController = cloudSessionController self.labSessionController = labSessionController
self.configLoader = configLoader self.configLoader = configLoader
} }
// MARK: - CloudAuthServicing // MARK: - LabAuthServicing
func printSession() throws { func printSession() throws {
let path = FileHandler.shared.currentPath let path = FileHandler.shared.currentPath
let config = try configLoader.loadConfig(path: path) let config = try configLoader.loadConfig(path: path)
guard let cloudURL = config.cloud?.url else { guard let labURL = config.lab?.url else {
throw CloudSessionServiceError.missingCloudURL throw LabSessionServiceError.missingLabURL
} }
try cloudSessionController.printSession(serverURL: cloudURL) try labSessionController.printSession(serverURL: labURL)
} }
} }

View File

@ -3,18 +3,18 @@ import RxSwift
import TuistCore import TuistCore
import TuistSupport import TuistSupport
public class CloudClient: CloudClienting { public class LabClient: LabClienting {
// MARK: - Attributes // MARK: - Attributes
let cloudHTTPRequestAuthenticator: CloudHTTPRequestAuthenticating let labHTTPRequestAuthenticator: LabHTTPRequestAuthenticating
let requestDispatcher: HTTPRequestDispatching let requestDispatcher: HTTPRequestDispatching
// MARK: - Init // MARK: - Init
public init(cloudHTTPRequestAuthenticator: CloudHTTPRequestAuthenticating = CloudHTTPRequestAuthenticator(), public init(labHTTPRequestAuthenticator: LabHTTPRequestAuthenticating = LabHTTPRequestAuthenticator(),
requestDispatcher: HTTPRequestDispatching = HTTPRequestDispatcher()) requestDispatcher: HTTPRequestDispatching = HTTPRequestDispatcher())
{ {
self.cloudHTTPRequestAuthenticator = cloudHTTPRequestAuthenticator self.labHTTPRequestAuthenticator = labHTTPRequestAuthenticator
self.requestDispatcher = requestDispatcher self.requestDispatcher = requestDispatcher
} }
@ -38,7 +38,7 @@ public class CloudClient: CloudClienting {
var request = request var request = request
if request.allHTTPHeaderFields == nil { request.allHTTPHeaderFields = [:] } if request.allHTTPHeaderFields == nil { request.allHTTPHeaderFields = [:] }
request.allHTTPHeaderFields?["Content-Type"] = "application/json;" request.allHTTPHeaderFields?["Content-Type"] = "application/json;"
return try self.cloudHTTPRequestAuthenticator.authenticate(request: request) return try self.labHTTPRequestAuthenticator.authenticate(request: request)
} }
} }
} }

View File

@ -1,6 +1,6 @@
import Foundation import Foundation
public enum CloudClientError: LocalizedError, Equatable { public enum LabClientError: LocalizedError, Equatable {
case unauthorized case unauthorized
public var errorDescription: String? { public var errorDescription: String? {

View File

@ -0,0 +1,2 @@
import TuistSupport
let logger = Logger(label: "io.tuist.lab")

View File

@ -1,7 +1,7 @@
import Foundation import Foundation
import TuistSupport import TuistSupport
public enum CloudSessionControllerError: FatalError, Equatable { public enum LabSessionControllerError: FatalError, Equatable {
case missingParameters case missingParameters
case authenticationError(String) case authenticationError(String)
case invalidParameters([String]) case invalidParameters([String])
@ -28,7 +28,7 @@ public enum CloudSessionControllerError: FatalError, Equatable {
} }
} }
public protocol CloudSessionControlling: AnyObject { public protocol LabSessionControlling: AnyObject {
/// It authenticates the user for the server with the given URL. /// It authenticates the user for the server with the given URL.
/// - Parameter serverURL: Server URL. /// - Parameter serverURL: Server URL.
func authenticate(serverURL: URL) throws func authenticate(serverURL: URL) throws
@ -42,7 +42,7 @@ public protocol CloudSessionControlling: AnyObject {
func logout(serverURL: URL) throws func logout(serverURL: URL) throws
} }
public final class CloudSessionController: CloudSessionControlling { public final class LabSessionController: LabSessionControlling {
static let port: UInt16 = 4545 static let port: UInt16 = 4545
/// Credentials store. /// Credentials store.
@ -77,7 +77,7 @@ public final class CloudSessionController: CloudSessionControlling {
self.opener = opener self.opener = opener
} }
// MARK: - CloudSessionControlling // MARK: - LabSessionControlling
public func authenticate(serverURL: URL) throws { public func authenticate(serverURL: URL) throws {
var components = URLComponents(url: serverURL, resolvingAgainstBaseURL: false)! var components = URLComponents(url: serverURL, resolvingAgainstBaseURL: false)!
@ -91,7 +91,7 @@ public final class CloudSessionController: CloudSessionControlling {
let logoURL = serverURL.appendingPathComponent("redirect-logo.svg") let logoURL = serverURL.appendingPathComponent("redirect-logo.svg")
let redirectMessage = "Switch back to your terminal to continue the authentication." let redirectMessage = "Switch back to your terminal to continue the authentication."
let result = httpRedirectListener.listen( let result = httpRedirectListener.listen(
port: CloudSessionController.port, port: LabSessionController.port,
path: "auth", path: "auth",
redirectMessage: redirectMessage, redirectMessage: redirectMessage,
logoURL: logoURL logoURL: logoURL
@ -100,17 +100,17 @@ public final class CloudSessionController: CloudSessionControlling {
case let .failure(error): throw error case let .failure(error): throw error
case let .success(parameters): case let .success(parameters):
guard let parameters = parameters else { guard let parameters = parameters else {
throw CloudSessionControllerError.missingParameters throw LabSessionControllerError.missingParameters
} }
if let error = parameters["error"] { if let error = parameters["error"] {
throw CloudSessionControllerError.authenticationError(error) throw LabSessionControllerError.authenticationError(error)
} else if let token = parameters["token"], let account = parameters["account"] { } else if let token = parameters["token"], let account = parameters["account"] {
logger.notice("Successfully authenticated. Storing credentials...") logger.notice("Successfully authenticated. Storing credentials...")
let credentials = Credentials(token: token, account: account) let credentials = Credentials(token: token, account: account)
try credentialsStore.store(credentials: credentials, serverURL: serverURL) try credentialsStore.store(credentials: credentials, serverURL: serverURL)
logger.notice("Credentials stored successfully", metadata: .success) logger.notice("Credentials stored successfully", metadata: .success)
} else { } else {
throw CloudSessionControllerError.invalidParameters(Array(parameters.keys)) throw LabSessionControllerError.invalidParameters(Array(parameters.keys))
} }
} }
} }

View File

@ -4,14 +4,14 @@ import TuistSupport
/// Protocol that defines the interface to map HTTP requests and include authentication information. /// Protocol that defines the interface to map HTTP requests and include authentication information.
/// Depending on th environment where Tuist is running (local or CI), it returns the token from the credentials store (i.e. Keychain) /// Depending on th environment where Tuist is running (local or CI), it returns the token from the credentials store (i.e. Keychain)
/// or a environment variable. /// or a environment variable.
public protocol CloudHTTPRequestAuthenticating { public protocol LabHTTPRequestAuthenticating {
/// Given a request, it returns a copy of it including information to authenticate requests to the cloud. /// Given a request, it returns a copy of it including information to authenticate requests to the lab.
/// - Parameter request: Request to authenticate. /// - Parameter request: Request to authenticate.
/// - Returns: Mapped request. /// - Returns: Mapped request.
func authenticate(request: URLRequest) throws -> URLRequest func authenticate(request: URLRequest) throws -> URLRequest
} }
public final class CloudHTTPRequestAuthenticator: CloudHTTPRequestAuthenticating { public final class LabHTTPRequestAuthenticator: LabHTTPRequestAuthenticating {
/// Utility to check whether we are running Tuist on CI. /// Utility to check whether we are running Tuist on CI.
let ciChecker: CIChecking let ciChecker: CIChecking
@ -38,7 +38,7 @@ public final class CloudHTTPRequestAuthenticator: CloudHTTPRequestAuthenticating
self.credentialsStore = credentialsStore self.credentialsStore = credentialsStore
} }
// MARK: - CloudHTTPRequestAuthenticating // MARK: - LabHTTPRequestAuthenticating
public func authenticate(request: URLRequest) throws -> URLRequest { public func authenticate(request: URLRequest) throws -> URLRequest {
var urlComponents = URLComponents(url: request.url!, resolvingAgainstBaseURL: false)! var urlComponents = URLComponents(url: request.url!, resolvingAgainstBaseURL: false)!
@ -48,7 +48,7 @@ public final class CloudHTTPRequestAuthenticator: CloudHTTPRequestAuthenticating
let token: String? let token: String?
if ciChecker.isCI() { if ciChecker.isCI() {
token = environmentVariables()[Constants.EnvironmentVariables.cloudToken] token = environmentVariables()[Constants.EnvironmentVariables.labToken]
} else { } else {
token = try credentialsStore.read(serverURL: serverURL)?.token token = try credentialsStore.read(serverURL: serverURL)?.token
} }

View File

@ -1,8 +1,8 @@
import Foundation import Foundation
@testable import TuistCloud @testable import TuistLab
public final class MockCloudSessionController: CloudSessionControlling { public final class MockLabSessionController: LabSessionControlling {
public init() {} public init() {}
public var authenticateArgs: [URL] = [] public var authenticateArgs: [URL] = []

View File

@ -2,9 +2,9 @@ import Foundation
import TuistSupport import TuistSupport
import XCTest import XCTest
@testable import TuistCloud @testable import TuistLab
final class MockCloudHTTPRequestAuthenticator: CloudHTTPRequestAuthenticating { final class MockLabHTTPRequestAuthenticator: LabHTTPRequestAuthenticating {
public init() {} public init() {}
public var authenticateStub: ((URLRequest) throws -> URLRequest)? public var authenticateStub: ((URLRequest) throws -> URLRequest)?

View File

@ -5,41 +5,41 @@ import TuistCore
import TuistGraph import TuistGraph
import TuistSupport import TuistSupport
enum CloudManifestMapperError: FatalError { enum LabManifestMapperError: FatalError {
/// Thrown when the cloud URL is invalid. /// Thrown when the lab URL is invalid.
case invalidCloudURL(String) case invalidLabURL(String)
/// Error type. /// Error type.
var type: ErrorType { var type: ErrorType {
switch self { switch self {
case .invalidCloudURL: return .abort case .invalidLabURL: return .abort
} }
} }
/// Error description. /// Error description.
var description: String { var description: String {
switch self { switch self {
case let .invalidCloudURL(url): case let .invalidLabURL(url):
return "The cloud URL '\(url)' is not a valid URL" return "The lab URL '\(url)' is not a valid URL"
} }
} }
} }
extension TuistGraph.Cloud { extension TuistGraph.Lab {
static func from(manifest: ProjectDescription.Cloud) throws -> TuistGraph.Cloud { static func from(manifest: ProjectDescription.Lab) throws -> TuistGraph.Lab {
var cloudURL: URL! var labURL: URL!
if let manifestCloudURL = URL(string: manifest.url) { if let manifestLabURL = URL(string: manifest.url) {
cloudURL = manifestCloudURL labURL = manifestLabURL
} else { } else {
throw CloudManifestMapperError.invalidCloudURL(manifest.url) throw LabManifestMapperError.invalidLabURL(manifest.url)
} }
let options = manifest.options.map(TuistGraph.Cloud.Option.from) let options = manifest.options.map(TuistGraph.Lab.Option.from)
return TuistGraph.Cloud(url: cloudURL, projectId: manifest.projectId, options: options) return TuistGraph.Lab(url: labURL, projectId: manifest.projectId, options: options)
} }
} }
extension TuistGraph.Cloud.Option { extension TuistGraph.Lab.Option {
static func from(manifest: ProjectDescription.Cloud.Option) -> TuistGraph.Cloud.Option { static func from(manifest: ProjectDescription.Lab.Option) -> TuistGraph.Lab.Option {
switch manifest { switch manifest {
case .insights: case .insights:
return .insights return .insights

View File

@ -16,9 +16,9 @@ extension TuistGraph.Config {
let generatorPaths = GeneratorPaths(manifestDirectory: path) let generatorPaths = GeneratorPaths(manifestDirectory: path)
let plugins = try manifest.plugins.map { try PluginLocation.from(manifest: $0, generatorPaths: generatorPaths) } let plugins = try manifest.plugins.map { try PluginLocation.from(manifest: $0, generatorPaths: generatorPaths) }
var cloud: TuistGraph.Cloud? var lab: TuistGraph.Lab?
if let manifestCloud = manifest.cloud { if let manifestLab = manifest.lab {
cloud = try TuistGraph.Cloud.from(manifest: manifestCloud) lab = try TuistGraph.Lab.from(manifest: manifestLab)
} }
var cache: TuistGraph.Cache? var cache: TuistGraph.Cache?
@ -33,7 +33,7 @@ extension TuistGraph.Config {
return TuistGraph.Config( return TuistGraph.Config(
compatibleXcodeVersions: compatibleXcodeVersions, compatibleXcodeVersions: compatibleXcodeVersions,
cloud: cloud, lab: lab,
cache: cache, cache: cache,
plugins: plugins, plugins: plugins,
generationOptions: generationOptions, generationOptions: generationOptions,

View File

@ -61,7 +61,7 @@ public enum Constants {
public static let forceConfigCacheDirectory = "TUIST_FORCE_CONFIG_CACHE_DIRECTORY" public static let forceConfigCacheDirectory = "TUIST_FORCE_CONFIG_CACHE_DIRECTORY"
public static let automationPath = "TUIST_AUTOMATION_PATH" public static let automationPath = "TUIST_AUTOMATION_PATH"
public static let queueDirectory = "TUIST_QUEUE_DIRECTORY" public static let queueDirectory = "TUIST_QUEUE_DIRECTORY"
public static let cloudToken = "TUIST_CLOUD_TOKEN" public static let labToken = "TUIST_LAB_TOKEN"
public static let cacheManifests = "TUIST_CACHE_MANIFESTS" public static let cacheManifests = "TUIST_CACHE_MANIFESTS"
public static let statsOptOut = "TUIST_STATS_OPT_OUT" public static let statsOptOut = "TUIST_STATS_OPT_OUT"
} }

View File

@ -5,7 +5,7 @@ import XCTest
final class ConfigTests: XCTestCase { final class ConfigTests: XCTestCase {
func test_config_toJSON() throws { func test_config_toJSON() throws {
let config = Config( let config = Config(
cloud: Cloud(url: "https://cloud.tuist.io", projectId: "123", options: [.insights]), lab: Lab(url: "https://lab.tuist.io", projectId: "123", options: [.insights]),
generationOptions: [ generationOptions: [
.xcodeProjectName("someprefix-\(.projectName)"), .xcodeProjectName("someprefix-\(.projectName)"),
.organizationName("TestOrg"), .organizationName("TestOrg"),
@ -41,7 +41,7 @@ final class ConfigTests: XCTestCase {
func test_config_toJSON_withAutogeneratedSchemes() throws { func test_config_toJSON_withAutogeneratedSchemes() throws {
let config = Config( let config = Config(
cloud: Cloud(url: "https://cloud.tuist.io", projectId: "123", options: [.insights]), lab: Lab(url: "https://lab.tuist.io", projectId: "123", options: [.insights]),
generationOptions: [ generationOptions: [
.xcodeProjectName("someprefix-\(.projectName)"), .xcodeProjectName("someprefix-\(.projectName)"),
.developmentRegion("de"), .developmentRegion("de"),

View File

@ -2,9 +2,9 @@ import Foundation
import XCTest import XCTest
@testable import ProjectDescription @testable import ProjectDescription
final class CloudTests: XCTestCase { final class LabTests: XCTestCase {
func test_config_toJSON() throws { func test_config_toJSON() throws {
let cloud = Cloud(url: "https://cloud.tuist.io", projectId: "123", options: [.insights]) let cloud = Lab(url: "https://lab.tuist.io", projectId: "123", options: [.insights])
XCTAssertCodable(cloud) XCTAssertCodable(cloud)
} }
} }

View File

@ -1,10 +1,10 @@
import RxSwift import RxSwift
import TSCBasic import TSCBasic
import TuistCacheTesting import TuistCacheTesting
import TuistCloud
import TuistCore import TuistCore
import TuistGraph import TuistGraph
import TuistGraphTesting import TuistGraphTesting
import TuistLab
import TuistSupport import TuistSupport
import XCTest import XCTest
@ -15,13 +15,13 @@ import XCTest
final class CacheRemoteStorageTests: TuistUnitTestCase { final class CacheRemoteStorageTests: TuistUnitTestCase {
var subject: CacheRemoteStorage! var subject: CacheRemoteStorage!
var cloudClient: MockCloudClient! var labClient: MockLabClient!
var fileArchiverFactory: MockFileArchivingFactory! var fileArchiverFactory: MockFileArchivingFactory!
var fileArchiver: MockFileArchiver! var fileArchiver: MockFileArchiver!
var fileUnarchiver: MockFileUnarchiver! var fileUnarchiver: MockFileUnarchiver!
var fileClient: MockFileClient! var fileClient: MockFileClient!
var zipPath: AbsolutePath! var zipPath: AbsolutePath!
var mockCloudCacheResourceFactory: MockCloudCacheResourceFactory! var mockLabCacheResourceFactory: MockLabCacheResourceFactory!
let receivedUploadURL = URL(string: "https://remote.storage.com/upload")! let receivedUploadURL = URL(string: "https://remote.storage.com/upload")!
var cacheDirectoriesProvider: MockCacheDirectoriesProvider! var cacheDirectoriesProvider: MockCacheDirectoriesProvider!
@ -30,7 +30,7 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
zipPath = fixturePath(path: RelativePath("uUI.xcframework.zip")) zipPath = fixturePath(path: RelativePath("uUI.xcframework.zip"))
mockCloudCacheResourceFactory = MockCloudCacheResourceFactory() mockLabCacheResourceFactory = MockLabCacheResourceFactory()
fileArchiverFactory = MockFileArchivingFactory() fileArchiverFactory = MockFileArchivingFactory()
fileArchiver = MockFileArchiver() fileArchiver = MockFileArchiver()
fileUnarchiver = MockFileUnarchiver() fileUnarchiver = MockFileUnarchiver()
@ -39,28 +39,28 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
fileArchiverFactory.stubbedMakeFileUnarchiverResult = fileUnarchiver fileArchiverFactory.stubbedMakeFileUnarchiverResult = fileUnarchiver
fileClient = MockFileClient() fileClient = MockFileClient()
fileClient.stubbedDownloadResult = Single.just(zipPath) fileClient.stubbedDownloadResult = Single.just(zipPath)
cloudClient = MockCloudClient() labClient = MockLabClient()
cacheDirectoriesProvider = try MockCacheDirectoriesProvider() cacheDirectoriesProvider = try MockCacheDirectoriesProvider()
cacheDirectoriesProvider.cacheDirectoryStub = try temporaryPath() cacheDirectoriesProvider.cacheDirectoryStub = try temporaryPath()
subject = CacheRemoteStorage( subject = CacheRemoteStorage(
cloudClient: cloudClient, labClient: labClient,
fileArchiverFactory: fileArchiverFactory, fileArchiverFactory: fileArchiverFactory,
fileClient: fileClient, fileClient: fileClient,
cloudCacheResponseFactory: mockCloudCacheResourceFactory, labCacheResourceFactory: mockLabCacheResourceFactory,
cacheDirectoriesProvider: cacheDirectoriesProvider cacheDirectoriesProvider: cacheDirectoriesProvider
) )
} }
override func tearDown() { override func tearDown() {
subject = nil subject = nil
cloudClient = nil labClient = nil
fileArchiver = nil fileArchiver = nil
fileArchiverFactory = nil fileArchiverFactory = nil
fileClient = nil fileClient = nil
zipPath = nil zipPath = nil
mockCloudCacheResourceFactory = nil mockLabCacheResourceFactory = nil
cacheDirectoriesProvider = nil cacheDirectoriesProvider = nil
super.tearDown() super.tearDown()
} }
@ -69,7 +69,7 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_exists_whenClientReturnsAnError() throws { func test_exists_whenClientReturnsAnError() throws {
// Given // Given
cloudClient.mock(error: CloudHEADResponseError()) labClient.mock(error: LabHEADResponseError())
// When // When
let result = subject.exists(hash: "acho tio") let result = subject.exists(hash: "acho tio")
@ -80,8 +80,8 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
switch result { switch result {
case .completed: case .completed:
XCTFail("Expected result to complete with error, but result was successful.") XCTFail("Expected result to complete with error, but result was successful.")
case let .failed(_, error) where error is CloudHEADResponseError: case let .failed(_, error) where error is LabHEADResponseError:
XCTAssertEqual(error as! CloudHEADResponseError, CloudHEADResponseError()) XCTAssertEqual(error as! LabHEADResponseError, LabHEADResponseError())
default: default:
XCTFail("Expected result to complete with error, but result error wasn't the expected type.") XCTFail("Expected result to complete with error, but result error wasn't the expected type.")
} }
@ -89,9 +89,9 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_exists_whenClientReturnsAnHTTPError() throws { func test_exists_whenClientReturnsAnHTTPError() throws {
// Given // Given
let cloudResponse: CloudResponse<CloudHEADResponse> = CloudResponse(status: "shaki", data: CloudHEADResponse()) let labResponse: LabResponse<LabHEADResponse> = LabResponse(status: "shaki", data: LabHEADResponse())
let httpResponse: HTTPURLResponse = .test(statusCode: 500) let httpResponse: HTTPURLResponse = .test(statusCode: 500)
cloudClient.mock(object: cloudResponse, response: httpResponse) labClient.mock(object: labResponse, response: httpResponse)
// When // When
let result = try subject.exists(hash: "acho tio") let result = try subject.exists(hash: "acho tio")
@ -104,9 +104,9 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_exists_whenClientReturnsASuccess() throws { func test_exists_whenClientReturnsASuccess() throws {
// Given // Given
let cloudResponse = CloudResponse<CloudHEADResponse>(status: "shaki", data: CloudHEADResponse()) let labResponse = LabResponse<LabHEADResponse>(status: "shaki", data: LabHEADResponse())
let httpResponse: HTTPURLResponse = .test() let httpResponse: HTTPURLResponse = .test()
cloudClient.mock(object: cloudResponse, response: httpResponse) labClient.mock(object: labResponse, response: httpResponse)
// When // When
let result = try subject.exists(hash: "acho tio") let result = try subject.exists(hash: "acho tio")
@ -119,9 +119,9 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_exists_whenClientReturnsA202() throws { func test_exists_whenClientReturnsA202() throws {
// Given // Given
let cloudResponse = CloudResponse<CloudHEADResponse>(status: "shaki", data: CloudHEADResponse()) let labResponse = LabResponse<LabHEADResponse>(status: "shaki", data: LabHEADResponse())
let httpResponse: HTTPURLResponse = .test(statusCode: 202) let httpResponse: HTTPURLResponse = .test(statusCode: 202)
cloudClient.mock(object: cloudResponse, response: httpResponse) labClient.mock(object: labResponse, response: httpResponse)
// When // When
let result = try subject.exists(hash: "acho tio") let result = try subject.exists(hash: "acho tio")
@ -136,8 +136,8 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_fetch_whenClientReturnsAnError() throws { func test_fetch_whenClientReturnsAnError() throws {
// Given // Given
let expectedError: CloudResponseError = .test() let expectedError: LabResponseError = .test()
cloudClient.mock(error: expectedError) labClient.mock(error: expectedError)
// When // When
let result = subject.fetch(hash: "acho tio") let result = subject.fetch(hash: "acho tio")
@ -148,8 +148,8 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
switch result { switch result {
case .completed: case .completed:
XCTFail("Expected result to complete with error, but result was successful.") XCTFail("Expected result to complete with error, but result was successful.")
case let .failed(_, error) where error is CloudResponseError: case let .failed(_, error) where error is LabResponseError:
XCTAssertEqual(error as! CloudResponseError, expectedError) XCTAssertEqual(error as! LabResponseError, expectedError)
default: default:
XCTFail("Expected result to complete with error, but result error wasn't the expected type.") XCTFail("Expected result to complete with error, but result error wasn't the expected type.")
} }
@ -158,9 +158,9 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_fetch_whenArchiveContainsIncorrectRootFolderAfterUnzipping_expectErrorThrown() throws { func test_fetch_whenArchiveContainsIncorrectRootFolderAfterUnzipping_expectErrorThrown() throws {
// Given // Given
let httpResponse: HTTPURLResponse = .test() let httpResponse: HTTPURLResponse = .test()
let cacheResponse = CloudCacheResponse(url: .test(), expiresAt: 123) let cacheResponse = LabCacheResponse(url: .test(), expiresAt: 123)
let cloudResponse = CloudResponse<CloudCacheResponse>(status: "shaki", data: cacheResponse) let labResponse = LabResponse<LabCacheResponse>(status: "shaki", data: cacheResponse)
cloudClient.mock(object: cloudResponse, response: httpResponse) labClient.mock(object: labResponse, response: httpResponse)
let hash = "foobar" let hash = "foobar"
let paths = try createFolders(["Unarchived/\(hash)/IncorrectRootFolderAfterUnzipping"]) let paths = try createFolders(["Unarchived/\(hash)/IncorrectRootFolderAfterUnzipping"])
@ -185,9 +185,9 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_fetch_whenClientReturnsASuccess_returnsCorrectRootFolderAfterUnzipping() throws { func test_fetch_whenClientReturnsASuccess_returnsCorrectRootFolderAfterUnzipping() throws {
// Given // Given
let httpResponse: HTTPURLResponse = .test() let httpResponse: HTTPURLResponse = .test()
let cacheResponse = CloudCacheResponse(url: .test(), expiresAt: 123) let cacheResponse = LabCacheResponse(url: .test(), expiresAt: 123)
let cloudResponse = CloudResponse<CloudCacheResponse>(status: "success", data: cacheResponse) let labResponse = LabResponse<LabCacheResponse>(status: "success", data: cacheResponse)
cloudClient.mock(object: cloudResponse, response: httpResponse) labClient.mock(object: labResponse, response: httpResponse)
let hash = "bar_foo" let hash = "bar_foo"
let paths = try createFolders(["Unarchived/\(hash)/myFramework.xcframework"]) let paths = try createFolders(["Unarchived/\(hash)/myFramework.xcframework"])
@ -207,9 +207,9 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
// Given // Given
let httpResponse: HTTPURLResponse = .test() let httpResponse: HTTPURLResponse = .test()
let url = URL(string: "https://tuist.io/acho/tio")! let url = URL(string: "https://tuist.io/acho/tio")!
let cacheResponse = CloudCacheResponse(url: url, expiresAt: 123) let cacheResponse = LabCacheResponse(url: url, expiresAt: 123)
let cloudResponse = CloudResponse<CloudCacheResponse>(status: "shaki", data: cacheResponse) let labResponse = LabResponse<LabCacheResponse>(status: "shaki", data: cacheResponse)
cloudClient.mock(object: cloudResponse, response: httpResponse) labClient.mock(object: labResponse, response: httpResponse)
let hash = "foo_bar" let hash = "foo_bar"
let paths = try createFolders(["Unarchived/\(hash)/myFramework.xcframework"]) let paths = try createFolders(["Unarchived/\(hash)/myFramework.xcframework"])
@ -227,9 +227,9 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_fetch_whenClientReturnsASuccess_givesFileArchiverTheCorrectDestinationPath() throws { func test_fetch_whenClientReturnsASuccess_givesFileArchiverTheCorrectDestinationPath() throws {
// Given // Given
let httpResponse: HTTPURLResponse = .test() let httpResponse: HTTPURLResponse = .test()
let cacheResponse = CloudCacheResponse(url: .test(), expiresAt: 123) let cacheResponse = LabCacheResponse(url: .test(), expiresAt: 123)
let cloudResponse = CloudResponse<CloudCacheResponse>(status: "shaki", data: cacheResponse) let labResponse = LabResponse<LabCacheResponse>(status: "shaki", data: cacheResponse)
cloudClient.mock(object: cloudResponse, response: httpResponse) labClient.mock(object: labResponse, response: httpResponse)
let paths = try createFolders(["Unarchived/\(hash)/Framework.framework"]) let paths = try createFolders(["Unarchived/\(hash)/Framework.framework"])
fileUnarchiver.stubbedUnzipResult = paths.first?.parentDirectory fileUnarchiver.stubbedUnzipResult = paths.first?.parentDirectory
@ -249,8 +249,8 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_store_whenClientReturnsAnError() throws { func test_store_whenClientReturnsAnError() throws {
// Given // Given
let expectedError = CloudResponseError.test() let expectedError = LabResponseError.test()
cloudClient.mock(error: expectedError) labClient.mock(error: expectedError)
// When // When
let result = subject.store(hash: "acho tio", paths: [.root]) let result = subject.store(hash: "acho tio", paths: [.root])
@ -261,8 +261,8 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
switch result { switch result {
case .completed: case .completed:
XCTFail("Expected result to complete with error, but result was successful.") XCTFail("Expected result to complete with error, but result was successful.")
case let .failed(_, error) where error is CloudResponseError: case let .failed(_, error) where error is LabResponseError:
XCTAssertEqual(error as! CloudResponseError, expectedError) XCTAssertEqual(error as! LabResponseError, expectedError)
default: default:
XCTFail("Expected result to complete with error, but result error wasn't the expected type.") XCTFail("Expected result to complete with error, but result error wasn't the expected type.")
} }
@ -270,7 +270,7 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_store_whenClientReturnsASuccess_returnsURLToUpload() throws { func test_store_whenClientReturnsASuccess_returnsURLToUpload() throws {
// Given // Given
configureCloudClientForSuccessfulUpload() configureLabClientForSuccessfulUpload()
// When // When
_ = subject.store(hash: "foo_bar", paths: [.root]) _ = subject.store(hash: "foo_bar", paths: [.root])
@ -288,7 +288,7 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_store_whenClientReturnsASuccess_usesTheRightHashToUpload() throws { func test_store_whenClientReturnsASuccess_usesTheRightHashToUpload() throws {
// Given // Given
let hash = "foo_bar" let hash = "foo_bar"
configureCloudClientForSuccessfulUpload() configureLabClientForSuccessfulUpload()
// When // When
_ = subject.store(hash: hash, paths: [.root]) _ = subject.store(hash: hash, paths: [.root])
@ -306,7 +306,7 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_store_whenClientReturnsASuccess_usesTheRightZipPathToUpload() throws { func test_store_whenClientReturnsASuccess_usesTheRightZipPathToUpload() throws {
// Given // Given
let hash = "foo_bar" let hash = "foo_bar"
configureCloudClientForSuccessfulUpload() configureLabClientForSuccessfulUpload()
fileArchiver.stubbedZipResult = zipPath fileArchiver.stubbedZipResult = zipPath
// When // When
@ -324,8 +324,8 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_store_whenClientReturnsAnUploadErrorVerifyIsNotCalled() throws { func test_store_whenClientReturnsAnUploadErrorVerifyIsNotCalled() throws {
// Given // Given
let expectedError = CloudResponseError.test() let expectedError = LabResponseError.test()
cloudClient.mock(error: expectedError) labClient.mock(error: expectedError)
// When // When
_ = subject.store(hash: "acho tio", paths: [.root]) _ = subject.store(hash: "acho tio", paths: [.root])
@ -333,12 +333,12 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
.materialize() .materialize()
// Then // Then
XCTAssertFalse(mockCloudCacheResourceFactory.invokedVerifyUploadResource) XCTAssertFalse(mockLabCacheResourceFactory.invokedVerifyUploadResource)
} }
func test_store_whenFileUploaderReturnsAnErrorFileArchiverIsCalled() throws { func test_store_whenFileUploaderReturnsAnErrorFileArchiverIsCalled() throws {
// Given // Given
configureCloudClientForSuccessfulUpload() configureLabClientForSuccessfulUpload()
fileClient.stubbedUploadResult = Single.error(TestError("Error uploading file")) fileClient.stubbedUploadResult = Single.error(TestError("Error uploading file"))
// When // When
@ -352,7 +352,7 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
func test_store_whenFileUploaderReturnsAnErrorVerifyIsNotCalled() throws { func test_store_whenFileUploaderReturnsAnErrorVerifyIsNotCalled() throws {
// Given // Given
configureCloudClientForSuccessfulUpload() configureLabClientForSuccessfulUpload()
fileClient.stubbedUploadResult = Single.error(TestError("Error uploading file")) fileClient.stubbedUploadResult = Single.error(TestError("Error uploading file"))
// When // When
@ -361,7 +361,7 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
.materialize() .materialize()
// Then // Then
XCTAssertFalse(mockCloudCacheResourceFactory.invokedVerifyUploadResource) XCTAssertFalse(mockLabCacheResourceFactory.invokedVerifyUploadResource)
} }
func test_store_whenVerifyFailsTheZipArchiveIsDeleted() throws { func test_store_whenVerifyFailsTheZipArchiveIsDeleted() throws {
@ -379,32 +379,32 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
// MARK: Private // MARK: Private
private func configureCloudClientForSuccessfulUpload() { private func configureLabClientForSuccessfulUpload() {
let uploadURLRequest = URLRequest.test(urlString: "https://tuist.cache.io/store") let uploadURLRequest = URLRequest.test(urlString: "https://tuist.cache.io/store")
let verifyUploadURLRequest = URLRequest.test(urlString: "https://tuist.cache.io/verify-upload") let verifyUploadURLRequest = URLRequest.test(urlString: "https://tuist.cache.io/verify-upload")
let receivedUploadURLRequest = URLRequest.test(url: receivedUploadURL) let receivedUploadURLRequest = URLRequest.test(url: receivedUploadURL)
let cacheResponse = CloudCacheResponse(url: receivedUploadURLRequest.url!, expiresAt: 123) let cacheResponse = LabCacheResponse(url: receivedUploadURLRequest.url!, expiresAt: 123)
let uploadURLObject = CloudResponse<CloudCacheResponse>(status: "uploadURLObject status", data: cacheResponse) let uploadURLObject = LabResponse<LabCacheResponse>(status: "uploadURLObject status", data: cacheResponse)
let cloudVerifyUploadResponse = CloudVerifyUploadResponse.test() let cloudVerifyUploadResponse = LabVerifyUploadResponse.test()
let verifyUploadObject = CloudResponse<CloudVerifyUploadResponse>(status: "cloudVerifyUploadResponse status", data: cloudVerifyUploadResponse) let verifyUploadObject = LabResponse<LabVerifyUploadResponse>(status: "cloudVerifyUploadResponse status", data: cloudVerifyUploadResponse)
cloudClient.mock(objectPerURLRequest: [ labClient.mock(objectPerURLRequest: [
uploadURLRequest: uploadURLObject, uploadURLRequest: uploadURLObject,
verifyUploadURLRequest: verifyUploadObject, verifyUploadURLRequest: verifyUploadObject,
]) ])
mockCloudCacheResourceFactory.stubbedStoreResourceResult = HTTPResource( mockLabCacheResourceFactory.stubbedStoreResourceResult = HTTPResource(
request: { uploadURLRequest }, request: { uploadURLRequest },
parse: { _, _ in uploadURLObject }, parse: { _, _ in uploadURLObject },
parseError: { _, _ in CloudResponseError.test() } parseError: { _, _ in LabResponseError.test() }
) )
mockCloudCacheResourceFactory.stubbedVerifyUploadResourceResult = HTTPResource( mockLabCacheResourceFactory.stubbedVerifyUploadResourceResult = HTTPResource(
request: { verifyUploadURLRequest }, request: { verifyUploadURLRequest },
parse: { _, _ in verifyUploadObject }, parse: { _, _ in verifyUploadObject },
parseError: { _, _ in CloudResponseError.test() } parseError: { _, _ in LabResponseError.test() }
) )
} }
@ -413,25 +413,25 @@ final class CacheRemoteStorageTests: TuistUnitTestCase {
let verifyUploadURLRequest = URLRequest.test(urlString: "https://tuist.cache.io/verify-upload") let verifyUploadURLRequest = URLRequest.test(urlString: "https://tuist.cache.io/verify-upload")
let receivedUploadURLRequest = URLRequest.test(url: receivedUploadURL) let receivedUploadURLRequest = URLRequest.test(url: receivedUploadURL)
let cacheResponse = CloudCacheResponse(url: receivedUploadURLRequest.url!, expiresAt: 123) let cacheResponse = LabCacheResponse(url: receivedUploadURLRequest.url!, expiresAt: 123)
let uploadURLObject = CloudResponse<CloudCacheResponse>(status: "uploadURLObject status", data: cacheResponse) let uploadURLObject = LabResponse<LabCacheResponse>(status: "uploadURLObject status", data: cacheResponse)
let cloudVerifyUploadResponse = CloudVerifyUploadResponse.test() let cloudVerifyUploadResponse = LabVerifyUploadResponse.test()
let verifyUploadObject = CloudResponse<CloudVerifyUploadResponse>(status: "cloudVerifyUploadResponse status", data: cloudVerifyUploadResponse) let verifyUploadObject = LabResponse<LabVerifyUploadResponse>(status: "cloudVerifyUploadResponse status", data: cloudVerifyUploadResponse)
let verifyUploadError = CloudResponseError.test() let verifyUploadError = LabResponseError.test()
cloudClient.mock( labClient.mock(
objectPerURLRequest: [uploadURLRequest: uploadURLObject], objectPerURLRequest: [uploadURLRequest: uploadURLObject],
errorPerURLRequest: [verifyUploadURLRequest: verifyUploadError] errorPerURLRequest: [verifyUploadURLRequest: verifyUploadError]
) )
mockCloudCacheResourceFactory.stubbedStoreResourceResult = HTTPResource( mockLabCacheResourceFactory.stubbedStoreResourceResult = HTTPResource(
request: { uploadURLRequest }, request: { uploadURLRequest },
parse: { _, _ in uploadURLObject }, parse: { _, _ in uploadURLObject },
parseError: { _, _ in CloudResponseError.test() } parseError: { _, _ in LabResponseError.test() }
) )
mockCloudCacheResourceFactory.stubbedVerifyUploadResourceResult = HTTPResource( mockLabCacheResourceFactory.stubbedVerifyUploadResourceResult = HTTPResource(
request: { verifyUploadURLRequest }, request: { verifyUploadURLRequest },
parse: { _, _ in verifyUploadObject }, parse: { _, _ in verifyUploadObject },
parseError: { _, _ in verifyUploadError } parseError: { _, _ in verifyUploadError }

View File

@ -59,7 +59,7 @@ final class SwiftPackageManagerInteractorTests: TuistUnitTestCase {
func test_generate_usesSystemGitCredentials() throws { func test_generate_usesSystemGitCredentials() throws {
// Given // Given
let temporaryPath = try self.temporaryPath() let temporaryPath = try self.temporaryPath()
let config = Config(compatibleXcodeVersions: .all, cloud: nil, cache: nil, plugins: [], generationOptions: [.resolveDependenciesWithSystemScm], path: nil) let config = Config(compatibleXcodeVersions: .all, lab: nil, cache: nil, plugins: [], generationOptions: [.resolveDependenciesWithSystemScm], path: nil)
let target = anyTarget(dependencies: [ let target = anyTarget(dependencies: [
.package(product: "Example"), .package(product: "Example"),

View File

@ -351,7 +351,7 @@ final class MultipleConfigurationsIntegrationTests: TuistUnitTestCase {
} }
private func createConfig() -> Config { private func createConfig() -> Config {
Config(compatibleXcodeVersions: .all, cloud: nil, cache: .default, plugins: [], generationOptions: [], path: nil) Config(compatibleXcodeVersions: .all, lab: nil, cache: .default, plugins: [], generationOptions: [], path: nil)
} }
private func createWorkspace(path: AbsolutePath, projects: [String]) throws -> Workspace { private func createWorkspace(path: AbsolutePath, projects: [String]) throws -> Workspace {

View File

@ -60,7 +60,9 @@ final class CacheXCFrameworkBuilderIntegrationTests: TuistTestCase {
XCTAssertEqual(FileHandler.shared.glob(temporaryPath, glob: "*.xcframework").count, 1) XCTAssertEqual(FileHandler.shared.glob(temporaryPath, glob: "*.xcframework").count, 1)
let xcframeworkPath = try XCTUnwrap(FileHandler.shared.glob(temporaryPath, glob: "*.xcframework").first) let xcframeworkPath = try XCTUnwrap(FileHandler.shared.glob(temporaryPath, glob: "*.xcframework").first)
let infoPlist = try self.infoPlist(xcframeworkPath: xcframeworkPath) let infoPlist = try self.infoPlist(xcframeworkPath: xcframeworkPath)
XCTAssertNotNil(infoPlist.availableLibraries.first(where: { $0.supportedArchitectures.contains("x86_64") })) XCTAssertNotNil(infoPlist.availableLibraries.first(where: { library in
library.supportedArchitectures.contains("x86_64") || library.supportedArchitectures.contains("arm64")
}))
XCTAssertTrue(infoPlist.availableLibraries.allSatisfy { $0.supportedPlatform == "macos" }) XCTAssertTrue(infoPlist.availableLibraries.allSatisfy { $0.supportedPlatform == "macos" })
try FileHandler.shared.delete(xcframeworkPath) try FileHandler.shared.delete(xcframeworkPath)
} }

View File

@ -1,9 +1,9 @@
import Foundation import Foundation
import TuistCache import TuistCache
import TuistCloud
import TuistCore import TuistCore
import TuistCoreTesting import TuistCoreTesting
import TuistGenerator import TuistGenerator
import TuistLab
import TuistSigning import TuistSigning
import TuistSupport import TuistSupport
import XCTest import XCTest

View File

@ -1,10 +1,10 @@
import Foundation import Foundation
import TuistCache import TuistCache
import TuistCloud
import TuistCoreTesting import TuistCoreTesting
import TuistGenerator import TuistGenerator
import TuistGraph import TuistGraph
import TuistGraphTesting import TuistGraphTesting
import TuistLab
import TuistSupport import TuistSupport
import XCTest import XCTest
@ -32,7 +32,7 @@ final class ProjectMapperProviderTests: TuistUnitTestCase {
// When // When
let got = subject.mapper( let got = subject.mapper(
config: Config.test(cloud: .test(options: [])) config: Config.test(lab: .test(options: []))
) )
// Then // Then

View File

@ -1,11 +1,11 @@
import Foundation import Foundation
import TSCBasic import TSCBasic
import TuistCache import TuistCache
import TuistCloud
import TuistCoreTesting import TuistCoreTesting
import TuistGenerator import TuistGenerator
import TuistGraph import TuistGraph
import TuistGraphTesting import TuistGraphTesting
import TuistLab
import TuistSupport import TuistSupport
import XCTest import XCTest

View File

@ -1,10 +1,10 @@
import Foundation import Foundation
import TSCBasic import TSCBasic
import TuistCloudTesting
import TuistCore import TuistCore
import TuistCoreTesting import TuistCoreTesting
import TuistGraph import TuistGraph
import TuistGraphTesting import TuistGraphTesting
import TuistLabTesting
import TuistLoader import TuistLoader
import TuistLoaderTesting import TuistLoaderTesting
import TuistSupport import TuistSupport
@ -13,21 +13,21 @@ import XCTest
@testable import TuistKit @testable import TuistKit
@testable import TuistSupportTesting @testable import TuistSupportTesting
final class CloudAuthServiceErrorTests: TuistUnitTestCase { final class LabAuthServiceErrorTests: TuistUnitTestCase {
func test_description_when_missingScaleURL() { func test_description_when_missingScaleURL() {
// Given // Given
let subject = CloudAuthServiceError.missingCloudURL let subject = LabAuthServiceError.missingLabURL
// When // When
let got = subject.description let got = subject.description
// Then // Then
XCTAssertEqual(got, "The cloud URL attribute is missing in your project's configuration.") XCTAssertEqual(got, "The lab URL attribute is missing in your project's configuration.")
} }
func test_type_when_missingCloudURL() { func test_type_when_missingCloudURL() {
// Given // Given
let subject = CloudAuthServiceError.missingCloudURL let subject = LabAuthServiceError.missingLabURL
// When // When
let got = subject.type let got = subject.type
@ -37,24 +37,24 @@ final class CloudAuthServiceErrorTests: TuistUnitTestCase {
} }
} }
final class CloudAuthServiceTests: TuistUnitTestCase { final class LabAuthServiceTests: TuistUnitTestCase {
var cloudSessionController: MockCloudSessionController! var labSessionController: MockLabSessionController!
var configLoader: MockConfigLoader! var configLoader: MockConfigLoader!
var subject: CloudAuthService! var subject: LabAuthService!
override func setUp() { override func setUp() {
super.setUp() super.setUp()
cloudSessionController = MockCloudSessionController() labSessionController = MockLabSessionController()
configLoader = MockConfigLoader() configLoader = MockConfigLoader()
subject = CloudAuthService( subject = LabAuthService(
cloudSessionController: cloudSessionController, labSessionController: labSessionController,
configLoader: configLoader configLoader: configLoader
) )
} }
override func tearDown() { override func tearDown() {
super.tearDown() super.tearDown()
cloudSessionController = nil labSessionController = nil
configLoader = nil configLoader = nil
subject = nil subject = nil
} }
@ -62,24 +62,24 @@ final class CloudAuthServiceTests: TuistUnitTestCase {
func test_authenticate_when_cloudURL_is_missing() { func test_authenticate_when_cloudURL_is_missing() {
// Given // Given
configLoader.loadConfigStub = { _ in configLoader.loadConfigStub = { _ in
Config.test(cloud: nil) Config.test(lab: nil)
} }
// Then // Then
XCTAssertThrowsSpecific(try subject.authenticate(), CloudAuthServiceError.missingCloudURL) XCTAssertThrowsSpecific(try subject.authenticate(), LabAuthServiceError.missingLabURL)
} }
func test_authenticate() throws { func test_authenticate() throws {
// Given // Given
let cloudURL = URL.test() let labURL = URL.test()
configLoader.loadConfigStub = { _ in configLoader.loadConfigStub = { _ in
Config.test(cloud: Cloud(url: cloudURL, projectId: "123", options: [])) Config.test(lab: Lab(url: labURL, projectId: "123", options: []))
} }
// When // When
try subject.authenticate() try subject.authenticate()
// Then // Then
XCTAssertTrue(cloudSessionController.authenticateArgs.contains(cloudURL)) XCTAssertTrue(labSessionController.authenticateArgs.contains(labURL))
} }
} }

View File

@ -1,10 +1,10 @@
import Foundation import Foundation
import TSCBasic import TSCBasic
import TuistCloudTesting
import TuistCore import TuistCore
import TuistCoreTesting import TuistCoreTesting
import TuistGraph import TuistGraph
import TuistGraphTesting import TuistGraphTesting
import TuistLabTesting
import TuistLoader import TuistLoader
import TuistLoaderTesting import TuistLoaderTesting
import TuistSupport import TuistSupport
@ -13,21 +13,21 @@ import XCTest
@testable import TuistKit @testable import TuistKit
@testable import TuistSupportTesting @testable import TuistSupportTesting
final class CloudLogoutServiceErrorTests: TuistUnitTestCase { final class LabLogoutServiceErrorTests: TuistUnitTestCase {
func test_description_when_missingScaleURL() { func test_description_when_missingScaleURL() {
// Given // Given
let subject = CloudLogoutServiceError.missingCloudURL let subject = LabLogoutServiceError.missingLabURL
// When // When
let got = subject.description let got = subject.description
// Then // Then
XCTAssertEqual(got, "The cloud URL attribute is missing in your project's configuration.") XCTAssertEqual(got, "The lab URL attribute is missing in your project's configuration.")
} }
func test_type_when_missingScaleURL() { func test_type_when_missingLabURL() {
// Given // Given
let subject = CloudLogoutServiceError.missingCloudURL let subject = LabLogoutServiceError.missingLabURL
// When // When
let got = subject.type let got = subject.type
@ -37,24 +37,24 @@ final class CloudLogoutServiceErrorTests: TuistUnitTestCase {
} }
} }
final class CloudLogoutServiceTests: TuistUnitTestCase { final class LabLogoutServiceTests: TuistUnitTestCase {
var cloudSessionController: MockCloudSessionController! var labSessionController: MockLabSessionController!
var configLoader: MockConfigLoader! var configLoader: MockConfigLoader!
var subject: CloudLogoutService! var subject: LabLogoutService!
override func setUp() { override func setUp() {
super.setUp() super.setUp()
cloudSessionController = MockCloudSessionController() labSessionController = MockLabSessionController()
configLoader = MockConfigLoader() configLoader = MockConfigLoader()
subject = CloudLogoutService( subject = LabLogoutService(
cloudSessionController: cloudSessionController, labSessionController: labSessionController,
configLoader: configLoader configLoader: configLoader
) )
} }
override func tearDown() { override func tearDown() {
super.tearDown() super.tearDown()
cloudSessionController = nil labSessionController = nil
configLoader = nil configLoader = nil
subject = nil subject = nil
} }
@ -62,24 +62,24 @@ final class CloudLogoutServiceTests: TuistUnitTestCase {
func test_printSession_when_cloudURL_is_missing() { func test_printSession_when_cloudURL_is_missing() {
// Given // Given
configLoader.loadConfigStub = { _ in configLoader.loadConfigStub = { _ in
Config.test(cloud: nil) Config.test(lab: nil)
} }
// Then // Then
XCTAssertThrowsSpecific(try subject.logout(), CloudLogoutServiceError.missingCloudURL) XCTAssertThrowsSpecific(try subject.logout(), LabLogoutServiceError.missingLabURL)
} }
func test_printSession() throws { func test_printSession() throws {
// Given // Given
let cloudURL = URL.test() let labURL = URL.test()
configLoader.loadConfigStub = { _ in configLoader.loadConfigStub = { _ in
Config.test(cloud: Cloud(url: cloudURL, projectId: "123", options: [])) Config.test(lab: Lab(url: labURL, projectId: "123", options: []))
} }
// When // When
try subject.logout() try subject.logout()
// Then // Then
XCTAssertTrue(cloudSessionController.logoutArgs.contains(cloudURL)) XCTAssertTrue(labSessionController.logoutArgs.contains(labURL))
} }
} }

View File

@ -1,10 +1,10 @@
import Foundation import Foundation
import TSCBasic import TSCBasic
import TuistCloudTesting
import TuistCore import TuistCore
import TuistCoreTesting import TuistCoreTesting
import TuistGraph import TuistGraph
import TuistGraphTesting import TuistGraphTesting
import TuistLabTesting
import TuistLoader import TuistLoader
import TuistLoaderTesting import TuistLoaderTesting
import TuistSupport import TuistSupport
@ -13,21 +13,21 @@ import XCTest
@testable import TuistKit @testable import TuistKit
@testable import TuistSupportTesting @testable import TuistSupportTesting
final class CloudSessionServiceErrorTests: TuistUnitTestCase { final class LabSessionServiceErrorTests: TuistUnitTestCase {
func test_description_when_missingCloudURL() { func test_description_when_missingCloudURL() {
// Given // Given
let subject = CloudSessionServiceError.missingCloudURL let subject = LabSessionServiceError.missingLabURL
// When // When
let got = subject.description let got = subject.description
// Then // Then
XCTAssertEqual(got, "The cloud URL attribute is missing in your project's configuration.") XCTAssertEqual(got, "The lab URL attribute is missing in your project's configuration.")
} }
func test_type_when_missingCloudURL() { func test_type_when_missingCloudURL() {
// Given // Given
let subject = CloudSessionServiceError.missingCloudURL let subject = LabSessionServiceError.missingLabURL
// When // When
let got = subject.type let got = subject.type
@ -37,24 +37,24 @@ final class CloudSessionServiceErrorTests: TuistUnitTestCase {
} }
} }
final class CloudSessionServiceTests: TuistUnitTestCase { final class LabSessionServiceTests: TuistUnitTestCase {
var cloudSessionController: MockCloudSessionController! var labSessionController: MockLabSessionController!
var configLoader: MockConfigLoader! var configLoader: MockConfigLoader!
var subject: CloudSessionService! var subject: LabSessionService!
override func setUp() { override func setUp() {
super.setUp() super.setUp()
cloudSessionController = MockCloudSessionController() labSessionController = MockLabSessionController()
configLoader = MockConfigLoader() configLoader = MockConfigLoader()
subject = CloudSessionService( subject = LabSessionService(
cloudSessionController: cloudSessionController, labSessionController: labSessionController,
configLoader: configLoader configLoader: configLoader
) )
} }
override func tearDown() { override func tearDown() {
super.tearDown() super.tearDown()
cloudSessionController = nil labSessionController = nil
configLoader = nil configLoader = nil
subject = nil subject = nil
} }
@ -62,24 +62,24 @@ final class CloudSessionServiceTests: TuistUnitTestCase {
func test_printSession_when_cloudURL_is_missing() { func test_printSession_when_cloudURL_is_missing() {
// Given // Given
configLoader.loadConfigStub = { _ in configLoader.loadConfigStub = { _ in
Config.test(cloud: nil) Config.test(lab: nil)
} }
// Then // Then
XCTAssertThrowsSpecific(try subject.printSession(), CloudSessionServiceError.missingCloudURL) XCTAssertThrowsSpecific(try subject.printSession(), LabSessionServiceError.missingLabURL)
} }
func test_printSession() throws { func test_printSession() throws {
// Given // Given
let cloudURL = URL.test() let labURL = URL.test()
configLoader.loadConfigStub = { _ in configLoader.loadConfigStub = { _ in
Config.test(cloud: Cloud(url: cloudURL, projectId: "123", options: [])) Config.test(lab: Lab(url: labURL, projectId: "123", options: []))
} }
// When // When
try subject.printSession() try subject.printSession()
// Then // Then
XCTAssertTrue(cloudSessionController.printSessionArgs.contains(cloudURL)) XCTAssertTrue(labSessionController.printSessionArgs.contains(labURL))
} }
} }

View File

@ -3,13 +3,13 @@ import TSCBasic
import TuistSupport import TuistSupport
import XCTest import XCTest
@testable import TuistCloud @testable import TuistLab
@testable import TuistSupportTesting @testable import TuistSupportTesting
final class CloudSessionControllerErrorTests: TuistUnitTestCase { final class LabSessionControllerErrorTests: TuistUnitTestCase {
func test_description_when_missingParameters() { func test_description_when_missingParameters() {
// Given // Given
let subject = CloudSessionControllerError.missingParameters let subject = LabSessionControllerError.missingParameters
// When // When
let got = subject.description let got = subject.description
@ -20,7 +20,7 @@ final class CloudSessionControllerErrorTests: TuistUnitTestCase {
func test_type_when_missingParameters() { func test_type_when_missingParameters() {
// Given // Given
let subject = CloudSessionControllerError.missingParameters let subject = LabSessionControllerError.missingParameters
// When // When
let got = subject.type let got = subject.type
@ -31,7 +31,7 @@ final class CloudSessionControllerErrorTests: TuistUnitTestCase {
func test_description_when_authenticationError() { func test_description_when_authenticationError() {
// Given // Given
let subject = CloudSessionControllerError.authenticationError("error") let subject = LabSessionControllerError.authenticationError("error")
// When // When
let got = subject.description let got = subject.description
@ -42,7 +42,7 @@ final class CloudSessionControllerErrorTests: TuistUnitTestCase {
func test_type_when_authenticationError() { func test_type_when_authenticationError() {
// Given // Given
let subject = CloudSessionControllerError.authenticationError("error") let subject = LabSessionControllerError.authenticationError("error")
// When // When
let got = subject.type let got = subject.type
@ -53,7 +53,7 @@ final class CloudSessionControllerErrorTests: TuistUnitTestCase {
func test_description_when_invalidParameters() { func test_description_when_invalidParameters() {
// Given // Given
let subject = CloudSessionControllerError.invalidParameters(["invalid"]) let subject = LabSessionControllerError.invalidParameters(["invalid"])
// When // When
let got = subject.description let got = subject.description
@ -64,7 +64,7 @@ final class CloudSessionControllerErrorTests: TuistUnitTestCase {
func test_type_when_invalidParameters() { func test_type_when_invalidParameters() {
// Given // Given
let subject = CloudSessionControllerError.invalidParameters(["invalid"]) let subject = LabSessionControllerError.invalidParameters(["invalid"])
// When // When
let got = subject.type let got = subject.type
@ -74,13 +74,13 @@ final class CloudSessionControllerErrorTests: TuistUnitTestCase {
} }
} }
final class CloudSessionControllerTests: TuistUnitTestCase { final class LabSessionControllerTests: TuistUnitTestCase {
var credentialsStore: MockCredentialsStore! var credentialsStore: MockCredentialsStore!
var httpRedirectListener: MockHTTPRedirectListener! var httpRedirectListener: MockHTTPRedirectListener!
var ciChecker: MockCIChecker! var ciChecker: MockCIChecker!
var opener: MockOpener! var opener: MockOpener!
var serverURL: URL! var serverURL: URL!
var subject: CloudSessionController! var subject: LabSessionController!
override func setUp() { override func setUp() {
credentialsStore = MockCredentialsStore() credentialsStore = MockCredentialsStore()
@ -88,7 +88,7 @@ final class CloudSessionControllerTests: TuistUnitTestCase {
ciChecker = MockCIChecker() ciChecker = MockCIChecker()
opener = MockOpener() opener = MockOpener()
serverURL = URL.test() serverURL = URL.test()
subject = CloudSessionController( subject = LabSessionController(
credentialsStore: credentialsStore, credentialsStore: credentialsStore,
httpRedirectListener: httpRedirectListener, httpRedirectListener: httpRedirectListener,
ciChecker: ciChecker, ciChecker: ciChecker,
@ -110,14 +110,14 @@ final class CloudSessionControllerTests: TuistUnitTestCase {
func test_authenticate_when_parametersAreMissing() throws { func test_authenticate_when_parametersAreMissing() throws {
// Given // Given
httpRedirectListener.listenStub = { (port, path, message, _) -> (Swift.Result<[String: String]?, HTTPRedirectListenerError>) in httpRedirectListener.listenStub = { (port, path, message, _) -> (Swift.Result<[String: String]?, HTTPRedirectListenerError>) in
XCTAssertEqual(port, CloudSessionController.port) XCTAssertEqual(port, LabSessionController.port)
XCTAssertEqual(path, "auth") XCTAssertEqual(path, "auth")
XCTAssertEqual(message, "Switch back to your terminal to continue the authentication.") XCTAssertEqual(message, "Switch back to your terminal to continue the authentication.")
return .success(nil) return .success(nil)
} }
// Then // Then
XCTAssertThrowsSpecific(try subject.authenticate(serverURL: serverURL), CloudSessionControllerError.missingParameters) XCTAssertThrowsSpecific(try subject.authenticate(serverURL: serverURL), LabSessionControllerError.missingParameters)
XCTAssertPrinterOutputContains(""" XCTAssertPrinterOutputContains("""
Opening \(authURL().absoluteString) to start the authentication flow Opening \(authURL().absoluteString) to start the authentication flow
""") """)
@ -126,14 +126,14 @@ final class CloudSessionControllerTests: TuistUnitTestCase {
func test_authenticate_when_parametersIncludeError() throws { func test_authenticate_when_parametersIncludeError() throws {
// Given // Given
httpRedirectListener.listenStub = { (port, path, message, _) -> (Swift.Result<[String: String]?, HTTPRedirectListenerError>) in httpRedirectListener.listenStub = { (port, path, message, _) -> (Swift.Result<[String: String]?, HTTPRedirectListenerError>) in
XCTAssertEqual(port, CloudSessionController.port) XCTAssertEqual(port, LabSessionController.port)
XCTAssertEqual(path, "auth") XCTAssertEqual(path, "auth")
XCTAssertEqual(message, "Switch back to your terminal to continue the authentication.") XCTAssertEqual(message, "Switch back to your terminal to continue the authentication.")
return .success(["error": "value"]) return .success(["error": "value"])
} }
// Then // Then
XCTAssertThrowsSpecific(try subject.authenticate(serverURL: serverURL), CloudSessionControllerError.authenticationError("value")) XCTAssertThrowsSpecific(try subject.authenticate(serverURL: serverURL), LabSessionControllerError.authenticationError("value"))
XCTAssertPrinterOutputContains(""" XCTAssertPrinterOutputContains("""
Opening \(authURL().absoluteString) to start the authentication flow Opening \(authURL().absoluteString) to start the authentication flow
""") """)
@ -142,7 +142,7 @@ final class CloudSessionControllerTests: TuistUnitTestCase {
func test_authenticate_when_tokenAndAccountParametersAreIncluded() throws { func test_authenticate_when_tokenAndAccountParametersAreIncluded() throws {
// Given // Given
httpRedirectListener.listenStub = { (port, path, message, _) -> (Swift.Result<[String: String]?, HTTPRedirectListenerError>) in httpRedirectListener.listenStub = { (port, path, message, _) -> (Swift.Result<[String: String]?, HTTPRedirectListenerError>) in
XCTAssertEqual(port, CloudSessionController.port) XCTAssertEqual(port, LabSessionController.port)
XCTAssertEqual(path, "auth") XCTAssertEqual(path, "auth")
XCTAssertEqual(message, "Switch back to your terminal to continue the authentication.") XCTAssertEqual(message, "Switch back to your terminal to continue the authentication.")
return .success(["account": "account", "token": "token"]) return .success(["account": "account", "token": "token"])
@ -164,14 +164,14 @@ final class CloudSessionControllerTests: TuistUnitTestCase {
func test_authenticate_when_parametersContainInvalidKeys() throws { func test_authenticate_when_parametersContainInvalidKeys() throws {
// Given // Given
httpRedirectListener.listenStub = { (port, path, message, _) -> (Swift.Result<[String: String]?, HTTPRedirectListenerError>) in httpRedirectListener.listenStub = { (port, path, message, _) -> (Swift.Result<[String: String]?, HTTPRedirectListenerError>) in
XCTAssertEqual(port, CloudSessionController.port) XCTAssertEqual(port, LabSessionController.port)
XCTAssertEqual(path, "auth") XCTAssertEqual(path, "auth")
XCTAssertEqual(message, "Switch back to your terminal to continue the authentication.") XCTAssertEqual(message, "Switch back to your terminal to continue the authentication.")
return .success(["invalid": "value"]) return .success(["invalid": "value"])
} }
// Then // Then
XCTAssertThrowsSpecific(try subject.authenticate(serverURL: serverURL), CloudSessionControllerError.invalidParameters(["invalid"])) XCTAssertThrowsSpecific(try subject.authenticate(serverURL: serverURL), LabSessionControllerError.invalidParameters(["invalid"]))
XCTAssertPrinterOutputContains(""" XCTAssertPrinterOutputContains("""
Opening \(authURL().absoluteString) to start the authentication flow Opening \(authURL().absoluteString) to start the authentication flow
""") """)

View File

@ -3,20 +3,20 @@ import TSCBasic
import TuistSupport import TuistSupport
import XCTest import XCTest
@testable import TuistCloud @testable import TuistLab
@testable import TuistSupportTesting @testable import TuistSupportTesting
final class CloudHTTPRequestAuthenticatorTests: TuistUnitTestCase { final class LabHTTPRequestAuthenticatorTests: TuistUnitTestCase {
var ciChecker: MockCIChecker! var ciChecker: MockCIChecker!
var credentialsStore: MockCredentialsStore! var credentialsStore: MockCredentialsStore!
var subject: CloudHTTPRequestAuthenticator! var subject: LabHTTPRequestAuthenticator!
var environmentVariables: [String: String] = [:] var environmentVariables: [String: String] = [:]
override func setUp() { override func setUp() {
super.setUp() super.setUp()
ciChecker = MockCIChecker() ciChecker = MockCIChecker()
credentialsStore = MockCredentialsStore() credentialsStore = MockCredentialsStore()
subject = CloudHTTPRequestAuthenticator( subject = LabHTTPRequestAuthenticator(
ciChecker: ciChecker, ciChecker: ciChecker,
environmentVariables: { self.environmentVariables }, environmentVariables: { self.environmentVariables },
credentialsStore: credentialsStore credentialsStore: credentialsStore
@ -34,8 +34,8 @@ final class CloudHTTPRequestAuthenticatorTests: TuistUnitTestCase {
// Given // Given
ciChecker.isCIStub = true ciChecker.isCIStub = true
let token = "TOKEN" let token = "TOKEN"
environmentVariables[Constants.EnvironmentVariables.cloudToken] = token environmentVariables[Constants.EnvironmentVariables.labToken] = token
let request = URLRequest(url: URL(string: "https://cloud.tuist.io/path")!) let request = URLRequest(url: URL(string: "https://lab.tuist.io/path")!)
// When // When
let got = try subject.authenticate(request: request) let got = try subject.authenticate(request: request)
@ -49,8 +49,8 @@ final class CloudHTTPRequestAuthenticatorTests: TuistUnitTestCase {
ciChecker.isCIStub = false ciChecker.isCIStub = false
let token = "TOKEN" let token = "TOKEN"
let credentials = Credentials(token: token, account: "test") let credentials = Credentials(token: token, account: "test")
try credentialsStore.store(credentials: credentials, serverURL: URL(string: "https://cloud.tuist.io")!) try credentialsStore.store(credentials: credentials, serverURL: URL(string: "https://lab.tuist.io")!)
let request = URLRequest(url: URL(string: "https://cloud.tuist.io/path")!) let request = URLRequest(url: URL(string: "https://lab.tuist.io/path")!)
// When // When
let got = try subject.authenticate(request: request) let got = try subject.authenticate(request: request)

View File

@ -74,7 +74,7 @@ final class ConfigLoaderTests: TuistUnitTestCase {
// Then // Then
XCTAssertEqual(result, TuistGraph.Config( XCTAssertEqual(result, TuistGraph.Config(
compatibleXcodeVersions: .all, compatibleXcodeVersions: .all,
cloud: nil, lab: nil,
cache: nil, cache: nil,
plugins: [], plugins: [],
generationOptions: [.developmentRegion("fr")], generationOptions: [.developmentRegion("fr")],
@ -116,7 +116,7 @@ final class ConfigLoaderTests: TuistUnitTestCase {
// Then // Then
XCTAssertEqual(result, TuistGraph.Config( XCTAssertEqual(result, TuistGraph.Config(
compatibleXcodeVersions: .all, compatibleXcodeVersions: .all,
cloud: nil, lab: nil,
cache: nil, cache: nil,
plugins: [], plugins: [],
generationOptions: [.developmentRegion("fr")], generationOptions: [.developmentRegion("fr")],

View File

@ -244,7 +244,7 @@ final class PluginServiceTests: TuistTestCase {
private func mockConfig(plugins: [TuistGraph.PluginLocation]) -> TuistGraph.Config { private func mockConfig(plugins: [TuistGraph.PluginLocation]) -> TuistGraph.Config {
Config( Config(
compatibleXcodeVersions: .all, compatibleXcodeVersions: .all,
cloud: nil, lab: nil,
cache: nil, cache: nil,
plugins: plugins, plugins: plugins,
generationOptions: [], generationOptions: [],