Skip to content

Commit

Permalink
Re-added dot/graphviz support with command line output option (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeger authored Sep 19, 2023
1 parent 4258079 commit 34f33b6
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 7 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ This is the hardest part: dealing with obscure Xcode formats. But if we get that
- `--base-branch`: Branch to compare against to find the relevant changes. If emitted, a local changeset is used (development mode).
- `--test-plan`: Path to the test plan. If not given, tool would try to infer the path.
- `--json`: Provide output in JSON format (STDOUT).
- `--dependency-graph`: Opens Safari with a dependency graph visualization.
- `--dependency-graph`: Opens Safari with a dependency graph visualization. Attention: if you don't trust Javascript ecosystem prefer using `--dot` option.
- `--dot`: Output dependency graph in Dot (Graphviz) format. To be used with Graphviz: `brew install graphviz`, then `xcode-selective-test --dot | dot -Tsvg > output.svg && open output.svg`
- `--verbose`: Provide verbose output.

## Configuration file `.xcode-selective-testing.yml`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,35 @@ import Foundation
import Workspace
import PathKit

extension DependencyGraph {
extension TargetIdentity {
var dotDescription: String {
return "\"\(self.description.replacingOccurrences(of: "-", with: "_"))\""
}
}

extension DependencyGraph {
func dot() -> String {
var dot = """
digraph {
rankdir=TB
"""
let grouped = groupByPath()

grouped.keys.forEach { path in
let targets = grouped[path]!

targets.forEach { target in
let deps = dependencies(for: target)
guard !deps.isEmpty else {
return
}
dot = dot + "\n\t\(target.dotDescription) -> { \(deps.map(\.dotDescription).joined(separator: " ")) }"
}
}
dot = dot + "\n}"
return dot
}

func mermaid(highlightTargets: Set<TargetIdentity>) -> String {
var result = "graph TD\n"
allTargets().forEach { target in
Expand Down
14 changes: 10 additions & 4 deletions Sources/SelectiveTestingCore/SelectiveTestingTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public final class SelectiveTestingTool {
private let basePath: Path
private let printJSON: Bool
private let renderDependencyGraph: Bool
private let dot: Bool
private let verbose: Bool
private let testPlan: String?
private let config: Config?
Expand All @@ -25,6 +26,7 @@ public final class SelectiveTestingTool {
testPlan: String?,
printJSON: Bool = false,
renderDependencyGraph: Bool = false,
dot: Bool = false,
verbose: Bool = false) throws {

if let configData = try? (Path.current + Config.defaultConfigName).read(),
Expand All @@ -44,6 +46,7 @@ public final class SelectiveTestingTool {
self.basePath = Path(finalBasePath)
self.printJSON = printJSON
self.renderDependencyGraph = renderDependencyGraph
self.dot = dot
self.verbose = verbose
self.testPlan = testPlan ?? config?.testPlan
}
Expand Down Expand Up @@ -75,6 +78,13 @@ public final class SelectiveTestingTool {
try Shell.exec("open -a Safari \"\(workspaceInfo.dependencyStructure.mermaidInURL(highlightTargets: affectedTargets))\"")
}

if printJSON {
try printJSON(affectedTargets: affectedTargets)
}
else if dot {
print(workspaceInfo.dependencyStructure.dot())
}

if verbose {
workspaceInfo.dependencyStructure
.allTargets()
Expand Down Expand Up @@ -108,10 +118,6 @@ public final class SelectiveTestingTool {
}
}

if printJSON {
try printJSON(affectedTargets: affectedTargets)
}

if let testPlan {
// 4. Configure workspace to test given targets
try enableTests(at: Path(testPlan),
Expand Down
6 changes: 5 additions & 1 deletion Sources/xcode-selective-test/SelectiveTesting.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ struct SelectiveTesting: AsyncParsableCommand {
@Flag(name: .long, help: "Output in JSON format")
var JSON: Bool = false

@Flag(help: "Render dependency graph in the browser")
@Flag(help: "Render dependency graph in the browser using Mermaid")
var dependencyGraph: Bool = false

@Flag(help: "Output dependency graph in Dot (Graphviz) format")
var dot: Bool = false

@Flag(help: "Produce verbose output")
var verbose: Bool = false

Expand All @@ -34,6 +37,7 @@ struct SelectiveTesting: AsyncParsableCommand {
testPlan: testPlan,
printJSON: JSON,
renderDependencyGraph: dependencyGraph,
dot: dot,
verbose: verbose)

do {
Expand Down

0 comments on commit 34f33b6

Please sign in to comment.