前言
如果你新加入一个团队,想要快速的了解团队的领域和团队中拥有的代码库的详细信息。
如果新团队中的代码库在 GitHub / GitLab 中并且你不熟悉代码所有权模型的概念或格式。本篇文章以 GitHub 为例,你可以使用 Glob 模式将一个或多个文件链接到 GitHub 团队。
如果新团队中的代码库有一个 GitHub 的 CODEOWNERS 文件,可以反映拥有的每个文件或文件组。这是对了解整个框架有很大帮助,如果没有,可以尝试创建一个。如下:
- /Tests/ @MyAwesomeOrg/cool-beans
- /Modules/Account/Tests/* @MyAwesomeOrg/cool-beans
- /Modules/Account/Settings/**/Views @MyAwesomeOrg/cool-beans
我曾经经历手动去查找团队拥有的文件中的文本出现的次数,比如固定模块的多次重复使用,这非常的耗费时间。
本篇文章讲帮助大家写一个小脚本来自动完成这项任务,给定一些文本片段和一个 GitHub 团队标签,它将在团队拥有的文件中找到该文本的所有出现次数。
项目设置
首先,要做的第一件事是创建一个可执行的 Swift Package:
mkdir find-code-owner && cd find-code-owner
swift package init --name FindCodeOwner --type executable
然后,将 ChimeHQ
的 GlobPattern Swift Package
添加为依赖项,以帮助确定包含查询文本的文件是否由提供的 GitHub 团队拥有:
// swift-tools-version: 5.10
import PackageDescription
let package = Package(
name: "FindCodeOwner",
platforms: [
.macOS(.v13)
],
dependencies: [
.package(url: "https://github.com/ChimeHQ/GlobPattern.git", exact: "0.1.1")
],
targets: [
.executableTarget(
name: "FindCodeOwner",
dependencies: ["GlobPattern"],
swiftSettings: [
.enableUpcomingFeature("BareSlashRegexLiterals")
]
),
]
)
查找文件
假设我们的团队想要迁移一个名为 Quick
的依赖,我们想要找到所有我们拥有的导入该库的文件。
让我们在我们的可执行目标中编写一些代码来实现这一点:
import Foundation
import GlobPattern
struct OwnershipRule {
let path: String
let teams: [String]
}
func getRules(from codeOwnersFile: String, relativeTo repository: String) -> [OwnershipRule] {
guard let content = try? String(contentsOfFile: codeOwnersFile) else {
return []
}
return content
.components(separatedBy: .newlines)
.filter { $0.isEmpty || $0.hasPrefix("#") }
.map { createRule(from: $0, relativeTo: repository) }
}
func createRule(from line: String, relativeTo repository: String) -> OwnershipRule {
let elements = line.components(separatedBy: .whitespaces)
.filter { !$0.isEmpty }
let teams = elements
.enumerated()
.filter { $0 != 0 && $1.hasPrefix("@") }
.map(\.1)
return OwnershipRule(path: repository + elements[0], teams: teams)
}
func getOwnersForFile(_ filePath: String, rules: [OwnershipRule]) -> [String] {
rules
.reversed()
.first { rule in
let globExpression = URL(string: rule.path)?.hasDirectoryPath == true ? rule.path + "*" : rule.path
let matcher = try? Glob.Pattern(globExpression)
return matcher?.match(filePath) == true
}?
.teams ?? []
}
// 1
let rootRepositoryDirectory = FileManager.default.currentDirectoryPath
let codeOwnersPath = rootRepositoryDirectory + "/.github/CODEOWNERS"
// 2
let allOwnershipRules = getRules(from: codeOwnersPath, relativeTo: rootRepositoryDirectory)
// 3
let matchingSearch = "import Quick"
let dirEnum = FileManager.default.enumerator(atPath: rootRepositoryDirectory)
var matchedFiles = [String]()
while let file = dirEnum?.nextObject() as? String {
guard file.hasSuffix(".swift") else { continue }
let fullPath = rootRepositoryDirectory + "/" + file
if let contents = FileManager.default.contents(atPath: fullPath),
let stringContents = String(data: contents, encoding: .utf8),
stringContents.contains(matchingSearch) {
matchedFiles.append(fullPath)
}
}
// 4
let matchedFilesOnwedByTeam = matchedFiles
.filter { fileContainingSearchQuery in
getOwnersForFile(fileContainingSearchQuery, rules: allOwnershipRules).contains("@MyAwesomeOrg/cool-beans")
}
// 5
print(matchedFilesOnwedByTeam)
上面这段代码的主要目的是从代码库中查找特定团队拥有的文件,并筛选出其中包含指定文本的文件。让我们逐步解释代码的意义、作用和可扩展性。
读取CODEOWNERS文件
通过 getRules(from: codeOwnersPath, relativeTo: rootRepositoryDirectory)
函数从 CODEOWNERS 文件中获取规则。
这些规则定义了哪些文件或目录由特定团队拥有。
解析规则
getRules(from: codeOwnersPath, relativeTo: rootRepositoryDirectory)
函数解析 CODEOWNERS 文件的内容,生成 OwnershipRule 结构体的数组。
每个 OwnershipRule 结构体包含文件路径和相应的团队。
搜索匹配的文件
脚本使用 FileManager
遍历当前代码库中的所有 .swift
文件。
对于每个文件,检查是否包含了匹配的文本(例如,import Quick
)。
确定文件所有者
对于包含匹配文本的文件,使用 getOwnersForFile(_:_:)
函数确定其所有者。
getOwnersForFile(_:_:)
函数根据文件路径和规则数组,确定文件的拥有者团队。
输出结果
将文件所有者为 @MyAwesomeOrg/cool-beans
的匹配文件打印输出。
通过这段脚本可以帮助开发者快速找到特定团队拥有的文件,并检查其中是否包含特定的文本。它的可扩展性取决于 CODEOWNERS 文件的格式和内容,以及要搜索的文本类型。例如,可以扩展代码以支持更多类型的文本搜索,或者为不同的团队提供不同的匹配逻辑。此外,可以根据需要添加更多的文件过滤规则或其他自定义逻辑。
总结
最后我想到了一些更加实用的功能,抽时间给大家分享。在未来,可以考虑添加更多的文件过滤规则或支持其他类型的文本搜索,以增强功能。例如,可以添加对不同文件类型的支持,或者实现更复杂的团队匹配逻辑。另外,还可以考虑添加用户界面和更友好的输出方式,以提升用户体验。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。