Skip to content

Commit

Permalink
Merge branch 'main' into customisable-terminating-byte-sequence
Browse files Browse the repository at this point in the history
  • Loading branch information
paulhdk authored Oct 3, 2024
2 parents a5cd6a0 + 89d49d2 commit 55bc9c7
Show file tree
Hide file tree
Showing 42 changed files with 410 additions and 634 deletions.
77 changes: 68 additions & 9 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,71 @@
name: Pull Request
name: PR

on:
pull_request:
types: [opened, reopened, synchronize, ready_for_review]
pull_request:
types: [opened, reopened, synchronize]

jobs:
call-reusable-pull-request-workflow:
name: Checks
uses: apple/swift-nio/.github/workflows/reusable_pull_request.yml@main
with:
benchmarks_linux_enabled: false
soundness:
name: Soundness
uses: apple/swift-nio/.github/workflows/soundness.yml@main
with:
api_breakage_check_enabled: true
broken_symlink_check_enabled: true
docs_check_enabled: true
format_check_enabled: true
license_header_check_enabled: true
license_header_check_project_name: "SwiftOpenAPIGenerator"
shell_check_enabled: true
unacceptable_language_check_enabled: true

unit-tests:
name: Unit tests
uses: apple/swift-nio/.github/workflows/unit_tests.yml@main
with:
linux_5_8_enabled: false
linux_5_9_arguments_override: "--explicit-target-dependency-import-check error"
linux_5_10_arguments_override: "--explicit-target-dependency-import-check error"
linux_nightly_6_0_arguments_override: "--explicit-target-dependency-import-check error"
linux_nightly_main_enabled: false

integration-test:
name: Integration test
uses: apple/swift-nio/.github/workflows/swift_matrix.yml@main
with:
name: "Integration test"
matrix_linux_command: "apt-get update -yq && apt-get install -yq jq && SWIFT_OPENAPI_GENERATOR_REPO_URL=file://${GITHUB_WORKSPACE} ./scripts/run-integration-test.sh"
matrix_linux_5_8_enabled: false
matrix_linux_nightly_main_enabled: false

compatibility-test:
name: Compatibility test
runs-on: ubuntu-latest
container:
image: swift:latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Run OpenAPI document compatibilty test
env:
SWIFT_OPENAPI_COMPATIBILITY_TEST_ENABLE: "true"
SWIFT_OPENAPI_COMPATIBILITY_TEST_SKIP_BUILD: "true"
SWIFT_OPENAPI_COMPATIBILITY_TEST_FILTER: OpenAPIGeneratorReferenceTests.CompatibilityTest
SWIFT_OPENAPI_COMPATIBILITY_TEST_PARALLEL_CODEGEN: "true"
SWIFT_OPENAPI_COMPATIBILITY_TEST_NUM_BUILD_JOBS: 1
run: swift test --filter ${SWIFT_OPENAPI_COMPATIBILITY_TEST_FILTER}

example-packages:
name: Example packages
uses: apple/swift-nio/.github/workflows/swift_matrix.yml@main
with:
name: "Example packages"
matrix_linux_command: "./scripts/test-examples.sh"
matrix_linux_5_8_enabled: false
matrix_linux_nightly_main_enabled: false

swift-6-language-mode:
name: Swift 6 Language Mode
uses: apple/swift-nio/.github/workflows/swift_6_language_mode.yml@main
if: false # Disabled for now.
32 changes: 32 additions & 0 deletions .github/workflows/scheduled.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Scheduled

on:
schedule:
- cron: "0 8,20 * * *"

jobs:
unit-tests:
name: Unit tests
uses: apple/swift-nio/.github/workflows/unit_tests.yml@main
with:
linux_5_8_enabled: false
linux_5_9_arguments_override: "--explicit-target-dependency-import-check error"
linux_5_10_arguments_override: "--explicit-target-dependency-import-check error"
linux_nightly_6_0_arguments_override: "--explicit-target-dependency-import-check error"
linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error"

integration-test:
name: Integration test
uses: apple/swift-nio/.github/workflows/swift_matrix.yml@main
with:
name: "Integration test"
matrix_linux_command: "apt-get update -yq && apt-get install -yq jq && SWIFT_OPENAPI_GENERATOR_REPO_URL=file://${GITHUB_WORKSPACE} ./scripts/run-integration-test.sh"
matrix_linux_5_8_enabled: false

example-packages:
name: Example packages
uses: apple/swift-nio/.github/workflows/swift_matrix.yml@main
with:
name: "Example packages"
matrix_linux_command: "./scripts/test-examples.sh"
matrix_linux_5_8_enabled: false
41 changes: 41 additions & 0 deletions .licenseignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.gitignore
.licenseignore
.swiftformatignore
.spi.yml
.swift-format
.github/*
CODE_OF_CONDUCT.md
CONTRIBUTING.md
CONTRIBUTORS.txt
LICENSE.txt
NOTICE.txt
Package.swift
Package.resolved
README.md
SECURITY.md
scripts/unacceptable-language.txt
Tests/PetstoreConsumerTests/Generated
Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/*
docker/*
**/*.docc/*
**/.gitignore
**/Package.swift
**/Package.resolved
**/README.md
**/openapi.yaml
**/malformed-openapi.yaml
**/openapi.yml
**/petstore.yaml
**/openapi-generator-config.yaml
**/openapi-generator-config.yml
**/docker-compose.yaml
**/docker/*
**/.dockerignore
Plugins/OpenAPIGenerator/PluginsShared
Plugins/OpenAPIGeneratorCommand/PluginsShared
Examples/HelloWorldiOSClientAppExample/HelloWorldiOSClientApp.*
Examples/HelloWorldiOSClientAppExample/HelloWorldiOSClientApp/Assets.xcassets/*
Examples/HelloWorldiOSClientAppExample/HelloWorldiOSClientApp/Preview*
Examples/**/Generated*
**/Makefile
**/*.html
4 changes: 4 additions & 0 deletions .swiftformatignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Tests/OpenAPIGeneratorReferenceTests/Resources
Sources/swift-openapi-generator/Documentation.docc
Examples/**/Generated/*
Examples/**/GeneratedSources/*
37 changes: 32 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,40 @@ A good patch is:
3. Documented, adding API documentation as needed to cover new functions and properties.
4. Accompanied by a great commit message, using our commit message template.

### Run `./scripts/soundness.sh`
### Run CI checks locally

The scripts directory contains a [soundness.sh script](https://github.com/apple/swift-openapi-generator/blob/main/scripts/soundness.sh)
that enforces additional checks, like license headers and formatting style.
You can run the Github Actions workflows locally using
[act](https://github.com/nektos/act). To run all the jobs that run on a pull
request, use the following command:

Please make sure to `./scripts/soundness.sh` before pushing a change upstream, otherwise it is likely the PR validation will fail
on minor changes such as a missing `self.` or similar formatting issues.
```
% act pull_request
```

To run just a single job, use `workflow_call -j <job>`, and specify the inputs
the job expects. For example, to run just shellcheck:

```
% act workflow_call -j soundness --input shell_check_enabled=true
```

To bind-mount the working directory to the container, rather than a copy, use
`--bind`. For example, to run just the formatting, and have the results
reflected in your working directory:

```
% act --bind workflow_call -j soundness --input format_check_enabled=true
```

If you'd like `act` to always run with certain flags, these can be be placed in
an `.actrc` file either in the current working directory or your home
directory, for example:

```
--container-architecture=linux/amd64
--remote-name upstream
--action-offline-mode
```

For frequent contributors, we recommend adding the script as a [git pre-push hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks), which you can do via executing the following command in the project root directory:

Expand Down
13 changes: 10 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ let package = Package(
// code.
.package(url: "https://github.com/apple/swift-openapi-runtime", from: "1.3.2"),
.package(url: "https://github.com/apple/swift-http-types", from: "1.0.2"),

// Build and preview docs
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.3.0"),
],
targets: [

Expand Down Expand Up @@ -114,6 +111,16 @@ let package = Package(
swiftSettings: swiftSettings
),

// Test Target for swift-openapi-generator
.testTarget(
name: "OpenAPIGeneratorTests",
dependencies: [
"swift-openapi-generator", .product(name: "ArgumentParser", package: "swift-argument-parser"),
],
resources: [.copy("Resources")],
swiftSettings: swiftSettings
),

// Generator CLI
.executableTarget(
name: "swift-openapi-generator",
Expand Down
63 changes: 49 additions & 14 deletions Sources/_OpenAPIGeneratorCore/Diagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,33 @@ public protocol DiagnosticCollector {

/// Submits a diagnostic to the collector.
/// - Parameter diagnostic: The diagnostic to submit.
func emit(_ diagnostic: Diagnostic)
/// - Throws: An error if the implementing type determines that one should be thrown.
func emit(_ diagnostic: Diagnostic) throws
}

/// A type that conforms to the `DiagnosticCollector` protocol.
///
/// It receives diagnostics and forwards them to an upstream `DiagnosticCollector`.
///
/// If a diagnostic with a severity of `.error` is emitted, this collector will throw the diagnostic as an error.
public struct ErrorThrowingDiagnosticCollector: DiagnosticCollector {
let upstream: any DiagnosticCollector

/// Initializes a new `ErrorThrowingDiagnosticCollector` with an upstream `DiagnosticCollector`.
///
/// The upstream collector is where this collector will forward all received diagnostics.
///
/// - Parameter upstream: The `DiagnosticCollector` to which this collector will forward diagnostics.
public init(upstream: any DiagnosticCollector) { self.upstream = upstream }

/// Emits a diagnostic to the collector.
///
/// - Parameter diagnostic: The diagnostic to be submitted.
/// - Throws: The diagnostic itself if its severity is `.error`.
public func emit(_ diagnostic: Diagnostic) throws {
try upstream.emit(diagnostic)
if diagnostic.severity == .error { throw diagnostic }
}
}

extension DiagnosticCollector {
Expand All @@ -180,8 +206,9 @@ extension DiagnosticCollector {
/// feature was detected.
/// - context: A set of key-value pairs that help the user understand
/// where the warning occurred.
func emitUnsupported(_ feature: String, foundIn: String, context: [String: String] = [:]) {
emit(Diagnostic.unsupported(feature, foundIn: foundIn, context: context))
/// - Throws: This method will throw the diagnostic if the severity of the diagnostic is `.error`.
func emitUnsupported(_ feature: String, foundIn: String, context: [String: String] = [:]) throws {
try emit(Diagnostic.unsupported(feature, foundIn: foundIn, context: context))
}

/// Emits a diagnostic for an unsupported schema found in the specified
Expand All @@ -193,9 +220,10 @@ extension DiagnosticCollector {
/// schema was detected.
/// - context: A set of key-value pairs that help the user understand
/// where the warning occurred.
func emitUnsupportedSchema(reason: String, schema: JSONSchema, foundIn: String, context: [String: String] = [:]) {
emit(Diagnostic.unsupportedSchema(reason: reason, schema: schema, foundIn: foundIn, context: context))
}
/// - Throws: This method will throw the diagnostic if the severity of the diagnostic is `.error`.
func emitUnsupportedSchema(reason: String, schema: JSONSchema, foundIn: String, context: [String: String] = [:])
throws
{ try emit(Diagnostic.unsupportedSchema(reason: reason, schema: schema, foundIn: foundIn, context: context)) }

/// Emits a diagnostic for an unsupported feature found in the specified
/// type name.
Expand All @@ -206,8 +234,9 @@ extension DiagnosticCollector {
/// - foundIn: The type name related to where the issue was detected.
/// - context: A set of key-value pairs that help the user understand
/// where the warning occurred.
func emitUnsupported(_ feature: String, foundIn: TypeName, context: [String: String] = [:]) {
emit(Diagnostic.unsupported(feature, foundIn: foundIn.description, context: context))
/// - Throws: This method will throw the diagnostic if the severity of the diagnostic is `.error`.
func emitUnsupported(_ feature: String, foundIn: TypeName, context: [String: String] = [:]) throws {
try emit(Diagnostic.unsupported(feature, foundIn: foundIn.description, context: context))
}

/// Emits a diagnostic for an unsupported feature found in the specified
Expand All @@ -222,9 +251,12 @@ extension DiagnosticCollector {
/// feature was detected.
/// - context: A set of key-value pairs that help the user understand
/// where the warning occurred.
func emitUnsupportedIfNotNil(_ test: Any?, _ feature: String, foundIn: String, context: [String: String] = [:]) {
/// - Throws: This method will throw the diagnostic if the severity of the diagnostic is `.error`.
func emitUnsupportedIfNotNil(_ test: Any?, _ feature: String, foundIn: String, context: [String: String] = [:])
throws
{
if test == nil { return }
emitUnsupported(feature, foundIn: foundIn, context: context)
try emitUnsupported(feature, foundIn: foundIn, context: context)
}

/// Emits a diagnostic for an unsupported feature found in the specified
Expand All @@ -239,14 +271,15 @@ extension DiagnosticCollector {
/// feature was detected.
/// - context: A set of key-value pairs that help the user understand
/// where the warning occurred.
/// - Throws: This method will throw the diagnostic if the severity of the diagnostic is `.error`.
func emitUnsupportedIfNotEmpty<C: Collection>(
_ test: C?,
_ feature: String,
foundIn: String,
context: [String: String] = [:]
) {
) throws {
guard let test = test, !test.isEmpty else { return }
emitUnsupported(feature, foundIn: foundIn, context: context)
try emitUnsupported(feature, foundIn: foundIn, context: context)
}

/// Emits a diagnostic for an unsupported feature found in the specified
Expand All @@ -261,9 +294,11 @@ extension DiagnosticCollector {
/// feature was detected.
/// - context: A set of key-value pairs that help the user understand
/// where the warning occurred.
func emitUnsupportedIfTrue(_ test: Bool, _ feature: String, foundIn: String, context: [String: String] = [:]) {
/// - Throws: This method will throw the diagnostic if the severity of the diagnostic is `.error`.
func emitUnsupportedIfTrue(_ test: Bool, _ feature: String, foundIn: String, context: [String: String] = [:]) throws
{
if !test { return }
emitUnsupported(feature, foundIn: foundIn, context: context)
try emitUnsupported(feature, foundIn: foundIn, context: context)
}
}

Expand Down
36 changes: 36 additions & 0 deletions Sources/_OpenAPIGeneratorCore/DiagnosticsCollectorProvider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

import Foundation

/// Prepares a diagnostics collector.
/// - Parameter outputPath: A file path where to persist the YAML file. If `nil`, diagnostics will be printed to stderr.
/// - Returns: A tuple containing:
/// - An instance of `DiagnosticCollector` conforming to `Sendable`.
/// - A closure to finalize the diagnostics collection
public func preparedDiagnosticsCollector(outputPath: URL?) -> (any DiagnosticCollector & Sendable, () throws -> Void) {
let innerDiagnostics: any DiagnosticCollector & Sendable
let finalizeDiagnostics: () throws -> Void

if let outputPath {
let _diagnostics = _YamlFileDiagnosticsCollector(url: outputPath)
finalizeDiagnostics = _diagnostics.finalize
innerDiagnostics = _diagnostics
} else {
innerDiagnostics = StdErrPrintingDiagnosticCollector()
finalizeDiagnostics = {}
}
let diagnostics = ErrorThrowingDiagnosticCollector(upstream: innerDiagnostics)
return (diagnostics, finalizeDiagnostics)
}
Loading

0 comments on commit 55bc9c7

Please sign in to comment.