Skip to content

Automatically format swift files in CI/CD#854

Open
KVSRoyal wants to merge 9 commits into
mainfrom
issue-849
Open

Automatically format swift files in CI/CD#854
KVSRoyal wants to merge 9 commits into
mainfrom
issue-849

Conversation

@KVSRoyal
Copy link
Copy Markdown
Member

@KVSRoyal KVSRoyal commented Apr 27, 2026

What

Resolves #849.

Automatic formatting will be enforced for .swift files using a combination of SwiftLint and SwiftFormat. Here is the developer flow:

  1. Local: Run formatting locally with just format-ios
  2. Pre-commit: When a dev commits any Swift files, formatting will be run via a husky pre-commit hook
  3. CI/CD: CI/CD will run a lint check and fail if there are any issues

This uses a new-to-this-repo tool, mint, to pin the same SwiftFormat and SwiftLint versions across dev environments.

Why

We would like to enable automatic formatting to catch some basic ios issues before review. This will reduce PR review burden.

Specifically, we chose to go with a mix of SwiftLint and SwiftFormat to leverage each one's specialties. SwiftLint is better at catching logic issues that cannot be automatically fixed, like force unwrapping, while SwiftFormat is better at fixing things automatically.

I chose mint and SwiftFormat (instead of Xcode's built-in swift-format) for this because:

  • mint with SwiftLint and SwiftFormat is way fast, running in < 1s for each format consistently locally
    • Does appear to take about 6 mins on the pipeline
  • mint allows us to pin SwiftLint and SwiftFormat versions via a Mintfile so devs can easily align on versions and have consistent formatting
  • mint is a lightweight wrapper that works well and we do not have to maintain

The drawback is that this is not bazel based. However, there does not seem to be a good bazel-based hermetic solution. In absence of such a solution, mint seems like the best option.

Other Options Considered

  • rules_swiftformat:
    • Pros: This is hermetic (does not require SwiftFormat on the machine). This is actually the recommended way according to the SwiftFormat github repo with Bazel, link
    • Cons: has not been maintained by a human since 2022. It does get some dependabot updates though
    • Blocking Problem: not in the bazel registry, doesn't appear to work with new MODULE-based Bazel
  • Fork rules_swiftformat:
    • Pros: hermetic
    • Cons: We would have to maintain this, including adding it to the bazel registry
  • rules_lint (replacement for bazel-super-formatter:
    • Pros: Actively maintained (last commit 3 weeks ago).
    • Cons: non-hermetic (depends on local SwiftFormat). Using local SwiftFormat means we'll all probably have different linters running
  • Use the SwiftFormat Swift package (link) and have a rules_player rule leverage it:
    • Pros: Easy way to align on the same version across machines
    • Cons: non-hermetic.
    • Blocking Problem: We apparently might need to reference the binary directly. Referencing the binary directly increases the rule complexity a lot
  • Use swift-format via Xcode
    • Pros: Built into Xcode, is a standard
    • Cons: Not-hermetic. Formatting will vary across different Xcode versions, even minor versions. Hard to align on versions across devs---doesn't fit our current development style well.

Change Type (required)

Indicate the type of change your pull request is:

  • patch
  • minor
  • major
  • N/A

Does your PR have any documentation updates?

  • Updated docs
  • No Update needed
  • Unable to update docs

@KVSRoyal KVSRoyal added the skip-release Preserve the current version when merged label Apr 27, 2026
@tmarmer
Copy link
Copy Markdown
Contributor

tmarmer commented Apr 27, 2026

Regarding rules_swiftformat:

Blocking Problem: not in the bazel registry so it's really hard, if not impossible to use

I thought we could target by a commit for rules repos not registered on the central bazel rules repository. The quickstart guide on the rules repo lists this as a way to install it too. If it's too much to manage, I think mint looks like the best alternative but want to make sure I understand exactly what's stopping us from using the recommended approach.

Comment thread .circleci/config.yml
- attach_workspace:
at: ~/player

- run:
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding rules_swiftformat:

Blocking Problem: not in the bazel registry so it's really hard, if not impossible to use

I thought we could target by a commit for rules repos not registered on the central bazel rules repository. The quickstart guide on the rules repo lists this as a way to install it too. If it's too much to manage, I think mint looks like the best alternative but want to make sure I understand exactly what's stopping us from using the recommended approach.

@tmarmer Yeah, it does list that but:

  1. I tried it and it didn't work
  2. I don't think this supports the new Bazel format. I got some errors I thought might be to that effect when trying
  3. The example says to use the last release, which is 0.4.1, which is from 2022. This is out of date and not really maintained

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well if it doesn't work, that's a good enough reason to do something else XD
If mint works and it's easy to keep everything up to date than I think that's a good approach.

@cehan-Chloe
Copy link
Copy Markdown
Contributor

cehan-Chloe commented May 4, 2026

My testing observation: I had two swift files with formatting issue, one staged one unstaged. running commit, the expected behavior is the commit failed with fixed version unstaged and an error about the linting and get it fixed since we have mint run swiftlint --fix. now formatting issue is still there and the error is

➜  player git:(issue-849) ✗ git commit -m "test"
✔ Preparing...
✔ Running tasks...
✖ Prevented an empty git commit!
✔ Reverting to original state because of errors...
✔ Cleaning up...

  ⚠ lint-staged prevented an empty git commit.
  Use the --allow-empty option to continue, or check your task configuration

husky - pre-commit hook exited with code 1 (error) 

i think it's because of the formatting issue is already fixed and no file change to commit then that leaves it an empty git commit. But it looks confusing since no linting error is pointed out or fixed and I still have staged change. Recording:
https://drive.google.com/file/d/1Vkkf8u2lIk9DJda6t_-GHtzkDtnnlOeg/view?usp=drive_link

Comment thread .circleci/config.yml
@KVSRoyal KVSRoyal marked this pull request as ready for review May 5, 2026 16:51
@KVSRoyal KVSRoyal requested review from a team as code owners May 5, 2026 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-release Preserve the current version when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

More robust SwiftLint

4 participants