Skip to content

Commit

Permalink
Merge 68fe483 into 51f2294
Browse files Browse the repository at this point in the history
  • Loading branch information
evandcoleman authored Sep 24, 2021
2 parents 51f2294 + 68fe483 commit 879037b
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 88 deletions.
2 changes: 1 addition & 1 deletion Sources/Scipio/Commands/BuildCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extension Command {
)
}

@OptionGroup var options: Main.Options
@OptionGroup var options: Run.Options
@OptionGroup var buildOptions: Options

func run() throws {
Expand Down
90 changes: 90 additions & 0 deletions Sources/Scipio/Commands/RunCommand.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import ArgumentParser
import PathKit
import ScipioKit

extension Command {
struct Run: ParsableCommand {
static var configuration: CommandConfiguration {
.init(
commandName: "run",
abstract: "Builds and uploads packages"
)
}

@OptionGroup var options: Options
@OptionGroup var buildOptions: Build.Options
@OptionGroup var uploadOptions: Upload.Options

func run() throws {
log.useColors = !options.noColors
log.level = options.logLevel

if let path = options.config {
Config.setPath(Path(path), buildDirectory: options.buildPath)
} else {
Config.readConfig()
}

let artifacts = try Runner.build(
dependencies: options.packages,
platforms: Config.current.platforms,
force: options.force || buildOptions.forceBuild,
skipClean: options.skipClean
).filter { artifact in
if let packages = options.packages {
return packages.contains(artifact.parentName)
} else {
return true
}
}

let cachedArtifacts = try Runner.upload(
artifacts: artifacts,
force: options.force || uploadOptions.forceUpload,
skipClean: options.skipClean
)

try Runner.updatePackageManifest(at: Config.current.packageRoot, with: cachedArtifacts, removeMissing: options.packages?.isEmpty != false)

log.success("✅ Done!")
}
}
}

extension Command.Run {
struct Options: ParsableArguments {
@Flag(help: "Enable verbose logging.")
var verbose: Bool = false

@Flag(help: "Enable quiet logging.")
var quiet: Bool = false

@Flag(help: "Disable color output")
var noColors: Bool = false

@Option(help: "Path to a config file")
var config: String?

@Argument(help: "An array of dependencies to process", transform: { $0.components(separatedBy: ",") })
var packages: [String]?

@Option(help: "Path to store and find build artifacts")
var buildPath: String?

@Flag(help: "If true will force build and upload packages")
var force: Bool = false

@Flag(help: "If true will reuse existing artifacts")
var skipClean: Bool = false

var logLevel: Log.Level {
if verbose {
return .verbose
} else if quiet {
return .error
} else {
return .info
}
}
}
}
45 changes: 43 additions & 2 deletions Sources/Scipio/Commands/UploadCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extension Command {
)
}

@OptionGroup var options: Main.Options
@OptionGroup var options: Run.Options
@OptionGroup var uploadOptions: Options

func run() throws {
Expand All @@ -24,7 +24,48 @@ extension Command {
Config.readConfig()
}

log.fatal("Not yet implemented")
let processorOptions = ProcessorOptions(
platforms: Config.current.platforms,
force: options.force || uploadOptions.forceUpload,
skipClean: options.skipClean
)

var artifacts: [AnyArtifact] = []

if let packages = Config.current.packages, !packages.isEmpty {
let processor = PackageProcessor(dependencies: packages, options: processorOptions)
let filtered = options.packages?
.compactMap { name in packages.first { $0.name == name } }
artifacts <<< try processor.existingArtifacts(dependencies: filtered).wait()
}

if let binaries = Config.current.binaries, !binaries.isEmpty {
let processor = BinaryProcessor(dependencies: binaries, options: processorOptions)
let filtered = options.packages?
.compactMap { name in binaries.first { $0.name == name } }
artifacts <<< try processor.existingArtifacts(dependencies: filtered).wait()
}

if let pods = Config.current.pods, !pods.isEmpty {
let processor = CocoaPodProcessor(dependencies: pods, options: processorOptions)
let filtered = options.packages?
.compactMap { name in pods.first { $0.name == name } }
artifacts <<< try processor.existingArtifacts(dependencies: filtered).wait()
}

let cachedArtifacts = try Runner.upload(
artifacts: artifacts,
force: options.force || uploadOptions.forceUpload,
skipClean: options.skipClean
)

try Runner.updatePackageManifest(
at: Config.current.packageRoot,
with: cachedArtifacts,
removeMissing: options.packages?.isEmpty != false
)

log.success("✅ Done!")
}
}
}
Expand Down
81 changes: 3 additions & 78 deletions Sources/Scipio/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,90 +10,15 @@ extension Command {
.init(
commandName: "Scipio",
abstract: "A program to pre-build and cache Swift packages",
version: "0.2.1",
version: "0.2.2",
subcommands: [
Command.Build.self,
Command.Upload.self,
]
],
defaultSubcommand: Command.Run.self
)
}

@OptionGroup var options: Options
@OptionGroup var buildOptions: Build.Options
@OptionGroup var uploadOptions: Upload.Options

func run() throws {
log.useColors = !options.noColors
log.level = options.logLevel

if let path = options.config {
Config.setPath(Path(path), buildDirectory: options.buildPath)
} else {
Config.readConfig()
}

let artifacts = try Runner.build(
dependencies: options.packages,
platforms: Config.current.platforms,
force: options.force || buildOptions.forceBuild,
skipClean: options.skipClean
).filter { artifact in
if let packages = options.packages {
return packages.contains(artifact.parentName)
} else {
return true
}
}

let cachedArtifacts = try Runner.upload(
artifacts: artifacts,
force: options.force || uploadOptions.forceUpload,
skipClean: options.skipClean
)

try Runner.updatePackageManifest(at: Config.current.packageRoot, with: cachedArtifacts, removeMissing: options.packages?.isEmpty != false)

log.success("✅ Done!")
}
}
}

extension Command.Main {
struct Options: ParsableArguments {
@Flag(help: "Enable verbose logging.")
var verbose: Bool = false

@Flag(help: "Enable quiet logging.")
var quiet: Bool = false

@Flag(help: "Disable color output")
var noColors: Bool = false

@Option(help: "Path to a config file")
var config: String?

@Argument(help: "An array of dependencies to process", transform: { $0.components(separatedBy: ",") })
var packages: [String]?

@Option(help: "Path to store and find build artifacts")
var buildPath: String?

@Flag(help: "If true will force build and upload packages")
var force: Bool = false

@Flag(help: "If true will reuse existing artifacts")
var skipClean: Bool = false

var logLevel: Log.Level {
if verbose {
return .verbose
} else if quiet {
return .error
} else {
return .info
}
}
}
}

Command.Main.main()
6 changes: 4 additions & 2 deletions Sources/ScipioKit/Cache Engines/CacheEngineDelegator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,10 @@ public final class CacheEngineDelegator: Decodable, Equatable, CacheEngine {
return self.cache
.get(product: product, in: parentName, version: version, destination: normalizedDestination)
.tryMap { artifact in
try self.versionCachePath(for: artifact.name, version: artifact.version)
.write(artifact.path.checksum(.sha256))
if artifact.path.exists, artifact.path.isFile {
try self.versionCachePath(for: artifact.name, version: artifact.version)
.write(artifact.path.checksum(.sha256))
}

return artifact
}
Expand Down
19 changes: 14 additions & 5 deletions Sources/ScipioKit/Cache Engines/HTTPCacheEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ public protocol HTTPCacheEngineProtocol: CacheEngine {
var uploadBaseUrl: URL { get }
var downloadBaseUrl: URL { get }
var urlSession: URLSession { get }

func uploadUrlRequest(url: URL) -> URLRequest
}

public enum HTTPCacheEngineError: Error {
Expand All @@ -25,6 +27,17 @@ extension HTTPCacheEngineProtocol {
return url(for: product, version: version, baseUrl: downloadBaseUrl)
}

public func uploadUrlRequest(url: URL) -> URLRequest {
var request = URLRequest(url: url)

request.httpMethod = "PUT"
request.allHTTPHeaderFields = [
"Content-Type": "application/zip"
]

return request
}

public func exists(product: String, version: String) -> AnyPublisher<Bool, Error> {
var request = URLRequest(url: downloadUrl(for: product, version: version))
request.httpMethod = "HEAD"
Expand All @@ -38,11 +51,7 @@ extension HTTPCacheEngineProtocol {

public func put(artifact: CompressedArtifact) -> AnyPublisher<CachedArtifact, Error> {
return Future { promise in
var request = URLRequest(url: uploadUrl(for: artifact.name, version: artifact.version))
request.httpMethod = "PUT"
request.allHTTPHeaderFields = [
"Content-Type": "application/zip"
]
let request = uploadUrlRequest(url: uploadUrl(for: artifact.name, version: artifact.version))

let task = urlSession
.uploadTask(with: request, fromFile: artifact.path.url, progressHandler: { log.progress(percent: $0) }) { data, response, error in
Expand Down
4 changes: 4 additions & 0 deletions Sources/ScipioKit/Cache Engines/LocalCacheEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ public struct LocalCacheEngine: CacheEngine, Decodable, Equatable {
return Just(cachePath)
.tryMap { cachePath -> Artifact in
if cachePath.exists {
if destination.exists {
try destination.delete()
}

try cachePath.copy(destination)

return Artifact(
Expand Down
12 changes: 12 additions & 0 deletions Sources/ScipioKit/Cache Engines/S3CacheEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,16 @@ public struct S3CacheEngine: HTTPCacheEngineProtocol, Decodable, Equatable {
case path
case cdnUrl
}

public func uploadUrlRequest(url: URL) -> URLRequest {
var request = URLRequest(url: url)

request.httpMethod = "PUT"
request.allHTTPHeaderFields = [
"Content-Type": "application/zip",
"x-amz-acl": "bucket-owner-full-control",
]

return request
}
}
10 changes: 10 additions & 0 deletions Sources/ScipioKit/Dependency Processors/CocoaPodProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,16 @@ project '\(projectPath.string)'
notIn: projectProducts
)

if filteredProductNames.contains(dependency.name) {
for target in project.pbxproj.targets(named: dependency.name) {
for config in target.buildConfigurationList?.buildConfigurations ?? [] {
config.buildSettings["PRODUCT_NAME"] = "\(dependency.name)Package"
}
}

try project.write(path: podsProjectPath)
}

return CocoaPodDescriptor(
name: dependency.name,
resolvedVersions: versions,
Expand Down
30 changes: 30 additions & 0 deletions Sources/ScipioKit/Dependency Processors/DependencyProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,36 @@ public protocol DependencyProducts {
}

extension DependencyProcessor {
public func existingArtifacts(dependencies onlyDependencies: [Input]? = nil) -> AnyPublisher<[AnyArtifact], Error> {
let dependencies = onlyDependencies ?? self.dependencies

return preProcess()
.map { resolvedDependencies -> [AnyArtifact] in
return resolvedDependencies
.filter { resolved in dependencies.contains(where: { $0.name == resolved.name }) }
.flatMap { dependency -> [AnyArtifact] in
return (dependency
.productNames ?? [])
.compactMap { productName in
let path = Config.current.buildPath + "\(productName).xcframework.zip"

guard path.exists else {
log.warning("Skipping \(path.lastComponent) because it doesn't exist.")
return nil
}

return AnyArtifact(Artifact(
name: productName,
parentName: dependency.name,
version: dependency.version(for: productName),
path: path
))
}
}
}
.eraseToAnyPublisher()
}

public func process(dependencies onlyDependencies: [Input]? = nil, accumulatedResolvedDependencies: [DependencyProducts]) -> AnyPublisher<([AnyArtifact], [DependencyProducts]), Error> {
return preProcess()
.tryFlatMap { dependencyProducts -> AnyPublisher<([AnyArtifact], [DependencyProducts]), Error> in
Expand Down

0 comments on commit 879037b

Please sign in to comment.