Skip to content

Add SwiftLint: CI workflow, config, and pre-commit hook#9

Open
odrobnik wants to merge 2 commits into
mainfrom
claude/agitated-thompson-63e790
Open

Add SwiftLint: CI workflow, config, and pre-commit hook#9
odrobnik wants to merge 2 commits into
mainfrom
claude/agitated-thompson-63e790

Conversation

@odrobnik

Copy link
Copy Markdown
Contributor

Wires up SwiftLint for the Swift code, mirroring XMLKit's three-part setup (CI workflow + shared config + opt-in local hook) so dev and CI run the same binary and rule set with no version drift.

What's added

  • .github/workflows/swiftlint.yml — macOS + Homebrew SwiftLint running lint --strict on PRs touching Swift/config files and on pushes to main. Checkout skips submodules: vendor/libgit2 is excluded from linting and the lint job never builds, so there's no reason to fetch it.
  • .swiftlint.yml — GitKit-specific tuning, with each decision commented in the file.
  • Scripts/hooks/pre-commit + Scripts/install-hooks.sh — opt-in local hook that auto-fixes and strict-lints staged Swift files. Run ./Scripts/install-hooks.sh once per clone to point core.hooksPath at it.

Config decisions (why this diverges from XMLKit's config)

GitKit's house style differs from XMLKit's, so the rule set is tuned rather than copied:

  • identifier_name length checks off — single-character names are the C-interop idiom here (rc for libgit2 return codes, u/p in withCString closures, p/n in the glob matcher). Case checks stay on. ~243 violations otherwise.
  • opening_brace, return_arrow_whitespace, statement_position disabled — the codebase uses deliberate tabular alignment (ColorPalette's SGR table aligns -> and trailing comments; Repository+Status's bitmask cascades align braces with uncuddled else if). Their --fix flattens these tables — it collapsed the Status cascade into single 400+ char lines during testing.
  • optional_data_string_conversion off — the lossy String(decoding:) calls are intentional for not-guaranteed-UTF-8 git data (blob content, sideband progress); the failable initializer this rule prefers would change behavior.
  • Metric thresholds (complexity 25, function body 110, etc.) sized just above current outliers — functions that assemble libgit2 option structs and drive C state machines linearly — still strict enough to flag new growth.

Code changes

9 files, all mechanical lint fixes: colon spacing, redundant var x: T? = nil, trailing commas, and 5 rewrapped over-long lines. The porcelain status strings were split so the emitted bytes are byte-for-byte identical.

Verification

  • swiftlint lint --strict --quiet exits clean (exactly what CI runs)
  • swift test passes 147/147
  • Smoke-tested the hook: planted a fixable violation, staged it — hook auto-fixed, re-staged, and passed strict

🤖 Generated with Claude Code

Mirror XMLKit's three-part SwiftLint setup, tuned to GitKit's style:

- .github/workflows/swiftlint.yml: macOS + Homebrew SwiftLint running
  `lint --strict` on PRs touching Swift/config and pushes to main.
  Checkout skips submodules — vendor/libgit2 is excluded from linting
  and the lint job never builds.
- .swiftlint.yml: GitKit-specific tuning, each choice commented. Length
  checks off for identifier_name (single-char names are the C-interop
  idiom: rc return codes, u/p in withCString closures); opening_brace,
  return_arrow_whitespace, statement_position disabled to preserve the
  deliberate tabular alignment in ColorPalette and Repository+Status;
  optional_data_string_conversion off (lossy String(decoding:) is
  intentional for not-guaranteed-UTF-8 git data); metric thresholds
  sized just above current outliers.
- Scripts/hooks/pre-commit + Scripts/install-hooks.sh: opt-in local hook
  (auto-fix + strict lint on staged Swift files), keeping CI and dev on
  the same binary and rule set. Run ./Scripts/install-hooks.sh once per
  clone to activate.

Code changes are mechanical lint fixes: colon spacing, redundant
`var x: T? = nil`, trailing commas, and 5 rewrapped over-long lines
(porcelain status strings split so emitted bytes are identical).

Verified: swiftlint lint --strict exits clean; swift test passes 147/147.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 24fcbf081f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/swiftlint.yml Outdated
CI ran `brew install swiftlint` (always latest) while the pre-commit hook
used whatever swiftlint was on a developer's PATH. A new Homebrew release
with changed rules or defaults could fail a PR that passed locally — the
lint gate wasn't reproducible.

- .swiftlint-version: single source of truth (0.63.2).
- CI installs that exact version from the GitHub release portable binary
  (universal x86_64 + arm64, runs natively on the arm64 macOS runner)
  instead of brew, and triggers on changes to the version file.
- pre-commit hook reads the same file and warns when the local binary
  differs (non-blocking — CI is the authoritative gate).

Addresses Codex review feedback on PR #9.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant