Last active
August 30, 2020 11:07
-
-
Save laevandus/7a7a8b9b505acc43d64a5c875c686c4d to your computer and use it in GitHub Desktop.
Pre-push hook written in Swift. Copy it to your repository's .git/hooks folder, rename it to pre-push (no path extension), and make it executable (chmode +x pre-push).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/swift | |
import Foundation | |
let projectType = "-workspace" | |
let projectPath = "SignalPath.xcworkspace" | |
let scheme = "SignalPathiOS" | |
let destinationDevice = "platform=iOS Simulator,name=iPhone 11 Pro Max" | |
let resultBundlePath = "PrePush.xcresult" | |
print("Building for testing…") | |
let buildCommand = [ | |
"xcodebuild", | |
"build-for-testing", | |
"-quiet", | |
projectType, projectPath.wrappedInQuotes, | |
"-scheme", scheme.wrappedInQuotes, | |
"-destination", destinationDevice.wrappedInQuotes | |
].joined(separator: " ") | |
let buildStatus = Process.runZshCommand(buildCommand) | |
if buildStatus != 0 { | |
exit(buildStatus) | |
} | |
removeResultBundle(at: resultBundlePath) | |
print("Running tests…") | |
let testCommand = [ | |
"xcodebuild", | |
"test-without-building", | |
"-quiet", | |
projectType, projectPath.wrappedInQuotes, | |
"-scheme", scheme.wrappedInQuotes, | |
"-destination", destinationDevice.wrappedInQuotes, | |
"-resultBundlePath", resultBundlePath.wrappedInQuotes | |
].joined(separator: " ") | |
let testStatus = Process.runZshCommand(testCommand) | |
if testStatus != 0 { | |
removeResultBundle(at: resultBundlePath) | |
exit(testStatus) | |
} | |
let coverageCommand = [ | |
"xcrun", | |
"xccov", | |
"view", | |
"--only-targets", | |
"--report", resultBundlePath.wrappedInQuotes | |
].joined(separator: " ") | |
Process.runZshCommand(coverageCommand) | |
removeResultBundle(at: resultBundlePath) | |
print("Success") | |
exit(0) | |
// MARK: - | |
extension String { | |
var wrappedInQuotes: String { | |
return "\"\(self)\"" | |
} | |
} | |
extension Process { | |
@discardableResult | |
static func runZshCommand(_ command: String) -> Int32 { | |
let process = Process() | |
process.launchPath = "/bin/zsh" | |
process.arguments = ["-c", command] | |
process.standardOutput = { | |
let pipe = Pipe() | |
pipe.fileHandleForReading.readabilityHandler = { handler in | |
guard let string = String(data: handler.availableData, encoding: .utf8), !string.isEmpty else { return } | |
print(string) | |
} | |
return pipe | |
}() | |
process.standardError = { | |
let pipe = Pipe() | |
pipe.fileHandleForReading.readabilityHandler = { handler in | |
guard let string = String(data: handler.availableData, encoding: .utf8), !string.isEmpty else { return } | |
print(string) | |
} | |
return pipe | |
}() | |
process.launch() | |
process.waitUntilExit() | |
(process.standardOutput as! Pipe).fileHandleForReading.readabilityHandler = nil | |
(process.standardError as! Pipe).fileHandleForReading.readabilityHandler = nil | |
return process.terminationStatus | |
} | |
} | |
func removeResultBundle(at path: String) { | |
guard FileManager.default.fileExists(atPath: path) else { return } | |
try? FileManager.default.removeItem(atPath: path) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment