Skip to content

Only regen in sbt OpenAPI codegen when input YAMLs change#5102

Merged
adamw merged 3 commits intosoftwaremill:masterfrom
aelred:caching
Mar 10, 2026
Merged

Only regen in sbt OpenAPI codegen when input YAMLs change#5102
adamw merged 3 commits intosoftwaremill:masterfrom
aelred:caching

Conversation

@aelred
Copy link
Contributor

@aelred aelred commented Mar 6, 2026

The current behaviour is:

  1. Run OpenAPI codegen (unconditionally)
  2. Write results to temporary files
  3. If a temporary file changed, copy it to the final destination

This saves some work (downstream recompilation etc.) but still means we always run codegen every time.

For larger YAMLs this can take a while, and impacts every build even with no code changes. For me this can add 20-30 seconds to

Changing this behaviour to use FileFunction.cached and / fileInputs to check the input YAML files instead:

  1. Check OpenAPI YAMLs have changed (if they haven't changed, stop)
  2. Run OpenAPI codegen
  3. Write results to final files

Manual test

Verified on my project by compiling the API model twice:

sbt:redzone> apiModel/compile
... first compile ...
sbt:redzone> apiModel/compile
[info] Total time: 80 ms
[info]   apiModel / Compile / compileIncremental                           : 31 ms
[info]   apiModel / Compile / managedSources                               : 12 ms
[info]   apiModel / scalaCompilerBridgeBinaryJar                           : 10 ms
[info]   apiModel / Compile / compile                                      :  9 ms
[info]   apiModel / Compile / generateTapirDefinitions                     :  6 ms
[info]   apiModel / Compile / compileOutputs                               :  4 ms
[info]   apiModel / Compile / scalacOptions                                :  3 ms
[info]   apiModel / update                                                 :  3 ms
[info]   apiModel / sass                                                   :  2 ms
[info]   apiModel / csrRecursiveResolvers                                  :  2 ms
[info]   apiModel / csrFallbackDependencies                                :  1 ms
[info]   apiModel / Compile / unmanagedSources / allInputPathsAndAttributes:  1 ms
[info]   apiModel / csrInterProjectDependencies                            :  1 ms
[success] Total time: 0 s, completed 6 Mar 2026, 15:05:06

Without new plugin:

sbt:redzone> apiModel/compile
... first compile ...
sbt:redzone> apiModel/compile
[info] Zipping file...
[info] Total time: 21062 ms
[info]   apiModel / Compile / managedSources                               : 20976 ms
[info]   apiModel / Compile / compileIncremental                           :    34 ms
[info]   apiModel / csrRecursiveResolvers                                  :    33 ms
[info]   apiModel / csrFallbackDependencies                                :    33 ms
[info]   apiModel / csrInterProjectDependencies                            :    33 ms
[info]   apiModel / scalaCompilerBridgeBinaryJar                           :    31 ms
[info]   apiModel / Compile / scalacOptions                                :    18 ms
[info]   apiModel / Compile / compile                                      :    10 ms
[info]   apiModel / update                                                 :     9 ms
[info]   apiModel / dependencyPositions                                    :     6 ms
[info]   apiModel / Compile / unmanagedSources / allInputPathsAndAttributes:     5 ms
[info]   apiModel / Compile / compileOutputs                               :     4 ms
[info]   apiModel / sass                                                   :     3 ms
[info]   apiModel / Compile / unmanagedSources / inputFileStamps           :     3 ms
[info]   apiModel / projectDescriptors                                     :     3 ms
[info]   apiModel / Compile / unmanagedClasspath                           :     2 ms
[info]   apiModel / Compile / unmanagedJars                                :     2 ms
[info]   apiModel / Compile / managedClasspath                             :     2 ms
[info]   apiModel / scalaInstance                                          :     1 ms
[info]   apiModel / csrProject                                             :     1 ms
[info]   apiModel / ivyModule                                              :     1 ms
[info]   apiModel / csrConfiguration                                       :     1 ms
[info]   apiModel / ivyConfiguration                                       :     1 ms
[info]   streams-manager                                                   :     1 ms
[success] Total time: 21 s, completed 6 Mar 2026, 15:11:56

@aelred aelred changed the title Only regenerate in sbt OpenAPI codegen when input YAMLs change Only regen in sbt OpenAPI codegen when input YAMLs change Mar 6, 2026
Copy link
Contributor

@hughsimpson hughsimpson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @aelred this has annoyed me for ages

@hughsimpson
Copy link
Contributor

hughsimpson commented Mar 9, 2026

Actually I think there are issues with this. If I change the config and rerun, then nothing's regenerated... 🤔

Edit: behaving as desired now, tnx

@hughsimpson
Copy link
Contributor

hughsimpson commented Mar 9, 2026

@adamw a big motivation for wanting this is if you have sourcecode generators to subsequently munge the output of the plugin -- ideally we should make it easier to skip those applications. I think this works as desired since locally it helps me skip a bunch of redundant reprocessing; and at least with my suggested changes, I can't think of any other things other than openapi, config, and plugin version that you'd want to react to.

Co-authored-by: hughsimpson <hughrsimpson@gmail.com>
@adamw adamw merged commit 7009e55 into softwaremill:master Mar 10, 2026
31 of 32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants