Danger Swift

repository·master·Indexed 22 days ago

https://github.com/danger/swift

A tool for formalizing Pull Request etiquette by writing automated rules in Swift. It inspects PR metadata to provide feedback via warnings, failures, and messages directly in the PR interface. Supports installation via Homebrew, Linux, GitHub Actions, and Swift Package Manager, with compatibility ranging from Swift 4.0 to 5.8.

Tokens
46.1K
Snippets
254
Records
289
Agent score
78%

What's inside Danger Swift

  1. Identify BitBucket Cloud Pull Request participant roles

    master

    When working with BitBucket Cloud pull requests in Danger Swift, the BitBucketCloud.PullRequest.Participant.Role enum is used to distinguish between different types of participants in a pull request. This enum conforms to Decodable and String.

    There are two available roles:

    • reviewer: Represents a user explicitly assigned as a reviewer.
    • participant: Represents a user involved in the pull request who is not specifically a reviewer.
    // The enum cases available for BitBucket Cloud pull request participants
    public enum Role: String, Decodable {
        case reviewer
        case participant
    }
  2. Explore Danger Swift provider types

    master

    Danger Swift includes specialized types for interacting with different VCS providers. Use these types to access metadata specific to your hosting service:

    • GitHub: Access GitHub.PullRequest, GitHub.Repo, GitHub.User, and GitHub.Review.
    • GitLab: Access GitLab.MergeRequest, GitLab.User, and GitLab.Metadata.
    • BitBucket Cloud: Access BitBucketCloud.PullRequest, BitBucketCloud.Commit, and BitBucketCloud.Repo.
    • BitBucket Server: Access BitBucketServer.PullRequest, BitBucketServer.Commit, and BitBucketServer.Project.
    • Git: Generic access to Git.Commit and Git.Commit.Author.

    These types allow you to write provider-agnostic logic or provider-specific logic when you need deep metadata (like labels, milestones, or specific reviewer states).

  3. Access GitHub metadata via the GitHub struct

    master

    The GitHub struct provides access to metadata associated with your pull request on GitHub. It includes information about the issue, the pull request itself, commits, reviews, requested reviewers, and a direct interface to the Octokit API.

    // Accessing the GitHub metadata object
    let githubMetadata = context.github
  4. Advanced Package.swift configuration for plugin testing

    master

    To make testing easier, you can import Danger directly in your Package.swift.

    Recommendation: If you define a dynamic library target (e.g., DangerDeps) for development purposes, use a tool like Rocket to comment it out before distribution. This prevents the DangerDeps library from being compiled and shipped to your users.

    let package = Package(
        // ...
        products: [
            .library(name: "DangerPlugin", targets: ["DangerPlugin"]),
            .library(name: "DangerDeps", type: .dynamic, targets: ["DangerPlugin"]),
        ],
        dependencies: [
            .package(url: "https://github.com/danger/swift.git", from: "1.0.0"),
        ],
        targets: [
            .target(name: "DangerPlugin", dependencies: ["Danger"]),
        ]
    )
  5. Use GitHub.Review.State to check review status

    master

    The GitHub.Review.State enum represents the possible states of a GitHub pull request review. It conforms to Decodable and String, making it easy to use when parsing review data. You can use the following cases to determine the outcome of a review:

    • approved: The reviewer has approved the changes.
    • requestedChanges: The reviewer has requested changes.
    • comment: The reviewer left a comment without a formal approval or request for changes.
    • pending: The review is in a pending state.
    • dismissed: The review has been dismissed.
    // Example of checking a review state
    switch review.state {
    case .approved:
        print("Review approved!")
    case .requestedChanges:
        print("Changes requested.")
    case .comment:
        print("Reviewer left a comment.")
    case .pending:
        print("Review is pending.")
    case .dismissed:
        print("Review was dismissed.")
    @unknown default:
        break
    }
  6. Access Git metadata in Danger Swift

    master

    The Git struct provides access to git-specific metadata associated with a pull request. You can use this to inspect changes made in the PR, such as which files were modified, created, or deleted, and to access information about the commits included in the PR.

    // Accessing the git property on the danger object
    let gitMetadata = danger.git
  7. Use FileDiff.Changes to inspect file changes

    master

    The FileDiff.Changes enum represents the type of change applied to a file in a pull request or commit. It conforms to Equatable and provides specific data depending on whether a file was created, deleted, modified, or renamed. You can use pattern matching to extract the specific lines or hunks associated with each change type.

    // Example of pattern matching on FileDiff.Changes
    switch change {
    case .created(let addedLines):
        print("File created with lines: \(addedLines)")
    case .deleted(let deletedLines):
        print("File deleted. Removed lines: \(deletedLines)")
    case .modified(let hunks):
        print("File modified with \(hunks.count) hunks")
    case .renamed(let oldPath, let hunks):
        print("File renamed from \(oldPath) with \(hunks.count) hunks")
    }
  8. How `danger local` works and how to share Dangerfiles

    master

    The danger local command provides a way to run your Dangerfile using git-hooks, allowing you to get feedback on your rules while working locally before pushing to a Pull Request.

    Unlike danger ci, which uses Pull Request metadata, danger local derives its environment from the local git differences between your current commit and the master branch.

    Important for sharing Dangerfiles: When running locally, platform-specific objects like danger.github and danger.bitbucketServer will be nil. To share a single Dangerfile.swift between local and CI environments, you must verify that these objects exist before attempting to use them.

    A recommended pattern is to create a separate, lightweight Dangerfile (e.g., Dangerfile.lite.swift) containing only rules that work with danger.git (such as CHANGELOG or README checks) and importing it into your main Dangerfile.

  9. Platform-specific metadata types

    master

    Depending on your hosting provider, Danger Swift provides specific metadata types to access PR details:

    • GitHub: Access GitHub metadata, including GitHub.PullRequest, GitHub.User, GitHub.Repo, GitHub.Review, and GitHub.Issue.
    • GitLab: Access GitLab metadata, including GitLab.MergeRequest, GitLab.User, and GitLab.Metadata.
    • BitBucket Cloud: Access BitBucketCloud metadata, including BitBucketCloud.PullRequest, BitBucketCloud.Repo, and BitBucketCloud.User.
    • BitBucket Server: Access BitBucketServer metadata, including BitBucketServer.PullRequest, BitBucketServer.Repo, and BitBucketServer.Project.
  10. How Danger Swift works

    master

    Danger Swift operates as a layer within a 'Swift sandwich' architecture powered by Danger JS. The workflow follows these steps:

    1. Metadata Collection: Danger JS identifies the CI environment (via environment variables) and the platform (GitHub, BitBucket Server, or GitLab).
    2. JSON Transformation: All collected CI and platform metadata is transformed into a JSON file.
    3. Swift Execution: This JSON is passed to Danger Swift. During this phase, plugins are set up and your Dangerfile.swift is evaluated.
    4. Evaluation: When you instantiate let danger = Danger() in your Dangerfile.swift, the JSON metadata is parsed into Swift objects. You use methods like markdown, warning, fail, or message to report results.
    5. Result Feedback: The results are converted back to JSON and passed to Danger JS, which then updates the code review platform (creating/editing comments) and determines if the build should pass or fail.
    // Typical entry point in Dangerfile.swift
    let danger = Danger()
    
    danger.message("Hello from Danger Swift!")
  11. Import Swift PM packages using Marathon syntax

    master

    You can directly import a Swift PM package as a dependency in your Dangerfile.swift by suffixing the import with package: [url].

    // Dangerfile.swift
    
    import DangerPlugin // package: https://github.com/username/DangerPlugin.git
    
    DangerPlugin.doYourThing()
    import DangerPlugin // package: https://github.com/username/DangerPlugin.git
    
    DangerPlugin.doYourThing()
  12. Configure SwiftLint linting styles with LintStyle

    master

    The LintStyle enum allows you to define which files SwiftLint should analyze during a Danger Swift run. You can choose to lint the entire project, only the files changed in the current pull request, or a specific subset of files.

    Available styles:

    • all(directory: String?): Lints all files in the project. You can optionally provide a directory string to set the --path for the SwiftLint execution.
    • modifiedAndCreatedFiles(directory: String?): Lints only the .swift files that have been modified or created in the current context. You can optionally provide a directory string to set the --path.
    • files([File]): Lints only the specific File objects provided in the array. This is useful for manual filtering. Note that files will be filtered to include only those with a .swift extension.
    // Example usage of different LintStyle cases
    
    // Lint everything in a specific directory
    let style1 = LintStyle.all(directory: "Sources")
    
    // Lint only changed files
    let style2 = LintStyle.modifiedAndCreatedFiles()
    
    // Lint a specific list of files
    let style3 = LintStyle.files([file1, file2])