From 81d1106fc975acb9d5b3b576e6bd6ed669b8b6c4 Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Thu, 10 Aug 2023 21:27:01 -0500 Subject: [PATCH] Remove use of legacy codepath when establishing Postgres connections (#249) * Switch to using SQLKit (and thus going through `execute()` instead of `send()`) for setting search paths * The usual CI cleanup bit --- .github/workflows/projectboard.yml | 2 +- .github/workflows/test.yml | 182 +++++++++--------- .../PostgresConnectionSource.swift | 7 +- Tests/PostgresKitTests/Utilities.swift | 6 +- 4 files changed, 104 insertions(+), 93 deletions(-) diff --git a/.github/workflows/projectboard.yml b/.github/workflows/projectboard.yml index a0e6d98..8c8f4bd 100644 --- a/.github/workflows/projectboard.yml +++ b/.github/workflows/projectboard.yml @@ -7,5 +7,5 @@ on: jobs: update_project_boards: name: Update project boards - uses: vapor/ci/.github/workflows/update-project-boards-for-issue.yml@reusable-workflows + uses: vapor/ci/.github/workflows/update-project-boards-for-issue.yml@main secrets: inherit diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 380e056..2999d9b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,100 +27,120 @@ jobs: api-breakage: if: ${{ !(github.event.pull_request.draft || false) }} runs-on: ubuntu-latest - container: swift:5.8-jammy + container: swift:jammy steps: - name: Check out code uses: actions/checkout@v3 with: { 'fetch-depth': 0 } - name: Run API breakage check action - uses: vapor/ci/.github/actions/ci-swift-check-api-breakage@reusable-workflows + uses: vapor/ci/.github/actions/ci-swift-check-api-breakage@main + + code-coverage: + if: ${{ !(github.event.pull_request.draft || false) }} + runs-on: ubuntu-latest + container: swift:jammy + services: + psql-a: + image: postgres:15 + 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@v3 + - name: Run unit tests for coverage data + run: swift test --enable-code-coverage + - name: Upload coverage data + uses: vapor/swift-codecov-action@v0.2 + + gh-codeql: + if: ${{ !(github.event.pull_request.draft || false) }} + strategy: + fail-fast: false + matrix: + runner_os: + - ubuntu-latest + - macos-13 + runs-on: ${{ matrix.runner_os }} + permissions: + security-events: write + steps: + - name: Select appropriate Xcode version + if: ${{ startsWith(matrix.runner_os, 'macos') }} + uses: maxim-lobanov/setup-xcode@v1 + with: { xcode-version: '~14.3' } + - name: Check out code + uses: actions/checkout@v3 + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: { languages: swift } + - name: Perform build + run: swift build + - name: Run CodeQL analyze + uses: github/codeql-action/analyze@v2 - # Run Linux unit tests against various configurations linux-unit: if: ${{ !(github.event.pull_request.draft || false) }} strategy: fail-fast: false matrix: - dbimage: ['postgres:15', 'postgres:13', 'postgres:11'] - swiftver: [ - 'swift:5.7-jammy', 'swift:5.8-jammy', - 'swiftlang/swift:nightly-5.9-jammy', - 'swiftlang/swift:nightly-main-jammy' - ] - include: [ - {dbimage: 'postgres:15', dbauth: 'scram-sha-256'}, - {dbimage: 'postgres:13', dbauth: 'md5'}, - {dbimage: 'postgres:11', dbauth: 'trust'} - ] + postgres-image: + - postgres:15 + - postgres:13 + - postgres:11 + swift-image: + - swift:5.7-jammy + - swift:5.8-jammy + - swiftlang/swift:nightly-5.9-jammy + - swiftlang/swift:nightly-main-jammy + include: + - postgres-image: postgres:15 + postgres-auth: scram-sha-256 + - postgres-image: postgres:13 + postgres-auth: md5 + - postgres-image: postgres:11 + postgres-auth: trust runs-on: ubuntu-latest - container: ${{ matrix.swiftver }} + container: ${{ matrix.swift-image }} services: psql-a: - image: ${{ matrix.dbimage }} + image: ${{ matrix.postgres-image }} env: - POSTGRES_USER: 'test_username' - POSTGRES_DB: 'test_database' - POSTGRES_PASSWORD: 'test_password' - POSTGRES_HOST_AUTH_METHOD: ${{ matrix.dbauth }} - POSTGRES_INITDB_ARGS: --auth-host=${{ matrix.dbauth }} - psql-b: - image: ${{ matrix.dbimage }} - env: - POSTGRES_USER: 'test_username' - POSTGRES_DB: 'test_database' - POSTGRES_PASSWORD: 'test_password' - POSTGRES_HOST_AUTH_METHOD: ${{ matrix.dbauth }} - POSTGRES_INITDB_ARGS: --auth-host=${{ matrix.dbauth }} + POSTGRES_USER: test_username + POSTGRES_DB: test_database + POSTGRES_PASSWORD: test_password + POSTGRES_HOST_AUTH_METHOD: ${{ matrix.postgres-auth }} + POSTGRES_INITDB_ARGS: --auth-host=${{ matrix.postgres-auth }} steps: - name: Check out package uses: actions/checkout@v3 - name: Run local tests - run: swift test --enable-code-coverage - - name: Note Swift version - if: ${{ contains(matrix.swiftver, 'nightly') }} - run: | - echo "SWIFT_PLATFORM=$(. /etc/os-release && echo "${ID}${VERSION_ID}")" >>"${GITHUB_ENV}" - echo "SWIFT_VERSION=$(cat /.swift_tag)" >>"${GITHUB_ENV}" - - name: Upload code coverage - uses: vapor/swift-codecov-action@v0.2 - env: - POSTGRES_VERSION: ${{ matrix.dbimage }} - POSTGRES_AUTH_METHOD: ${{ matrix.dbauth }} - with: - cc_env_vars: 'SWIFT_VERSION,SWIFT_PLATFORM,RUNNER_OS,RUNNER_ARCH,POSTGRES_VERSION,POSTGRES_AUTH_METHOD' + run: swift test - # Test integration with dependent package on Linux linux-integration: if: ${{ !(github.event.pull_request.draft || false) }} - strategy: - fail-fast: false - matrix: - dbimage: ['postgres:15'] - dbauth: ['scram-sha-256'] - swiftver: [ - 'swift:5.7-jammy', 'swift:5.8-jammy', - 'swiftlang/swift:nightly-5.9-jammy', - 'swiftlang/swift:nightly-main-jammy' - ] runs-on: ubuntu-latest - container: ${{ matrix.swiftver }} + container: swift:5.8-jammy services: psql-a: - image: ${{ matrix.dbimage }} + image: postgres:15 env: - POSTGRES_USER: 'test_username' - POSTGRES_DB: 'test_database' - POSTGRES_PASSWORD: 'test_password' - POSTGRES_HOST_AUTH_METHOD: ${{ matrix.dbauth }} - POSTGRES_INITDB_ARGS: --auth-host=${{ matrix.dbauth }} + 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 psql-b: - image: ${{ matrix.dbimage }} + image: postgres:15 env: - POSTGRES_USER: 'test_username' - POSTGRES_DB: 'test_database' - POSTGRES_PASSWORD: 'test_password' - POSTGRES_HOST_AUTH_METHOD: ${{ matrix.dbauth }} - POSTGRES_INITDB_ARGS: --auth-host=${{ matrix.dbauth }} + 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 package uses: actions/checkout@v3 @@ -133,17 +153,15 @@ jobs: - name: Run fluent-postgres-kit tests run: swift test --package-path fluent-postgres-driver - # Run macOS unit tests against various configurations macos-unit: if: ${{ !(github.event.pull_request.draft || false) }} strategy: fail-fast: false matrix: - dbimage: ['postgresql@14'] - dbauth: ['scram-sha-256'] - macos: ['macos-13'] - xcode: ['latest-stable'] - runs-on: ${{ matrix.macos }} + xcode-version: + - '~14.3' + - '15.0-beta' + runs-on: macos-13 env: POSTGRES_HOSTNAME: 127.0.0.1 POSTGRES_DB: postgres @@ -151,25 +169,15 @@ jobs: - name: Select latest available Xcode uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: ${{ matrix.xcode }} + xcode-version: ${{ matrix.xcode-version }} - name: Install Postgres, setup DB and auth, and wait for server start - env: - POSTGRES_VERSION: ${{ matrix.dbimage }} - POSTGRES_AUTH_METHOD: ${{ matrix.dbauth }} run: | - export PATH="$(brew --prefix)/opt/${POSTGRES_VERSION}/bin:$PATH" PGDATA=/tmp/vapor-postgres-test - (brew unlink postgresql || true) && brew install "${POSTGRES_VERSION}" && brew link --force "${POSTGRES_VERSION}" - initdb --locale=C --auth-host "${POSTGRES_AUTH_METHOD}" -U "${POSTGRES_USER}" --pwfile=<(echo "${POSTGRES_PASSWORD}") + export PATH="$(brew --prefix)/opt/postgresql@14/bin:$PATH" PGDATA=/tmp/vapor-postgres-test + (brew unlink postgresql || true) && brew install "postgresql@14" && brew link --force "postgresql@14" + initdb --locale=C --auth-host "scram-sha-256" -U "${POSTGRES_USER}" --pwfile=<(echo "${POSTGRES_PASSWORD}") pg_ctl start --wait timeout-minutes: 2 - name: Checkout code uses: actions/checkout@v3 - name: Run local tests - run: swift test --enable-code-coverage - - name: Upload code coverage - uses: vapor/swift-codecov-action@v0.2 - env: - POSTGRES_VERSION: ${{ matrix.dbimage }} - POSTGRES_AUTH_METHOD: ${{ matrix.dbauth }} - with: - cc_env_vars: 'MD_APPLE_SDK_ROOT,SWIFT_VERSION,SWIFT_PLATFORM,RUNNER_OS,RUNNER_ARCH,POSTGRES_VERSION,POSTGRES_AUTH_METHOD' + run: swift test diff --git a/Sources/PostgresKit/PostgresConnectionSource.swift b/Sources/PostgresKit/PostgresConnectionSource.swift index 7728b6f..4bc2a23 100644 --- a/Sources/PostgresKit/PostgresConnectionSource.swift +++ b/Sources/PostgresKit/PostgresConnectionSource.swift @@ -3,6 +3,7 @@ import Atomics import AsyncKit import Logging import PostgresNIO +import SQLKit import NIOCore public struct PostgresConnectionSource: ConnectionPoolSource { @@ -27,8 +28,10 @@ public struct PostgresConnectionSource: ConnectionPoolSource { if let searchPath = self.sqlConfiguration.searchPath { return connectionFuture.flatMap { conn in - let string = searchPath.map { #""\#($0)""# }.joined(separator: ", ") - return conn.simpleQuery("SET search_path = \(string)").map { _ in conn } + conn.sql(queryLogLevel: nil) + .raw("SET search_path TO \(idents: searchPath, joinedBy: ",")") + .run() + .map { _ in conn } } } else { return connectionFuture diff --git a/Tests/PostgresKitTests/Utilities.swift b/Tests/PostgresKitTests/Utilities.swift index dc6562a..01e3a54 100644 --- a/Tests/PostgresKitTests/Utilities.swift +++ b/Tests/PostgresKitTests/Utilities.swift @@ -16,9 +16,9 @@ extension SQLPostgresConfiguration { .init( hostname: env("POSTGRES_HOSTNAME") ?? "localhost", port: env("POSTGRES_PORT").flatMap(Int.init) ?? Self.ianaPortNumber, - username: env("POSTGRES_USER") ?? "vapor_username", - password: env("POSTGRES_PASSWORD") ?? "vapor_password", - database: env("POSTGRES_DB") ?? "vapor_database", + username: env("POSTGRES_USER") ?? "test_username", + password: env("POSTGRES_PASSWORD") ?? "test_password", + database: env("POSTGRES_DB") ?? "test_database", tls: .disable ) }