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.
-
Add the dependency to your
Package.swiftfile: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
- In Xcode, navigate to
File > Add Packages.... - Enter the following URL:
https://github.com/SimplyDanny/SwiftLintPlugins - Follow the prompts to add the package.
Homebrew (macOS)
brew install swiftlint
CocoaPods
- Add the following to your
Podfile:pod 'SwiftLint' - Run
pod installin your project directory. This will download SwiftLint binaries toPods/and allow invocation via${PODS_ROOT}/SwiftLint/swiftlintin Script Build Phases.
Mint
mint install realm/SwiftLint
Bazel
-
For
MODULE.bazel(recommended for modern Bazel projects):bazel_dep(name = "swiftlint", version = "0.52.4", repo_name = "SwiftLint") -
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:
-
Open your Xcode project.
-
Select your target.
-
Go to the "Build Phases" tab.
-
Click the
+button and choose "New Run Script Phase". -
Drag the new script phase above "Compile Sources".
-
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" fiIf 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 swiftlintcompleted successfully andswiftlintis in your system's PATH. You might need to restart your terminal. - CocoaPods: Verify
pod installran and the path${PODS_ROOT}/SwiftLint/swiftlintis 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.ymlpath: Ensure the.swiftlint.ymlfile is in the root of your project or specified correctly using the--configflag. - 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-excludeor clean your project build folder. - Excluded paths: Check your
excludedpaths in.swiftlint.ymlto 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.ymlunderopt_in_rules.
Performance issues
- Large project: Linting an entire large project can be slow. Use the
includedandexcludedconfigurations 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:disablecomments.
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 correctSyntaxKindvalues for your custom rule. If you're unsure, try removingmatch_kindsinitially to see if the regex matches, then refine.- Severity: Check if the severity is set to
warningorerror. 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).