Implement basic test command
This commit is contained in:
parent
3a0c68ed88
commit
0695689d3d
|
@ -3,10 +3,10 @@
|
|||
name: Danger
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push or pull request
|
||||
# events but only for the master branch
|
||||
# events but only for the main branch
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master]
|
||||
branches: [main]
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
|
|
|
@ -2,9 +2,9 @@ name: Build and test
|
|||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
macos_build:
|
||||
|
|
10
README.md
10
README.md
|
@ -22,12 +22,12 @@ It is currently work in progress, so watch the repository for imminent updates!
|
|||
- macOS 10.15 and Xcode 11.4 or later for macOS users.
|
||||
- [Swift 5.2 or later](https://swift.org/download/) for Linux users.
|
||||
|
||||
On either platform you should install cross-compilation SwiftWasm toolchain via
|
||||
[`swiftenv`](https://github.com/kylef/swiftenv) as described in [the SwiftWasm
|
||||
Book](https://swiftwasm.github.io/swiftwasm-book/GettingStarted.html), in addition to the
|
||||
On either platform you should install cross-compilation SwiftWasm toolchain via
|
||||
[`swiftenv`](https://github.com/kylef/swiftenv) as described in [the SwiftWasm
|
||||
Book](https://swiftwasm.github.io/swiftwasm-book/GettingStarted.html), in addition to the
|
||||
host Swift 5.2 toolchain mentioned above.
|
||||
|
||||
In the future, manual installation of SwiftWasm won't be required, please see issue
|
||||
In the future, manual installation of SwiftWasm won't be required, please see issue
|
||||
[#3](https://github.com/swiftwasm/carton/issues/3) for more details.
|
||||
|
||||
## Installation
|
||||
|
@ -83,6 +83,6 @@ PRs before merging.
|
|||
### Code of Conduct
|
||||
|
||||
This project adheres to the [Contributor Covenant Code of
|
||||
Conduct](https://github.com/swiftwasm/carton/blob/master/CODE_OF_CONDUCT.md).
|
||||
Conduct](https://github.com/swiftwasm/carton/blob/main/CODE_OF_CONDUCT.md).
|
||||
By participating, you are expected to uphold this code. Please report
|
||||
unacceptable behavior to conduct@carton.dev.
|
||||
|
|
|
@ -17,11 +17,11 @@ import Foundation
|
|||
import OpenCombine
|
||||
import TSCBasic
|
||||
|
||||
struct BuilderError: Error, CustomStringConvertible {
|
||||
struct ProcessRunnerError: Error, CustomStringConvertible {
|
||||
let description: String
|
||||
}
|
||||
|
||||
final class Builder {
|
||||
final class ProcessRunner {
|
||||
let publisher: AnyPublisher<String, Error>
|
||||
|
||||
private var subscription: AnyCancellable?
|
||||
|
@ -32,19 +32,6 @@ final class Builder {
|
|||
.handleEvents(receiveOutput: {
|
||||
terminal.clearLine()
|
||||
terminal.write(String($0.dropLast()))
|
||||
}, receiveCompletion: {
|
||||
switch $0 {
|
||||
case .finished:
|
||||
terminal.write("\nBuild completed successfully\n", inColor: .green, bold: false)
|
||||
case let .failure(error):
|
||||
let errorString = String(describing: error)
|
||||
if errorString.isEmpty {
|
||||
terminal.write("Build failed, check the build process output above.\n", inColor: .red)
|
||||
} else {
|
||||
terminal.write("Build failed and produced following output: \n", inColor: .red)
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
})
|
||||
.eraseToAnyPublisher()
|
||||
|
||||
|
@ -79,7 +66,7 @@ final class Builder {
|
|||
subject.send(completion: .failure(error))
|
||||
default:
|
||||
let errorDescription = String(data: Data(stderrBuffer), encoding: .utf8) ?? ""
|
||||
return subject.send(completion: .failure(BuilderError(description: errorDescription)))
|
||||
return subject.send(completion: .failure(ProcessRunnerError(description: errorDescription)))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,16 +17,11 @@ import Foundation
|
|||
import OpenCombine
|
||||
import TSCBasic
|
||||
|
||||
func processDataOutput(_ arguments: [String]) throws -> Data {
|
||||
func processDataOutput(_ arguments: [String]) throws -> [UInt8] {
|
||||
let process = Process(arguments: arguments, startNewProcessGroup: false)
|
||||
try process.launch()
|
||||
let result = try process.waitUntilExit()
|
||||
return try Data(result.output.get())
|
||||
}
|
||||
|
||||
func processStringsOutput(_ arguments: [String]) throws -> [String] {
|
||||
try String(data: processDataOutput(arguments), encoding: .utf8)?
|
||||
.components(separatedBy: CharacterSet.newlines) ?? []
|
||||
return try result.output.get()
|
||||
}
|
||||
|
||||
private let dependency = Dependency(
|
||||
|
@ -51,10 +46,9 @@ struct Dev: ParsableCommand {
|
|||
|
||||
try dependency.check(on: localFileSystem, terminal)
|
||||
let swiftPath = try localFileSystem.inferSwiftPath(terminal)
|
||||
|
||||
let output = try processDataOutput([swiftPath, "package", "dump-package"])
|
||||
let package = try JSONDecoder().decode(Package.self, from: output)
|
||||
var candidateNames = package.targets.filter { $0.type == .regular }.map(\.name)
|
||||
var candidateNames = try Package(with: swiftPath).targets
|
||||
.filter { $0.type == .regular }
|
||||
.map(\.name)
|
||||
|
||||
if let target = target {
|
||||
candidateNames = candidateNames.filter { $0 == target }
|
||||
|
@ -74,18 +68,15 @@ struct Dev: ParsableCommand {
|
|||
}
|
||||
terminal.logLookup("- development target: ", candidateNames[0])
|
||||
|
||||
guard let binPath = try processStringsOutput([
|
||||
swiftPath, "build", "--triple", "wasm32-unknown-wasi", "--show-bin-path",
|
||||
]).first else { fatalError("failed to decode UTF8 output of the `swift build` invocation") }
|
||||
|
||||
let mainWasmPath = AbsolutePath(binPath).appending(component: candidateNames[0])
|
||||
let binPath = try localFileSystem.inferBinPath(swiftPath: swiftPath)
|
||||
let mainWasmPath = binPath.appending(component: candidateNames[0])
|
||||
terminal.logLookup("- development binary to serve: ", mainWasmPath.pathString)
|
||||
|
||||
terminal.preWatcherBuildNotice()
|
||||
|
||||
let builderArguments = [swiftPath, "build", "--triple", "wasm32-unknown-wasi"]
|
||||
|
||||
try Builder(builderArguments, terminal).waitUntilFinished()
|
||||
try ProcessRunner(builderArguments, terminal).waitUntilFinished()
|
||||
|
||||
guard localFileSystem.exists(mainWasmPath) else {
|
||||
return terminal.write(
|
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import ArgumentParser
|
||||
import OpenCombine
|
||||
import TSCBasic
|
||||
|
||||
private let dependency = Dependency(
|
||||
|
@ -26,6 +27,16 @@ struct Test: ParsableCommand {
|
|||
func run() throws {
|
||||
guard let terminal = TerminalController(stream: stdoutStream)
|
||||
else { fatalError("failed to create an instance of `TerminalController`") }
|
||||
try dependency.check(on: localFileSystem, terminal)
|
||||
|
||||
// try dependency.check(on: localFileSystem, terminal)
|
||||
let swiftPath = try localFileSystem.inferSwiftPath(terminal)
|
||||
|
||||
let package = try Package(with: swiftPath)
|
||||
let binPath = try localFileSystem.inferBinPath(swiftPath: swiftPath)
|
||||
let testBundlePath = binPath.appending(component: "\(package.name)PackageTests.xctest")
|
||||
terminal.logLookup("- test bundle: ", testBundlePath)
|
||||
|
||||
let output = try processStringOutput(["wasmer", testBundlePath.pathString])!
|
||||
print("output is: \n\(output)")
|
||||
}
|
||||
}
|
|
@ -15,6 +15,10 @@
|
|||
import Foundation
|
||||
import TSCBasic
|
||||
|
||||
func processStringOutput(_ arguments: [String]) throws -> String? {
|
||||
try ByteString(processDataOutput(arguments)).validDescription
|
||||
}
|
||||
|
||||
extension FileSystem {
|
||||
func traverseRecursively(_ root: AbsolutePath) throws -> [AbsolutePath] {
|
||||
precondition(isDirectory(root))
|
||||
|
@ -54,4 +58,15 @@ extension FileSystem {
|
|||
|
||||
return swiftPath
|
||||
}
|
||||
|
||||
func inferBinPath(swiftPath: String) throws -> AbsolutePath {
|
||||
guard
|
||||
let output = try processStringOutput([
|
||||
swiftPath, "build", "--triple", "wasm32-unknown-wasi", "--show-bin-path",
|
||||
])?.components(separatedBy: CharacterSet.newlines),
|
||||
let binPath = output.first
|
||||
else { fatalError("failed to decode UTF8 output of the `swift build` invocation") }
|
||||
|
||||
return AbsolutePath(binPath)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,23 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Simple Package structure from package dump
|
||||
*/
|
||||
struct Package: Codable {
|
||||
let name: String
|
||||
let products: [Product]
|
||||
let targets: [Target]
|
||||
|
||||
init(with swiftPath: String) throws {
|
||||
let output = try Data(processDataOutput([swiftPath, "package", "dump-package"]))
|
||||
|
||||
self = try JSONDecoder().decode(Package.self, from: output)
|
||||
}
|
||||
}
|
||||
|
||||
struct ProductType: Codable {
|
||||
let executable: String?
|
||||
let library: [String]
|
||||
|
@ -25,15 +42,6 @@ struct Product: Codable {
|
|||
let type: ProductType
|
||||
}
|
||||
|
||||
/**
|
||||
Simple Package structure from package dump
|
||||
*/
|
||||
struct Package: Codable {
|
||||
let name: String
|
||||
let products: [Product]
|
||||
let targets: [Target]
|
||||
}
|
||||
|
||||
enum TargetType: String, Codable {
|
||||
case regular
|
||||
case test
|
||||
|
|
|
@ -31,7 +31,7 @@ final class Server {
|
|||
private var connections = Set<WebSocket>()
|
||||
private var subscriptions = [AnyCancellable]()
|
||||
private let watcher: Watcher
|
||||
private var builder: Builder?
|
||||
private var builder: ProcessRunner?
|
||||
private let app: Application
|
||||
|
||||
init(
|
||||
|
@ -61,11 +61,25 @@ final class Server {
|
|||
for change in changes.map(\.pathString) {
|
||||
terminal.write("- \(change)\n", inColor: .cyan)
|
||||
}
|
||||
return Builder(builderArguments, terminal)
|
||||
return ProcessRunner(builderArguments, terminal)
|
||||
.publisher
|
||||
.handleEvents(receiveCompletion: { [weak self] in
|
||||
guard case .finished = $0 else { return }
|
||||
self?.connections.forEach { $0.send("reload") }
|
||||
switch $0 {
|
||||
case .finished:
|
||||
terminal.write("\nBuild completed successfully\n", inColor: .green, bold: false)
|
||||
self?.connections.forEach { $0.send("reload") }
|
||||
case let .failure(error):
|
||||
let errorString = String(describing: error)
|
||||
if errorString.isEmpty {
|
||||
terminal.write(
|
||||
"Build failed, check the build process output above.\n",
|
||||
inColor: .red
|
||||
)
|
||||
} else {
|
||||
terminal.write("Build failed and produced following output: \n", inColor: .red)
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch { _ in Empty().eraseToAnyPublisher() }
|
||||
.eraseToAnyPublisher()
|
||||
|
|
Loading…
Reference in New Issue