From fc0bc08998973899bef1b4abd6041cd3235dadd8 Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 30 Jul 2025 16:56:10 +0100 Subject: [PATCH 1/4] Update integration test to repro issue with AOT codegen on targets with dependencies --- .licenseignore | 1 + IntegrationTest/Package.swift | 10 ++++++++++ IntegrationTest/Sources/Empty/Empty.swift | 0 IntegrationTest/Sources/TypesAOT/Empty.swift | 0 .../TypesAOT/openapi-generator-config.yaml | 4 ++++ IntegrationTest/Sources/TypesAOT/openapi.yaml | 1 + .../Sources/TypesAOTWithDependency/Empty.swift | 0 .../openapi-generator-config.yaml | 4 ++++ .../TypesAOTWithDependency/openapi.yaml | 1 + scripts/run-integration-test.sh | 18 ++++++++++++++++++ 10 files changed, 39 insertions(+) create mode 100644 IntegrationTest/Sources/Empty/Empty.swift create mode 100644 IntegrationTest/Sources/TypesAOT/Empty.swift create mode 100644 IntegrationTest/Sources/TypesAOT/openapi-generator-config.yaml create mode 120000 IntegrationTest/Sources/TypesAOT/openapi.yaml create mode 100644 IntegrationTest/Sources/TypesAOTWithDependency/Empty.swift create mode 100644 IntegrationTest/Sources/TypesAOTWithDependency/openapi-generator-config.yaml create mode 120000 IntegrationTest/Sources/TypesAOTWithDependency/openapi.yaml diff --git a/.licenseignore b/.licenseignore index dab614423..5820d02f6 100644 --- a/.licenseignore +++ b/.licenseignore @@ -43,3 +43,4 @@ Examples/streaming-chatgpt-proxy/players.txt **/Makefile **/*.html .editorconfig +IntegrationTest/**/Empty.swift diff --git a/IntegrationTest/Package.swift b/IntegrationTest/Package.swift index a15544ccc..b891683fd 100644 --- a/IntegrationTest/Package.swift +++ b/IntegrationTest/Package.swift @@ -51,5 +51,15 @@ let package = Package( name: "MockTransportServer", dependencies: ["Server", .product(name: "OpenAPIRuntime", package: "swift-openapi-runtime")] ), + // Targets to integration test the command plugin + .target(name: "Empty"), + .target( + name: "TypesAOT", + dependencies: [.product(name: "OpenAPIRuntime", package: "swift-openapi-runtime")], + ), + .target( + name: "TypesAOTWithDependency", + dependencies: ["Empty", .product(name: "OpenAPIRuntime", package: "swift-openapi-runtime")], + ), ] ) diff --git a/IntegrationTest/Sources/Empty/Empty.swift b/IntegrationTest/Sources/Empty/Empty.swift new file mode 100644 index 000000000..e69de29bb diff --git a/IntegrationTest/Sources/TypesAOT/Empty.swift b/IntegrationTest/Sources/TypesAOT/Empty.swift new file mode 100644 index 000000000..e69de29bb diff --git a/IntegrationTest/Sources/TypesAOT/openapi-generator-config.yaml b/IntegrationTest/Sources/TypesAOT/openapi-generator-config.yaml new file mode 100644 index 000000000..a12e67bf7 --- /dev/null +++ b/IntegrationTest/Sources/TypesAOT/openapi-generator-config.yaml @@ -0,0 +1,4 @@ +generate: + - types +accessModifier: package +namingStrategy: idiomatic diff --git a/IntegrationTest/Sources/TypesAOT/openapi.yaml b/IntegrationTest/Sources/TypesAOT/openapi.yaml new file mode 120000 index 000000000..1c2a243ef --- /dev/null +++ b/IntegrationTest/Sources/TypesAOT/openapi.yaml @@ -0,0 +1 @@ +../openapi.yaml \ No newline at end of file diff --git a/IntegrationTest/Sources/TypesAOTWithDependency/Empty.swift b/IntegrationTest/Sources/TypesAOTWithDependency/Empty.swift new file mode 100644 index 000000000..e69de29bb diff --git a/IntegrationTest/Sources/TypesAOTWithDependency/openapi-generator-config.yaml b/IntegrationTest/Sources/TypesAOTWithDependency/openapi-generator-config.yaml new file mode 100644 index 000000000..a12e67bf7 --- /dev/null +++ b/IntegrationTest/Sources/TypesAOTWithDependency/openapi-generator-config.yaml @@ -0,0 +1,4 @@ +generate: + - types +accessModifier: package +namingStrategy: idiomatic diff --git a/IntegrationTest/Sources/TypesAOTWithDependency/openapi.yaml b/IntegrationTest/Sources/TypesAOTWithDependency/openapi.yaml new file mode 120000 index 000000000..1c2a243ef --- /dev/null +++ b/IntegrationTest/Sources/TypesAOTWithDependency/openapi.yaml @@ -0,0 +1 @@ +../openapi.yaml \ No newline at end of file diff --git a/scripts/run-integration-test.sh b/scripts/run-integration-test.sh index f4196cfab..84a698c1e 100755 --- a/scripts/run-integration-test.sh +++ b/scripts/run-integration-test.sh @@ -49,4 +49,22 @@ log "Running command plugin on integration test package: ${INTEGRATION_TEST_PACK swift package --package-path "${INTEGRATION_TEST_PACKAGE_PATH}" \ --allow-writing-to-package-directory generate-code-from-openapi +log "Running command plugin on integration test package AOT target: ${INTEGRATION_TEST_PACKAGE_PATH}" +swift package --package-path "${INTEGRATION_TEST_PACKAGE_PATH}" \ + --allow-writing-to-package-directory generate-code-from-openapi \ + --target TypesAOT + +log "Building integration test package AOT target: ${INTEGRATION_TEST_PACKAGE_PATH}" +swift build --package-path "${INTEGRATION_TEST_PACKAGE_PATH}" \ + --target TypesAOT + +log "Running command plugin on integration test package AOT target with dependency: ${INTEGRATION_TEST_PACKAGE_PATH}" +swift package --package-path "${INTEGRATION_TEST_PACKAGE_PATH}" \ + --allow-writing-to-package-directory generate-code-from-openapi \ + --target TypesAOTWithDependency + +log "Building integration test package AOT target with dependency: ${INTEGRATION_TEST_PACKAGE_PATH}" +swift build --package-path "${INTEGRATION_TEST_PACKAGE_PATH}" \ + --target TypesAOTWithDependency + log "✅ Successfully built integration test package." From d5949a10165a415c439cd3cdfd79d2f907f366bd Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 30 Jul 2025 17:51:07 +0100 Subject: [PATCH 2/4] Fix command plugin when run on targets with dependencies --- Plugins/OpenAPIGeneratorCommand/plugin.swift | 22 +++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Plugins/OpenAPIGeneratorCommand/plugin.swift b/Plugins/OpenAPIGeneratorCommand/plugin.swift index 9b3d6524d..65002d3ac 100644 --- a/Plugins/OpenAPIGeneratorCommand/plugin.swift +++ b/Plugins/OpenAPIGeneratorCommand/plugin.swift @@ -81,16 +81,24 @@ extension SwiftOpenAPIGeneratorPlugin: CommandPlugin { log("- ✅ OpenAPI code generation for target '\(target.name)' successfully completed.") hadASuccessfulRun = true } catch let error as PluginError { - if targetNameArguments.isEmpty, case .fileErrors(let errors) = error, + if case .fileErrors(let errors) = error, Set(errors.map(\.fileKind)) == Set(FileError.Kind.allCases), errors.map(\.issue).allSatisfy({ $0 == FileError.Issue.noFilesFound }) { - // The command plugin was run with no --target argument so its looping over all targets. - // If a target does not have any of the required files, this should only be considered an error - // if the plugin is being explicitly run on a target, either using the build plugin, or using the - // command plugin with a --target argument. - log("- Skipping because target isn't configured for OpenAPI code generation.") - continue + // The error is that neither of the required files are present for code generation for this target. + // This should only be considered an error if this target was explicitly provided as a target for + // code generation with --target. + // We may get this error for other targets if: + // + // 1. The command plugin was run with no --target arguments, in which case the plugin loops over + // all targets; or + // 2. This target is a dependency of a target that was requested using --target. + // + // In either of these cases, we should not consider this an error and skip the target. + if !targetNameArguments.contains(target.name) { + log("- Skipping because target isn't configured for OpenAPI code generation.") + continue + } } if error.isMisconfigurationError { From b99b13c419ebb64ae550a7547626f2841be14833 Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 30 Jul 2025 18:03:56 +0100 Subject: [PATCH 3/4] fixup: Remove trailing commas in IntegrationTest/Package.swift for older Swift CI --- IntegrationTest/Package.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IntegrationTest/Package.swift b/IntegrationTest/Package.swift index b891683fd..64943f51d 100644 --- a/IntegrationTest/Package.swift +++ b/IntegrationTest/Package.swift @@ -55,11 +55,11 @@ let package = Package( .target(name: "Empty"), .target( name: "TypesAOT", - dependencies: [.product(name: "OpenAPIRuntime", package: "swift-openapi-runtime")], + dependencies: [.product(name: "OpenAPIRuntime", package: "swift-openapi-runtime")] ), .target( name: "TypesAOTWithDependency", - dependencies: ["Empty", .product(name: "OpenAPIRuntime", package: "swift-openapi-runtime")], + dependencies: ["Empty", .product(name: "OpenAPIRuntime", package: "swift-openapi-runtime")] ), ] ) From de7eb0bad089c291534a1706a576f5583be533ae Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 30 Jul 2025 18:04:23 +0100 Subject: [PATCH 4/4] fixup: soundness format --- IntegrationTest/Package.swift | 5 +---- Plugins/OpenAPIGeneratorCommand/plugin.swift | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/IntegrationTest/Package.swift b/IntegrationTest/Package.swift index 64943f51d..0875530ca 100644 --- a/IntegrationTest/Package.swift +++ b/IntegrationTest/Package.swift @@ -53,10 +53,7 @@ let package = Package( ), // Targets to integration test the command plugin .target(name: "Empty"), - .target( - name: "TypesAOT", - dependencies: [.product(name: "OpenAPIRuntime", package: "swift-openapi-runtime")] - ), + .target(name: "TypesAOT", dependencies: [.product(name: "OpenAPIRuntime", package: "swift-openapi-runtime")]), .target( name: "TypesAOTWithDependency", dependencies: ["Empty", .product(name: "OpenAPIRuntime", package: "swift-openapi-runtime")] diff --git a/Plugins/OpenAPIGeneratorCommand/plugin.swift b/Plugins/OpenAPIGeneratorCommand/plugin.swift index 65002d3ac..d0e3d6f3e 100644 --- a/Plugins/OpenAPIGeneratorCommand/plugin.swift +++ b/Plugins/OpenAPIGeneratorCommand/plugin.swift @@ -81,8 +81,7 @@ extension SwiftOpenAPIGeneratorPlugin: CommandPlugin { log("- ✅ OpenAPI code generation for target '\(target.name)' successfully completed.") hadASuccessfulRun = true } catch let error as PluginError { - if case .fileErrors(let errors) = error, - Set(errors.map(\.fileKind)) == Set(FileError.Kind.allCases), + if case .fileErrors(let errors) = error, Set(errors.map(\.fileKind)) == Set(FileError.Kind.allCases), errors.map(\.issue).allSatisfy({ $0 == FileError.Issue.noFilesFound }) { // The error is that neither of the required files are present for code generation for this target.