Skip to content

Commit

Permalink
Enable built-in web server for serving build artifacts
Browse files Browse the repository at this point in the history
  • Loading branch information
Vladislav Alekseev committed Dec 13, 2021
1 parent 7ea8cd3 commit c160003
Show file tree
Hide file tree
Showing 36 changed files with 675 additions and 154 deletions.
50 changes: 43 additions & 7 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -282,11 +282,12 @@ let package = Package(
name: "Deployer",
dependencies: [
"EmceeLogging",
.product(name: "FileSystem", package: "CommandLineToolkit"),
.product(name: "PathLib", package: "CommandLineToolkit"),
.product(name: "ProcessController", package: "CommandLineToolkit"),
"QueueModels",
.product(name: "Tmp", package: "CommandLineToolkit"),
"UniqueIdentifierGenerator",
"Zip",
],
path: "Sources/Deployer"
),
Expand All @@ -302,12 +303,12 @@ let package = Package(
name: "DeployerTests",
dependencies: [
"Deployer",
.product(name: "FileSystemTestHelpers", package: "CommandLineToolkit"),
.product(name: "PathLib", package: "CommandLineToolkit"),
.product(name: "ProcessController", package: "CommandLineToolkit"),
.product(name: "ProcessControllerTestHelpers", package: "CommandLineToolkit"),
.product(name: "TestHelpers", package: "CommandLineToolkit"),
.product(name: "Tmp", package: "CommandLineToolkit"),
"UniqueIdentifierGeneratorTestHelpers",
"ZipTestHelpers",
],
path: "Tests/DeployerTests"
),
Expand Down Expand Up @@ -352,15 +353,16 @@ let package = Package(
dependencies: [
"Deployer",
"EmceeLogging",
.product(name: "FileSystem", package: "CommandLineToolkit"),
.product(name: "LaunchdUtils", package: "CommandLineToolkit"),
.product(name: "PathLib", package: "CommandLineToolkit"),
.product(name: "ProcessController", package: "CommandLineToolkit"),
"QueueModels",
"SSHDeployer",
.product(name: "SocketModels", package: "CommandLineToolkit"),
.product(name: "Tmp", package: "CommandLineToolkit"),
"TypedResourceLocation",
"UniqueIdentifierGenerator",
"Zip",
],
path: "Sources/DistDeployer"
),
Expand Down Expand Up @@ -541,6 +543,7 @@ let package = Package(
"QueueServer",
"QueueServerPortProvider",
"RESTMethods",
"RESTServer",
"RemotePortDeterminer",
"RequestSender",
"ResourceLocation",
Expand All @@ -554,6 +557,7 @@ let package = Package(
"SimulatorPoolModels",
.product(name: "SocketModels", package: "CommandLineToolkit"),
.product(name: "Statsd", package: "CommandLineToolkit"),
.product(name: "Swifter", package: "Swifter"),
.product(name: "SynchronousWaiter", package: "CommandLineToolkit"),
"TestArgFile",
"TestDiscovery",
Expand All @@ -565,6 +569,7 @@ let package = Package(
"WorkerAlivenessProvider",
"WorkerCapabilities",
"WorkerCapabilitiesModels",
"Zip",
],
path: "Sources/EmceeLib"
),
Expand Down Expand Up @@ -774,10 +779,10 @@ let package = Package(
"DistWorkerModels",
"EmceeLogging",
"FileLock",
.product(name: "FileSystem", package: "CommandLineToolkit"),
"LocalHostDeterminer",
"LoggingSetup",
"MetricsExtensions",
.product(name: "ProcessController", package: "CommandLineToolkit"),
"QueueCommunication",
"QueueModels",
"QueueServer",
Expand All @@ -787,6 +792,7 @@ let package = Package(
.product(name: "SynchronousWaiter", package: "CommandLineToolkit"),
.product(name: "Tmp", package: "CommandLineToolkit"),
"UniqueIdentifierGenerator",
"Zip",
],
path: "Sources/LocalQueueServerRunner"
),
Expand Down Expand Up @@ -1262,6 +1268,7 @@ let package = Package(
dependencies: [
"AutomaticTermination",
"EmceeLogging",
.product(name: "PathLib", package: "CommandLineToolkit"),
"QueueModels",
"RESTInterfaces",
"RESTMethods",
Expand Down Expand Up @@ -1559,24 +1566,26 @@ let package = Package(
dependencies: [
"Deployer",
"EmceeLogging",
.product(name: "FileSystem", package: "CommandLineToolkit"),
.product(name: "PathLib", package: "CommandLineToolkit"),
.product(name: "ProcessController", package: "CommandLineToolkit"),
.product(name: "Shout", package: "Shout"),
.product(name: "Tmp", package: "CommandLineToolkit"),
"UniqueIdentifierGenerator",
"Zip",
],
path: "Sources/SSHDeployer"
),
.testTarget(
name: "SSHDeployerTests",
dependencies: [
"Deployer",
.product(name: "FileSystemTestHelpers", package: "CommandLineToolkit"),
.product(name: "PathLib", package: "CommandLineToolkit"),
.product(name: "ProcessControllerTestHelpers", package: "CommandLineToolkit"),
"SSHDeployer",
.product(name: "TestHelpers", package: "CommandLineToolkit"),
.product(name: "Tmp", package: "CommandLineToolkit"),
"UniqueIdentifierGeneratorTestHelpers",
"ZipTestHelpers",
],
path: "Tests/SSHDeployerTests"
),
Expand Down Expand Up @@ -2072,5 +2081,32 @@ let package = Package(
],
path: "Sources/XcodebuildTestRunnerConstants"
),
.target(
name: "Zip",
dependencies: [
.product(name: "PathLib", package: "CommandLineToolkit"),
.product(name: "ProcessController", package: "CommandLineToolkit"),
],
path: "Sources/Zip"
),
.target(
name: "ZipTestHelpers",
dependencies: [
.product(name: "PathLib", package: "CommandLineToolkit"),
.product(name: "TestHelpers", package: "CommandLineToolkit"),
"Zip",
],
path: "Tests/ZipTestHelpers"
),
.testTarget(
name: "ZipTests",
dependencies: [
.product(name: "PathLib", package: "CommandLineToolkit"),
.product(name: "ProcessControllerTestHelpers", package: "CommandLineToolkit"),
.product(name: "TestHelpers", package: "CommandLineToolkit"),
"Zip",
],
path: "Tests/ZipTests"
),
]
)
19 changes: 13 additions & 6 deletions Sources/Deployer/Deployer.swift
Original file line number Diff line number Diff line change
@@ -1,39 +1,43 @@
import FileSystem
import Foundation
import EmceeLogging
import PathLib
import ProcessController
import Tmp
import UniqueIdentifierGenerator
import Zip

/** Basic class that defines a logic for deploying a number of DeployableItems. */
open class Deployer {
public let deploymentId: String
public let deployables: [DeployableItem]
public let deployableCommands: [DeployableCommand]
public let destination: DeploymentDestination
private let fileSystem: FileSystem
private let logger: ContextualLogger
private let processControllerProvider: ProcessControllerProvider
private let temporaryFolder: TemporaryFolder
private let uniqueIdentifierGenerator: UniqueIdentifierGenerator
private let zipCompressor: ZipCompressor

public init(
deploymentId: String,
deployables: [DeployableItem],
deployableCommands: [DeployableCommand],
destination: DeploymentDestination,
fileSystem: FileSystem,
logger: ContextualLogger,
processControllerProvider: ProcessControllerProvider,
temporaryFolder: TemporaryFolder,
uniqueIdentifierGenerator: UniqueIdentifierGenerator
uniqueIdentifierGenerator: UniqueIdentifierGenerator,
zipCompressor: ZipCompressor
) throws {
self.deploymentId = deploymentId
self.deployables = deployables
self.deployableCommands = deployableCommands
self.destination = destination
self.fileSystem = fileSystem
self.logger = logger
self.processControllerProvider = processControllerProvider
self.temporaryFolder = temporaryFolder
self.uniqueIdentifierGenerator = uniqueIdentifierGenerator
self.zipCompressor = zipCompressor
}

/** Deploys all the deployable items and invokes deployment commands. */
Expand All @@ -51,7 +55,10 @@ open class Deployer {
let syncQueue = DispatchQueue(label: "Deployer.syncQueue")
var deployablesFailedToPrepare = [DeployableItem]()
var pathToDeployable = [AbsolutePath: DeployableItem]()
let packager = Packager(processControllerProvider: processControllerProvider)
let packager = Packager(
fileSystem: fileSystem,
zipCompressor: zipCompressor
)

let queue = DispatchQueue(
label: "Deployer.queue",
Expand Down
57 changes: 28 additions & 29 deletions Sources/Deployer/Packager.swift
Original file line number Diff line number Diff line change
@@ -1,53 +1,52 @@
import Foundation
import FileSystem
import PathLib
import ProcessController
import Tmp
import Zip

/** Packs DeployableItem, returns URL to a single file with a package. */
public final class Packager {
private let fileManager = FileManager()
private let processControllerProvider: ProcessControllerProvider
private let fileSystem: FileSystem
private let zipCompressor: ZipCompressor

public init(processControllerProvider: ProcessControllerProvider) {
self.processControllerProvider = processControllerProvider
public init(
fileSystem: FileSystem,
zipCompressor: ZipCompressor
) {
self.fileSystem = fileSystem
self.zipCompressor = zipCompressor
}

/**
* Packs a given DeployableItem into provided temporary folder and returns a URL to the package.
* If the DeployableItem has been already packed, it will return URL without re-packing it.
*/
public func preparePackage(deployable: DeployableItem, packageFolder: AbsolutePath) throws -> AbsolutePath {
let archivePath = deployable.name.components(separatedBy: "/").reduce(packageFolder) { $0.appending($1) }
try fileManager.createDirectory(atPath: archivePath.removingLastComponent)
let archivePath = deployable.name.components(separatedBy: "/")
.reduce(packageFolder) { $0.appending($1) }

if fileManager.fileExists(atPath: archivePath.pathString) {
try fileSystem.createDirectory(
path: archivePath.removingLastComponent,
withIntermediateDirectories: true,
ignoreExisting: true
)

if fileSystem.exists(path: archivePath) {
return archivePath
}

let temporaryFolder = try TemporaryFolder()

for file in deployable.files {
let containerPath = file.destination.removingLastComponent
if !fileManager.fileExists(atPath: containerPath.pathString) {
_ = try temporaryFolder.createDirectory(components: containerPath.components)
}
try fileManager.copyItem(
atPath: file.source.pathString,
toPath: temporaryFolder.absolutePath.appending(relativePath: file.destination).pathString
try fileSystem.copy(
source: file.source,
destination: packageFolder.appending(relativePath: file.destination),
overwrite: false,
ensureDirectoryExists: true
)
}

let controller = try processControllerProvider.createProcessController(
subprocess: Subprocess(
arguments: ["/usr/bin/zip", archivePath.pathString, "-r", "."],
workingDirectory: temporaryFolder.absolutePath
)
return try zipCompressor.createArchive(
archivePath: archivePath,
workingDirectory: packageFolder,
contentsToCompress: "."
)
try controller.startAndListenUntilProcessDies()
if archivePath.extension.isEmpty {
return archivePath.appending(extension: "zip")
} else {
return archivePath
}
}
}
20 changes: 12 additions & 8 deletions Sources/DistDeployer/DistDeployer.swift
Original file line number Diff line number Diff line change
@@ -1,42 +1,45 @@
import Deployer
import EmceeLogging
import FileSystem
import Foundation
import ProcessController
import SSHDeployer
import Tmp
import UniqueIdentifierGenerator
import Zip

/// Class for generic usage: it deploys the provided deployable items to the provided deployment destinations, and
/// invokes the provided deployable commands.
final class DistDeployer {

private let deploymentId: String
private let deploymentDestination: DeploymentDestination
private let deployableItems: [DeployableItem]
private let deployableCommands: [DeployableCommand]
private let fileSystem: FileSystem
private let logger: ContextualLogger
private let processControllerProvider: ProcessControllerProvider
private let tempFolder: TemporaryFolder
private let uniqueIdentifierGenerator: UniqueIdentifierGenerator
private let zipCompressor: ZipCompressor

public init(
deploymentId: String,
deploymentDestination: DeploymentDestination,
deployableItems: [DeployableItem],
deployableCommands: [DeployableCommand],
fileSystem: FileSystem,
logger: ContextualLogger,
processControllerProvider: ProcessControllerProvider,
tempFolder: TemporaryFolder,
uniqueIdentifierGenerator: UniqueIdentifierGenerator
uniqueIdentifierGenerator: UniqueIdentifierGenerator,
zipCompressor: ZipCompressor
) {
self.deploymentId = deploymentId
self.deploymentDestination = deploymentDestination
self.deployableItems = deployableItems
self.deployableCommands = deployableCommands
self.fileSystem = fileSystem
self.logger = logger
self.processControllerProvider = processControllerProvider
self.tempFolder = tempFolder
self.uniqueIdentifierGenerator = uniqueIdentifierGenerator
self.zipCompressor = zipCompressor
}

public func deploy() throws {
Expand All @@ -46,10 +49,11 @@ final class DistDeployer {
deployables: deployableItems,
deployableCommands: deployableCommands,
destination: deploymentDestination,
fileSystem: fileSystem,
logger: logger,
processControllerProvider: processControllerProvider,
temporaryFolder: tempFolder,
uniqueIdentifierGenerator: uniqueIdentifierGenerator
uniqueIdentifierGenerator: uniqueIdentifierGenerator,
zipCompressor: zipCompressor
)
try deployer.deploy()
}
Expand Down
Loading

0 comments on commit c160003

Please sign in to comment.