mirror of
https://github.com/CocoaLumberjack/CocoaLumberjack.git
synced 2026-05-07 20:12:46 +00:00
194 lines
7.6 KiB
Swift
194 lines
7.6 KiB
Swift
import Foundation
|
|
import Danger
|
|
|
|
fileprivate extension Danger.File {
|
|
var isInSources: Bool { hasPrefix("Sources/") }
|
|
var isInTests: Bool { hasPrefix("Tests/") }
|
|
var isInDemos: Bool { hasPrefix("Demos/") }
|
|
var isInBenchmarking: Bool { hasPrefix("Benchmarking/") }
|
|
|
|
var isInVendor: Bool { contains("/Vendor/") }
|
|
var isInFMDB: Bool { contains("/FMDB/") }
|
|
|
|
var isSourceFile: Bool {
|
|
fileType == .swift || fileType == .m || fileType == .mm || fileType == .h
|
|
}
|
|
|
|
private static let spmOnlyTargetNames: Set<String> = [
|
|
"CocoaLumberjackSwiftLogBackend",
|
|
]
|
|
var isSPMOnlySourceFile: Bool {
|
|
guard isSourceFile else { return false }
|
|
if isInSources {
|
|
return Self.spmOnlyTargetNames.contains(where: { contains("/\($0)/") })
|
|
} else if isInTests {
|
|
return Self.spmOnlyTargetNames.contains(where: { contains("/\($0)Tests/") })
|
|
}
|
|
return false
|
|
}
|
|
|
|
var isSwiftPackageDefintion: Bool {
|
|
hasPrefix("Package") && fileType == .swift
|
|
}
|
|
|
|
var isDangerfile: Bool {
|
|
self == "Dangerfile.swift"
|
|
}
|
|
}
|
|
|
|
let danger = Danger()
|
|
let git = danger.git
|
|
|
|
// Sometimes it's a README fix, or something like that
|
|
let isDeclaredTrivial = danger.github?.pullRequest.title.contains("#trivial") ?? false
|
|
let hasSourceChanges = (git.modifiedFiles + git.createdFiles).contains(where: \.isInSources)
|
|
|
|
// Make it more obvious that a PR is a work in progress and shouldn't be merged yet
|
|
if danger.github?.pullRequest.title.contains("WIP") == true && danger.github?.pullRequest.draft != true {
|
|
warn("PR is marked as Work in Progress. Please consider marking the PR as Draft in GitHub to prevent merges.")
|
|
}
|
|
|
|
// Warn when there is a big PR
|
|
if let additions = danger.github?.pullRequest.additions,
|
|
let deletions = danger.github?.pullRequest.deletions,
|
|
case let sum = additions + deletions, sum > 1000 {
|
|
warn("Pull request is relatively big (\(sum) lines changed). If this PR contains multiple changes, consider splitting it into separate PRs for easier reviews.")
|
|
}
|
|
|
|
// Warn when library files has been updated but not tests.
|
|
if hasSourceChanges && !git.modifiedFiles.contains(where: \.isInTests) {
|
|
warn("The library files were changed, but the tests remained unmodified. Consider updating or adding to the tests to match the library changes.")
|
|
}
|
|
|
|
// Run SwiftLint
|
|
SwiftLint.lint(.modifiedAndCreatedFiles(directory: "Sources"), inline: true)
|
|
|
|
// Added (or removed) library files need to be added (or removed) from the
|
|
// Carthage Xcode project to avoid breaking things for our Carthage users.
|
|
let xcodeProjectFile: Danger.File = "Lumberjack.xcodeproj/project.pbxproj"
|
|
let xcodeProjectWasModified = git.modifiedFiles.contains(xcodeProjectFile)
|
|
if (git.createdFiles + git.deletedFiles).contains(where: { $0.isInSources && $0.isSourceFile && !$0.isSPMOnlySourceFile })
|
|
&& !xcodeProjectWasModified {
|
|
fail("Added or removed library files require the Carthage Xcode project to be updated.")
|
|
}
|
|
|
|
// Check xcodeproj settings are not changed
|
|
// Check to see if any of our project files contains a line with "SOURCE_ROOT" which indicates that the file isn't in sync with Finder.
|
|
if xcodeProjectWasModified {
|
|
let acceptedSettings: Set<String> = [
|
|
"APPLICATION_EXTENSION_API_ONLY",
|
|
"ASSETCATALOG_COMPILER_APPICON_NAME",
|
|
"ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME",
|
|
"ATTRIBUTES",
|
|
"CODE_SIGN_IDENTITY",
|
|
"COMBINE_HIDPI_IMAGES",
|
|
"FRAMEWORK_VERSION",
|
|
"GCC_PRECOMPILE_PREFIX_HEADER",
|
|
"GCC_PREFIX_HEADER",
|
|
"IBSC_MODULE",
|
|
"INFOPLIST_FILE",
|
|
"MODULEMAP_FILE",
|
|
"PRIVATE_HEADERS_FOLDER_PATH",
|
|
"PRODUCT_BUNDLE_IDENTIFIER",
|
|
"PRODUCT_NAME",
|
|
"PUBLIC_HEADERS_FOLDER_PATH",
|
|
"SDKROOT",
|
|
"SUPPORTED_PLATFORMS",
|
|
"TARGETED_DEVICE_FAMILY",
|
|
"WRAPPER_EXTENSION",
|
|
]
|
|
[xcodeProjectFile]
|
|
.lazy
|
|
.filter { FileManager.default.fileExists(atPath: $0) }
|
|
.forEach { projectFile in
|
|
danger.utils.readFile(projectFile).split(separator: "\n").enumerated().forEach { (offset, line) in
|
|
if line.contains("sourceTree = SOURCE_ROOT;") &&
|
|
line.contains("PBXFileReference") &&
|
|
!line.contains("path = Sources/CocoaLumberjackSwiftSupport/include/") {
|
|
warn(message: "Files should be in sync with project structure", file: projectFile, line: offset + 1)
|
|
}
|
|
if let range = line.range(of: "[A-Z_]+ = .*;", options: .regularExpression) {
|
|
let setting = String(line[range].prefix(while: { $0 != " " }))
|
|
if !acceptedSettings.contains(setting) {
|
|
warn(message: "Xcode settings need to remain in Configs/*.xcconfig. Please move " + setting + " to the xcconfig file", file: projectFile, line: offset + 1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check Copyright
|
|
let copyrightLines = (
|
|
source: [
|
|
"// Software License Agreement (BSD License)",
|
|
"//",
|
|
"// Copyright (c) 2010-2026, Deusty, LLC",
|
|
"// All rights reserved.",
|
|
"//",
|
|
"// Redistribution and use of this software in source and binary forms,",
|
|
"// with or without modification, are permitted provided that the following conditions are met:",
|
|
"//",
|
|
"// * Redistributions of source code must retain the above copyright notice,",
|
|
"// this list of conditions and the following disclaimer.",
|
|
"//",
|
|
"// * Neither the name of Deusty nor the names of its contributors may be used",
|
|
"// to endorse or promote products derived from this software without specific",
|
|
"// prior written permission of Deusty, LLC.",
|
|
],
|
|
demos: [
|
|
"//",
|
|
"// ",
|
|
"// ",
|
|
"//",
|
|
"// CocoaLumberjack Demos",
|
|
"//",
|
|
],
|
|
benchmarking: [
|
|
"//",
|
|
"// ",
|
|
"// ",
|
|
"//",
|
|
"// CocoaLumberjack Benchmarking",
|
|
"//",
|
|
]
|
|
)
|
|
|
|
// let sourcefilesToCheck = Dir.glob("*/*/*") // uncomment when we want to test all the files (locally)
|
|
let sourcefilesToCheck = Set(git.modifiedFiles + git.createdFiles)
|
|
let filesWithInvalidCopyright = sourcefilesToCheck.lazy
|
|
.filter { $0.isSourceFile }
|
|
.filter { !$0.isSwiftPackageDefintion }
|
|
.filter { !$0.isDangerfile }
|
|
.filter { !$0.isInVendor && !$0.isInFMDB }
|
|
.filter { FileManager.default.fileExists(atPath: $0) }
|
|
.filter {
|
|
// Use correct copyright lines depending on source file location
|
|
let (expectedLines, shouldMatchExactly): (Array<String>, Bool)
|
|
if $0.isInDemos {
|
|
expectedLines = copyrightLines.demos
|
|
shouldMatchExactly = false
|
|
} else if $0.isInBenchmarking {
|
|
expectedLines = copyrightLines.benchmarking
|
|
shouldMatchExactly = false
|
|
} else {
|
|
expectedLines = copyrightLines.source
|
|
shouldMatchExactly = true
|
|
}
|
|
let actualLines = danger.utils.readFile($0).split(separator: "\n").lazy.map(String.init)
|
|
if shouldMatchExactly {
|
|
return !actualLines.starts(with: expectedLines)
|
|
} else {
|
|
return !zip(actualLines, expectedLines).allSatisfy { $0.starts(with: $1) }
|
|
}
|
|
}
|
|
if !filesWithInvalidCopyright.isEmpty {
|
|
filesWithInvalidCopyright.sorted().forEach {
|
|
warn(message: "Invalid copyright!", file: $0, line: 1)
|
|
}
|
|
warn("""
|
|
Copyright is not valid. See our default copyright in all of our files (Sources, Demos and Benchmarking use different formats).<br/>
|
|
Invalid files:<br/>
|
|
\(filesWithInvalidCopyright.map { "- \($0)" }.joined(separator: "<br/>\n"))
|
|
""")
|
|
}
|