Merge pull request #32 from shibapm/git_status_check

Git status check
This commit is contained in:
Franco Meloni 2019-10-31 08:15:51 +00:00 committed by GitHub
commit 2dcd79560c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 186 additions and 16 deletions

View File

@ -1,11 +1,13 @@
---
steps:
- script:
pre_release_checks:
- clean_git
steps:
- script:
content: echo "Testing Release for $VERSION"
- script:
- script:
content: echo "releasing $VERSION"
- hide_dev_dependencies
- git_add:
paths:
- Package.swift
- unhide_dev_dependencies
- unhide_dev_dependencies

View File

@ -19,7 +19,7 @@ if let bump = VersionBumpOption(rawValue: CommandLine.arguments[1]) {
version = CommandLine.arguments[1]
}
var stepsDictionary: [String: Any]!
var dictionary: [String: Any]!
let startingTime = Date()
@ -30,16 +30,24 @@ if let rocketYamlPath = RocketFileFinder.rocketFilePath() {
exit(1)
}
stepsDictionary = loadedDictionary
dictionary = loadedDictionary
} else if let packageConfig = try? PackageConfiguration.load().configuration,
let rocketConfig = packageConfig["rocket"] as? [String: Any] {
stepsDictionary = rocketConfig
dictionary = rocketConfig
} else {
stepsDictionary = [:]
dictionary = [:]
}
let checks = ChecksParser.parsePreReleaseChecks(fromDictionary: dictionary)
let failedChecks = checks.filter { !$0.check() }
guard failedChecks.count == 0 else {
logger.logError("Pre release checks failed")
exit(1)
}
let stepPrinter = StepDescriptionPrinter()
let stepExecutors = StepsParser.parseSteps(fromDictionary: stepsDictionary, logger: logger)
let stepExecutors = StepsParser.parseSteps(fromDictionary: dictionary, logger: logger)
stepExecutors.forEach {
$0.printStartStepDescription(logger: logger)
$0.executeStep(version: version, logger: logger)

View File

@ -0,0 +1,14 @@
enum PreReleseCheck: String {
case cleanGit = "clean_git"
func check(dictionary _: [String: Any]?) -> Check {
return checkType.init()
}
private var checkType: Check.Type {
switch self {
case .cleanGit:
return CleanGitStatusCheck.self
}
}
}

View File

@ -0,0 +1,4 @@
public protocol Check {
init()
func check() -> Bool
}

View File

@ -0,0 +1,19 @@
import Foundation
struct CleanGitStatusCheck: Check {
let launcher: ScriptLaunching
init() {
self.init(launcher: ScriptLauncher())
}
init(launcher: ScriptLaunching) {
self.launcher = launcher
}
func check() -> Bool {
let result = try? launcher.launchScript(withContent: "git diff --name-only", version: nil)
return result?.isEmpty ?? true
}
}

View File

@ -0,0 +1,21 @@
import Logger
public enum ChecksParser {
private enum CodingKeys: String {
case preReleaseChecks = "pre_release_checks"
}
public static func parsePreReleaseChecks(fromDictionary dictionary: [String: Any]) -> [Check] {
let checksArray: [Any] = dictionary[CodingKeys.preReleaseChecks] ?? []
return checksArray.compactMap(parseElement)
}
private static func parseElement(_ element: Any) -> Check? {
if let string = element as? String,
let check = PreReleseCheck(rawValue: string) {
return check.check(dictionary: nil)
} else {
return nil
}
}
}

View File

@ -11,6 +11,13 @@ protocol ScriptLaunching {
func launchScript(withContent content: String, version: String?) throws -> String
}
extension ScriptLaunching {
@discardableResult
func launchScript(withContent content: String) throws -> String {
return try launchScript(withContent: content, version: nil)
}
}
struct ScriptLauncher: ScriptLaunching {
func launchScript(withContent content: String, version: String?) throws -> String {
var runnableContent: String

View File

@ -1,7 +1,13 @@
import Foundation
import Logger
public class StepsParser {
public enum StepsParser {
enum CodingKeys: String {
case steps
case before
case after
}
private static let defaultSteps: [Any] = [
Step.hideDependencies.rawValue,
Step.gitAdd.rawValue,
@ -13,12 +19,6 @@ public class StepsParser {
Step.push.rawValue,
]
enum CodingKeys: String {
case steps
case before
case after
}
public static func parseSteps(fromDictionary dictionary: [String: Any], logger: Logger) -> [StepExecutor] {
guard let stepsArray = steps(fromDictionary: dictionary) else {
logger.logError("Invalid steps")

View File

@ -0,0 +1,26 @@
import Nimble
@testable import RocketLib
import XCTest
final class ChecksParserTests: XCTestCase {
func testItParsesCorrectlyAValidDictionary() {
let dictionary = ["pre_release_checks": ["clean_git"]]
let checks = ChecksParser.parsePreReleaseChecks(fromDictionary: dictionary)
expect(checks.count) == 1
expect(checks[0]).to(beAKindOf(CleanGitStatusCheck.self))
}
func testItIgnoresTheInvalidSteps() {
let dictionary = ["pre_release_checks": [
"clean_git",
"invalid",
]]
let checks = ChecksParser.parsePreReleaseChecks(fromDictionary: dictionary)
expect(checks.count) == 1
expect(checks[0]).to(beAKindOf(CleanGitStatusCheck.self))
}
}

View File

@ -0,0 +1,28 @@
import Nimble
@testable import RocketLib
import TestSpy
import XCTest
final class CleanGitStatusCheckTests: XCTestCase {
func testReturnsTrueWhenThereIsAreNoModifiedFiles() {
let scriptLauncher = SpyScriptLauncher()
scriptLauncher.result = ""
let check = CleanGitStatusCheck(launcher: scriptLauncher)
let result = check.check()
expect(result).to(beTrue())
expect(scriptLauncher).to(haveReceived(.launchScript(content: "git diff --name-only", version: nil)))
}
func testReturnsFalseWhenThereIsAreModifiedFiles() {
let scriptLauncher = SpyScriptLauncher()
scriptLauncher.result = "/Franco/Test.swift"
let check = CleanGitStatusCheck(launcher: scriptLauncher)
let result = check.check()
expect(result).to(beFalse())
expect(scriptLauncher).to(haveReceived(.launchScript(content: "git diff --name-only", version: nil)))
}
}

View File

@ -1,5 +1,27 @@
import XCTest
extension BranchExecutorTests {
static let __allTests = [
("testItSendsEmptyScriptIfTheDictionaryIsNil", testItSendsEmptyScriptIfTheDictionaryIsNil),
("testItSendsTheCorrectBranchNameToScriptLauncher", testItSendsTheCorrectBranchNameToScriptLauncher),
("testItUsesAWorkaroundToGenerateTheTestsOnLinux", testItUsesAWorkaroundToGenerateTheTestsOnLinux),
]
}
extension ChecksParserTests {
static let __allTests = [
("testItIgnoresTheInvalidSteps", testItIgnoresTheInvalidSteps),
("testItParsesCorrectlyAValidDictionary", testItParsesCorrectlyAValidDictionary),
]
}
extension CleanGitStatusCheckTests {
static let __allTests = [
("testReturnsFalseWhenThereIsAreModifiedFiles", testReturnsFalseWhenThereIsAreModifiedFiles),
("testReturnsTrueWhenThereIsAreNoModifiedFiles", testReturnsTrueWhenThereIsAreNoModifiedFiles),
]
}
extension CommitExecutorTests {
static let __allTests = [
("testItSetsTheParameterIfTheGitHookFolderExists", testItSetsTheParameterIfTheGitHookFolderExists),
@ -9,6 +31,13 @@ extension CommitExecutorTests {
]
}
extension CurrentVersionProviderTests {
static let __allTests = [
("testItReturnsTheCorrectTag", testItReturnsTheCorrectTag),
("testItReturnsTheCorrectVersionIfThereAreNoTags", testItReturnsTheCorrectVersionIfThereAreNoTags),
]
}
extension DefaultExecutorStepDescriptionTests {
static let __allTests = [
("testItShowsTheCorrectEndDescriptionWhenThereAreNoParameters", testItShowsTheCorrectEndDescriptionWhenThereAreNoParameters),
@ -40,6 +69,12 @@ extension HideDevDependenciesExecutorTests {
]
}
extension NewVersionProviderTests {
static let __allTests = [
("testReturnsTheCorrectNewVersion", testReturnsTheCorrectNewVersion),
]
}
extension PushExecutorTests {
static let __allTests = [
("testItAddsTheNoVerifyParameterIfGitHookFolderIsPresent", testItAddsTheNoVerifyParameterIfGitHookFolderIsPresent),
@ -74,6 +109,7 @@ extension StepsParserTests {
("testItParsesCorrectlyBeforeAndAfterSteps", testItParsesCorrectlyBeforeAndAfterSteps),
("testItParsesCorrectlyWhenOnlyAfterIsSpecified", testItParsesCorrectlyWhenOnlyAfterIsSpecified),
("testItParsesCorrectlyWhenOnlyBeforeIsSpecified", testItParsesCorrectlyWhenOnlyBeforeIsSpecified),
("testItParsesItReturnsTheDefaultParametersIfTheDictionaryIsEmpty", testItParsesItReturnsTheDefaultParametersIfTheDictionaryIsEmpty),
]
}
@ -102,11 +138,16 @@ extension UnhideDevDependenciesExecutorTests {
#if !os(macOS)
public func __allTests() -> [XCTestCaseEntry] {
return [
testCase(BranchExecutorTests.__allTests),
testCase(ChecksParserTests.__allTests),
testCase(CleanGitStatusCheckTests.__allTests),
testCase(CommitExecutorTests.__allTests),
testCase(CurrentVersionProviderTests.__allTests),
testCase(DefaultExecutorStepDescriptionTests.__allTests),
testCase(DevDependenciesModifierTests.__allTests),
testCase(GitAddExecutorTests.__allTests),
testCase(HideDevDependenciesExecutorTests.__allTests),
testCase(NewVersionProviderTests.__allTests),
testCase(PushExecutorTests.__allTests),
testCase(RocketFileFinderTests.__allTests),
testCase(ScriptExecutorTests.__allTests),