# Danger Swift puts pull request etiquette in a typed Dangerfile

> 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.

**danger/swift** — ⚠️ Stop saying "you forgot to …" in code review

- Repository: https://github.com/danger/swift
- Website: https://danger.systems/swift/
- Stars: 1,125 · Forks: 152
- Language: Swift
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/danger-swift

## 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:

```swift
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:

```sh
# Install danger-swift, and a bundled danger-js locally
brew install danger/tap/danger-swift
 # Run danger
danger-swift ci
```

On 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:

```swift
// 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:

```swift
// 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:

```yml
jobs:
  build:
    runs-on: ubuntu-latest
    name: "Run Danger"
    steps:
      - uses: actions/checkout@v1
      - name: Danger
        uses: danger/swift@3.15.0
        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.

## 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.

## FAQ

### 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.

## Sources

- [danger/swift on GitHub](https://github.com/danger/swift)
- [License: MIT](https://github.com/danger/swift/blob/master/LICENSE)
- [Project website](https://danger.systems/swift/)
- [README](https://github.com/danger/swift/blob/master/README.md)
- [Releases](https://github.com/danger/swift/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/danger-swift
