apple / swift-openapi-generator

Generate Swift client and server code from an OpenAPI document.
https://swiftpackageindex.com/apple/swift-openapi-generator/documentation
Apache License 2.0
1.26k stars 92 forks source link

Command Plugin for generating the source code #98

Closed MahdiBM closed 11 months ago

MahdiBM commented 11 months ago

Motivation

This PR adds the option to use the package as a Command plugin instead of a BuildTool plugin.

This benefits those who use heavy OpenAPI documents, and prefer not to have to wait for an extra round of OpenAPI code generation which can be accidentally triggered at times, for example if you clean your build folder.

The whole idea of creating this Command plugin came after @czechboy0 's comment here: https://github.com/apple/swift-openapi-generator/pull/96#issuecomment-1615969962

Modifications

Generally, add a Command plugin target to the package, plus modifying the functions etc... to match/allow this addition.

Result

There is a new Command plugin, and users can choose between the Command plugin and the BuildTool plugin at will.

Test Plan

As visible in the PR discussions below, we've done enough manual-testing of the Command plugin.

MahdiBM commented 11 months ago

I'm wondering if we should prefer to factor out the common bits into an internal target

That's a known limitation of plugins. They can't depend on non-executable targets, and i tried again too:

plugin 'OpenAPIGeneratorCommandPlugin' cannot depend on 'PluginsShared' of type 'library'; this dependency is unsupported

it appears some parts of https://github.com/apple/swift-openapi-generator/pull/99 have crept into this PR

I do try to not mix PRs together, but that was intentional. Notice how i didn't mix #96 into this, as i think that PR might be up for debate. I can of course still revert the #99 changes if it is needed by the time this is ready for review.

The reason was that i thought there is a low chance for #99 for rejection (as you've now approved it ๐Ÿ™‚), and i also thought i can save myself some trouble by just merging that PR into this, since we're using this PR in production.

simonjbeaumont commented 11 months ago

I'm wondering if we should prefer to factor out the common bits into an internal target

That's a known limitation of plugins. They can't depend on non-executable targets, and i tried again too:

plugin 'OpenAPIGeneratorCommandPlugin' cannot depend on 'PluginsShared' of type 'library'; this dependency is unsupported

Of courseโ€”it's all coming back to me now ๐Ÿ˜…

it appears some parts of #99 have crept into this PR

I do try to not mix PRs together, but that was intentional. Notice how i didn't mix #96 into this, as i think that PR might be up for debate. I can of course still revert the #99 changes if it is needed by the time this is ready for review.

The reason was that i thought there is a low chance for #99 for rejection (as you've now approved it ๐Ÿ™‚), and i also thought i can save myself some trouble by just merging that PR into this, since we're using this PR in production.

Makes total sense. And yes, I expect #99 will land before this PR so will likely become a moot point.

I'm just getting back from vacation so apologies for the delay in taking a look at this. When you're ready for a review proper, let us know.

Just looking at your checklist in the PR description:

  • [ ] Better names e.g. for the Command plugin target

I'm not sure we'll do much better than OpenAPIGeneratorCommandPlugin (which you went for), given we already have the namespace-hogging OpenAPIGenerator to refer to the build tool plugin.

  • [x] (Won't Do) Work with all targets without needing to specify a specific target through Xcode UI or CLI arguments. Will worsen the error handling ... seems to not be worth it.

Could you elaborate here? I assume the original intention is that it would run once per target for which it found an OpenAPI document and config file. In this case, was your concern it exiting on the first error would lead to a game of whack-an-error for users?

  • [ ] Unit tests? If any?

For what we can unit test, great. Otherwise, we could probably add a CI that runs the ahead-of-time generation workflow and diffs against the reference code. We'll have to think about whether it's worth it. WDYT, @czechboy0?

MahdiBM commented 11 months ago

I'm just getting back from vacation so apologies for the delay in taking a look at this. When you're ready for a review proper, let us know.

No worries. Hopefully i didn't interrupt your vacation ๐Ÿ˜…

Could you elaborate here? I assume the original intention is that it would run once per target for which it found an OpenAPI document and config file. In this case, was your concern it exiting on the first error would lead to a game of whack-an-error for users?

Basically yes ... i haven't actually tried implementing it since it didn't work out in my mind. I can try if you think it might be worth it. It was kind of a hard decision that i'm still not sure about. I can't even properly remember what situations i was thinking about when i decided it might not be worth it... I guess i'll give it an actual try and see what happens ...

czechboy0 commented 11 months ago

Hi @MahdiBM โ€“ย I'm happy to see this change, added a few high level comments, but like @simonjbeaumont, I'll respect your the Draft status of the PR and will not dive into detailed code review. I'll say, #99 might need a bit more work, so I think it's best if you remove those changes from this PR.

I do think we just need to use symlinks to share code between the two plugins, and for the code that doesn't need to also be used by the CLI, you can just add it as a separate file in one of the plugins, and symlink it to the other.

So, like:

Plugins
    OpenAPIGenerator
        plugin.swift
        GeneratorMode.swift -> ../../Sources/_OpenAPIGeneratorCore/GeneratorMode.swift
        PluginUtils.swift
    OpenAPIGeneratorCommand
        plugin.swift
        GeneratorMode.swift -> ../../Sources/_OpenAPIGeneratorCore/GeneratorMode.swift
        PluginUtils.swift -> ../OpenAPIGenerator/PluginUtils.swift
Sources
    _OpenAPIGeneratorCore
        GeneratorMode.swift
MahdiBM commented 11 months ago

So i finally managed to settle on the general form of how this is going to work (comments, docs etc... are not done yet) Some notes:

MahdiBM commented 11 months ago

@simonjbeaumont @czechboy0

The PR is now ready for review. If it seems acceptable, i can work on the docs part too.

From @simonjbeaumont:

For what we can unit test, great. Otherwise, we could probably add a CI that runs the ahead-of-time generation workflow and diffs against the reference code. We'll have to think about whether it's worth it. WDYT, @czechboy0?

I think we'll need that?

From @czechboy0:

I do think we just need to use symlinks to share code between the two plugins, and for the code that doesn't need to also be used by the CLI, you can just add it as a separate file in one of the plugins, and symlink it to the other.

I'll do that if you insist, but it looks cleaner to me this way because there are 4 files (GeneratorMode, InvocationSource, PluginError, PluginUtils) and 3 of them are required in both plugins. GeneratorMode is only required for the BuildTool plugin, but i still moved it to the PluginsShared directory to make it look cleaner. The PluginsShared directory is only used by plugins.

Also i renamed the directory from GeneratedSources to OpenAPISources to basically eliminate chances of name collisions with another plugin in the command-plugin considering both GeneratedSources and names like Types/Client/Server are common.

Please feel free to make naming suggestions, comment corrections etc...

MahdiBM commented 11 months ago

I also have paid attention to the soundness CI. I'm just not sure what-to-do/how-to-do with the remainder of the warnings.

MahdiBM commented 11 months ago

@czechboy0 @simonjbeaumont Take 3!

As "bullet points" since that's easier to write for me:

If you wanted my opinion, i'd say yeah it's suboptimal that Xcode UI doesn't allow passing of any target names you want through the UI itself, but i still think the command plugin is still good enough to be worth it.

You may also ask why not just go back to doing it for all targets of the package at least? And to answer, i'm not 100% sure but i'm fine with this small level of explicitly choosing a product from Xcode's UI although it's one more click, considering it allows us to throw slightly more meaningful/accurate errors. Again, not sure, i can set it back to just run on all of a package's targets at once if you think that's better.

czechboy0 commented 11 months ago

The main problem this time around was that i noticed Xcode's command plugin run UI doesn't include all targets to pass to a command plugin.

Well, that's unfortunate. We have at least these two options:

I'm on the fence, but at this point leaning towards what you did, and please file a FB on Xcode to support any targets, not just products, and we'll link it here to ensure that we can clean up the behavior in the future once Xcode improves that behavior.

Also curious which direction @simonjbeaumont is leaning.

Ok, let me re-review the code now ๐Ÿ™‚

MahdiBM commented 11 months ago

live with that limitation, and ask adopters to wrap any target with OpenAPI documents in a product

Honestly that idea did not occur to me. It does sound like a good idea. I just tried adding the generator-related target to the products array of the package. It worked seamlessly and made Xcode show the target to choose for the command plugin.

czechboy0 commented 11 months ago

live with that limitation, and ask adopters to wrap any target with OpenAPI documents in a product

Honestly that idea did not occur to me. It does sound like a good idea. I just tried adding the generator-related target to the products array of the package. It worked seamlessly and made Xcode show the target to choose for the command plugin.

Right, the question is whether this is a reasonable thing to ask people, to basically publicize any target where they use the plugin. Maybe that goes against our documented recommendations. Idk, @simonjbeaumont what do you think?

MahdiBM commented 11 months ago

One thing that i forgot ... should i make the command-plugin-invocation delete the build-plugin-invocation generated files? So users don't need to manually clean-build or modify DerivedData.

The build plugin won't be able to do the same though, considering it doesn't have write access to the source code.

czechboy0 commented 11 months ago

One thing that i forgot ... should i make the command-plugin-invocation delete the build-plugin-invocation generated files? So users don't need to manually clean-build or modify DerivedData.

The build plugin won't be able to do the same though, considering it doesn't have write access to the source code.

I don't think so, they each produce files into different locations. The build plugin produces them in GeneratedSources in Derived Data, the command plugin writes them back to the package source directory. I wouldn't want them to try to delete each other's files, seems it could go wrong very badly very quickly, even if the sandbox allowed it (I don't think it would).

simonjbeaumont commented 11 months ago

Catching up a bit here...

live with that limitation, and ask adopters to wrap any target with OpenAPI documents in a product

Honestly that idea did not occur to me. It does sound like a good idea. I just tried adding the generator-related target to the products array of the package. It worked seamlessly and made Xcode show the target to choose for the command plugin.

Right, the question is whether this is a reasonable thing to ask people, to basically publicize any target where they use the plugin. Maybe that goes against our documented recommendations. Idk, @simonjbeaumont what do you think?

Just confirming my understanding here: are we saying that it works as expected with swift package ... but with Xcode there's some issues, that require this workaround?

In that event I don't think we should hold back the utility of having a supported workflow for Swift PM users.

We then are free to choose how to approach the Xcode flow, in light of any limitations it might have:

  1. Actively disable it in code.
  2. Let people use it but call out it's not supported in docs.
  3. Actively support it and call out how to use it in docs, with all the limitations, and consequences of any workarounds.

One thing that i forgot ... should i make the command-plugin-invocation delete the build-plugin-invocation generated files? So users don't need to manually clean-build or modify DerivedData.

The build plugin won't be able to do the same though, considering it doesn't have write access to the source code.

I think I'd be OK with it removing things from DerivedData. But I don't feel strongly about it. What are the other options?

Aside: Does the build plugin have read access to the source tree? If it did, it might be able to provide sensible errors/warnings, even if it cannot delete things automatically.

czechboy0 commented 11 months ago

Just confirming my understanding here: are we saying that it works as expected with swift package ... but with Xcode there's some issues, that require this workaround?

Right, from CLI it always works, but to support Xcode, which doesn't allow selecting a target, only a product, we had to do a bunch more implementation complexity. So with this PR, we support both, it's just a little more complex than if Xcode allowed selecting targets to run commands on. But it's done now, and should work, so I wouldn't advocate to go and remove it.

Regarding removing other files: just to clarify, this would only be needed for people who are switching between using the build plugin and the command plugin. I wouldn't worry about it, as long as people follow our docs, they'll get into a good state. I wouldn't want to open the can of worms of tracking user's local state and try to get them out of having a bad cache, as not even the build system tries to do that โ€“ย so I'm okay with them cleaning their build folder and trying again, at which point it'll work.

MahdiBM commented 11 months ago

@czechboy0 one more thing i remembered: If a project has been using the build plugin and switches to the command plugin, Xcode/Swift would throw the error that says "there are files with same names". Though i think it'll still be fine, because even if we change file names, then Xcode will just throw "duplicate type name" errors instead. So i think the solution is to just point this out in the docs. Possibly have a "Switching between plugins" tutorial.

czechboy0 commented 11 months ago

@czechboy0 one more thing i remembered: If a project has been using the build plugin and switches to the command plugin, Xcode/Swift would throw the error that says "there are files with same names". Though i think it'll still be fine, because even if we change file names, then Xcode will just throw "duplicate type name" errors instead. So i think the solution is to just point this out in the docs. Possibly have a "Switching between plugins" tutorial.

We'll see if people actually hit it and struggle to figure it out, but I'm fine with us not adding complexity just to catch this one case and try to provide a better error. It seems it'd be too fragile anyway, as it'd rely on a bunch of implementation details of the build system and Xcode, so I'd like to avoid it.

MahdiBM commented 11 months ago

@czechboy0

please file a FB on Xcode to support any targets, not just products, and we'll link it here to ensure that we can clean up the behavior in the future once Xcode improves that behavior.

FB12674830 ๐Ÿ™‚

MahdiBM commented 11 months ago

@czechboy0 one more try ๐Ÿ™‚ :

Not choosing any product from Xcode UI:

Screenshot 2023-07-20 at 10 47 45โ€ฏAM

Choosing 'AutoPingsLambda' which doesn't have OpenAPI files, and its local dependencies too:

Screenshot 2023-07-20 at 10 49 54โ€ฏAM

Choosing the exact product:

Screenshot 2023-07-20 at 10 50 43โ€ฏAM
simonjbeaumont commented 11 months ago

This seems good to me. To summarise:

  1. If you don't select any target, it tries them all and "skips" targets that aren't deemed appropriate.
  2. If you explicitly select an appropriate target, it succeeds.
  3. If you explicitly select an inappropriate target, it fails.

In scenario (1), I can see in the screenshot two things that would be nice to improve:

I don't mind deferring that to another PR though. WDYT @czechboy0 @MahdiBM?

MahdiBM commented 11 months ago

@simonjbeaumont I know this PR has been going for long enough that you probably don't want to bother me anymore, but those changes are small enough, and even if they weren't, i still wouldn't mind them ๐Ÿ˜…

The order of the logs: would be nice to log the target being operated on before the rest of the logging. This reads clearer IMO.

Good idea but will basically duplicate the logs because we'll need to say running on target '----' then run failed on target '-----'. (Unless the target is just straight up not a swift source module in which case no need for duplication.)

Should i go for it? or did you mean something else?

Would be nice for these "skipped" targets to appear as "skipped" or "warnings" rather than "failed" in the logs.

No objections, but can you mention some examples so i know what you exactly have in mind? Like just changing the words, or kind of flagging the print statements by starting them with e.g. Skipped target '----':, Warnings for target '-----':? EDIT: Ah reading your message again, you probably just meant changing the word. Though i still like the other idea ๐Ÿค”

MahdiBM commented 11 months ago

What i do prefer though, is for the Docs part to be deferred to another PR considering this has taken enough time/length ๐Ÿ˜… would prefer this to be merged sooner than later, when possible, so i can also start using the main Apple repo in my Package.swifts ๐Ÿ™‚

simonjbeaumont commented 11 months ago

@simonjbeaumont I know this PR has been going for long enough that you probably don't want to bother me anymore, but those changes are small enough, and even if they weren't, i still wouldn't mind them ๐Ÿ˜…

OK, great!

Both of these comments pertain to this logging from your screenshot above, so I'll paste the textual version here before continuing to discuss your specific questions:

โœ… Invoking plug-in command "OpenAPIGeneratorCommand" 18.5 seconds
- Target 'PennyTests': OpenAPI code generation failed. No expected config or OpenAPI document files.
- Target 'Models': OpenAPI code generation failed. No expected config or OpenAPI document files.
- Target 'Penny': OpenAPI code generation failed. No expected config or OpenAPI document files.
Swift OpenAPI Generator is running with the following configuration:
- OpenAPI document path: /Users/mahdibm/Github/penny-bot/Sources/GitHubAP|/openapi.yaml
- Configuration path: /Users/mahdibm/Github/penny-bot/Sources/GitHubAP|/openapi-generator-config.yml
- Generator modes: types, client
- Output file names: Types.swift, Client.swift
- Output directory: /Users/mahdibm/Github/penny-bot/Sources/GitHubAP|/GeneratedSources
- Diagnostics output path: <none - logs to stderr>
- Current directory: /Users/mahdibm/Github/penny-bot
- Plugin source: command
- Additional imports: <none>
File Types.swift: unchanged
File Client.swift: unchanged
- Target 'GitHubAPI': OpenAPI code generation successfully completed.
- Target 'Extensions': OpenAPI code generation failed. No expected config or OpenAPI document files.
- Target 'GHHooksLambda': OpenAPI code generation failed. No expected config or OpenAPI document files.
- Target 'Fake': OpenAPI code generation failed. No expected config or OpenAPI document files.
- Target 'SponsorsLambda': OpenAPI code generation failed. No expected config or OpenAPI document files.
- Target 'SharedServices': OpenAPI code generation failed. No expected config or OpenAPI document files.
- Target 'CoinsLambda': OpenAPI code generation failed. No expected config or OpenAPI document files.
- Target 'FaqsLambda': OpenAPI code generation failed. No expected config or OpenAPI document files.
- Target 'AutoPingsLambda': OpenAPI code generation failed. No expected config or OpenAPI document files.
โœ… Activity Log Complete 7/20/23, 10:50 AM 17.8 seconds
No issues

The order of the logs: would be nice to log the target being operated on before the rest of the logging. This reads clearer IMO.

Good idea but will basically duplicate the logs because we'll need to say running on target '----' then run failed on target '-----'. (Unless the target is just straight up not a swift source module in which case no need for duplication.)

Should i go for it? or did you mean something else?

Personally, I prefer logging to be before an operation, and, looking through the build logs in Xcode for a target I happen to have open I see this pattern. Examples include Compiling ..., and Discovering Swift tasks after .... When an operation is failed, there is some "duplicate" logging; here is a textual version of what I see in the report navigator when I replace print with pint (note, the emojis aren't actually in the logโ€”they are a representation of how Xcode renders the icons):

...
โœ… Planning Swift module swift_openapi_generator (arm64)
โ„น๏ธ Compiling runGenerator.swift 
    โ„น๏ธ Compile runGenerator.swift (arm64)
        โŒ Cannot find 'pint' in scope
โŒ Build failed ...

When the issue if fixed, I see:

โœ… Planning Swift module swift_openapi_generator (arm64)
โœ… Compiling runGenerator.swift 
    โœ… Compile runGenerator.swift (arm64)
...
โœ… Build succeeded ...

Would be nice for these "skipped" targets to appear as "skipped" or "warnings" rather than "failed" in the logs.

No objections, but can you mention some examples so i know what you exactly have in mind? Like just changing the words, or kind of flagging the print statement by starting them with e.g. Skipped target '----':, Warnings for target '-----':?

I think it's odd to see big green check marks and lots of <some operation> failed in the logs.

I'm not suggesting we go for emojis, but I'd be happy with us finding some terminology that is clear about what's going on, for example:

Considering target for OpenAPI generation: InappropriateTarget
Skipped target (no OpenAPI document): InappropriateTarget
Considering target for OpenAPI generation: AppropriateTarget
Running Swift OpenAPI Generator on target AppropriateTarget with the following configuration:
...

I'd be happy if it then printed a line explicitly saying whether it was succeeded or failed.

IMHO this small amount of "duplicate" logging is a small price to pay for clarity when debugging a failed build.

MahdiBM commented 11 months ago

@simonjbeaumont This is what i came up with.

Please let me know if i can improve any of the sentences.

I used the โœ… emoji for a successful code generation because i think it makes long logs like this more skimmable.

The - Stopping because target isn't configured for OpenAPI code generation. logs don't feel satisfying in terms of being different from the theme/mood of the rest of the logs, but that's the best i could come up with.

Screenshot 2023-07-20 at 4 39 04โ€ฏPM
simonjbeaumont commented 11 months ago

@simonjbeaumont This is what i came up with. Thanks for going the extra mile on this one.

I used the โœ… emoji for a successful code generation because i think it makes long logs like this more skimmable.

While I initially hinted at not doing this, I think I agree; it does make it easier to read at a glance so I'm fine with it ๐Ÿ‘

Please let me know if i can improve any of the sentences.

The - Stopping because target isn't configured for OpenAPI code generation. logs don't feel satisfying in terms of being different from the theme/mood of the rest of the logs, but that's the best i could come up with.

Aside from tone, this one in particular isn't informativeโ€”why isn't it "configured" and what does it mean for it to be configured? I this case we could have something like: - Skipped target: Target does not contain OpenAPI document or something similar?

Other than that I'm pleased with how this is looking.

@czechboy0 do you have anything to add before we push this over the line?

MahdiBM commented 11 months ago

@simonjbeaumont i made it non-informative because i suspected @czechboy0 would not like the duplication of "there are no files" messages as he requested some changes about them in the past reviews.

Though i think both views are completely valid. It's just a question of if the information is worth the duplication. I'm personally fine with both, maybe slightly leaning towards the current non-informative message.

simonjbeaumont commented 11 months ago

@simonjbeaumont i made it non-informative because i suspected @czechboy0 would not like the duplication of "there are no files" messages as he requested some changes about them in the past reviews.

Though i think both views are completely valid. It's just a question of if the information is worth the duplication. I'm personally fine with both, maybe slightly leaning towards the current non-informative message.

OK, that's fair enough, and sorry for missing that historical review context.

I'm happy with things the way they are now (subject to the soundness check passing again).

MahdiBM commented 11 months ago

Honestly i had no idea what some of the warnings were requesting:


** โœ… Found no unacceptable language.
** Running /code/scripts/check-license-headers.sh...
** ERROR: Unsupported file extension for file (exclude or update this script): Plugins/OpenAPIGenerator/PluginsShared
** Running /code/scripts/run-swift-format.sh...
Plugins/PluginsShared/PluginUtils.swift:4:92: warning: [UseEarlyExits] replace the `if/else` block with a `guard` statement containing the early exit
Plugins/PluginsShared/PluginUtils.swift:4:92: warning: [UseEarlyExits] replace the `if/else` block with a `guard` statement containing the early exit
/code/Package.swift:173:10: warning: [TrailingComma] add trailing comma to the last element in multiline collection literal
Package.swift:164:1: warning: [LineLength] line is too long
Plugins/PluginsShared/PluginError.swift:14:1: warning: [LineLength] line is too long
Plugins/PluginsShared/PluginError.swift:21:1: warning: [LineLength] line is too long
Plugins/PluginsShared/PluginError.swift:97:1: warning: [LineLength] line is too long
Plugins/PluginsShared/PluginError.swift:99:1: warning: [LineLength] line is too long
Plugins/PluginsShared/PluginError.swift:104:1: warning: [LineLength] line is too long
Plugins/PluginsShared/PluginError.swift:106:1: warning: [LineLength] line is too long
Plugins/PluginsShared/PluginUtils.swift:4:1: warning: [LineLength] line is too long
Plugins/OpenAPIGeneratorCommand/plugin.swift:58:1: warning: [LineLength] line is too long
Plugins/OpenAPIGeneratorCommand/plugin.swift:59:1: warning: [LineLength] line is too long
Plugins/OpenAPIGeneratorCommand/plugin.swift:62:1: warning: [LineLength] line is too long
** ERROR: โŒ Running swift-format produced errors.

  To fix, run the following command:

    % git ls-files -z '*.swift' | xargs -0 swift-format --in-place --parallel

A few of the warnings were also pointing at non-existent (or wrong) lines (like Package.swift being 172 lines and swift-format complaining about the 173 rd line!) But luckily i noticed the CI also mentions git ls-files -z '*.swift' | xargs -0 swift-format --in-place --parallel which automatically solved the problems.

EDIT: Not to mention the line is too long warnings which were in short complaining about something that couldn't have been solved, and even the command didn't really fix anything, it just moved the long lines to the line after the returns which is the best it could do.

MahdiBM commented 11 months ago

@simonjbeaumont @czechboy0 what should i do to resolve this last soundness error?


** โœ… Found no unacceptable language.
** Running /code/scripts/check-license-headers.sh...
** ERROR: Unsupported file extension for file (exclude or update this script): Plugins/OpenAPIGenerator/PluginsShared
** Running /code/scripts/run-swift-format.sh...
** โœ… Ran swift-format with no errors.
MahdiBM commented 11 months ago

Had to exclude 2 to directories from check-license-headers.sh. These are the symlinked directories, and the actual files are still checked for headers, as it threw errors for the files that didn't have the headers in the second to last CI run.

read -ra PATHS_TO_CHECK_FOR_LICENSE <<< "$( \
  git -C "${REPO_ROOT}" ls-files -z \
  ":(exclude).gitignore" \
  ":(exclude).spi.yml" \
  ":(exclude).swift-format" \
  ":(exclude).github/*" \
  ":(exclude)CODE_OF_CONDUCT.md" \
  ":(exclude)CONTRIBUTING.md" \
  ":(exclude)CONTRIBUTORS.txt" \
  ":(exclude)LICENSE.txt" \
  ":(exclude)NOTICE.txt" \
  ":(exclude)Package.swift" \
  ":(exclude)Package.resolved" \
  ":(exclude)README.md" \
  ":(exclude)SECURITY.md" \
  ":(exclude)scripts/unacceptable-language.txt" \
  ":(exclude)Tests/PetstoreConsumerTests/Generated" \
  ":(exclude)Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/*" \
  ":(exclude)docker/*" \
  ":(exclude)**/*.docc/*" \
  ":(exclude)**/.gitignore" \
  ":(exclude)**/Package.swift" \
  ":(exclude)**/Package.resolved" \
  ":(exclude)**/README.md" \
  ":(exclude)**/openapi.yaml" \
  ":(exclude)**/openapi.yml" \
  ":(exclude)**/petstore.yaml" \
  ":(exclude)**/openapi-generator-config.yaml" \
  ":(exclude)**/openapi-generator-config.yml" \
+  ":(exclude)Plugins/OpenAPIGenerator/PluginsShared" \
+  ":(exclude)Plugins/OpenAPIGeneratorCommand/PluginsShared" \
  | xargs -0 \
)"
czechboy0 commented 11 months ago

Thanks @MahdiBM for bearing with us during this marathon of a PR ๐Ÿ™‚ Just updated from main and will land once CI passes.