forked from DebugSwift/DebugSwift
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDangerfile.swift
More file actions
225 lines (177 loc) · 5.72 KB
/
Dangerfile.swift
File metadata and controls
225 lines (177 loc) · 5.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
// MARK: Imports
import Danger
import DangerSwiftCoverage
import DangerXCodeSummary
import Foundation
// MARK: Validate
Validator.shared.validate()
// MARK: Lint
SwiftLint.lint(configFile: ".swiftlint.yml")
// MARK: Validation rules
internal class Validator {
// MARK: Lifecycle
// Private initializer and shared instance for Validator.
private init() {}
internal static let shared = Validator()
private var danger = Danger()
// MARK: Properties
// Properties related to PR details and changes.
private lazy var additions = danger.github.pullRequest.additions!
private lazy var deletions = danger.github.pullRequest.deletions!
private lazy var changedFiles = danger.github.pullRequest.changedFiles!
private lazy var modified = danger.git.modifiedFiles
private lazy var editedFiles = modified + danger.git.createdFiles
private lazy var prTitle = danger.github.pullRequest.title
private lazy var branchHeadName = danger.github.pullRequest.head.ref
private lazy var branchBaseName = danger.github.pullRequest.base.ref
// Methods
// Methods for various validation checks.
internal func validate() {
checkSize()
checkDescription()
checkUnitTest()
checkTitle()
checkAssignee()
checkModifiedFiles()
checkFails()
logResume()
}
}
internal class DescriptionValidator {
// MARK: Lifecycle
// Private initializer and shared instance for DescriptionValidator.
private init() {}
internal static let shared = DescriptionValidator()
private var danger = Danger()
// MARK: Properties
// Property to store the PR body.
private lazy var body = danger.github.pullRequest.body ?? ""
// Methods
// Method to validate PR description.
internal func validate() {
let message = "PR does not have a description. You must provide a description of the changes made."
guard !body.isEmpty else {
fail(message)
return
}
}
}
internal class UnitTestValidator {
// MARK: Lifecycle
// Private initializer and shared instance for UnitTestValidator.
private init() {}
internal static let shared = UnitTestValidator()
private var danger = Danger()
// Methods
// Methods for unit test validation.
internal func validate() {
checkUnitTestSummary()
checkUnitTestCoverage()
}
}
// MARK: Validator Methods
// Extension with methods for Validator class.
fileprivate extension Validator {
func checkSize() {
if (additions + deletions) > ValidationRules.bigPRThreshold {
let message =
"""
The size of the PR seems relatively large. \
If possible, in the future if the PR contains multiple changes, split each into a separate PR. \
This helps in faster and easier review.
"""
warn(message)
}
}
func checkDescription() {
DescriptionValidator.shared.validate()
}
func checkUnitTest() {
UnitTestValidator.shared.validate()
}
func checkTitle() {
let result = prTitle.range(
of: #"\[[A-zÀ-ú0-9 ]*\][A-zÀ-ú0-9- ]+"#,
options: .regularExpression
) != nil
if !result {
let message = "The PR title should be: [<i>Feature or Flow</i>] <i>What flow was done</i>"
warn(message)
}
}
func checkAssignee() {
if danger.github.pullRequest.assignee == nil {
warn("Please assign yourself to the PR.")
}
}
func checkModifiedFiles() {
if changedFiles > ValidationRules.maxChangedFiles {
let message =
"""
PR contains too many changed files. If possible, next time try to split into smaller features.
"""
warn(message)
}
}
func checkFails() {
if !danger.fails.isEmpty {
_ = danger.utils.exec("touch Danger-has-fails.swift")
}
}
func logResume() {
let overview =
"""
The PR added \(additions) and removed \(deletions) lines. \(changedFiles) file(s) changed.
"""
// TODO: - Add PR documentation link
// let seeOurDocumentation =
// """
// Documentation: \
// <a href=''> \
// Link</a>
// """
// message(seeOurDocumentation)
message(overview)
}
}
// MARK: Constants
// Constants related to validation rules.
private enum ValidationRules {
static let maxChangedFiles = 20
static let bigPRThreshold = 3000
}
// MARK: Extensions
// Extension with additional file-related methods.
fileprivate extension Danger.File {
var isInSources: Bool { hasPrefix("Sources/") }
var isInTests: Bool { hasPrefix("Tests/") }
var isSourceFile: Bool {
hasSuffix(".swift") || hasSuffix(".h") || hasSuffix(".m")
}
var isSwiftPackageDefintion: Bool {
hasPrefix("Package") && hasSuffix(".swift")
}
var isDangerfile: Bool {
self == "Dangerfile.swift"
}
}
// MARK: UnitTestValidator Methods
// Extension with methods for UnitTestValidator class.
fileprivate extension UnitTestValidator {
func checkUnitTestSummary() {
let file = "build/reports/errors.json"
if FileManager.default.fileExists(atPath: file) {
let summary = XCodeSummary(filePath: file) { result in
result.category != .warning
}
summary.report()
}
}
func checkUnitTestCoverage() {
Coverage.xcodeBuildCoverage(
.xcresultBundle("Example/fastlane/test_output/Example.xcresult"),
minimumCoverage: 70,
excludedTargets: ["DangerSwiftCoverageTests.xctest"]
)
}
}