getyourguide/spmgraph
A CLI tool that **unlocks Swift dependency graphs**, giving you extra information and capabilities.
Visualize
Generate an image that visually represents your dependency graph. Open the map!
spmgraph visualize <package-path> --helpTests
Selective testing based on git changes or a given list of changed files. <br> The output is a comma-separated list of test targets that can be fed into xcodebuild's -only-testing:TEST-IDENTIFIER or fastlane scan's only_testing
spmgraph tests <package-path> --helpLint
Verifies whether the dependency graph follows the team-defined best practices.
It's built on top of a user-defined SPMGraphConfig.swift, which allows teams to configure their own dependency graph rules leveraging Swift and the SwiftPM library. <br>
SPMGraphConfig.default provides the standard definition with built-in rules and extensible rules that can also be used on custom configurations.
For that, the steps are:
Config & Load
1. Config
Init or edit your spmgraph config
spmgraph config <package-path> --help- if none, it creates an initial
SPMGraphConfig.swifton the same path as yourPackage.swift - spmgraph opens up a temporary Swift Package where you configure spmgraph in Swift and build to check that everything is correct
Examples
For example, enforce that
- Feature modules don't depend on each other
- Linked dependencies are imported (used) at least once
- Base modules don't depend on feature modules
- The dependency graph isn't too deep
All possible using Swift. Below is an example of creating your own lint rule by traversing the dependency graph:
extension SPMGraphConfig.Lint.Rule {
static let unregisteredLiveModules = Self(
id: "unregisteredLiveModules",
name: "Unregistered Live modules",
abstract: "Live modules need to be added to the app target/feature module as dependencies.",
validate: { package, excludedSuffixes in
let liveModules = package
.modules
.compactMap { module -> Module? in
guard !module.containsOneOf(suffixes: excludedSuffixes), module.isLiveModule else {
return nil
}
return module
}
guard
let featureModule = package
.modules
.first(where: { $0.name == "GetYourGuideFeature" }),
case let featureModuleDependencies = featureModule
.dependencies
.compactMap(\.module)
else {
return [LintError.missingFeatureModule]
}
return liveModules.compactMap { liveModule in
if !featureModuleDependencies.contains(liveModule) {
return LintError.unregisteredLiveModules(
moduleName: liveModule.name,
appModule: featureModule.name
)
}
return nil
}
}
)
}2. Load
Load the latest SPMGraphConfig.swift into spmgraph
spmgraph load <package-path> --helpRun the linter
spmgraph lint <package-path> --helpFail on warnings
spmgraph lint <package-path> --strict <other-options>Allowed warnings count
Bypass the strict mode on a given number of allowed warnings
spmgraph lint <package-path> --strict --warningsCount 3 <other-options>CI
Custom GitHub actions are available for running the different spmgraph commands in CI environments.
To speed up builds
- Pass a custom config build directory via the
--config-build-directory/--build-diroption - It allows caching and pre-warming the config package
Cache warm
- Run
config,load, andlintpassing the--config-build-directory/--build-diroption - Store the whole directory as an artifact
Cache pull
- Pull the stored directory used when warming the cache
- Skip running
configandload, unless theSPMGraphConfig.swifthas changed - Run
lintpassing the cached directory to the--config-build-directory/--build-diroption
Requirements
- graphviz (available via
brew install graphviz) - Xcode 16.3+ and the Swift 6.1+ toolchain
Installation
Mint
mint install getyourguide/spmgraph- For optimal build times, make sure
~/.mint/bin/spmgraphis cached on your CI runner.
Acknowledgments
- Inspired by the work that the Tuist team does for the Apple developers community and their focus on leveraging the dependency graph to provide amazing features for engineers. Also, a source of inspiration for our shell abstraction layer.
Contributing
Check the CONTRIBUTING.md file.
Package Metadata
Repository: getyourguide/spmgraph
Default branch: main
README: README.md