Просмотр исходного кода

Migrate CI to use swiftlang / SwiftNIO common GitHub Actions. (#2105)

### Motivation:

* Reduce duplication
* Centralise boilerplate changes when new Swift versions are picked up.
* Benefit from centralised work to add new linting / test
infrastructure.

### Modifications:

Changes of note:
* Use soundness checks from swiftlang/github-workflows.
* Define a gRPC-specific soundness check which retains bespoke
license-checking code for .swift files as the gRPC header style is very
different to most templates and checks that generated code is
up-to-date.

### Result:

More test, linting, formatting coverage. More common CI with other Swift
on Server projects.
Rick Newton-Rogers 1 год назад
Родитель
Сommit
07e38e9756
47 измененных файлов с 404 добавлено и 283 удалено
  1. 14 0
      .github/release.yml
  2. 0 82
      .github/workflows/ci.yaml
  3. 26 0
      .github/workflows/main.yml
  4. 51 0
      .github/workflows/pull_request.yml
  5. 18 0
      .github/workflows/pull_request_label.yml
  6. 37 0
      .github/workflows/soundness.yml
  7. 13 0
      .license_header_template
  8. 42 0
      .licenseignore
  9. 2 0
      .swiftformatignore
  10. 3 0
      .unacceptablelanguageignore
  11. 4 0
      CONTRIBUTING.md
  12. 0 37
      Examples/hello-world/Protos
  13. 1 0
      Examples/hello-world/Protos/HelloWorld.proto
  14. 21 21
      IntegrationTests/Benchmarks/Package.swift
  15. 0 0
      IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Add_binary.p90.json
  16. 0 0
      IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Add_string.p90.json
  17. 0 0
      IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Iterate_all_values.p90.json
  18. 0 0
      IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_binary_values_stored.p90.json
  19. 0 0
      IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_strings_stored.p90.json
  20. 0 0
      IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Iterate_string_values.p90.json
  21. 0 0
      IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Remove_values_for_key.p90.json
  22. 7 0
      IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Add_binary.p90.json
  23. 7 0
      IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Add_string.p90.json
  24. 7 0
      IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Iterate_all_values.p90.json
  25. 7 0
      IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_binary_values_stored.p90.json
  26. 7 0
      IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_strings_stored.p90.json
  27. 7 0
      IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Iterate_string_values.p90.json
  28. 7 0
      IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Remove_values_for_key.p90.json
  29. 5 7
      Package.swift
  30. 3 3
      Sources/GRPCCore/Configuration/MethodConfig.swift
  31. 1 1
      Sources/GRPCCore/Configuration/ServiceConfig.swift
  32. 1 1
      Sources/GRPCCore/Documentation.docc/Development/Design.md
  33. 2 2
      Sources/GRPCCore/Internal/Base64.swift
  34. 1 1
      Sources/GRPCCore/Internal/Metadata+GRPC.swift
  35. 1 1
      Sources/GRPCCore/Status.swift
  36. 1 1
      Sources/GRPCCore/Timeout.swift
  37. 1 1
      Sources/GRPCCore/Transport/RetryThrottle.swift
  38. 2 2
      Sources/GRPCInProcessTransport/Documentation.docc/Documentation.md
  39. 6 6
      Sources/GRPCInProcessTransport/InProcessTransport+Client.swift
  40. 5 5
      Sources/GRPCInProcessTransport/InProcessTransport+Server.swift
  41. 13 14
      dev/build-examples.sh
  42. 13 14
      dev/check-generated-code.sh
  43. 14 16
      dev/format.sh
  44. 15 20
      dev/license-check.sh
  45. 13 15
      dev/protos/fetch.sh
  46. 13 14
      dev/protos/generate.sh
  47. 13 19
      dev/soundness.sh

+ 14 - 0
.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

+ 0 - 82
.github/workflows/ci.yaml

@@ -1,82 +0,0 @@
-name: CI
-on:
-  push:
-    branches: [main]
-  pull_request:
-    branches: [main]
-jobs:
-  preflight:
-    name: License Header and Formatting Checks
-    runs-on: ubuntu-latest
-    container:
-      image: swift:6.0-jammy
-    steps:
-    - name: "Checkout repository"
-      uses: actions/checkout@v4
-    - name: Mark the workspace as safe
-      run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
-    - name: "Install protoc"
-      run: apt update && apt install -y protobuf-compiler
-    - name: "Formatting, License Headers, and Generated Code check"
-      run: |
-        ./dev/sanity.sh
-  unit-tests:
-    strategy:
-      fail-fast: false
-      matrix:
-        include:
-          - image: swiftlang/swift:nightly-jammy
-            # No TSAN because of: https://github.com/apple/swift/issues/59068
-            # swift-test-flags: "--sanitize=thread"
-          - image: swift:6.0-jammy
-            # No TSAN because of: https://github.com/apple/swift/issues/59068
-            # swift-test-flags: "--sanitize=thread"
-    name: Build and Test on ${{ matrix.image }}
-    runs-on: ubuntu-latest
-    container:
-      image: ${{ matrix.image }}
-    steps:
-    - uses: actions/checkout@v4
-    - name: 🔧 Build
-      run: swift build ${{ matrix.swift-build-flags }}
-      timeout-minutes: 20
-    - name: 🧪 Test
-      run: swift test ${{ matrix.swift-test-flags }}
-      timeout-minutes: 20
-  performance-tests:
-    strategy:
-      fail-fast: false
-      matrix:
-        include:
-          - image: swiftlang/swift:nightly-jammy
-            swift-version: 'main'
-          - image: swift:6.0-jammy
-            swift-version: '6.0'
-    name: Performance Tests on ${{ matrix.image }}
-    runs-on: ubuntu-latest
-    container:
-      image: ${{ matrix.image }}
-    steps:
-    - uses: actions/checkout@v4
-    - name: Install jemalloc for benchmarking
-      run: apt update && apt-get install -y libjemalloc-dev
-      timeout-minutes: 20
-    - name: Run Benchmarks
-      working-directory: "./IntegrationTests/Benchmarks"
-      run: swift package benchmark baseline check --no-progress --check-absolute-path Thresholds/${{ matrix.swift-version }}/
-      timeout-minutes: 20
-  examples:
-    strategy:
-      fail-fast: false
-      matrix:
-        include:
-          - image: swiftlang/swift:nightly-jammy
-          - image: swift:6.0-jammy
-    name: Build examples using ${{ matrix.image }}
-    runs-on: ubuntu-latest
-    container:
-      image: ${{ matrix.image }}
-    steps:
-    - uses: actions/checkout@v4
-    - name: Build examples
-      run: ./dev/build-examples.sh

+ 26 - 0
.github/workflows/main.yml

@@ -0,0 +1,26 @@
+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_enabled: false
+      linux_5_10_enabled: false
+      linux_6_0_arguments_override: "--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"
+
+  benchmarks:
+    name: Benchmarks
+    uses: apple/swift-nio/.github/workflows/benchmarks.yml@main
+    with:
+      benchmark_package_path: "IntegrationTests/Benchmarks"
+      linux_5_9_enabled: false
+      linux_5_10_enabled: false

+ 51 - 0
.github/workflows/pull_request.yml

@@ -0,0 +1,51 @@
+name: PR
+
+on:
+  pull_request:
+    branches: [main]
+    types: [opened, reopened, synchronize]
+
+jobs:
+  soundness:
+    name: Soundness
+    uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
+    with:
+      license_header_check_project_name: "gRPC"
+
+  grpc-soundness:
+    name: Soundness
+    uses: ./.github/workflows/soundness.yml
+
+  unit-tests:
+    name: Unit tests
+    uses: apple/swift-nio/.github/workflows/unit_tests.yml@main
+    with:
+      linux_5_9_enabled: false
+      linux_5_10_enabled: false
+      linux_6_0_arguments_override: "--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"
+
+  examples:
+    name: Examples
+    uses: apple/swift-nio/.github/workflows/swift_matrix.yml@main
+    with:
+      name: "Examples"
+      matrix_linux_5_9_enabled: false
+      matrix_linux_5_10_enabled: false
+      matrix_linux_command: "./dev/build-examples.sh"
+
+  benchmarks:
+    name: Benchmarks
+    uses: apple/swift-nio/.github/workflows/benchmarks.yml@main
+    with:
+      benchmark_package_path: "IntegrationTests/Benchmarks"
+      linux_5_9_enabled: false
+      linux_5_10_enabled: false
+
+  cxx-interop:
+    name: Cxx interop
+    uses: apple/swift-nio/.github/workflows/cxx_interop.yml@main
+    with:
+      linux_5_9_enabled: false
+      linux_5_10_enabled: false

+ 18 - 0
.github/workflows/pull_request_label.yml

@@ -0,0 +1,18 @@
+name: PR
+
+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

+ 37 - 0
.github/workflows/soundness.yml

@@ -0,0 +1,37 @@
+name: Soundness
+
+on:
+  workflow_call:
+
+jobs:
+  swift-license-check:
+    name: Swift license headers check
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+        with:
+          persist-credentials: false
+      - name: Mark the workspace as safe
+        run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
+      - name: Run license check
+        run: |
+          ./dev/license-check.sh
+
+  check-generated-code:
+    name: Check generated code
+    runs-on: ubuntu-latest
+    container:
+      image: swift:latest
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+        with:
+          persist-credentials: false
+      - name: Mark the workspace as safe
+        run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
+      - name: Install protoc
+        run: apt update && apt install -y protobuf-compiler
+      - name: Run soundness checks
+        run: |
+          ./dev/check-generated-code.sh

+ 13 - 0
.license_header_template

@@ -0,0 +1,13 @@
+@@ Copyright YEARS, gRPC Authors All rights reserved.
+@@
+@@ Licensed under the Apache License, Version 2.0 (the "License");
+@@ you may not use this file except in compliance with the License.
+@@ You may obtain a copy of the License at
+@@
+@@     http://www.apache.org/licenses/LICENSE-2.0
+@@
+@@ Unless required by applicable law or agreed to in writing, software
+@@ distributed under the License is distributed on an "AS IS" BASIS,
+@@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@@ See the License for the specific language governing permissions and
+@@ limitations under the License.

+ 42 - 0
.licenseignore

@@ -0,0 +1,42 @@
+.gitignore
+**/.gitignore
+.licenseignore
+.gitattributes
+.git-blame-ignore-revs
+.gitmodules
+.mailfilter
+.mailmap
+.spi.yml
+.swift-format
+.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
+dev/version-bump.commit.template
+.unacceptablelanguageignore
+.swiftformatignore
+LICENSE
+**/*.swift
+dev/protos/**/*.proto
+Examples/hello-world/Protos/HelloWorld.proto

+ 2 - 0
.swiftformatignore

@@ -0,0 +1,2 @@
+*.grpc.swift
+*.pb.swift

+ 3 - 0
.unacceptablelanguageignore

@@ -0,0 +1,3 @@
+**/*.pb.swift
+**/*.grpc.swift
+dev/protos/upstream/**/*.proto

+ 4 - 0
CONTRIBUTING.md

@@ -17,3 +17,7 @@ In order to protect both you and ourselves, you will need to sign the
 
 Please see the [main gRPC repository](https://github.com/grpc/grpc) for
 more information about gRPC.
+
+### Run CI checks locally
+
+You can run the GitHub Actions workflows locally using [act](https://github.com/nektos/act) or in some cases calling scripts directly. For detailed steps on how to do this please see [https://github.com/swiftlang/github-workflows?tab=readme-ov-file#running-workflows-locally](https://github.com/swiftlang/github-workflows?tab=readme-ov-file#running-workflows-locally).

+ 0 - 37
Examples/hello-world/Protos

@@ -1,37 +0,0 @@
-// Copyright 2015 gRPC authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-syntax = "proto3";
-
-option java_multiple_files = true;
-option java_package = "io.grpc.examples.helloworld";
-option java_outer_classname = "HelloWorldProto";
-option objc_class_prefix = "HLW";
-
-package helloworld;
-
-// The greeting service definition.
-service Greeter {
-  // Sends a greeting
-  rpc SayHello (HelloRequest) returns (HelloReply) {}
-}
-
-// The request message containing the user's name.
-message HelloRequest {
-  string name = 1;
-}
-
-// The response message containing the greetings
-message HelloReply {
-  string message = 1;
-}

+ 1 - 0
Examples/hello-world/Protos/HelloWorld.proto

@@ -0,0 +1 @@
+../../..//dev/protos/upstream/grpc/examples/helloworld.proto

+ 21 - 21
IntegrationTests/Benchmarks/Package.swift

@@ -17,25 +17,25 @@
 import PackageDescription
 
 let package = Package(
-    name: "benchmarks",
-    platforms: [
-        .macOS(.v13),
-    ],
-    dependencies: [
-        .package(path: "../../"),
-        .package(url: "https://github.com/ordo-one/package-benchmark", from: "1.11.2")
-    ],
-    targets: [
-        .executableTarget(
-            name: "GRPCSwiftBenchmark",
-            dependencies: [
-                .product(name: "Benchmark", package: "package-benchmark"),
-                .product(name: "GRPCCore", package: "grpc-swift")
-            ],
-            path: "Benchmarks/GRPCSwiftBenchmark",
-            plugins: [
-                .plugin(name: "BenchmarkPlugin", package: "package-benchmark")
-            ]
-        ),
-    ]
+  name: "benchmarks",
+  platforms: [
+    .macOS(.v13)
+  ],
+  dependencies: [
+    .package(path: "../../"),
+    .package(url: "https://github.com/ordo-one/package-benchmark", from: "1.11.2"),
+  ],
+  targets: [
+    .executableTarget(
+      name: "GRPCSwiftBenchmark",
+      dependencies: [
+        .product(name: "Benchmark", package: "package-benchmark"),
+        .product(name: "GRPCCore", package: "grpc-swift"),
+      ],
+      path: "Benchmarks/GRPCSwiftBenchmark",
+      plugins: [
+        .plugin(name: "BenchmarkPlugin", package: "package-benchmark")
+      ]
+    )
+  ]
 )

+ 0 - 0
IntegrationTests/Benchmarks/Thresholds/main/GRPCSwiftBenchmark.Metadata_Add_binary.p90.json → IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Add_binary.p90.json


+ 0 - 0
IntegrationTests/Benchmarks/Thresholds/main/GRPCSwiftBenchmark.Metadata_Add_string.p90.json → IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Add_string.p90.json


+ 0 - 0
IntegrationTests/Benchmarks/Thresholds/main/GRPCSwiftBenchmark.Metadata_Iterate_all_values.p90.json → IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Iterate_all_values.p90.json


+ 0 - 0
IntegrationTests/Benchmarks/Thresholds/main/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_binary_values_stored.p90.json → IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_binary_values_stored.p90.json


+ 0 - 0
IntegrationTests/Benchmarks/Thresholds/main/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_strings_stored.p90.json → IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_strings_stored.p90.json


+ 0 - 0
IntegrationTests/Benchmarks/Thresholds/main/GRPCSwiftBenchmark.Metadata_Iterate_string_values.p90.json → IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Iterate_string_values.p90.json


+ 0 - 0
IntegrationTests/Benchmarks/Thresholds/main/GRPCSwiftBenchmark.Metadata_Remove_values_for_key.p90.json → IntegrationTests/Benchmarks/Thresholds/nightly-6.0/GRPCSwiftBenchmark.Metadata_Remove_values_for_key.p90.json


+ 7 - 0
IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Add_binary.p90.json

@@ -0,0 +1,7 @@
+{
+  "mallocCountTotal" : 11,
+  "memoryLeaked" : 0,
+  "releaseCount" : 3012,
+  "retainCount" : 2000,
+  "syscalls" : 0
+}

+ 7 - 0
IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Add_string.p90.json

@@ -0,0 +1,7 @@
+{
+  "mallocCountTotal" : 11,
+  "memoryLeaked" : 0,
+  "releaseCount" : 4012,
+  "retainCount" : 2000,
+  "syscalls" : 0
+}

+ 7 - 0
IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Iterate_all_values.p90.json

@@ -0,0 +1,7 @@
+{
+  "mallocCountTotal" : 0,
+  "memoryLeaked" : 0,
+  "releaseCount" : 3001,
+  "retainCount" : 1000,
+  "syscalls" : 0
+}

+ 7 - 0
IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_binary_values_stored.p90.json

@@ -0,0 +1,7 @@
+{
+  "mallocCountTotal" : 0,
+  "memoryLeaked" : 0,
+  "releaseCount" : 3001,
+  "retainCount" : 1000,
+  "syscalls" : 0
+}

+ 7 - 0
IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_strings_stored.p90.json

@@ -0,0 +1,7 @@
+{
+  "mallocCountTotal" : 2000,
+  "memoryLeaked" : 0,
+  "releaseCount" : 7001,
+  "retainCount" : 3000,
+  "syscalls" : 0
+}

+ 7 - 0
IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Iterate_string_values.p90.json

@@ -0,0 +1,7 @@
+{
+  "mallocCountTotal" : 0,
+  "memoryLeaked" : 0,
+  "releaseCount" : 3001,
+  "retainCount" : 1000,
+  "syscalls" : 0
+}

+ 7 - 0
IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Remove_values_for_key.p90.json

@@ -0,0 +1,7 @@
+{
+  "mallocCountTotal" : 0,
+  "memoryLeaked" : 0,
+  "releaseCount" : 2002001,
+  "retainCount" : 1999000,
+  "syscalls" : 0
+}

+ 5 - 7
Package.swift

@@ -15,7 +15,6 @@
  * limitations under the License.
  */
 
-
 import PackageDescription
 
 let products: [Product] = [
@@ -49,7 +48,7 @@ let dependencies: [Package.Dependency] = [
 let defaultSwiftSettings: [SwiftSetting] = [
   .swiftLanguageMode(.v6),
   .enableUpcomingFeature("ExistentialAny"),
-  .enableUpcomingFeature("InternalImportsByDefault")
+  .enableUpcomingFeature("InternalImportsByDefault"),
 ]
 
 let targets: [Target] = [
@@ -57,7 +56,7 @@ let targets: [Target] = [
   .target(
     name: "GRPCCore",
     dependencies: [
-      .product(name: "DequeModule", package: "swift-collections"),
+      .product(name: "DequeModule", package: "swift-collections")
     ],
     swiftSettings: defaultSwiftSettings
   ),
@@ -66,7 +65,7 @@ let targets: [Target] = [
     dependencies: [
       .target(name: "GRPCCore"),
       .target(name: "GRPCInProcessTransport"),
-      .product(name: "SwiftProtobuf", package: "swift-protobuf")
+      .product(name: "SwiftProtobuf", package: "swift-protobuf"),
     ],
     resources: [
       .copy("Configuration/Inputs")
@@ -91,8 +90,7 @@ let targets: [Target] = [
   // Code generator library for protoc-gen-grpc-swift
   .target(
     name: "GRPCCodeGen",
-    dependencies: [
-    ],
+    dependencies: [],
     swiftSettings: defaultSwiftSettings
   ),
   .testTarget(
@@ -100,7 +98,7 @@ let targets: [Target] = [
     dependencies: [
       .target(name: "GRPCCodeGen")
     ]
-  )
+  ),
 ]
 
 let package = Package(

+ 3 - 3
Sources/GRPCCore/Configuration/MethodConfig.swift

@@ -16,7 +16,7 @@
 
 /// Configuration values for executing an RPC.
 ///
-/// See also: https://github.com/grpc/grpc-proto/blob/master/grpc/service_config/service_config.proto
+/// See also: https://github.com/grpc/grpc-proto/blob/0b30c8c05277ab78ec72e77c9cbf66a26684673d/grpc/service_config/service_config.proto
 public struct MethodConfig: Hashable, Sendable {
   public struct Name: Sendable, Hashable {
     /// The name of the service, including the namespace.
@@ -211,7 +211,7 @@ public struct RPCExecutionPolicy: Hashable, Sendable {
 /// and `min(initialBackoff * backoffMultiplier^(n-1), maxBackoff)`.
 ///
 /// For more information see [gRFC A6 Client
-/// Retries](https://github.com/grpc/proposal/blob/master/A6-client-retries.md).
+/// Retries](https://github.com/grpc/proposal/blob/0e1807a6e30a1a915c0dcadc873bca92b9fa9720/A6-client-retries.md).
 public struct RetryPolicy: Hashable, Sendable {
   /// The maximum number of RPC attempts, including the original attempt.
   ///
@@ -328,7 +328,7 @@ public struct RetryPolicy: Hashable, Sendable {
 /// by ``hedgingDelay``.
 ///
 /// For more information see [gRFC A6 Client
-/// Retries](https://github.com/grpc/proposal/blob/master/A6-client-retries.md).
+/// Retries](https://github.com/grpc/proposal/blob/0e1807a6e30a1a915c0dcadc873bca92b9fa9720/A6-client-retries.md).
 public struct HedgingPolicy: Hashable, Sendable {
   /// The maximum number of RPC attempts, including the original attempt.
   ///

+ 1 - 1
Sources/GRPCCore/Configuration/ServiceConfig.swift

@@ -16,7 +16,7 @@
 
 /// Service configuration values.
 ///
-/// See also: https://github.com/grpc/grpc-proto/blob/master/grpc/service_config/service_config.proto
+/// See also: https://github.com/grpc/grpc-proto/blob/0b30c8c05277ab78ec72e77c9cbf66a26684673d/grpc/service_config/service_config.proto
 public struct ServiceConfig: Hashable, Sendable {
   /// Per-method configuration.
   public var methodConfig: [MethodConfig]

+ 1 - 1
Sources/GRPCCore/Documentation.docc/Development/Design.md

@@ -76,7 +76,7 @@ doing this doesn't leave the other side waiting indefinitely.
 
 gRPC has mechanisms to deliver method-specific configuration at the transport
 layer which can also change dynamically (see [gRFC A2: ServiceConfig in
-DNS](https://github.com/grpc/proposal/blob/master/A2-service-configs-in-dns.md).)
+DNS](https://github.com/grpc/proposal/blob/0e1807a6e30a1a915c0dcadc873bca92b9fa9720/A2-service-configs-in-dns.md).)
 This configuration is used to determine how clients should interact with servers
 and how methods should be executed, such as the conditions under which they
 may be retried. Some of this is exposed via the ``ClientTransport`` as

+ 2 - 2
Sources/GRPCCore/Internal/Base64.swift

@@ -15,7 +15,7 @@
  */
 // This base64 implementation is heavily inspired by:
 
-// https://github.com/lemire/fastbase64/blob/master/src/chromiumbase64.c
+// https://github.com/lemire/fastbase64/blob/a2e0967dfcb8f0129ea45b9b24cc410e4cac117f/src/chromiumbase64.c
 /*
  Copyright (c) 2015-2016, Wojciech Muła, Alfred Klomp,  Daniel Lemire
  (Unless otherwise stated in the source code)
@@ -45,7 +45,7 @@
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// https://github.com/client9/stringencoders/blob/master/src/modp_b64.c
+// https://github.com/client9/stringencoders/blob/e1448a9415f4ebf6f559c86718193ba067cbb99d/src/modp_b64.c
 /*
  The MIT License (MIT)
 

+ 1 - 1
Sources/GRPCCore/Internal/Metadata+GRPC.swift

@@ -91,7 +91,7 @@ extension Metadata {
         self = .retryAfter(Duration(secondsComponent: seconds, attosecondsComponent: attoseconds))
       } else {
         // Negative or not parseable means stop trying.
-        // Source: https://github.com/grpc/proposal/blob/master/A6-client-retries.md
+        // Source: https://github.com/grpc/proposal/blob/0e1807a6e30a1a915c0dcadc873bca92b9fa9720/A6-client-retries.md
         self = .stopRetrying
       }
     }

+ 1 - 1
Sources/GRPCCore/Status.swift

@@ -111,7 +111,7 @@ extension Status {
   ///
   /// The outcome of every RPC is indicated by a status code.
   public struct Code: Hashable, CustomStringConvertible, Sendable {
-    // Source: https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
+    // Source: https://github.com/grpc/grpc/blob/6c0578099835c854b0ff36a4b8db98ed49278ed5/doc/statuscodes.md
     enum Wrapped: UInt8, Hashable, Sendable {
       case ok = 0
       case cancelled = 1

+ 1 - 1
Sources/GRPCCore/Timeout.swift

@@ -46,7 +46,7 @@ struct Timeout: CustomStringConvertible, Hashable, Sendable {
   }
 
   /// The wire encoding of this timeout as described in the gRPC protocol.
-  /// See "Timeout" in https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests
+  /// See "Timeout" in https://github.com/grpc/grpc/blob/6c0578099835c854b0ff36a4b8db98ed49278ed5/doc/PROTOCOL-HTTP2.md#requests
   var wireEncoding: String {
     "\(amount)\(unit.rawValue)"
   }

+ 1 - 1
Sources/GRPCCore/Transport/RetryThrottle.swift

@@ -29,7 +29,7 @@ private import Synchronization
 /// ``HedgingPolicy/nonFatalStatusCodes``) or when the client receives a pushback response from
 /// the server.
 ///
-/// See also [gRFC A6: client retries](https://github.com/grpc/proposal/blob/master/A6-client-retries.md).
+/// See also [gRFC A6: client retries](https://github.com/grpc/proposal/blob/0e1807a6e30a1a915c0dcadc873bca92b9fa9720/A6-client-retries.md).
 public final class RetryThrottle: Sendable {
   // Note: only three figures after the decimal point from the original token ratio are used so
   //   all computation is done a scaled number of tokens (tokens * 1000). This allows us to do all

+ 2 - 2
Sources/GRPCInProcessTransport/Documentation.docc/Documentation.md

@@ -13,5 +13,5 @@ use cases.
 ### Transports
 
 - ``InProcessTransport``
-- ``InProcessClientTransport``
-- ``InProcessServerTransport``
+- ``InProcessTransport/Client``
+- ``InProcessTransport/Server``

+ 6 - 6
Sources/GRPCInProcessTransport/InProcessTransport+Client.swift

@@ -18,13 +18,13 @@ public import GRPCCore
 private import Synchronization
 
 extension InProcessTransport {
-  /// An in-process implementation of a ``ClientTransport``.
+  /// An in-process implementation of a `ClientTransport`.
   ///
   /// This is useful when you're interested in testing your application without any actual networking layers
   /// involved, as the client and server will communicate directly with each other via in-process streams.
   ///
-  /// To use this client, you'll have to provide a ``ServerTransport`` upon creation, as well
-  /// as a ``ServiceConfig``.
+  /// To use this client, you'll have to provide a `ServerTransport` upon creation, as well
+  /// as a `ServiceConfig`.
   ///
   /// Once you have a client, you must keep a long-running task executing ``connect()``, which
   /// will return only once all streams have been finished and ``beginGracefulShutdown()`` has been called on this client; or
@@ -34,7 +34,7 @@ extension InProcessTransport {
   /// called before ``connect()`` is called, then any streams will remain pending and the call will
   /// block until ``connect()`` is called or the task is cancelled.
   ///
-  /// - SeeAlso: ``ClientTransport``
+  /// - SeeAlso: `ClientTransport`
   public final class Client: ClientTransport {
     private enum State: Sendable {
       struct UnconnectedState {
@@ -187,7 +187,7 @@ extension InProcessTransport {
     /// Signal to the transport that no new streams may be created.
     ///
     /// Existing streams may run to completion naturally but calling ``withStream(descriptor:options:_:)``
-    /// will result in an ``RPCError`` with code ``RPCError/Code/failedPrecondition`` being thrown.
+    /// will result in an `RPCError` with code `RPCError/Code/failedPrecondition` being thrown.
     ///
     /// If you want to forcefully cancel all active streams then cancel the task running ``connect()``.
     public func beginGracefulShutdown() {
@@ -215,7 +215,7 @@ extension InProcessTransport {
     ///
     /// - Important: The opened stream is closed after the closure is finished.
     ///
-    /// This transport implementation throws ``RPCError/Code/failedPrecondition`` if the transport
+    /// This transport implementation throws `RPCError/Code/failedPrecondition` if the transport
     /// is closing or has been closed.
     ///
     ///   This implementation will queue any streams (and thus block this call) if this function is called before

+ 5 - 5
Sources/GRPCInProcessTransport/InProcessTransport+Server.swift

@@ -18,16 +18,16 @@ public import GRPCCore
 private import Synchronization
 
 extension InProcessTransport {
-  /// An in-process implementation of a ``ServerTransport``.
+  /// An in-process implementation of a `ServerTransport`.
   ///
   /// This is useful when you're interested in testing your application without any actual networking layers
   /// involved, as the client and server will communicate directly with each other via in-process streams.
   ///
   /// To use this server, you call ``listen(streamHandler:)`` and iterate over the returned `AsyncSequence` to get all
-  /// RPC requests made from clients (as ``RPCStream``s).
+  /// RPC requests made from clients (as `RPCStream`s).
   /// To stop listening to new requests, call ``beginGracefulShutdown()``.
   ///
-  /// - SeeAlso: ``ClientTransport``
+  /// - SeeAlso: `ClientTransport`
   public final class Server: ServerTransport, Sendable {
     public typealias Inbound = RPCAsyncSequence<RPCRequestPart, any Error>
     public typealias Outbound = RPCWriter<RPCResponsePart>.Closable
@@ -123,9 +123,9 @@ extension InProcessTransport {
       }
     }
 
-    /// Stop listening to any new ``RPCStream`` publications.
+    /// Stop listening to any new `RPCStream` publications.
     ///
-    /// - SeeAlso: ``ServerTransport``
+    /// - SeeAlso: `ServerTransport`
     public func beginGracefulShutdown() {
       self.newStreamsContinuation.finish()
       for handle in self.handles.withLock({ $0.beginShutdown() }) {

+ 13 - 14
dev/build-examples.sh

@@ -1,18 +1,17 @@
 #!/bin/bash
-
-# Copyright 2024, gRPC Authors All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+## Copyright 2024, gRPC Authors All rights reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+##     http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
 
 set -euo pipefail
 

+ 13 - 14
dev/check-generated-code.sh

@@ -1,18 +1,17 @@
 #!/bin/bash
-
-# Copyright 2024, gRPC Authors All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+## Copyright 2024, gRPC Authors All rights reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+##     http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
 
 set -euo pipefail
 

+ 14 - 16
dev/format.sh

@@ -1,18 +1,17 @@
 #!/bin/bash
-
-# Copyright 2020, gRPC Authors All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+## Copyright 2020, gRPC Authors All rights reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+##     http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
 
 set -eu
 
@@ -70,8 +69,7 @@ if "$lint"; then
     To fix, run the following command:
 
     % $here/format.sh -f
-    "
-    exit "${SWIFT_FORMAT_RC}"
+    " "${SWIFT_FORMAT_RC}"
   fi
 
   log "Ran swift format lint with no errors."

+ 15 - 20
dev/license-check.sh

@@ -1,18 +1,17 @@
 #!/bin/bash
-
-# Copyright 2019, gRPC Authors All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+## Copyright 2019, gRPC Authors All rights reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+##     http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
 
 # This script checks the copyright headers in source *.swift source files and
 # exits if they do not match the expected header. The year, or year range in
@@ -38,10 +37,6 @@ read -r -d '' COPYRIGHT_HEADER_SWIFT << 'EOF'
 EOF
 SWIFT_SHA=$(echo "$COPYRIGHT_HEADER_SWIFT" | shasum | awk '{print $1}')
 
-replace_years() {
-  sed -e 's/201[56789]-20[12][0-9]/YEARS/' -e 's/201[56789]/YEARS/'
-}
-
 # Checks the Copyright headers for *.swift files in this repository against the
 # expected headers.
 #
@@ -74,12 +69,12 @@ check_copyright_headers() {
         drop_first=1
         expected_lines=15
         ;;
-      */Package@swift-*.swift)
+      */Package@swift-*.*.swift)
         expected_sha="$SWIFT_SHA"
         drop_first=1
         expected_lines=15
         ;;
-      */Package@swift-*.*.swift)
+      */Package@swift-*.swift)
         expected_sha="$SWIFT_SHA"
         drop_first=1
         expected_lines=15

+ 13 - 15
dev/protos/fetch.sh

@@ -1,24 +1,22 @@
 #!/bin/bash
-#
-# Copyright 2024, gRPC Authors All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+## Copyright 2024, gRPC Authors All rights reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+##     http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
 
 set -eu
 
 here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 upstream="$here/upstream"
-root="$here/../.."
 
 # Create a temporary directory for the repo checkouts.
 checkouts="$(mktemp -d)"

+ 13 - 14
dev/protos/generate.sh

@@ -1,18 +1,17 @@
 #!/bin/bash
-#
-# Copyright 2024, gRPC Authors All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+## Copyright 2024, gRPC Authors All rights reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+##     http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
 
 set -eu
 

+ 13 - 19
dev/sanity.sh → dev/soundness.sh

@@ -1,18 +1,17 @@
 #!/bin/bash
-
-# Copyright 2020, gRPC Authors All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+## Copyright 2020, gRPC Authors All rights reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+##     http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
 
 set -eu
 
@@ -41,16 +40,11 @@ function check_license_headers() {
   run_logged "Checking license headers" "$here/license-check.sh"
 }
 
-function check_formatting() {
-  run_logged "Checking formatting" "$here/format.sh -l"
-}
-
 function check_generated_code_is_up_to_date() {
   run_logged "Checking generated code is up-to-date" "$here/check-generated-code.sh"
 }
 
 errors=0
 check_license_headers
-check_formatting
 check_generated_code_is_up_to_date
 exit $errors