Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,42 @@ jobs:
echo "✅ All changed Swift files are properly formatted"
fi

lint:
name: SwiftLint
runs-on: macos-26
timeout-minutes: 10
env:
SWIFTLINT_VERSION: "0.65.0"
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Cache SwiftLint binary
id: cache-swiftlint
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: /usr/local/bin/swiftlint
key: swiftlint-${{ env.SWIFTLINT_VERSION }}-${{ runner.os }}
- name: Install SwiftLint ${{ env.SWIFTLINT_VERSION }}
if: steps.cache-swiftlint.outputs.cache-hit != 'true'
run: |
curl -fL \
"https://github.com/realm/SwiftLint/releases/download/${SWIFTLINT_VERSION}/portable_swiftlint.zip" \

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.

I guess this should also be pinned somehow (if we want the same security as for the actions)? Because github releases can change...

-o /tmp/swiftlint.zip
unzip -q -o /tmp/swiftlint.zip -d /tmp/swiftlint
sudo mv /tmp/swiftlint/swiftlint /usr/local/bin/swiftlint
- name: Verify SwiftLint version
run: |
INSTALLED=$(swiftlint version)
if [ "$INSTALLED" != "$SWIFTLINT_VERSION" ]; then
echo "Expected SwiftLint $SWIFTLINT_VERSION, got $INSTALLED" && exit 1
fi
echo "SwiftLint $INSTALLED"
- name: Run SwiftLint
run: swiftlint lint --strict

ci-success:
name: CI Success
if: always()
needs: [macos, macos-legacy, spm, linux, integration-tests, library-evolution, examples, spell-check, docs, format-check]
needs: [macos, macos-legacy, spm, linux, integration-tests, library-evolution, examples, spell-check, docs, format-check, lint]
runs-on: ubuntu-latest
steps:
- name: Check all jobs
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
branches:
- main
- release/*
- v3
workflow_dispatch:

permissions:
Expand Down
47 changes: 47 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# SwiftLint configuration for supabase-swift
# https://github.com/realm/SwiftLint
#
# Pinned version: 0.65.0
# Install locally: brew install swiftlint
# CI pins the exact binary via portable_swiftlint.zip from GitHub releases.
#
# Only rules that currently trigger violations are disabled. Enable them
# one-by-one in follow-up PRs once the violations are fixed or configured.

included:
- Sources
- Tests

excluded:
- .build
- Tests/IntegrationTests/supabase
- "**/__Snapshots__"

# Rules disabled because they currently have violations.
# Remove entries here as violations are fixed in follow-up PRs.
disabled_rules:
- class_delegate_protocol
- closure_parameter_position
- comment_spacing
- cyclomatic_complexity
- file_length
- for_where
- force_cast
- force_try
- function_body_length
- function_name_whitespace
- function_parameter_count
- identifier_name
- implicit_optional_initialization
- line_length
- multiple_closures_with_trailing_closure
- nesting
- non_optional_string_data_conversion
- opening_brace
- optional_data_string_conversion
- orphaned_doc_comment
- redundant_discardable_let
- todo
- trailing_comma
- type_body_length
- type_name
16 changes: 16 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,21 @@ npm ci --prefix tools/node # one-time setup (re-run only when tools/node/packa

Legitimate technical terms and project-specific words go in `dictionary.txt` at the repository root.

### Linting

```bash
# Lint Sources and Tests (fails on any new violation)
swiftlint lint --strict

# Autocorrect violations that SwiftLint can fix
swiftlint lint --fix
```
Comment thread
grdsdev marked this conversation as resolved.

This uses [SwiftLint](https://github.com/realm/SwiftLint) for code-smell and
correctness rules; `swift-format` remains the source of truth for formatting,
so the SwiftLint config (`.swiftlint.yml`) disables the purely stylistic rules
that overlap with it. Install SwiftLint locally with `brew install swiftlint`.

### Documentation

```bash
Expand Down Expand Up @@ -297,6 +312,7 @@ supabase stop
## Important Notes for AI Coding Agents

- Always run `./scripts/format.sh` before committing Swift code
- Run `swiftlint lint --strict` before committing; it must not report new violations
- Ensure new public APIs have DocC documentation comments
- Add tests for all new functionality
- Keep changes minimal and focused
Expand Down
2 changes: 1 addition & 1 deletion Sources/Helpers/Base64URL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ package enum Base64URL {
let paddingLength = requiredLength - length
if paddingLength > 0 {
let padding = "".padding(toLength: Int(paddingLength), withPad: "=", startingAt: 0)
base64 = base64 + padding
base64 += padding
}
return Data(base64Encoded: base64, options: .ignoreUnknownCharacters)
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/RealtimeV2/WebSocket/URLSessionWebSocket.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ final class URLSessionWebSocket: WebSocket {

let session = URLSession.sessionWithConfiguration(
configuration ?? .default,
onComplete: { session, task, error in
onComplete: { _, _, error in
mutableState.withValue {
if let webSocket = $0.webSocket {
// There are three possibilities here:
Expand Down Expand Up @@ -111,7 +111,7 @@ final class URLSessionWebSocket: WebSocket {
$0.continuation.resume(returning: $0.webSocket!)
}
},
onWebSocketTaskClosed: { session, task, code, reason in
onWebSocketTaskClosed: { _, _, code, reason in
mutableState.withValue {
assert($0.webSocket != nil, "connection should exist by this time")
$0.webSocket!._connectionClosed(code: code, reason: reason)
Expand Down
4 changes: 2 additions & 2 deletions Sources/TestHelpers/URLRequestSnapshot.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
#endif

extension Snapshotting where Value == URLRequest, Format == String {
/// A snapshot strategy for comparing requests based on a cURL representation.
///
// A snapshot strategy for comparing requests based on a cURL representation.
//
// ``` swift
// assertSnapshot(of: request, as: .curl)
// ```
Expand Down
5 changes: 0 additions & 5 deletions Tests/FunctionsTests/FunctionsClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ final class FunctionsClientTests: XCTestCase {
sessionConfiguration: sessionConfiguration
)

override func setUp() {
super.setUp()
// isRecording = true
}

func testInit() async {
let client = FunctionsClient(
url: url,
Expand Down
4 changes: 2 additions & 2 deletions Tests/IntegrationTests/RealtimeIntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@

// Verify both clients can decode presence
// Note: Due to timing, exact presence changes may vary, but structure should be correct
XCTAssertTrue(presenceChanges1.count > 0, "Client 1 should receive presence changes")
XCTAssertTrue(!presenceChanges1.isEmpty, "Client 1 should receive presence changes")

// Verify messages were received by both clients
XCTAssertEqual(messages1.count, 3, "Client 1 should receive all 3 messages")
Expand Down Expand Up @@ -816,7 +816,7 @@

// Verify user 1 leaving is detected by user 2
// Note: Due to timing, exact presence changes may vary, but structure should be correct
XCTAssertTrue(presenceChanges2.count > 0, "Client 2 should receive presence changes")
XCTAssertTrue(!presenceChanges2.isEmpty, "Client 2 should receive presence changes")

// Cleanup
await channel1.unsubscribe()
Expand Down
5 changes: 0 additions & 5 deletions Tests/PostgRESTTests/PostgrestFilterBuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ import XCTest

final class PostgrestFilterBuilderTests: PostgrestQueryTests {

override func setUp() {
super.setUp()
// isRecording = true
}

func testNotFilter() async throws {
Mock(
url: url.appendingPathComponent("users"),
Expand Down
4 changes: 0 additions & 4 deletions Tests/PostgRESTTests/PostgrestQueryBuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ import TestHelpers
import XCTest

final class PostgrestQueryBuilderTests: PostgrestQueryTests {
override func setUp() {
super.setUp()
// isRecording = true
}

func testSetAuth() {
XCTAssertNil(sut.configuration.headers["Authorization"])
Expand Down
2 changes: 1 addition & 1 deletion Tests/RealtimeTests/RealtimeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ import XCTest
"custom.access.token"
}
),
wsTransport: { url, headers in
wsTransport: { url, _ in
assertInlineSnapshot(of: url, as: .description) {
"""
ws://localhost:54321/realtime/v1/websocket?apikey=publishable.api.key&vsn=2.0.0&log_level=warn
Expand Down
4 changes: 2 additions & 2 deletions Tests/StorageTests/StorageFileAPITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ final class StorageFileAPITests: XCTestCase {
do {
try await storage.from("bucket")
.move(from: "source", to: "destination")
XCTFail()
XCTFail("Expected StorageError to be thrown")
} catch let error as StorageError {
XCTAssertEqual(error.message, "Error")
}
Expand Down Expand Up @@ -485,7 +485,7 @@ final class StorageFileAPITests: XCTestCase {
do {
try await storage.from("bucket")
.move(from: "source", to: "destination")
XCTFail()
XCTFail("Expected HTTPError to be thrown")
} catch let error as HTTPError {
XCTAssertEqual(error.data, Data("error".utf8))
XCTAssertEqual(error.response.statusCode, 412)
Expand Down
1 change: 1 addition & 0 deletions dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ Supabase
supabase
SUPABASE
supabot
swiftlint
testpath
testuser
timestamptz
Expand Down
Loading