Skip hot-reloading if build fails (#480)
* Send error from plugin * revert loglevel change
This commit is contained in:
parent
f734c39ed8
commit
8c7ac43e79
|
@ -109,13 +109,16 @@ struct CartonDevPluginCommand: CommandPlugin {
|
||||||
while let _ = try buildRequestFileHandle.read(upToCount: 1) {
|
while let _ = try buildRequestFileHandle.read(upToCount: 1) {
|
||||||
Diagnostics.remark("[Plugin] Received build request")
|
Diagnostics.remark("[Plugin] Received build request")
|
||||||
let buildResult = try self.packageManager.build(buildSubset, parameters: parameters)
|
let buildResult = try self.packageManager.build(buildSubset, parameters: parameters)
|
||||||
|
let responseMessage: Data
|
||||||
if !buildResult.succeeded {
|
if !buildResult.succeeded {
|
||||||
Diagnostics.remark("[Plugin] **Build Failed**")
|
Diagnostics.remark("[Plugin] **Build Failed**")
|
||||||
print(buildResult.logText)
|
print(buildResult.logText, terminator: "")
|
||||||
|
responseMessage = Data([0])
|
||||||
} else {
|
} else {
|
||||||
Diagnostics.remark("[Plugin] **Build Succeeded**")
|
Diagnostics.remark("[Plugin] **Build Succeeded**")
|
||||||
|
responseMessage = Data([1])
|
||||||
}
|
}
|
||||||
try buildResponseFileHandle.write(contentsOf: Data([1]))
|
try buildResponseFileHandle.write(contentsOf: responseMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
frontend.waitUntilExit()
|
frontend.waitUntilExit()
|
||||||
|
|
|
@ -17,23 +17,27 @@ import CartonHelpers
|
||||||
import CartonKit
|
import CartonKit
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct CartonFrontendDevCommand: AsyncParsableCommand {
|
enum DevCommandError: Error & CustomStringConvertible {
|
||||||
enum Error: Swift.Error & CustomStringConvertible {
|
case noBuildRequestOption
|
||||||
case noBuildRequestOption
|
case noBuildResponseOption
|
||||||
case noBuildResponseOption
|
case failedToOpenBuildRequestPipe
|
||||||
case failedToOpenBuildRequestPipe
|
case failedToOpenBuildResponsePipe
|
||||||
case failedToOpenBuildResponsePipe
|
case pluginConnectionClosed
|
||||||
|
case brokenPluginResponse
|
||||||
|
|
||||||
var description: String {
|
var description: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .noBuildRequestOption: "--build-request option is necessary if you want to watch, but has not been specified."
|
case .noBuildRequestOption: "--build-request option is necessary if you want to watch, but has not been specified."
|
||||||
case .noBuildResponseOption: "--build-response option is necessary if you want to watch, but has not been specified."
|
case .noBuildResponseOption: "--build-response option is necessary if you want to watch, but has not been specified."
|
||||||
case .failedToOpenBuildRequestPipe: "failed to open build request pipe"
|
case .failedToOpenBuildRequestPipe: "failed to open build request pipe."
|
||||||
case .failedToOpenBuildResponsePipe: "failed to open build response pipe"
|
case .failedToOpenBuildResponsePipe: "failed to open build response pipe."
|
||||||
}
|
case .pluginConnectionClosed: "connection with the plugin has been closed."
|
||||||
|
case .brokenPluginResponse: "response from the plugin was broken."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CartonFrontendDevCommand: AsyncParsableCommand {
|
||||||
static let entrypoint = Entrypoint(fileName: "dev.js", content: StaticResource.dev)
|
static let entrypoint = Entrypoint(fileName: "dev.js", content: StaticResource.dev)
|
||||||
|
|
||||||
@Option(help: "Specify name of an executable product in development.")
|
@Option(help: "Specify name of an executable product in development.")
|
||||||
|
@ -126,10 +130,10 @@ struct CartonFrontendDevCommand: AsyncParsableCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let buildRequest else {
|
guard let buildRequest else {
|
||||||
throw Error.noBuildRequestOption
|
throw DevCommandError.noBuildRequestOption
|
||||||
}
|
}
|
||||||
guard let buildResponse else {
|
guard let buildResponse else {
|
||||||
throw Error.noBuildResponseOption
|
throw DevCommandError.noBuildResponseOption
|
||||||
}
|
}
|
||||||
|
|
||||||
let pathsToWatch = try watchPaths.map {
|
let pathsToWatch = try watchPaths.map {
|
||||||
|
@ -137,10 +141,10 @@ struct CartonFrontendDevCommand: AsyncParsableCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let buildRequest = FileHandle(forWritingAtPath: buildRequest) else {
|
guard let buildRequest = FileHandle(forWritingAtPath: buildRequest) else {
|
||||||
throw Error.failedToOpenBuildRequestPipe
|
throw DevCommandError.failedToOpenBuildRequestPipe
|
||||||
}
|
}
|
||||||
guard let buildResponse = FileHandle(forReadingAtPath: buildResponse) else {
|
guard let buildResponse = FileHandle(forReadingAtPath: buildResponse) else {
|
||||||
throw Error.failedToOpenBuildResponsePipe
|
throw DevCommandError.failedToOpenBuildResponsePipe
|
||||||
}
|
}
|
||||||
|
|
||||||
return SwiftPMPluginBuilder(
|
return SwiftPMPluginBuilder(
|
||||||
|
@ -202,6 +206,20 @@ struct SwiftPMPluginBuilder: BuilderProtocol {
|
||||||
func run() async throws {
|
func run() async throws {
|
||||||
// We expect single response per request
|
// We expect single response per request
|
||||||
try buildRequest.write(contentsOf: Data([1]))
|
try buildRequest.write(contentsOf: Data([1]))
|
||||||
_ = try buildResponse.read(upToCount: 1)
|
guard let responseMessage = try buildResponse.read(upToCount: 1) else {
|
||||||
|
throw DevCommandError.pluginConnectionClosed
|
||||||
|
}
|
||||||
|
if responseMessage.count < 1 {
|
||||||
|
throw DevCommandError.brokenPluginResponse
|
||||||
|
}
|
||||||
|
switch responseMessage[0] {
|
||||||
|
case 0:
|
||||||
|
throw BuilderProtocolSimpleBuildFailedError()
|
||||||
|
case 1:
|
||||||
|
// build succeeded
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
throw DevCommandError.brokenPluginResponse
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,10 @@ extension Event: Decodable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct BuilderProtocolSimpleBuildFailedError: Error {
|
||||||
|
public init() {}
|
||||||
|
}
|
||||||
|
|
||||||
/// A protocol for a builder that can be used to build the app.
|
/// A protocol for a builder that can be used to build the app.
|
||||||
public protocol BuilderProtocol {
|
public protocol BuilderProtocol {
|
||||||
var pathsToWatch: [AbsolutePath] { get }
|
var pathsToWatch: [AbsolutePath] { get }
|
||||||
|
@ -392,9 +396,19 @@ public actor Server {
|
||||||
_ builder: any BuilderProtocol,
|
_ builder: any BuilderProtocol,
|
||||||
_ terminal: InteractiveWriter
|
_ terminal: InteractiveWriter
|
||||||
) async throws {
|
) async throws {
|
||||||
try await builder.run()
|
do {
|
||||||
|
try await builder.run()
|
||||||
|
} catch {
|
||||||
|
terminal.write("Build failed\n", inColor: .red)
|
||||||
|
switch error {
|
||||||
|
case is BuilderProtocolSimpleBuildFailedError: break
|
||||||
|
default:
|
||||||
|
terminal.write("\(error)\n", inColor: .red)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
terminal.write("\nBuild completed successfully\n", inColor: .green, bold: false)
|
terminal.write("Build completed successfully\n", inColor: .green)
|
||||||
terminal.logLookup("The app is currently hosted at ", localURL)
|
terminal.logLookup("The app is currently hosted at ", localURL)
|
||||||
connections.forEach { $0.reload() }
|
connections.forEach { $0.reload() }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue