← Back to realm/SwiftLint

How to Deploy & Use realm/SwiftLint

SwiftLint Deployment and Usage Guide

This guide provides comprehensive instructions for deploying and using SwiftLint, a tool designed to enforce Swift style and conventions.

1. Prerequisites

SwiftLint is written in Swift and relies on SwiftSyntax, Clang, and SourceKit. Ensure you have a compatible Swift development environment set up.

  • Xcode: Required for Swift development, which includes the Swift toolchain.
  • Swift Package Manager (SPM): Included with Xcode.
  • Homebrew (macOS): Recommended for easy installation on macOS.
  • CocoaPods: For integrating SwiftLint into CocoaPods projects.
  • Mint: A package manager for command-line tools.
  • Bazel: A build system for large-scale projects.

2. Installation

SwiftLint can be installed using various package managers or integrated directly into your Swift projects.

Swift Package Manager (SPM)

SwiftLint can be integrated as a command plugin or a build tool plugin. It's recommended to use the dedicated SwiftLintPlugins repository for easier adoption.

  1. Add the dependency to your Package.swift file:

    To consume the latest release:

    .package(url: "https://github.com/SimplyDanny/SwiftLintPlugins", from: "<version>")
    

    To pin to a specific version:

    .package(url: "https://github.com/SimplyDanny/SwiftLintPlugins", exact: "<version>")
    

    Replace <version> with the desired version (e.g., 0.52.4).

Xcode Package Dependency

  1. In Xcode, navigate to File > Add Packages....
  2. Enter the following URL:
    https://github.com/SimplyDanny/SwiftLintPlugins
    
  3. Follow the prompts to add the package.

Homebrew (macOS)

brew install swiftlint

CocoaPods

  1. Add the following to your Podfile:
    pod 'SwiftLint'
    
  2. Run pod install in your project directory. This will download SwiftLint binaries to Pods/ and allow invocation via ${PODS_ROOT}/SwiftLint/swiftlint in Script Build Phases.

Mint

mint install realm/SwiftLint

Bazel

  1. For MODULE.bazel (recommended for modern Bazel projects):

    bazel_dep(name = "swiftlint", version = "0.52.4", repo_name = "SwiftLint")
    
  2. For WORKSPACE (for older Bazel projects):

    load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
    
    http_archive(
        name = "build_bazel_rules_apple",
        sha256 = "390841dd5f8a85fc25776684f4793d56e21b098dfd7243cd145b9831e6ef8be6",
        url = "https://github.com/bazelbuild/rules_apple/releases/download/2.4.1/rules_apple.2.4.1.tar.gz",
    )
    
    load(
        "@build_bazel_rules_apple//apple:repositories.bzl",
        "apple_rules_dependencies",
    )
    
    apple_rules_dependencies()
    
    load(
        "@build_bazel_rules_swift//swift:repositories.bzl",
        "swift_rules_dependencies",
    )
    
    swift_rules_dependencies()
    
    load(
        "@build_bazel_rules_swift//swift:extras.bzl",
        "swift_rules_extra_dependencies",
    )
    
    swift_rules_extra_dependencies()
    
    http_archive(
        name = "SwiftLint",
        sha256 = "c6ea58b9c72082cdc1ada4a2d48273ecc355896ed72204cedcc586b6ccb8aca6",
        url = "https://github.com/realm/SwiftLint/releases/download/0.52.4/bazel.tar.gz",
    )
    
    load("@SwiftLint//bazel:repos.bzl", "swiftlint_repos")
    
    swiftlint_repos()
    
    load("@SwiftLint//bazel:deps.bzl", "swiftl
    

3. Configuration

SwiftLint is configured using a .swiftlint.yml file placed in the root of your project. This file allows you to enable/disable rules, customize severity, and define custom rules.

Basic Configuration

A minimal .swiftlint.yml might look like this:

disabled_rules: # rule identifiers to exclude from running
  - colon
  - comma
  - control_statement
opt_in_rules: # some rules are only opt-in
  - empty_count
  - force_unwrapping
included: # paths to include in linting
  - Source
excluded: # paths to exclude from linting
  - Carthage
  - Pods
  - Tests
# configurable rules can be customized from this configuration file
line_length: 120
type_body_length:
  - 300 # warning
  - 400 # error
file_length:
  warning: 500
  error: 1200

Custom Rules

You can define custom rules using regular expressions. For example, to enforce a specific naming convention:

custom_rules:
  my_custom_rule:
    name: "MyCustomRule"
    message: "Custom rule violation"
    regex: "regex" # Your regular expression here
    match_kinds: comment # Apply only to comments, or other SyntaxKind values
    excluded_match_kinds: # Exclude specific SyntaxKind values
    severity: error # warning or error

The match_kinds and excluded_match_kinds can be used to target specific syntax elements like comment, identifier, keyword, etc. (Refer to SyntaxKind.allKinds in the source for a complete list).

Multiple Configurations

SwiftLint supports merging configurations from different .swiftlint.yml files. Child configurations can override or extend parent configurations.

Example: If Config._0 disables ForceCastRule and Config._2 enables it, merging Config._0 with Config._2 will result in ForceCastRule being disabled if Config._0 is the base.

// Example from ConfigurationTests+MultipleConfigs.swift
// config0Merge2 = Mock.Config._0.merged(withChild: Mock.Config._2)
// XCTAssertFalse(Mock.Config._0.contains(rule: ForceCastRule.self)) // true
// XCTAssertTrue(Mock.Config._2.contains(rule: ForceCastRule.self))  // true
// XCTAssertFalse(config0Merge2.contains(rule: ForceCastRule.self)) // true if _0 disables it.

4. Build & Run

SwiftLint is primarily a command-line tool.

Running SwiftLint Locally

Navigate to your project directory in the terminal and run:

swiftlint

This will lint the files in your current directory and subdirectories, reporting violations to the console.

Auto-correcting Violations

Many SwiftLint rules can automatically correct violations.

swiftlint autocorrect

Integrating with Xcode Build Phases

To run SwiftLint automatically with every build in Xcode:

  1. Open your Xcode project.

  2. Select your target.

  3. Go to the "Build Phases" tab.

  4. Click the + button and choose "New Run Script Phase".

  5. Drag the new script phase above "Compile Sources".

  6. Add the following script:

    If installed via Homebrew:

    if which swiftlint >/dev/null; then
      swiftlint
    else
      echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
    fi
    

    If installed via CocoaPods:

    "${PODS_ROOT}/SwiftLint/swiftlint"
    

    If using SPM build tool plugin: Xcode should automatically integrate it.

Running Specific Files or Directories

swiftlint lint --path Source/MyFile.swift
swiftlint lint --path MyModule/

5. Deployment

SwiftLint is typically used as a development tool and integrated into CI/CD pipelines rather than being "deployed" in the traditional sense.

CI/CD Integration

To ensure code style consistency across your team and prevent unlinted code from being merged, integrate SwiftLint into your CI/CD pipeline.

Example for a generic CI script:

# Install SwiftLint (if not pre-installed on CI runner)
brew install swiftlint || true # Use '|| true' to prevent build failure if already installed

# Run SwiftLint
swiftlint

# Optionally, run autocorrect and fail if there are still violations
# swiftlint autocorrect --format && git diff --exit-code

Using SwiftLint with GitHub Actions:

You can add a step to your GitHub Actions workflow:

name: SwiftLint

on: [push, pull_request]

jobs:
  lint:
    runs-on: macos-latest
    steps:
    - uses: actions/checkout@v3
    - name: Install SwiftLint
      run: brew install swiftlint
    - name: Run SwiftLint
      run: swiftlint

6. Troubleshooting

SwiftLint not found

  • Homebrew: Ensure brew install swiftlint completed successfully and swiftlint is in your system's PATH. You might need to restart your terminal.
  • CocoaPods: Verify pod install ran and the path ${PODS_ROOT}/SwiftLint/swiftlint is correct in your Xcode Build Phase.
  • SPM: Ensure the package dependency is correctly added and Xcode has resolved it. Clean your build folder (Shift + Cmd + K).

Rules not being applied

  • Incorrect .swiftlint.yml path: Ensure the .swiftlint.yml file is in the root of your project or specified correctly using the --config flag.
  • Syntax errors in .swiftlint.yml: YAML is sensitive to indentation. Use a YAML linter to check for errors.
  • Caching issues: Sometimes SwiftLint caches configurations. Run swiftlint lint --force-exclude or clean your project build folder.
  • Excluded paths: Check your excluded paths in .swiftlint.yml to ensure the files you expect to be linted are not accidentally excluded.
  • Opt-in rules: Remember that some rules are opt-in and must be explicitly enabled in your .swiftlint.yml under opt_in_rules.

Performance issues

  • Large project: Linting an entire large project can be slow. Use the included and excluded configurations to limit the scope of linting.
  • SourceKit/Clang issues: Some rules rely on SourceKit or Clang, which can sometimes be slower. If you notice specific rules causing slowdowns, consider disabling them or using file-specific // swiftlint:disable comments.

Custom rule not working

  • Regex issues: Test your regular expression thoroughly. Online regex testers can be helpful.
  • match_kinds / excluded_match_kinds: Ensure you are targeting the correct SyntaxKind values for your custom rule. If you're unsure, try removing match_kinds initially to see if the regex matches, then refine.
  • Severity: Check if the severity is set to warning or error. Warnings might be overlooked.

Xcode integration warnings not showing

  • Ensure the "Run Script Phase" is placed before "Compile Sources" in your Xcode target's Build Phases.
  • Check the build log for any errors from the SwiftLint script.
  • Verify that the output format is compatible with Xcode (SwiftLint's default output is usually Xcode-compatible).