diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4bc22a8..3f0c3b3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: api-breakage: if: ${{ github.event_name == 'pull_request' && !(github.event.pull_request.draft || false) }} runs-on: ubuntu-latest - container: swift:jammy + container: swift:noble steps: - name: Checkout uses: actions/checkout@v4 @@ -36,86 +36,25 @@ jobs: git config --global --add safe.directory "${GITHUB_WORKSPACE}" swift package diagnose-api-breaking-changes origin/main - dependency-graph: - if: ${{ github.event_name == 'push' }} - runs-on: ubuntu-latest - container: swift:jammy - permissions: - contents: write - steps: - - name: Check out code - uses: actions/checkout@v4 - - name: Fix Git configuration - run: | - git config --global --add safe.directory "${GITHUB_WORKSPACE}" - apt-get update && apt-get install -y curl - - name: Submit dependency graph - uses: vapor-community/swift-dependency-submission@v0.1 - - code-coverage: - if: ${{ !(github.event.pull_request.draft || false) }} - runs-on: ubuntu-latest - container: swift:jammy - services: - psql-a: - image: postgres:16 - env: - POSTGRES_USER: test_username - POSTGRES_DB: test_database - POSTGRES_PASSWORD: test_password - POSTGRES_HOST_AUTH_METHOD: scram-sha-256 - POSTGRES_INITDB_ARGS: --auth-host=scram-sha-256 - steps: - - name: Check out code - uses: actions/checkout@v4 - - name: Run unit tests for coverage data - run: swift test --enable-code-coverage - - name: Upload coverage data - uses: vapor/swift-codecov-action@v0.3 - with: - codecov_token: ${{ secrets.CODECOV_TOKEN }} - -# gh-codeql: -# if: ${{ !(github.event.pull_request.draft || false) }} -# runs-on: ubuntu-latest -# container: -# image: swift:5.10-jammy -# permissions: { actions: write, contents: read, security-events: write } -# timeout-minutes: 60 -# steps: -# - name: Check out code -# uses: actions/checkout@v4 -# - name: Mark repo safe in non-fake global config -# run: | -# git config --global --add safe.directory "${GITHUB_WORKSPACE}" -# - name: Initialize CodeQL -# uses: github/codeql-action/init@v3 -# with: { languages: swift } -# - name: Perform build -# run: swift build -# - name: Run CodeQL analyze -# uses: github/codeql-action/analyze@v3 - linux-unit: if: ${{ !(github.event.pull_request.draft || false) }} strategy: fail-fast: false matrix: postgres-image: - - postgres:16 - - postgres:14 - - postgres:12 + - postgres:17 + - postgres:15 + - postgres:13 swift-image: - - swift:5.8-jammy - swift:5.9-jammy - - swift:5.10-jammy - - swiftlang/swift:nightly-main-jammy + - swift:5.10-noble + - swift:6.0-noble include: - - postgres-image: postgres:16 + - postgres-image: postgres:17 postgres-auth: scram-sha-256 - - postgres-image: postgres:14 + - postgres-image: postgres:15 postgres-auth: md5 - - postgres-image: postgres:12 + - postgres-image: postgres:13 postgres-auth: trust runs-on: ubuntu-latest container: ${{ matrix.swift-image }} @@ -132,15 +71,19 @@ jobs: - name: Check out package uses: actions/checkout@v4 - name: Run local tests - run: swift test --sanitize=thread + run: swift test --sanitize=thread --enable-code-coverage + - name: Upload coverage data + uses: vapor/swift-codecov-action@v0.3 + with: + codecov_token: ${{ secrets.CODECOV_TOKEN || '' }} linux-integration: if: ${{ !(github.event.pull_request.draft || false) }} runs-on: ubuntu-latest - container: swift:5.10-jammy + container: swift:6.0-noble services: psql-a: - image: postgres:16 + image: postgres:17 env: POSTGRES_USER: test_username POSTGRES_DB: test_database @@ -173,10 +116,10 @@ jobs: fail-fast: false matrix: include: - - macos-version: macos-13 - xcode-version: '~14.3' - macos-version: macos-14 - xcode-version: latest + xcode-version: latest-stable + - macos-version: macos-15 + xcode-version: latest-stable runs-on: ${{ matrix.macos-version }} env: POSTGRES_HOSTNAME: 127.0.0.1 @@ -197,4 +140,20 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - name: Run local tests - run: swift test --sanitize=thread + run: swift test --sanitize=thread --enable-code-coverage + - name: Upload coverage data + uses: vapor/swift-codecov-action@v0.3 + with: + codecov_token: ${{ secrets.CODECOV_TOKEN || '' }} + + musl: + runs-on: ubuntu-latest + container: swift:6.0-noble + timeout-minutes: 30 + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Install SDK + run: swift sdk install https://download.swift.org/swift-6.0.3-release/static-sdk/swift-6.0.3-RELEASE/swift-6.0.3-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz --checksum 67f765e0030e661a7450f7e4877cfe008db4f57f177d5a08a6e26fd661cdd0bd + - name: Build + run: swift build --swift-sdk x86_64-swift-linux-musl diff --git a/Package.swift b/Package.swift index 8248f26..b982c5c 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.8 +// swift-tools-version:5.9 import PackageDescription let package = Package( @@ -39,6 +39,9 @@ let package = Package( ) var swiftSettings: [SwiftSetting] { [ + .enableUpcomingFeature("ExistentialAny"), .enableUpcomingFeature("ConciseMagicFile"), .enableUpcomingFeature("ForwardTrailingClosures"), + .enableUpcomingFeature("DisableOutwardActorInference"), + .enableExperimentalFeature("StrictConcurrency=complete"), ] } diff --git a/Package@swift-5.9.swift b/Package@swift-5.9.swift deleted file mode 100644 index 051be68..0000000 --- a/Package@swift-5.9.swift +++ /dev/null @@ -1,47 +0,0 @@ -// swift-tools-version:5.9 -import PackageDescription - -let package = Package( - name: "postgres-kit", - platforms: [ - .macOS(.v10_15), - .iOS(.v13), - .watchOS(.v6), - .tvOS(.v13), - ], - products: [ - .library(name: "PostgresKit", targets: ["PostgresKit"]), - ], - dependencies: [ - .package(url: "https://github.com/vapor/postgres-nio.git", from: "1.20.2"), - .package(url: "https://github.com/vapor/sql-kit.git", from: "3.28.0"), - .package(url: "https://github.com/vapor/async-kit.git", from: "1.19.0"), - ], - targets: [ - .target( - name: "PostgresKit", - dependencies: [ - .product(name: "AsyncKit", package: "async-kit"), - .product(name: "PostgresNIO", package: "postgres-nio"), - .product(name: "SQLKit", package: "sql-kit"), - ], - swiftSettings: swiftSettings - ), - .testTarget( - name: "PostgresKitTests", - dependencies: [ - .target(name: "PostgresKit"), - .product(name: "SQLKitBenchmark", package: "sql-kit"), - ], - swiftSettings: swiftSettings - ), - ] -) - -var swiftSettings: [SwiftSetting] { [ - .enableUpcomingFeature("ExistentialAny"), - .enableUpcomingFeature("ConciseMagicFile"), - .enableUpcomingFeature("ForwardTrailingClosures"), - .enableUpcomingFeature("DisableOutwardActorInference"), - .enableExperimentalFeature("StrictConcurrency=complete"), -] } diff --git a/README.md b/README.md index 1b75ca6..46b29a4 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ MIT License Continuous Integration -Swift 5.8+ +Swift 5.9+


diff --git a/Sources/PostgresKit/ConnectionPool+Postgres.swift b/Sources/PostgresKit/ConnectionPool+Postgres.swift index 9d46e03..080666f 100644 --- a/Sources/PostgresKit/ConnectionPool+Postgres.swift +++ b/Sources/PostgresKit/ConnectionPool+Postgres.swift @@ -1,7 +1,7 @@ -import NIOCore -import PostgresNIO @preconcurrency import AsyncKit import Logging +import NIOCore +import PostgresNIO extension EventLoopGroupConnectionPool where Source == PostgresConnectionSource { public func database(logger: Logger) -> any PostgresDatabase { @@ -39,11 +39,11 @@ private struct _EventLoopConnectionPoolPostgresDatabase: PostgresDatabase { var eventLoop: any EventLoop { self.pool.eventLoop } - + func send(_ request: any PostgresRequest, logger: Logger) -> EventLoopFuture { self.pool.withConnection(logger: logger) { $0.send(request, logger: logger) } } - + func withConnection(_ closure: @escaping (PostgresConnection) -> EventLoopFuture) -> EventLoopFuture { self.pool.withConnection(logger: self.logger, closure) } diff --git a/Sources/PostgresKit/Deprecations/PostgresConfiguration.swift b/Sources/PostgresKit/Deprecations/PostgresConfiguration.swift index edb9d8d..98446ec 100644 --- a/Sources/PostgresKit/Deprecations/PostgresConfiguration.swift +++ b/Sources/PostgresKit/Deprecations/PostgresConfiguration.swift @@ -1,6 +1,6 @@ -import NIOSSL import Foundation import NIOCore +import NIOSSL @available(*, deprecated, message: "Use `SQLPostgresConfiguration` instead.") public struct PostgresConfiguration { diff --git a/Sources/PostgresKit/Deprecations/PostgresConnectionSource+PostgresConfiguration.swift b/Sources/PostgresKit/Deprecations/PostgresConnectionSource+PostgresConfiguration.swift index 4a03461..3c36668 100644 --- a/Sources/PostgresKit/Deprecations/PostgresConnectionSource+PostgresConfiguration.swift +++ b/Sources/PostgresKit/Deprecations/PostgresConnectionSource+PostgresConfiguration.swift @@ -1,8 +1,8 @@ -import NIOSSL import Atomics import Logging -import PostgresNIO import NIOCore +import NIOSSL +import PostgresNIO extension PostgresConnectionSource { @available(*, deprecated, message: "Use `sqlConfiguration` instead.") diff --git a/Sources/PostgresKit/Deprecations/PostgresDatabase+SQL+Deprecated.swift b/Sources/PostgresKit/Deprecations/PostgresDatabase+SQL+Deprecated.swift index 272b917..ccc813b 100644 --- a/Sources/PostgresKit/Deprecations/PostgresDatabase+SQL+Deprecated.swift +++ b/Sources/PostgresKit/Deprecations/PostgresDatabase+SQL+Deprecated.swift @@ -1,5 +1,5 @@ -import PostgresNIO import Foundation +import PostgresNIO import SQLKit @available(*, deprecated, message: "Use `.sql(jsonEncoder:jsonDecoder:)` instead.") diff --git a/Sources/PostgresKit/Docs.docc/theme-settings.json b/Sources/PostgresKit/Docs.docc/theme-settings.json index de0d11a..d78a16f 100644 --- a/Sources/PostgresKit/Docs.docc/theme-settings.json +++ b/Sources/PostgresKit/Docs.docc/theme-settings.json @@ -8,6 +8,9 @@ "psqlkit": "#336791", "documentation-intro-fill": "radial-gradient(circle at top, var(--color-psqlkit) 30%, #000 100%)", "documentation-intro-accent": "var(--color-psqlkit)", + "documentation-intro-eyebrow": "white", + "documentation-intro-figure": "white", + "documentation-intro-title": "white", "logo-base": { "dark": "#fff", "light": "#000" }, "logo-shape": { "dark": "#000", "light": "#fff" }, "fill": { "dark": "#000", "light": "#fff" } diff --git a/Sources/PostgresKit/PostgresConnectionSource.swift b/Sources/PostgresKit/PostgresConnectionSource.swift index 87ada6c..37f7054 100644 --- a/Sources/PostgresKit/PostgresConnectionSource.swift +++ b/Sources/PostgresKit/PostgresConnectionSource.swift @@ -1,16 +1,16 @@ -import NIOSSL -import NIOConcurrencyHelpers import AsyncKit import Logging +import NIOConcurrencyHelpers +import NIOCore +import NIOSSL import PostgresNIO import SQLKit -import NIOCore public struct PostgresConnectionSource: ConnectionPoolSource { public let sqlConfiguration: SQLPostgresConfiguration - + private static let idGenerator = NIOLockedValueBox(0) - + public init(sqlConfiguration: SQLPostgresConfiguration) { self.sqlConfiguration = sqlConfiguration } @@ -22,10 +22,13 @@ public struct PostgresConnectionSource: ConnectionPoolSource { let connectionFuture = PostgresConnection.connect( on: eventLoop, configuration: self.sqlConfiguration.coreConfiguration, - id: Self.idGenerator.withLockedValue { $0 += 1; return $0 }, + id: Self.idGenerator.withLockedValue { + $0 += 1 + return $0 + }, logger: logger ) - + if let searchPath = self.sqlConfiguration.searchPath { return connectionFuture.flatMap { conn in conn.sql(queryLogLevel: nil) @@ -39,4 +42,4 @@ public struct PostgresConnectionSource: ConnectionPoolSource { } } -extension PostgresConnection: ConnectionPoolItem {} +extension PostgresNIO.PostgresConnection: AsyncKit.ConnectionPoolItem {} diff --git a/Sources/PostgresKit/PostgresDataTranslation.swift b/Sources/PostgresKit/PostgresDataTranslation.swift index 51f5c1c..3e04d79 100644 --- a/Sources/PostgresKit/PostgresDataTranslation.swift +++ b/Sources/PostgresKit/PostgresDataTranslation.swift @@ -1,5 +1,5 @@ -import PostgresNIO import Foundation +import PostgresNIO /// Quick and dirty ``CodingKey``, borrowed from FluentKit. If ``CodingKeyRepresentable`` wasn't broken by design /// (specifically, it can't be back-deployed before macOS 12.3 etc., even though it was introduced in Swift 5.6), @@ -17,7 +17,7 @@ private extension PostgresCell { } /// Sidestep problems with URL coding behavior by making it conform directly to Postgres coding. -extension URL: PostgresNonThrowingEncodable, PostgresDecodable { +extension Foundation.URL: PostgresNIO.PostgresNonThrowingEncodable, PostgresNIO.PostgresDecodable { public static var psqlType: PostgresDataType { String.psqlType } diff --git a/Sources/PostgresKit/PostgresDatabase+SQL.swift b/Sources/PostgresKit/PostgresDatabase+SQL.swift index a3d996b..95d38c7 100644 --- a/Sources/PostgresKit/PostgresDatabase+SQL.swift +++ b/Sources/PostgresKit/PostgresDatabase+SQL.swift @@ -1,5 +1,5 @@ -import PostgresNIO import Logging +import PostgresNIO import SQLKit extension PostgresDatabase { @@ -95,7 +95,7 @@ extension PostgresSQLDatabase: SQLDatabase, PostgresDatabase { self.database.withConnection(closure) } - func withSession(_ closure: @escaping @Sendable (any SQLDatabase) async throws -> R) async throws -> R { + func withSession(_ closure: @escaping @Sendable (any SQLDatabase) async throws -> R) async throws -> R { try await self.withConnection { c in c.eventLoop.makeFutureWithTask { try await closure(c.sql( diff --git a/Sources/PostgresKit/PostgresRow+SQL.swift b/Sources/PostgresKit/PostgresRow+SQL.swift index 7ac3233..ab945ac 100644 --- a/Sources/PostgresKit/PostgresRow+SQL.swift +++ b/Sources/PostgresKit/PostgresRow+SQL.swift @@ -1,5 +1,5 @@ -import PostgresNIO import Foundation +import PostgresNIO import SQLKit extension PostgresRow { @@ -7,7 +7,7 @@ extension PostgresRow { public func sql() -> some SQLRow { self.sql(decodingContext: .default) } - + public func sql(decodingContext: PostgresDecodingContext) -> some SQLRow { _PostgresSQLRow(randomAccessView: self.makeRandomAccess(), decodingContext: decodingContext) } @@ -39,7 +39,7 @@ extension _PostgresSQLRow: SQLRow { guard self.randomAccessView.contains(column) else { throw _Error.missingColumn(column) } - + return try PostgresDataTranslation.decode(T.self, from: self.randomAccessView[column], in: self.decodingContext) } } diff --git a/Sources/PostgresKit/SQLPostgresConfiguration.swift b/Sources/PostgresKit/SQLPostgresConfiguration.swift index 6169f34..e9d9def 100644 --- a/Sources/PostgresKit/SQLPostgresConfiguration.swift +++ b/Sources/PostgresKit/SQLPostgresConfiguration.swift @@ -1,10 +1,10 @@ -import NIOSSL import Foundation import NIOCore +import NIOSSL import PostgresNIO /// Provides configuration paramters for establishing PostgreSQL database connections. -public struct SQLPostgresConfiguration { +public struct SQLPostgresConfiguration: Sendable { /// IANA-assigned port number for PostgreSQL /// `UInt16(getservbyname("postgresql", "tcp").pointee.s_port).byteSwapped` public static var ianaPortNumber: Int { 5432 } diff --git a/Tests/PostgresKitTests/PostgresKitTests.swift b/Tests/PostgresKitTests/PostgresKitTests.swift index c927a2d..7253612 100644 --- a/Tests/PostgresKitTests/PostgresKitTests.swift +++ b/Tests/PostgresKitTests/PostgresKitTests.swift @@ -1,23 +1,28 @@ -@testable import PostgresKit -import SQLKitBenchmark -import XCTest +import Foundation import Logging -import PostgresNIO import NIOCore -import Foundation +import PostgresNIO +import SQLKitBenchmark +import XCTest +@testable import PostgresKit final class PostgresKitTests: XCTestCase { - func testSQLKitBenchmark() throws { - let conn = try PostgresConnection.test(on: self.eventLoop).wait() - defer { try? conn.close().wait() } - let benchmark = SQLBenchmarker(on: conn.sql()) + func testSQLKitBenchmark() async throws { + let conn = try await PostgresConnection.test(on: self.eventLoop).get() do { - try benchmark.run() + let benchmark = SQLBenchmarker(on: conn.sql()) + + try await benchmark.runAllTests() } catch { + try? await conn.close() XCTFail("Caught error: \(String(reflecting: error))") + throw error } + try await conn.close() } - + + // Disable for now, test is of questionable utility + /* func testPerformance() throws { let db = PostgresConnectionSource(sqlConfiguration: .test) let pool = EventLoopGroupConnectionPool( @@ -42,6 +47,7 @@ final class PostgresKitTests: XCTestCase { } } } + */ func testLeak() throws { struct Foo: Codable { diff --git a/Tests/PostgresKitTests/SQLPostgresConfigurationTests.swift b/Tests/PostgresKitTests/SQLPostgresConfigurationTests.swift index 64959ee..8281122 100644 --- a/Tests/PostgresKitTests/SQLPostgresConfigurationTests.swift +++ b/Tests/PostgresKitTests/SQLPostgresConfigurationTests.swift @@ -1,4 +1,4 @@ -@testable import PostgresKit +import PostgresKit import XCTest final class SQLPostgresConfigurationTests: XCTestCase { diff --git a/Tests/PostgresKitTests/Utilities.swift b/Tests/PostgresKitTests/Utilities.swift index 3c52f2d..ed2d189 100644 --- a/Tests/PostgresKitTests/Utilities.swift +++ b/Tests/PostgresKitTests/Utilities.swift @@ -1,13 +1,16 @@ -import XCTest -import PostgresKit -import Logging import Foundation +import Logging import NIOCore +import PostgresKit import PostgresNIO +import XCTest extension PostgresConnection { static func test(on eventLoop: any EventLoop) -> EventLoopFuture { - PostgresConnectionSource(sqlConfiguration: .test).makeConnection(logger: .init(label: "vapor.codes.postgres-kit.test"), on: eventLoop) + PostgresConnectionSource(sqlConfiguration: .test).makeConnection( + logger: .init(label: "vapor.codes.postgres-kit.test"), + on: eventLoop + ) } }