Danger Swift puts pull request etiquette in a typed Dangerfile
⚠️ Stop saying "you forgot to …" in code review
At a glance
- What is it?
- Danger Swift lets you write your pull request checks in Swift, with a fully typed API over the Danger metadata, so a rule about a missing changelog entry is a couple of lines rather than a shell script. It runs on macOS and Linux, installs through Homebrew or Swift Package Manager, and is usable from GitHub Actions as a Docker image.
- Who is it for?
- Adopt Danger Swift if your team already works in Swift and wants its pull request checks to be type-checked rather than assembled from string matching in a shell script, since the API is fully typed and the plugin mechanism avoids copying the same rules across repositories. Do not adopt it if your team is not in Swift, because the whole point is writing the rules in the language your team uses.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The example Dangerfile is the whole argument
The README shows a Dangerfile that reads the pull request metadata and acts on it, and it is short enough to read as documentation:
import Danger
let danger = Danger()
let allSourceFiles = danger.git.modifiedFiles + danger.git.createdFiles
let changelogChanged = allSourceFiles.contains("CHANGELOG.md")
let sourceChanges = allSourceFiles.first(where: { $0.hasPrefix("Sources") })
if !changelogChanged && sourceChanges != nil {
warn("No CHANGELOG entry added.")
}The pattern is a rule about a missing changelog entry, expressed as ordinary Swift: a set of file names, a `contains` check, an optional lookup, and a conditional. What you do with the finding is one of four functions, and the distinctions between them matter for how a pull request behaves. `message` highlights something in the table, `warn` is for something bad but not important enough to fail the build, `fail` is for something that must be changed, and `markdown` puts free-form content under the table. The stated purpose of the project is to stop saying you forgot to in code review, which is a comment on how the tooling frames a finding rather than on what it checks.
The Swift version you have decides the version you take
The requirements table is long and specific, and it is the first thing to check. The latest version requires Swift 5.8. For older toolchains the table maps them to the supported Danger version: Swift 5.5 to 5.7 goes with v3.18.1, 5.4 with v3.15.0, 5.3 with v3.13.0, 5.2 with v3.11.1, 5.1 with v3.8.0, and then the 4.x series maps to v2.0.7, v0.4.1 and v0.3.6. The rule is simple, pick the Danger version that matches your compiler. The current release is 3.23.0 from 2026-09-09, and the last push to the master branch was on 2026-10-18, so the line is active. The licence is MIT.
Two installation routes, and a warning about the SwiftPM one
On a Mac the documented install is a Homebrew tap plus the run command:
# Install danger-swift, and a bundled danger-js locally
brew install danger/tap/danger-swift
# Run danger
danger-swift ciOn Linux the route is a clone and a make install, followed by a global npm install of danger, which is the JavaScript half that the Swift side talks to. The Swift Package Manager route is the one the documentation marks as more performant, and it is also the one with the sharpest edges. The recommendation is to use Rocket or a similar tool to comment out the development dependencies from your Package.swift, so consumers of your framework do not download and compile the Danger dependencies, and to cache the `.build` folder on your repository. There is also a `--cwd` parameter for when a Package.swift in the root folder gets in the way, which matters because Xcode since version 11 does not show an xcodeproj or xcworkspace in the Open Recents menu when a Package.swift sits in the same folder. You have to run danger-swift from the directory with the Package.swift and pass a path relative to it.
Four commands, and they differ in what they look at
The command list is short. `danger-swift ci` is the one for continuous integration. `danger-swift pr` takes a pull request URL and is what you use while building a Dangerfile, for example `danger-swift pr https://github.com/Moya/Harvey/pull/23`. `danger-swift local` runs Danger against your local changes from master, which is the loop you want while iterating on a rule. And `danger-swift edit` creates a temporary Xcode project for working on a Dangerfile, which is a small quality-of-life feature that matters more than it sounds, because a Dangerfile is a Swift program and editing it in a real project with a real compiler is much easier than in a text field. There is also a `--danger-js-path` argument for pointing at a locally compiled copy of danger-js instead of the installed one.
Plugins are Swift packages you can share between repositories
Infrastructure exists to support plugins, and the stated purpose is to avoid repeating the same Danger rules across separate repositories. A plugin is a Swift struct with a public entry point, and the example is minimal:
// DangerPlugin.swift
import Danger
public struct DangerPlugin {
let danger = Danger()
public static func doYourThing() {
// Code goes here
}
}The plugin is then either declared in your Package.swift as a package dependency and imported normally, or pulled in directly by suffixing the import with the URL, in the style the documentation calls Marathon:
// Dangerfile.swift
import DangerPlugin // package: https://github.com/username/DangerPlugin.git
DangerPlugin.doYourThing()For the SwiftPM route you also need to create a `DangerDependencies` folder inside `Sources` with an empty file in it, which is what keeps the dev dependencies from leaking into the consumer's build. The linked example is a plugin wrapping SwiftLint, and the documentation suggests caching the `~/.danger-swift` folder for the Marathon case.
Running it in GitHub Actions
The action is used as a step in a workflow, and the shape of it is the standard one, with the action version and the arguments that decide whether a finding fails the build:
jobs:
build:
runs-on: ubuntu-latest
name: "Run Danger"
steps:
- uses: actions/checkout@v1
- name: Danger
uses: danger/[email protected]
with:
args: --failOnErrors --no-publish-check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}The `GITHUB_TOKEN` has to be in the environment, because Danger needs to write its findings back to the pull request. There are two prebuilt images you can use instead, one plain and one that also includes SwiftLint, and you pull them with a `docker://` prefix pointing at the ghcr registry. The Dockerfile behind them is worth a look because it explains what the image does: it starts from a Swift image, installs Node and the danger npm package, downloads a SwiftLint release from GitHub, builds and installs danger-swift globally, and sets the entrypoint to `danger-swift ci` so that any arguments you pass are forwarded.
A Makefile of release chores
The repository root is a Swift package with the usual Danger pieces, including a `Dangerfile.swift` of its own, a `DangerfileExtensions/` directory, a `DangerfileWithDependencies.swift`, `Documentation/`, `Scripts/`, `Tests/` and `fixtures/`. The Makefile is a set of release chores rather than a build file. The `install` and `uninstall` targets install to `/usr/local/bin/danger-swift` through a script, the `docs` target runs the Swift doc generator over the Sources directory and then a Ruby script to update the docs, and there are separate version targets that run shell scripts to update the Makefile, the Danger version and the changelog, plus a target that creates the Homebrew tap. The `.swift-version` file pins the toolchain, and a `.swiftlint.yml` is present, which connects to the second prebuilt image that bundles SwiftLint alongside Danger.
Editorial conclusion
Adopt Danger Swift if your team already works in Swift and wants its pull request checks to be type-checked rather than assembled from string matching in a shell script, since the API is fully typed and the plugin mechanism avoids copying the same rules across repositories. Do not adopt it if your team is not in Swift, because the whole point is writing the rules in the language your team uses. Verify first which Swift version you have against the support table, that the Danger JavaScript runtime it depends on is installed, and that the plugins you want exist, since the plugin ecosystem is community-built.
Frequently asked questions
What is Danger Swift?
It is a way to write Dangerfiles in Swift, so pull request rules are expressed in a fully typed Swift API over the Danger metadata. The README's example checks the modified and created files for a changelog entry and warns when one is missing.
Which Swift versions does Danger Swift support?
The latest version requires Swift 5.8. Older toolchains use an earlier Danger release: 5.5 to 5.7 with v3.18.1, 5.4 with v3.15.0, 5.3 with v3.13.0, 5.2 with v3.11.1, 5.1 with v3.8.0, and the 4.x series with v2.0.7, v0.4.1 and v0.3.6.
How do I install Danger Swift on macOS and Linux?
On macOS, `brew install danger/tap/danger-swift` installs it along with a bundled danger-js, and `danger-swift ci` runs it. On Linux you clone the repository, run `make install`, and install danger with `npm install -g danger`.
What commands does danger-swift provide?
There are four: `ci` for continuous integration, `pr` with a pull request URL for building a Dangerfile, `local` to run against your local changes from master, and `edit` to create a temporary Xcode project for working on a Dangerfile.
How do Danger Swift plugins work?
A plugin is a Swift package exposing a struct, so the same rules can be shared across repositories instead of being copied. It is imported normally when declared in Package.swift, or directly by suffixing the import with a package URL in what the documentation calls the Marathon style, and the SwiftPM route also needs a DangerDependencies folder inside Sources with an empty file in it.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/danger-swift)Was this useful?