From 26a0a427b62ba5eef8d5168fb25a523bbdc0f195 Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 4 Dec 2024 09:33:26 +0000 Subject: [PATCH 01/13] github: Add standard workflows configuration --- .github/workflows/main.yml | 18 ++++++++++++++++ .github/workflows/pull_request.yml | 26 ++++++++++++++++++++++++ .github/workflows/pull_request_label.yml | 18 ++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/pull_request.yml create mode 100644 .github/workflows/pull_request_label.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..400a1b9 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,18 @@ +name: Main + +on: + push: + branches: [main] + schedule: + - cron: "0 8,20 * * *" + +jobs: + unit-tests: + name: Unit tests + uses: apple/swift-nio/.github/workflows/unit_tests.yml@main + with: + linux_5_9_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" + linux_5_10_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" + linux_6_0_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" + linux_nightly_6_0_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" + linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 0000000..d688072 --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,26 @@ +name: PR + +on: + pull_request: + types: [opened, reopened, synchronize] + +jobs: + soundness: + name: Soundness + uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main + with: + license_header_check_project_name: "swift-etcd-client-gsoc" + + unit-tests: + name: Unit tests + uses: apple/swift-nio/.github/workflows/unit_tests.yml@main + with: + linux_5_9_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" + linux_5_10_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" + linux_6_0_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" + linux_nightly_6_0_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" + linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" + + cxx-interop: + name: Cxx interop + uses: apple/swift-nio/.github/workflows/cxx_interop.yml@main diff --git a/.github/workflows/pull_request_label.yml b/.github/workflows/pull_request_label.yml new file mode 100644 index 0000000..8fd47c1 --- /dev/null +++ b/.github/workflows/pull_request_label.yml @@ -0,0 +1,18 @@ +name: PR label + +on: + pull_request: + types: [labeled, unlabeled, opened, reopened, synchronize] + +jobs: + semver-label-check: + name: Semantic version label check + runs-on: ubuntu-latest + timeout-minutes: 1 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Check for Semantic Version label + uses: apple/swift-nio/.github/actions/pull_request_semver_label_checker@main From 85d6bc6ac58b2500c1daf45c36edd2c2430d5fd2 Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 4 Dec 2024 09:33:40 +0000 Subject: [PATCH 02/13] github: Add release.yml --- .github/release.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/release.yml diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..f96b514 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,14 @@ +changelog: + categories: + - title: SemVer Major + labels: + - ⚠️ semver/major + - title: SemVer Minor + labels: + - semver/minor + - title: SemVer Patch + labels: + - semver/patch + - title: Other Changes + labels: + - semver/none From 82c79fda2b2a8aeacbb07f6cd8d59b89ca99c0d3 Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 4 Dec 2024 09:32:38 +0000 Subject: [PATCH 03/13] licence-check: Add standard .licenseignore --- .licenseignore | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .licenseignore diff --git a/.licenseignore b/.licenseignore new file mode 100644 index 0000000..3121799 --- /dev/null +++ b/.licenseignore @@ -0,0 +1,37 @@ +.gitignore +**/.gitignore +.licenseignore +.gitattributes +.git-blame-ignore-revs +.mailfilter +.mailmap +.spi.yml +.swiftformat +.swift-format +.swiftformatignore +.editorconfig +.github/* +*.md +*.txt +*.yml +*.yaml +*.json +Package.swift +**/Package.swift +Package@-*.swift +**/Package@-*.swift +Package.resolved +**/Package.resolved +Makefile +*.modulemap +**/*.modulemap +**/*.docc/* +*.xcprivacy +**/*.xcprivacy +*.symlink +**/*.symlink +Dockerfile +**/Dockerfile +Snippets/* +dev/git.commit.template +.unacceptablelanguageignore From 9ff4b390fd211c3a23961ab98af360eacc255cca Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 4 Dec 2024 09:41:52 +0000 Subject: [PATCH 04/13] license-check: Ignore proto files and generated Swift --- .licenseignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.licenseignore b/.licenseignore index 3121799..2e49a7e 100644 --- a/.licenseignore +++ b/.licenseignore @@ -16,6 +16,9 @@ *.yml *.yaml *.json +*.proto +*.pb.swift +*.grpc.swift Package.swift **/Package.swift Package@-*.swift From a0574b9e404de86833c48eb1299479d8249d97bb Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 4 Dec 2024 09:42:21 +0000 Subject: [PATCH 05/13] license-check: Move imports below license header --- Sources/ETCDExample/ETCDExample.swift | 4 ++-- Tests/ETCDTests/ETCDTests.swift | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/ETCDExample/ETCDExample.swift b/Sources/ETCDExample/ETCDExample.swift index 9b5eef0..5ee22d3 100644 --- a/Sources/ETCDExample/ETCDExample.swift +++ b/Sources/ETCDExample/ETCDExample.swift @@ -1,5 +1,3 @@ -import Dispatch - //===----------------------------------------------------------------------===// // // This source file is part of the swift-etcd-client-gsoc open source project @@ -13,6 +11,8 @@ import Dispatch // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +import Dispatch import ETCD import NIO diff --git a/Tests/ETCDTests/ETCDTests.swift b/Tests/ETCDTests/ETCDTests.swift index 178d925..aca0c9f 100644 --- a/Tests/ETCDTests/ETCDTests.swift +++ b/Tests/ETCDTests/ETCDTests.swift @@ -1,6 +1,3 @@ -import ETCD -import NIO - //===----------------------------------------------------------------------===// // // This source file is part of the swift-etcd-client-gsoc open source project @@ -14,6 +11,9 @@ import NIO // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +import ETCD +import NIO import XCTest final class EtcdClientTests: XCTestCase { From de31c8afefe839eda38f55adf4eb88e84511ca4e Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 4 Dec 2024 09:45:22 +0000 Subject: [PATCH 06/13] format-check: Apply result of swift-format --- Package.swift | 2 +- Sources/ETCD/DeleteRangeRequest.swift | 6 +++--- Sources/ETCD/ETCDClient.swift | 10 ++++++++-- Tests/ETCDTests/ETCDTests.swift | 4 ++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Package.swift b/Package.swift index 8b21c53..5656b6e 100644 --- a/Package.swift +++ b/Package.swift @@ -27,7 +27,7 @@ let package = Package( .library( name: "ETCD", targets: ["ETCD"] - ), + ) ], dependencies: [ .package(url: "https://github.com/apple/swift-nio.git", from: "2.56.0"), diff --git a/Sources/ETCD/DeleteRangeRequest.swift b/Sources/ETCD/DeleteRangeRequest.swift index f831082..1d5346e 100644 --- a/Sources/ETCD/DeleteRangeRequest.swift +++ b/Sources/ETCD/DeleteRangeRequest.swift @@ -19,13 +19,13 @@ public struct DeleteRangeRequest { public var key: Data public var rangeEnd: Data? public var prevKV: Bool = false - + init(protoDeleteRangeRequest: Etcdserverpb_DeleteRangeRequest) { self.key = protoDeleteRangeRequest.key self.rangeEnd = protoDeleteRangeRequest.rangeEnd.isEmpty ? nil : protoDeleteRangeRequest.rangeEnd self.prevKV = protoDeleteRangeRequest.prevKv } - + /// Struct representing a deleteRangeRequest in etcd. /// /// - Parameters: @@ -37,7 +37,7 @@ public struct DeleteRangeRequest { self.rangeEnd = rangeEnd self.prevKV = prevKV } - + func toProto() -> Etcdserverpb_DeleteRangeRequest { var protoDeleteRangeRequest = Etcdserverpb_DeleteRangeRequest() protoDeleteRangeRequest.key = self.key diff --git a/Sources/ETCD/ETCDClient.swift b/Sources/ETCD/ETCDClient.swift index 1ba08cc..6072031 100644 --- a/Sources/ETCD/ETCDClient.swift +++ b/Sources/ETCD/ETCDClient.swift @@ -110,7 +110,10 @@ public final class EtcdClient: @unchecked Sendable { /// - Parameters: /// - key: The key for which the value is watched. Parameter is of type Sequence. /// - operation: The operation to be run on the WatchAsyncSequence for the key. - public func watch(_ key: some Sequence, _ operation: (WatchAsyncSequence) async throws -> Result) async throws -> Result { + public func watch( + _ key: some Sequence, + _ operation: (WatchAsyncSequence) async throws -> Result + ) async throws -> Result { let request = [Etcdserverpb_WatchRequest.with { $0.createRequest.key = Data(key) }] let watchAsyncSequence = WatchAsyncSequence(grpcAsyncSequence: watchClient.watch(request)) return try await operation(watchAsyncSequence) @@ -121,7 +124,10 @@ public final class EtcdClient: @unchecked Sendable { /// - Parameters: /// - key: The key for which the value is watched. Parameter is of type String. /// - operation: The operation to be run on the WatchAsyncSequence for the key. - public func watch(_ key: String, _ operation: (WatchAsyncSequence) async throws -> Result) async throws -> Result { + public func watch( + _ key: String, + _ operation: (WatchAsyncSequence) async throws -> Result + ) async throws -> Result { try await watch(key.utf8, operation) } } diff --git a/Tests/ETCDTests/ETCDTests.swift b/Tests/ETCDTests/ETCDTests.swift index aca0c9f..a34009c 100644 --- a/Tests/ETCDTests/ETCDTests.swift +++ b/Tests/ETCDTests/ETCDTests.swift @@ -54,7 +54,7 @@ final class EtcdClientTests: XCTestCase { let deleteRangeRequest = DeleteRangeRequest(key: rangeRequestKey) try await etcdClient.deleteRange(deleteRangeRequest) - + fetchedValue = try await etcdClient.getRange(rangeRequest) XCTAssertNil(fetchedValue) } @@ -68,7 +68,7 @@ final class EtcdClientTests: XCTestCase { let deleteRangeRequest = DeleteRangeRequest(key: key) try await etcdClient.deleteRange(deleteRangeRequest) - + fetchedValue = try await etcdClient.getRange(rangeRequest) XCTAssertNil(fetchedValue) } From 2cd875a8338d5f235b1939d0cf44d65ac07eff6c Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 4 Dec 2024 09:47:34 +0000 Subject: [PATCH 07/13] scripts: Remove legacy CI scripts --- scripts/generate_contributors_list.sh | 39 ------ scripts/run-swift-format.sh | 66 ---------- scripts/soundness.sh | 175 -------------------------- 3 files changed, 280 deletions(-) delete mode 100755 scripts/generate_contributors_list.sh delete mode 100755 scripts/run-swift-format.sh delete mode 100755 scripts/soundness.sh diff --git a/scripts/generate_contributors_list.sh b/scripts/generate_contributors_list.sh deleted file mode 100755 index c90c5ed..0000000 --- a/scripts/generate_contributors_list.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -##===----------------------------------------------------------------------===## -## -## This source file is part of the swift-etcd-client-gsoc open source project -## -## Copyright (c) 2024 Apple Inc. and the swift-etcd-client-gsoc project authors -## Licensed under Apache License v2.0 -## -## See LICENSE.txt for license information -## See CONTRIBUTORS.txt for the list of swift-etcd-client-gsoc project authors -## -## SPDX-License-Identifier: Apache-2.0 -## -##===----------------------------------------------------------------------===## - -set -eu -here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -contributors=$( cd "$here"/.. && git shortlog -es | cut -f2 | sed 's/^/- /' ) - -cat > "$here/../CONTRIBUTORS.txt" <<- EOF - For the purpose of tracking copyright, this is the list of individuals and - organizations who have contributed source code to swift-etcd-client-gsoc. - - For employees of an organization/company where the copyright of work done - by employees of that company is held by the company itself, only the company - needs to be listed here. - - ## COPYRIGHT HOLDERS - - - Apple Inc. (all contributors with '@apple.com') - - ### Contributors - - $contributors - - **Updating this list** - - Please do not edit this file manually. It is generated using \`./scripts/generate_contributors_list.sh\`. If a name is misspelled or appearing multiple times: add an entry in \`./.mailmap\` -EOF diff --git a/scripts/run-swift-format.sh b/scripts/run-swift-format.sh deleted file mode 100755 index 17aa008..0000000 --- a/scripts/run-swift-format.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash -##===----------------------------------------------------------------------===## -## -## This source file is part of the swift-etcd-client-gsoc open source project -## -## Copyright (c) 2024 Apple Inc. and the swift-etcd-client-gsoc project authors -## Licensed under Apache License v2.0 -## -## See LICENSE.txt for license information -## See CONTRIBUTORS.txt for the list of swift-etcd-client-gsoc project authors -## -## SPDX-License-Identifier: Apache-2.0 -## -##===----------------------------------------------------------------------===## -##===----------------------------------------------------------------------===## -## -## This source file is part of the SwiftCertificates open source project -## -## Copyright (c) 2023 Apple Inc. and the SwiftCertificates project authors -## Licensed under Apache License v2.0 -## -## See LICENSE.txt for license information -## See CONTRIBUTORS.txt for the list of SwiftCertificates project authors -## -## SPDX-License-Identifier: Apache-2.0 -## -##===----------------------------------------------------------------------===## -##===----------------------------------------------------------------------===## -## -## This source file is part of the SwiftOpenAPIGenerator open source project -## -## Copyright (c) 2023 Apple Inc. and the SwiftOpenAPIGenerator project authors -## Licensed under Apache License v2.0 -## -## See LICENSE.txt for license information -## See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors -## -## SPDX-License-Identifier: Apache-2.0 -## -##===----------------------------------------------------------------------===## -set -euo pipefail - -function log() { printf -- "** %s\n" "$*" >&2; } -function error() { printf -- "** ERROR: %s\n" "$*" >&2; } -function fatal() { error "$*"; exit 1; } - -current_script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -repo_root="$(git -C "${current_script_dir}" rev-parse --show-toplevel)" - -swift format lint \ - --parallel --recursive --strict \ - "${repo_root}/Sources" "${repo_root}/Tests" \ - "${repo_root}/Benchmarks/Benchmarks" \ - && swift_format_rc=$? || swift_format_rc=$? - -if [[ "${swift_format_rc}" -ne 0 ]]; then - fatal "❌ Running swift-format produced errors. - - To fix, run the following command: - - % swift format format --parallel --recursive --in-place Sources Tests Benchmarks/Benchmarks - " - exit "${swift_format_rc}" -fi - -log "✅ Ran swift-format with no errors." diff --git a/scripts/soundness.sh b/scripts/soundness.sh deleted file mode 100755 index 45171f9..0000000 --- a/scripts/soundness.sh +++ /dev/null @@ -1,175 +0,0 @@ -#!/bin/bash -##===----------------------------------------------------------------------===## -## -## This source file is part of the swift-etcd-client-gsoc open source project -## -## Copyright (c) 2023 Apple Inc. and the swift-etcd-client-gsoc project authors -## Licensed under Apache License v2.0 -## -## See LICENSE.txt for license information -## See CONTRIBUTORS.txt for the list of swift-etcd-client-gsoc project authors -## -## SPDX-License-Identifier: Apache-2.0 -## -##===----------------------------------------------------------------------===## - -set -eu -here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -function replace_acceptable_years() { - # this needs to replace all acceptable forms with 'YEARS' - sed -e 's/20[12][78901234]-20[12][8901234]/YEARS/' -e 's/20[12][8901234]/YEARS/' -} - -printf "=> Checking for unacceptable language... " -# This greps for unacceptable terminology. The square bracket[s] are so that -# "git grep" doesn't find the lines that greps :). -unacceptable_terms=( - -e blacklis[t] - -e whitelis[t] - -e slav[e] - -e sanit[y] -) - -# We have to exclude the code of conduct because it gives examples of unacceptable language. -exclude_files=( - CODE_OF_CONDUCT.md -) -for word in "${exclude_files[@]}"; do - exclude_files+=(":(exclude)$word") -done -exclude_files_str=$(printf " %s" "${exclude_files[@]}") - -if git grep --color=never -i "${unacceptable_terms[@]}" -- . $exclude_files_str > /dev/null; then - printf "\033[0;31mUnacceptable language found.\033[0m\n" - git grep -i "${unacceptable_terms[@]}" -- . $exclude_files_str - exit 1 -fi -printf "\033[0;32mokay.\033[0m\n" - -printf "=> Checking format... " -# swift-format -swift_format_script="${here}/run-swift-format.sh" -if ! bash "${swift_format_script}"; then - exit 1 -fi - - -printf "=> Checking license headers... " -tmp=$(mktemp /tmp/.swift-etcd-client-gsoc-soundness_XXXXXX) - -for language in swift-or-c bash dtrace python; do - declare -a matching_files - declare -a exceptions - expections=( ) - matching_files=( -name '*' ) - case "$language" in - swift-or-c) - exceptions=( -name Package.swift ) - matching_files=( -name '*.swift' -o -name '*.c' -o -name '*.h' ) - cat > "$tmp" <<"EOF" -//===----------------------------------------------------------------------===// -// -// This source file is part of the swift-etcd-client-gsoc open source project -// -// Copyright (c) YEARS Apple Inc. and the swift-etcd-client-gsoc project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of swift-etcd-client-gsoc project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// -EOF - ;; - bash) - matching_files=( -name '*.sh' ) - cat > "$tmp" <<"EOF" -#!/bin/bash -##===----------------------------------------------------------------------===## -## -## This source file is part of the swift-etcd-client-gsoc open source project -## -## Copyright (c) YEARS Apple Inc. and the swift-etcd-client-gsoc project authors -## Licensed under Apache License v2.0 -## -## See LICENSE.txt for license information -## See CONTRIBUTORS.txt for the list of swift-etcd-client-gsoc project authors -## -## SPDX-License-Identifier: Apache-2.0 -## -##===----------------------------------------------------------------------===## -EOF - ;; - python) - matching_files=( -name '*.py' ) - cat > "$tmp" <<"EOF" -#!/usr/bin/env python3 -##===----------------------------------------------------------------------===## -## -## This source file is part of the swift-etcd-client-gsoc open source project -## -## Copyright (c) YEARS Apple Inc. and the swift-etcd-client-gsoc project authors -## Licensed under Apache License v2.0 -## -## See LICENSE.txt for license information -## See CONTRIBUTORS.txt for the list of swift-etcd-client-gsoc project authors -## -## SPDX-License-Identifier: Apache-2.0 -## -##===----------------------------------------------------------------------===## -EOF - ;; - dtrace) - matching_files=( -name '*.d' ) - cat > "$tmp" <<"EOF" -#!/usr/sbin/dtrace -q -s -/*===----------------------------------------------------------------------===* - * - * This source file is part of the swift-etcd-client-gsoc open source project - * - * Copyright (c) YEARS Apple Inc. and the swift-etcd-client-gsoc project authors - * Licensed under Apache License v2.0 - * - * See LICENSE.txt for license information - * See CONTRIBUTORS.txt for the list of swift-etcd-client-gsoc project authors - * - * SPDX-License-Identifier: Apache-2.0 - * - *===----------------------------------------------------------------------===*/ -EOF - ;; - *) - echo >&2 "ERROR: unknown language '$language'" - ;; - esac - - expected_lines=$(cat "$tmp" | wc -l) - expected_sha=$(cat "$tmp" | shasum) - - ( - cd "$here/.." - { - find . \ - \( \! -path '*/.build/*' -a \ - \( "${matching_files[@]}" \) -a \ - \( \! \( "${exceptions[@]}" \) \) \) - - if [[ "$language" = bash ]]; then - # add everything with a shell shebang too - git grep --full-name -l '#!/bin/bash' - git grep --full-name -l '#!/bin/sh' - fi - } | while read line; do - if [[ "$(cat "$line" | replace_acceptable_years | head -n $expected_lines | shasum)" != "$expected_sha" ]]; then - printf "\033[0;31mmissing headers in file '$line'!\033[0m\n" - diff -u <(cat "$line" | replace_acceptable_years | head -n $expected_lines) "$tmp" - exit 1 - fi - done - printf "\033[0;32mokay.\033[0m\n" - ) -done - -rm "$tmp" From 109ad02a30a31df4ba22b8af153d2616f788be4b Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 4 Dec 2024 10:19:04 +0000 Subject: [PATCH 08/13] package: Bump minimum Swift version to 5.9 --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 5656b6e..46986c0 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.7 +// swift-tools-version: 5.9 //===----------------------------------------------------------------------===// // // This source file is part of the swift-etcd-client-gsoc open source project From 116bbf94a70493805f156a1cf221a3855e99032c Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 4 Dec 2024 10:19:23 +0000 Subject: [PATCH 09/13] package: Enable StrictConcurrency=complete --- Package.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Package.swift b/Package.swift index 46986c0..86cd67c 100644 --- a/Package.swift +++ b/Package.swift @@ -59,3 +59,9 @@ let package = Package( ), ] ) + +for target in package.targets { + var settings = target.swiftSettings ?? [] + settings.append(.enableExperimentalFeature("StrictConcurrency=complete")) + target.swiftSettings = settings +} From 3e46c2d51e711e5a8a61313821ec2c6646ed2e1b Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 4 Dec 2024 12:55:01 +0000 Subject: [PATCH 10/13] strict-concurrency: Remove sendability issues in tests --- Tests/ETCDTests/ETCDTests.swift | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/Tests/ETCDTests/ETCDTests.swift b/Tests/ETCDTests/ETCDTests.swift index a34009c..3765ffd 100644 --- a/Tests/ETCDTests/ETCDTests.swift +++ b/Tests/ETCDTests/ETCDTests.swift @@ -17,15 +17,9 @@ import NIO import XCTest final class EtcdClientTests: XCTestCase { - var eventLoopGroup: EventLoopGroup! - var etcdClient: EtcdClient! - - override func setUp() async throws { - eventLoopGroup = MultiThreadedEventLoopGroup.singleton - etcdClient = EtcdClient(host: "localhost", port: 2379, eventLoopGroup: eventLoopGroup) - } - func testSetAndGetStringValue() async throws { + let etcdClient = EtcdClient.testClient + try await etcdClient.set("testKey", value: "testValue") let key = "testKey".data(using: .utf8)! let rangeRequest = RangeRequest(key: key) @@ -36,6 +30,8 @@ final class EtcdClientTests: XCTestCase { } func testGetNonExistentKey() async throws { + let etcdClient = EtcdClient.testClient + let key = "nonExistentKey".data(using: .utf8)! let rangeRequest = RangeRequest(key: key) let result = try await etcdClient.getRange(rangeRequest) @@ -43,6 +39,8 @@ final class EtcdClientTests: XCTestCase { } func testDeleteKeyExists() async throws { + let etcdClient = EtcdClient.testClient + let key = "testKey" let value = "testValue" try await etcdClient.set(key, value: value) @@ -60,6 +58,8 @@ final class EtcdClientTests: XCTestCase { } func testDeleteNonExistentKey() async throws { + let etcdClient = EtcdClient.testClient + let key = "testKey".data(using: .utf8)! let rangeRequest = RangeRequest(key: key) @@ -74,6 +74,8 @@ final class EtcdClientTests: XCTestCase { } func testUpdateExistingKey() async throws { + let etcdClient = EtcdClient.testClient + let key = "testKey" let value = "testValue" try await etcdClient.set(key, value: value) @@ -95,6 +97,8 @@ final class EtcdClientTests: XCTestCase { } func testWatch() async throws { + let etcdClient = EtcdClient.testClient + let key = "testKey" let value = "testValue".data(using: .utf8)! @@ -102,7 +106,7 @@ final class EtcdClientTests: XCTestCase { try await withThrowingTaskGroup(of: Void.self) { group in group.addTask { - try await self.etcdClient.watch(key) { watchAsyncSequence in + try await etcdClient.watch(key) { watchAsyncSequence in var iterator = watchAsyncSequence.makeAsyncIterator() let events = try await iterator.next() guard let events = events else { @@ -122,8 +126,16 @@ final class EtcdClientTests: XCTestCase { } try await Task.sleep(nanoseconds: 1_000_000_000) - try await self.etcdClient.put(key, value: String(data: value, encoding: .utf8)!) + try await etcdClient.put(key, value: String(data: value, encoding: .utf8)!) group.cancelAll() } } } + +extension EtcdClient { + fileprivate static let testClient = EtcdClient( + host: "localhost", + port: 2379, + eventLoopGroup: .singletonMultiThreadedEventLoopGroup + ) +} From e7b4486359f24d238392c206b00d27bb26d1e0f1 Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Thu, 5 Dec 2024 10:17:15 +0000 Subject: [PATCH 11/13] tests: Rename tests IntegrationTests only run if enabled --- .../IntegrationTests.swift} | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) rename Tests/{ETCDTests/ETCDTests.swift => IntegrationTests/IntegrationTests.swift} (86%) diff --git a/Tests/ETCDTests/ETCDTests.swift b/Tests/IntegrationTests/IntegrationTests.swift similarity index 86% rename from Tests/ETCDTests/ETCDTests.swift rename to Tests/IntegrationTests/IntegrationTests.swift index 3765ffd..16918f3 100644 --- a/Tests/ETCDTests/ETCDTests.swift +++ b/Tests/IntegrationTests/IntegrationTests.swift @@ -16,7 +16,14 @@ import ETCD import NIO import XCTest -final class EtcdClientTests: XCTestCase { +final class IntegrationTests: XCTestCase { + + private static let integrationTestEnabled = getBoolEnv("SWIFT_ETCD_CLIENT_INTEGRATION_TEST_ENABLED") ?? false + + override func setUp() async throws { + try XCTSkipUnless(Self.integrationTestEnabled) + } + func testSetAndGetStringValue() async throws { let etcdClient = EtcdClient.testClient @@ -134,8 +141,19 @@ final class EtcdClientTests: XCTestCase { extension EtcdClient { fileprivate static let testClient = EtcdClient( - host: "localhost", - port: 2379, + host: ProcessInfo.processInfo.environment["ETCD_HOST"] ?? "localhost", + port: getIntEnv("ETCD_PORT") ?? 2379, eventLoopGroup: .singletonMultiThreadedEventLoopGroup ) } + +/// Returns true if `key` is a truthy string, otherwise returns false. +private func getBoolEnv(_ key: String) -> Bool? { + switch ProcessInfo.processInfo.environment[key]?.lowercased() { + case .none: return nil + case "true", "y", "yes", "on", "1": return true + default: return false + } +} + +private func getIntEnv(_ key: String) -> Int? { ProcessInfo.processInfo.environment[key].flatMap(Int.init(_:)) } From 691b39a504b4efa35371e792ed457cc84d3a0d16 Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Thu, 5 Dec 2024 10:19:47 +0000 Subject: [PATCH 12/13] github: Add integration test job that runs with etcd service container --- .github/workflows/pull_request.yml | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d688072..fecb1fa 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -21,6 +21,38 @@ jobs: linux_nightly_6_0_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" + # Integration tests use a running etcd so this job uses a service container. + integration-tests: + name: Integration tests + runs-on: ubuntu-latest + services: + etcd: + image: quay.io/coreos/etcd:v3.5.6 + env: + ETCD_ADVERTISE_CLIENT_URLS: http://0.0.0.0:2379 + ETCD_LISTEN_CLIENT_URLS: http://0.0.0.0:2379 + ETCD_INITIAL_CLUSTER_STATE: new + ports: + - 2379:2379 + container: + image: swift:6.0-noble + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Build package + run: swift build --build-tests + - name: Run integration tests + shell: bash # explicitly choose bash, which ensures -o pipefail + run: swift test --filter "IntegrationTests" | tee test.out + env: + SWIFT_ETCD_CLIENT_INTEGRATION_TEST_ENABLED: true + ETCD_HOST: etcd + ETCD_PORT: 2379 + - name: Check integration tests actually did run + run: test -r test.out && ! grep -i -e "executed 0 tests" -e "skipped" test.out + cxx-interop: name: Cxx interop uses: apple/swift-nio/.github/workflows/cxx_interop.yml@main From 017710ef7e8520b36e67b579d0ae4b6a82c4ef32 Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Thu, 5 Dec 2024 10:28:06 +0000 Subject: [PATCH 13/13] github: Disable warnings-as-errors on 5.9 and 5.10 (keep on 6.0+) --- .github/workflows/main.yml | 4 ++-- .github/workflows/pull_request.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 400a1b9..fa1d4b0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,8 +11,8 @@ jobs: name: Unit tests uses: apple/swift-nio/.github/workflows/unit_tests.yml@main with: - linux_5_9_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" - linux_5_10_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" + linux_5_9_arguments_override: "--explicit-target-dependency-import-check error" + linux_5_10_arguments_override: --explicit-target-dependency-import-check error" linux_6_0_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" linux_nightly_6_0_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index fecb1fa..6215da3 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -15,8 +15,8 @@ jobs: name: Unit tests uses: apple/swift-nio/.github/workflows/unit_tests.yml@main with: - linux_5_9_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" - linux_5_10_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" + linux_5_9_arguments_override: "--explicit-target-dependency-import-check error" + linux_5_10_arguments_override: "--explicit-target-dependency-import-check error" linux_6_0_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" linux_nightly_6_0_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"