Skip to content

Commit

Permalink
Merge pull request #6 from AppDifferentia/update-document
Browse files Browse the repository at this point in the history
[Doc] Update documentation
  • Loading branch information
weisunOW authored Sep 8, 2021
2 parents 82b0732 + a728c50 commit 8e4702e
Show file tree
Hide file tree
Showing 23 changed files with 131 additions and 52 deletions.
79 changes: 77 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,77 @@
# danger-swift-commit-lint
A Danger-Swift plugin to check commit messages
# Commit Lint For Danger-Swift

A [`danger-swift`]("https://github.com/danger/swift") plugin to check each commit messages on the branch. This project is inspired by [`danger-commit-lint`](https://github.com/jonallured/danger-commit_lint) and its commit linting rules are ported too.

## Installation

Add `DangerSwiftCommitLint` to your `Package.file`
```Swift
.package(url: "https://github.com/AppDifferentia/danger-swift-commit-lint", from: "0.0.1")
```

## Usage

Simply add the following lines to your `Dangerfile.swift`

```Swift
import Danger

let danger = Danger()

//...

let commitLint = DangerSwiftCommitLint(danger: danger)
commitLint.check()
```

That will check each commit in the PR to ensure the following is true:

- Commit subject begins with a capital letter (`Sources/DangerSwiftLint/CommitLint/SubjectCapitalLetter`)
- Commit subject is more than one word (`Sources/DangerSwiftLint/CommitLint/SubjectWord`)
- Commit subject is no longer than 50 characters (`Sources/DangerSwiftLint/CommitLint/SubjectLength`)
- Commit subject does not end in a period (`Sources/DangerSwiftLint/CommitLint/SubjectPeriod`)
- Commit subject and body are separated by an empty line (`Sources/DangerSwiftLint/CommitLint/BodyEmptyLine`)

By default, Commit Lint fails, but you can configure this behavior.

E.g.

```Swift
import Danger

let danger = Danger()

//...

let configuration = DangerSwiftCommitLint.Configuration(warn: .all)
let commitLint = DangerSwiftCommitLint(danger: danger, configuration: configuration)
commitLint.check()
```

## Configuration

The commit lint can be configured with following 5 parameters.

- `disabled`: can be `.all` or `.selected([ ... ])`, see [`DangerSwiftCommitLint/Configuration`]("DangerSwiftCommitLint/Configuration")
- `warn`: can be `.all` or `.selected([ ... ])`, see [`DangerSwiftCommitLint/Configuration`]("DangerSwiftCommitLint/Configuration")
- `fail`: can be `.all` or `.selected([ ... ])`, see [`DangerSwiftCommitLint/Configuration`]("DangerSwiftCommitLint/Configuration")
- `limit`: limits the number commits to lint. E.g. `limit: 1` will limit the commit to the oldest commit on the branch
- `custom`: allow caller to pass an array of custom linter that conforms to `DangerSwiftCommitLint.CommitLint` protocol

E.g.

```Swift
struct Configuration {

init(
disabled: CommitLintSelection = .selected([]),
warn: CommitLintSelection = .selected([]),
fail: CommitLintSelection = .all,
limit: Int = 0,
custom: [CommitLint.Type] = []
) {
// ...
}

}
```
49 changes: 25 additions & 24 deletions Sources/DangerSwiftCommitLint/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,66 @@ import Foundation

public extension DangerSwiftCommitLint {
/// All commit checkers provided by `DangerSwiftCommitLint`
enum CommitCheckerType: CaseIterable, Hashable {
/// Commit subject and body are separated by an empty line (`CommitChecker/BodyEmptyLineCheck`)
enum CommitLintType: CaseIterable, Hashable {
/// Commit subject and body are separated by an empty line (`CommitLint/BodyEmptyLineCheck`)
case bodyEmptyLine
/// Commit subject begins with a capital letter (`CommitChecker/SubjectCapCheck`)
/// Commit subject begins with a capital letter (`CommitLint/SubjectCapCheck`)
case subjectCapitalLetter
/// Commit subject is no longer than 50 characters (`CommitChecker/SubjectLengthCheck`)
/// Commit subject is no longer than 50 characters (`CommitLint/SubjectLengthCheck`)
case subjectLength
/// Commit subject does not end in a period (`CommitChecker/SubjectPeriodCheck`)
/// Commit subject does not end in a period (`CommitLint/SubjectPeriodCheck`)
case subjectPeriod
/// Commit subject is more than one word (`CommitChecker/SubjectWordCheck`)
/// Commit subject is more than one word (`CommitLint/SubjectWordCheck`)
case subjectWord
}

/// Checker selection
enum CommitCheckerSelection {
enum CommitLintSelection {
/// Select all checkers
case all
/// Select a set of checkers
case selected(Set<CommitCheckerType>)
case selected(Set<CommitLintType>)
}

/// Configuration for `DangerSwiftCommitLint`
struct Configuration {
let limit: Int

private let disabled: CommitCheckerSelection
private let warn: CommitCheckerSelection
private let fail: CommitCheckerSelection
private let customCheckers: [CommitLint.Type]
private let disabled: CommitLintSelection
private let warn: CommitLintSelection
private let fail: CommitLintSelection
private let custom: [CommitLint.Type]

/// Initialize the configuration.
/// - Parameters:
/// - disabled: The selected checks to skip.
/// - warn: The selected checks to warn on.
/// - fail: The selected checks to fail on.
/// - disabled: The selected commit lint to skip.
/// - warn: The selected commit lint to warn on.
/// - fail: The selected commit lint to fail on.
/// - limit: The number of commits to check.
/// - customCheckers: An array of custom checkers.
/// - customCheckers: An array of custom checkers. This array will be added to all checkers.
public init(
disabled: CommitCheckerSelection = .selected([]),
warn: CommitCheckerSelection = .selected([]),
fail: CommitCheckerSelection = .all,
disabled: CommitLintSelection = .selected([]),
warn: CommitLintSelection = .selected([]),
fail: CommitLintSelection = .all,
limit: Int = 0,
customCheckers: [CommitLint.Type] = []
custom: [CommitLint.Type] = []
) {
self.disabled = disabled
self.warn = warn
self.fail = fail
self.limit = limit
self.customCheckers = customCheckers
self.custom = custom
}
}
}

extension DangerSwiftCommitLint.Configuration {
static var defaultCheckers: [CommitLint.Type] {
DangerSwiftCommitLint.CommitCheckerType.allCases.map(\.type)
DangerSwiftCommitLint.CommitLintType.allCases.map(\.type)
}

var allCheckers: [CommitLint.Type] {
Self.defaultCheckers + customCheckers
Self.defaultCheckers + custom
}

var disabledCheckers: [CommitLint.Type] {
Expand Down Expand Up @@ -96,7 +97,7 @@ extension DangerSwiftCommitLint.Configuration {
}
}

private extension DangerSwiftCommitLint.CommitCheckerType {
private extension DangerSwiftCommitLint.CommitLintType {
var type: CommitLint.Type {
switch self {
case .bodyEmptyLine: return BodyEmptyLine.self
Expand Down
5 changes: 4 additions & 1 deletion Sources/DangerSwiftCommitLint/DangerSwiftCommitLint.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import Danger
import Foundation

/// A protocol for dependency inject `DangerDSL`.
/// - `DangerSwiftCommitLint` only require these interfaces.
public protocol DangerDSLProviding {
var git: Git { get }

Expand All @@ -10,6 +12,7 @@ public protocol DangerDSLProviding {

extension DangerDSL: DangerDSLProviding {}

/// A Danger-Swift plugin to lint each commit in the PR. See `Configuration` for linter configuration.
public final class DangerSwiftCommitLint {
private enum Constants {
static let disableAllChecksMessage = "All checks were disabled, nothing to do."
Expand All @@ -22,7 +25,7 @@ public final class DangerSwiftCommitLint {
/// - Parameters:
/// - danger: An instance of `Danger.DangerDSL`.
/// - configuration: Linter configuration.
public init(danger: DangerDSLProviding = Danger(), configuration: Configuration) {
public init(danger: DangerDSLProviding = Danger(), configuration: Configuration = .init()) {
self.danger = danger
self.configuration = configuration
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Danger
@testable import DangerSwiftCommitLint
import XCTest

final class BodyEmptyLineCheckTests: XCTestCase {
final class BodyEmptyLineTests: XCTestCase {
private let commitSubjectAndBody = GitCommitMessage(subject: "Title Test", bodyLinesOfText: ["", "Body Test"], sha: "Test SHA")
private let commitSubjectOnly = GitCommitMessage(subject: "Title Test", bodyLinesOfText: [], sha: "Test SHA")
private let commitNoNewline = GitCommitMessage(subject: "Title Test", bodyLinesOfText: ["Body Test"], sha: "Test SHA")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@testable import DangerSwiftCommitLint
import XCTest

final class SubjectCapCheckTests: XCTestCase {
final class SubjectCapitalLetterTests: XCTestCase {
func testSuccess() {
let commitMessage = GitCommitMessage(subject: "Subject", bodyLinesOfText: [], sha: "Test SHA")
let testSubject = SubjectCapitalLetter(commitMessage)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@testable import DangerSwiftCommitLint
import XCTest

final class SubjectLengthCheckTests: XCTestCase {
final class SubjectLengthTests: XCTestCase {
func testSuccess() {
let commitMessage = GitCommitMessage(subject: "Valid title", bodyLinesOfText: [], sha: "Test SHA")
let testSubject = SubjectLength(commitMessage)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@testable import DangerSwiftCommitLint
import XCTest

final class SubjectPeriodCheckTests: XCTestCase {
final class SubjectPeriodTests: XCTestCase {
func testSuccess() {
let commitMessage = GitCommitMessage(subject: "Test title without period at the end", bodyLinesOfText: [], sha: "Test SHA")
let testSubject = SubjectPeriod(commitMessage)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@testable import DangerSwiftCommitLint
import XCTest

final class SubjectWordCheckTests: XCTestCase {
final class SubjectWordTests: XCTestCase {
func testSuccess() {
let commitMessage = GitCommitMessage(subject: "Test title more than one word", bodyLinesOfText: [], sha: "Test SHA")
let testSubject = SubjectWord(commitMessage)
Expand Down
4 changes: 2 additions & 2 deletions Tests/DangerSwiftCommitLintTests/ConfigurationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ final class DangerSwiftCommitLintConfigurationTests: XCTestCase {
}

func testDisableAllChecksWithCustomChecker() {
let testSubject = Configuration(disabled: .all, customCheckers: [MockChecker.self])
let testSubject = Configuration(disabled: .all, custom: [MockChecker.self])
XCTAssertTrue(testSubject.enabledCheckers.isEmpty)
XCTAssertEqual(testSubject.allCheckers.count, Configuration.defaultCheckers.count + 1)
XCTAssertTrue(testSubject.allCheckers.isEqual(to: testSubject.disabledCheckers))
Expand All @@ -40,7 +40,7 @@ final class DangerSwiftCommitLintConfigurationTests: XCTestCase {
}

func testWarnAllChecksWithCustomChecker() {
let testSubject = Configuration(warn: .all, customCheckers: [MockChecker.self])
let testSubject = Configuration(warn: .all, custom: [MockChecker.self])
XCTAssertEqual(testSubject.allCheckers.count, Configuration.defaultCheckers.count + 1)
XCTAssertTrue(testSubject.enabledCheckers.isEqual(to: testSubject.allCheckers))
XCTAssertTrue(testSubject.enabledCheckers.isEqual(to: testSubject.warningCheckers))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ final class DangerSwiftCommitLintTests: XCTestCase {
let git = CommitParser.parseGit(with: gitIssuesOnLastTwoCommitsJSON)
let mockDanger = MockDangerDSL(git: git)
let configuration = Configuration(
disabled: .selected(Set<DangerSwiftCommitLint.CommitCheckerType>([.bodyEmptyLine])),
warn: .selected(Set<DangerSwiftCommitLint.CommitCheckerType>([.subjectPeriod, .subjectWord])),
disabled: .selected(Set<DangerSwiftCommitLint.CommitLintType>([.bodyEmptyLine])),
warn: .selected(Set<DangerSwiftCommitLint.CommitLintType>([.subjectPeriod, .subjectWord])),
fail: .all
)
let testSubject = DangerSwiftCommitLint(danger: mockDanger, configuration: configuration)
Expand All @@ -112,7 +112,7 @@ final class DangerSwiftCommitLintTests: XCTestCase {
func testCustomChecker() {
let git = CommitParser.parseGit(with: gitJSON)
let mockDanger = MockDangerDSL(git: git)
let configuration = Configuration(warn: .all, customCheckers: [MockChecker.self])
let configuration = Configuration(warn: .all, custom: [MockChecker.self])
let testSubject = DangerSwiftCommitLint(danger: mockDanger, configuration: configuration)
testSubject.check()
XCTAssertEqual(mockDanger.warningMessages, ["\(MockChecker.linterMessage)\ntestshacommit3\ntestshacommit2\ntestshacommit1"])
Expand Down
30 changes: 15 additions & 15 deletions Tests/DangerSwiftCommitLintTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#if !canImport(ObjectiveC)
import XCTest

extension BodyEmptyLineCheckTests {
extension BodyEmptyLineTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__BodyEmptyLineCheckTests = [
static let __allTests__BodyEmptyLineTests = [
("testFailureNoNewlineOnly", testFailureNoNewlineOnly),
("testSuccessCommitSubjectAndBody", testSuccessCommitSubjectAndBody),
("testSuccessSubjectOnly", testSuccessSubjectOnly),
Expand Down Expand Up @@ -61,61 +61,61 @@
]
}

extension SubjectCapCheckTests {
extension SubjectCapitalLetterTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__SubjectCapCheckTests = [
static let __allTests__SubjectCapitalLetterTests = [
("testEdgeCase", testEdgeCase),
("testFailure", testFailure),
("testSuccess", testSuccess),
("testSuccessWithNonLetterCharacters", testSuccessWithNonLetterCharacters),
]
}

extension SubjectLengthCheckTests {
extension SubjectLengthTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__SubjectLengthCheckTests = [
static let __allTests__SubjectLengthTests = [
("testFailure", testFailure),
("testSuccess", testSuccess),
("testSuccessWithGitHubMergeCommit", testSuccessWithGitHubMergeCommit),
("testSuccessWithGitMergeCommit", testSuccessWithGitMergeCommit),
]
}

extension SubjectPeriodCheckTests {
extension SubjectPeriodTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__SubjectPeriodCheckTests = [
static let __allTests__SubjectPeriodTests = [
("testFailure", testFailure),
("testSuccess", testSuccess),
]
}

extension SubjectWordCheckTests {
extension SubjectWordTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__SubjectWordCheckTests = [
static let __allTests__SubjectWordTests = [
("testFailure", testFailure),
("testSuccess", testSuccess),
]
}

public func __allTests() -> [XCTestCaseEntry] {
[
testCase(BodyEmptyLineCheckTests.__allTests__BodyEmptyLineCheckTests),
testCase(BodyEmptyLineTests.__allTests__BodyEmptyLineTests),
testCase(CommitMessageTests.__allTests__CommitMessageTests),
testCase(DangerSwiftCommitLintConfigurationTests.__allTests__DangerSwiftCommitLintConfigurationTests),
testCase(DangerSwiftCommitLintTests.__allTests__DangerSwiftCommitLintTests),
testCase(RegexHelperTests.__allTests__RegexHelperTests),
testCase(SubjectCapCheckTests.__allTests__SubjectCapCheckTests),
testCase(SubjectLengthCheckTests.__allTests__SubjectLengthCheckTests),
testCase(SubjectPeriodCheckTests.__allTests__SubjectPeriodCheckTests),
testCase(SubjectWordCheckTests.__allTests__SubjectWordCheckTests),
testCase(SubjectCapitalLetterTests.__allTests__SubjectCapitalLetterTests),
testCase(SubjectLengthTests.__allTests__SubjectLengthTests),
testCase(SubjectPeriodTests.__allTests__SubjectPeriodTests),
testCase(SubjectWordTests.__allTests__SubjectWordTests),
]
}
#endif

0 comments on commit 8e4702e

Please sign in to comment.