Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically Load Liquibase Resource Files for Native Image Build #41928

Merged
merged 6 commits into from
Jul 25, 2024

Conversation

gcw-it
Copy link
Contributor

@gcw-it gcw-it commented Jul 16, 2024

Fixes #40574
Fixes #40575
Fixes #42143

It seems, that after upgrading the liquibase-core version, the additional resource files that were added, weren't incorporated in the build.

To avoid this problem for future updates, this patch loads the following iquibase-core resources automatically:

  • all .property files in the root folder
  • all .xsd XML Schema Definitions from the www.liquibase.org/xml/ns/dbchangelog folder
  • all service definitions in META-INF/services

The i18n resources were already automatically loaded before.

If in a future liquibase version a service is added, that needs initialisation at runtime, this information needs to be manually added to the code.
Manual intervention is also necessary, should any other resource types or locations be added to liquibase.

@quarkus-bot
Copy link

quarkus-bot bot commented Jul 16, 2024

Thanks for your pull request!

Your pull request does not follow our editorial rules. Could you have a look?

  • title should preferably start with an uppercase character (if it makes sense!)

This message is automatically generated by a bot.

@gcw-it gcw-it changed the title liquibase resource files are automatically loaded for native image build Automatically Load Liquibase Resource Files for Native Image Build Jul 16, 2024
@gsmet
Copy link
Member

gsmet commented Jul 16, 2024

Thanks! It's definitely a good idea as we have been struggling with it a lot. I'll have a look soon.

Copy link
Member

@gsmet gsmet left a comment

Choose a reason for hiding this comment

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

I added a few suggestions. Can you give it a try. I think it would improve the code but I haven't tried so please push back if you don't see it working.

Thanks!

Comment on lines 236 to 252
var jarUrlTemplate = "jar:%s!/";
try {
var srcUrl = Objects.requireNonNull(Liquibase.class
.getProtectionDomain()
.getCodeSource()
.getLocation());
var jarUrl = new java.net.URL(jarUrlTemplate.formatted(srcUrl.toString())).toURI();

try (var ignored = FileSystems.newFileSystem(jarUrl, Collections.EMPTY_MAP)) {
var rootPath = Paths.get(jarUrl);
loadLiquibaseServiceProviderConfig(rootPath, services, reflective, runtimeInitialized);
loadLiquibaseRootProperties(rootPath, resource);
loadLiquibaseXsdResources(rootPath, resource);
}
} catch (URISyntaxException | IOException ex) {
throw new IllegalStateException(ex);
}
Copy link
Member

Choose a reason for hiding this comment

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

I'm not entirely sure about the implementation here.

I think, maybe using CurateOutcomeBuildItem to get the ApplicationModel would be better. Then you could get a ResolvedDependency from getDependencies that match Liquibase and use getContentTree(PathFilter).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the pointer. Done.

Comment on lines 266 to 267
.map(this::classFromString)
.filter(not(runtimeInitializationServices::contains))
Copy link
Member

Choose a reason for hiding this comment

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

I think I would avoid transforming this to a class then a String again. You can make runtimeInitializationServices a set of strings and use liquibase.configuration.ConfigurationValueProvider.class.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.
I realised the same happened for the static initialisation. I changed it there, too.

BuildProducer<ReflectiveClassBuildItem> reflective,
BuildProducer<RuntimeInitializedClassBuildItem> runtimeInitialized) throws IOException {

List<Class<?>> runtimeInitializationServices = List.of(
Copy link
Member

Choose a reason for hiding this comment

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

For now it doesn't make a lot of difference as you only have one item but let's make it a HashSet in case it grows in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@quarkus-bot

This comment has been minimized.

@gsmet
Copy link
Member

gsmet commented Jul 17, 2024

@gcw-it I sent you an email on the email you use to commit (hopefully you read it!), let's try to figure out things there so that your setup works.

return dependency.getResolvedPaths().stream()
.map(Path::getFileName)
.map(Path::toString)
.anyMatch(s -> s.contains(LIQUIBASE_ARTIFACT_NAME));
Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't dependency.getArtifactId().equals(LIQUIBASE_ARTIFACT_NAME) work here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right, somehow I managed to overlook that possibility.
I will change this accordingly.

Copy link
Member

Choose a reason for hiding this comment

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

Please do that and also test the groupId. Typically you could have someone having a my-groupid:liquibase-core in their app and you don't want to catch that.

Also I recommend using the CONSTANT.equals(variable) pattern instead of variable.equals(CONSTANT). In this case, the variables won't be null so it won't change anything but it's a good practice to avoid NPEs. Once you have this habit, you're a lot safer.

Copy link
Member

@gsmet gsmet left a comment

Choose a reason for hiding this comment

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

I think we're nearly there. I added a few additional comments/advices.

return dependency.getResolvedPaths().stream()
.map(Path::getFileName)
.map(Path::toString)
.anyMatch(s -> s.contains(LIQUIBASE_ARTIFACT_NAME));
Copy link
Member

Choose a reason for hiding this comment

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

Please do that and also test the groupId. Typically you could have someone having a my-groupid:liquibase-core in their app and you don't want to catch that.

Also I recommend using the CONSTANT.equals(variable) pattern instead of variable.equals(CONSTANT). In this case, the variables won't be null so it won't change anything but it's a good practice to avoid NPEs. Once you have this habit, you're a lot safer.

// Register Precondition services, and the implementation class for reflection while also registering fields for reflection
consumeService(liquibase.precondition.Precondition.class, (serviceClass, implementations) -> {
services.produce(new ServiceProviderBuildItem(serviceClass.getName(), implementations.toArray(new String[0])));
consumeService("liquibase.precondition.Precondition", (serviceClass, implementations) -> {
Copy link
Member

Choose a reason for hiding this comment

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

I suggested to use liquibase.precondition.Precondition.class.getName() (and same for the others, for instance in RUNTIME_INITIALIZATION_SERVICES). Keep in mind that we don't manage the Liquibase development so better get a compilation warning if they change something in this area.

It's a bit more nuanced than that because we sometimes use the strings because either the classes are not accessible or because we want to avoid loading them if we can, but in this very case, I think it's better to use .class.getName().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I understand your reasoning here, but doesn't this contradict, what you wrote above?

I think I would avoid transforming this to a class then a String again. You can make runtimeInitializationServices a set of strings and use liquibase.configuration.ConfigurationValueProvider.class.

I'm fine with restoring this to the class-based version, but I'd like to avoid any misunderstanding.

Copy link
Member

Choose a reason for hiding this comment

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

I think you're confused because I made a mistake in my very first comment :).

Use liquibase.precondition.Precondition.class.getName() with .getName() so that you get the String name. That's what I wanted to write the first time but I somehow missed the .getName().

That way we will have compilation checked and we will avoid going back and forth with classes and strings.

Is it all clear now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, i see. I will change the code accordingly.

@quarkus-bot

This comment has been minimized.

@gcw-it
Copy link
Contributor Author

gcw-it commented Jul 20, 2024

I enabled quarkus.liquibase.clean-at-start for the liquibase extension integration test.
With clean-at-start=true the IT fails before integrating this patch and succeeds afterwards.

@gcw-it
Copy link
Contributor Author

gcw-it commented Jul 22, 2024

I realised, that my code for the runtime initialisation of the services is incorrect. It only registers the service type, and not the corresponding implementations. Correcting this leads unfortunately to another problem.

The reason why I registered the ConfigurationValueProvider service at runtime was a GraalVM build time compilation error for the EnvironmentValueProvider service implementation:
Error: Unsupported field liquibase.configuration.core.EnvironmentValueProvider.environment is reachable (see the detailed error message below).
This happens with GraalVM 21.0.4 as well as 22.0.2.

When I register the unproblematic service implementations correctly, and ConfigurationValueProvider at runtime, ConfigurationValueProvider will be optimised away during compilation, which in consequence leads to an exception at runtime:
Cannot load service: java.util.ServiceConfigurationError: liquibase.configuration.ConfigurationValueProvider: Provider liquibase.configuration.core.EnvironmentValueProvider not found.

Registering ConfigurationValueProvider additionally for reflection, that it won't get removed during compilation leads again to the 'Unsupported field' error.

I think, the best course of action right now is, to not register the ConfigurationValueProvider services at all, since Quarkus has its own method for configuring Liquibase. Additionally the service wasn't registered in the previous version of the code, to no apparent adverse effect.

Error encountered while parsing com.oracle.svm.core.code.FactoryMethodHolder.EnvironmentValueProvider_constructor_f0afbab60625ae84e3a446aaf418c470e965b9de(generated:0)
Parsing context:
   at static root method.(Unknown Source)

Detailed message:

com.oracle.svm.core.util.UserError$UserException: Unsupported field liquibase.configuration.core.EnvironmentValueProvider.environment is reachable
To diagnose the issue, you can add the option --report-unsupported-elements-at-runtime. The unsupported element is then reported at run time when it is accessed the first time.
Error encountered while parsing com.oracle.svm.core.code.FactoryMethodHolder.EnvironmentValueProvider_constructor_f0afbab60625ae84e3a446aaf418c470e965b9de(generated:0)
Parsing context:
   at static root method.(Unknown Source)

Detailed message:

	at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.UserError.abort(UserError.java:97)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.FallbackFeature.reportAsFallback(FallbackFeature.java:248)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:833)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:571)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:537)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:526)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:701)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.start(NativeImageGeneratorRunner.java:140)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:95)
Caused by: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Unsupported field liquibase.configuration.core.EnvironmentValueProvider.environment is reachable
To diagnose the issue, you can add the option --report-unsupported-elements-at-runtime. The unsupported element is then reported at run time when it is accessed the first time.
Error encountered while parsing com.oracle.svm.core.code.FactoryMethodHolder.EnvironmentValueProvider_constructor_f0afbab60625ae84e3a446aaf418c470e965b9de(generated:0)
Parsing context:
   at static root method.(Unknown Source)

Detailed message:

	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.constraints.UnsupportedFeatures.report(UnsupportedFeatures.java:126)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:828)
	... 6 more
Caused by: com.oracle.svm.hosted.substitute.DeletedElementException: Unsupported field liquibase.configuration.core.EnvironmentValueProvider.environment is reachable
To diagnose the issue, you can add the option --report-unsupported-elements-at-runtime. The unsupported element is then reported at run time when it is accessed the first time.
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.lookup(AnnotationSubstitutionProcessor.java:185)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor$ChainedSubstitutionProcessor.lookup(SubstitutionProcessor.java:135)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisUniverse.lookupAllowUnresolved(AnalysisUniverse.java:359)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.infrastructure.AnalysisConstantPool.lookupField(AnalysisConstantPool.java:42)
	at jdk.graal.compiler/jdk.graal.compiler.java.BytecodeParser.lookupField(BytecodeParser.java:4395)
	at jdk.graal.compiler/jdk.graal.compiler.java.BytecodeParser.genPutField(BytecodeParser.java:4924)
	at jdk.graal.compiler/jdk.graal.compiler.java.BytecodeParser.processBytecode(BytecodeParser.java:5465)
	at jdk.graal.compiler/jdk.graal.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3473)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.iterateBytecodesForBlock(SharedGraphBuilderPhase.java:790)
	at jdk.graal.compiler/jdk.graal.compiler.java.BytecodeParser.handleBytecodeBlock(BytecodeParser.java:3433)
	at jdk.graal.compiler/jdk.graal.compiler.java.BytecodeParser.processBlock(BytecodeParser.java:3275)
	at jdk.graal.compiler/jdk.graal.compiler.java.BytecodeParser.build(BytecodeParser.java:1136)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.build(SharedGraphBuilderPhase.java:202)
	at jdk.graal.compiler/jdk.graal.compiler.java.BytecodeParser.buildRootMethod(BytecodeParser.java:1028)
	at jdk.graal.compiler/jdk.graal.compiler.java.GraphBuilderPhase$Instance.run(GraphBuilderPhase.java:102)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase.run(SharedGraphBuilderPhase.java:154)
	at jdk.graal.compiler/jdk.graal.compiler.phases.Phase.run(Phase.java:49)
	at jdk.graal.compiler/jdk.graal.compiler.phases.BasePhase.apply(BasePhase.java:435)
	at jdk.graal.compiler/jdk.graal.compiler.phases.Phase.apply(Phase.java:42)
	at jdk.graal.compiler/jdk.graal.compiler.phases.Phase.apply(Phase.java:38)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.AnalysisParsedGraph.parseBytecode(AnalysisParsedGraph.java:144)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisMethod.parseGraph(AnalysisMethod.java:888)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisMethod.ensureGraphParsedHelper(AnalysisMethod.java:853)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisMethod.ensureGraphParsed(AnalysisMethod.java:836)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.phases.InlineBeforeAnalysisGraphDecoder.lookupEncodedGraph(InlineBeforeAnalysisGraphDecoder.java:198)
	at jdk.graal.compiler/jdk.graal.compiler.replacements.PEGraphDecoder.doInline(PEGraphDecoder.java:1215)
	at jdk.graal.compiler/jdk.graal.compiler.replacements.PEGraphDecoder.tryInline(PEGraphDecoder.java:1198)
	at jdk.graal.compiler/jdk.graal.compiler.replacements.PEGraphDecoder.trySimplifyInvoke(PEGraphDecoder.java:1053)
	at jdk.graal.compiler/jdk.graal.compiler.replacements.PEGraphDecoder.handleInvokeWithCallTarget(PEGraphDecoder.java:1005)
	at jdk.graal.compiler/jdk.graal.compiler.replacements.PEGraphDecoder.handleInvoke(PEGraphDecoder.java:991)
	at jdk.graal.compiler/jdk.graal.compiler.nodes.GraphDecoder.processNextNode(GraphDecoder.java:930)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.phases.InlineBeforeAnalysisGraphDecoder.processNextNode(InlineBeforeAnalysisGraphDecoder.java:377)
	at jdk.graal.compiler/jdk.graal.compiler.nodes.GraphDecoder.decode(GraphDecoder.java:658)
	at jdk.graal.compiler/jdk.graal.compiler.replacements.PEGraphDecoder.decode(PEGraphDecoder.java:895)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.phases.InlineBeforeAnalysis.decodeGraph(InlineBeforeAnalysis.java:73)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.parse(MethodTypeFlowBuilder.java:198)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.apply(MethodTypeFlowBuilder.java:608)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.createFlowsGraph(MethodTypeFlow.java:167)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.ensureFlowsGraphCreated(MethodTypeFlow.java:152)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.getOrCreateMethodFlowsGraphInfo(MethodTypeFlow.java:110)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.DefaultAnalysisPolicy.staticRootMethodGraph(DefaultAnalysisPolicy.java:209)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.PointsToAnalysis.lambda$addRootMethod$0(PointsToAnalysis.java:337)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.AbstractAnalysisEngine$1.run(AbstractAnalysisEngine.java:333)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:169)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:154)
	at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute(ForkJoinTask.java:1726)
	at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute(ForkJoinTask.java:1717)
	at java.base/java.util.concurrent.ForkJoinTask$InterruptibleTask.exec(ForkJoinTask.java:1641)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:507)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1489)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:2071)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2033)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187)

@gsmet
Copy link
Member

gsmet commented Jul 22, 2024

I agree we should ideally be in line with what was done before.

@quarkus-bot

This comment has been minimized.

@gcw-it
Copy link
Contributor Author

gcw-it commented Jul 22, 2024

If everything is in order, I will squash the commits.
I kept them separate for now, to make it possible to monitor the changes.

@gcw-it
Copy link
Contributor Author

gcw-it commented Jul 23, 2024

After digging a bit deeper into the codebase, I found the culprit for the strange GraalVM build time exception.

The runtime package of the liquibase extension uses a GraalVM substitution (liquibase.runtime.graal.SubstituteEnvironmentValueProvider), that fixes an issue on Windows (#22449).

This substitution deletes a field, that is later referenced by the default constructor, hence the DeletedElementException.

Substituting the constructor leads only to a temporary relief. The build is now successful, but at runtime a NullPointerException is thrown. It appears that the substitution of the constructor also removes/prevents the initialisation of some fields of the parent class AbstractMapConfigurationValueProvider. In this case the ReentrantLock knownValuesLock is null, which causes the NullPointerException. Explicitly calling super() from the substituted constructor makes no difference.

We could limit the application of the substitution to the Windows platform, but on my Windows machine (Windows 10 22H2 19045 4651, GraalVM 21.02+13.1), the error DeletedElementException occurs as well.
On the other hand, after removing the SubstituteEnvironmentValueProvider the build succeeds.

Maybe the upgrade to liquibase 4.27.0 helped, or newer GraalVM versions remediated problem #22449, but it seems, the patch isn't necessary anymore. I'm not entirely sure if the patch was necessary at all in the latest Quarkus versions, because the targeted class wasn't even included in the native image.

Ideally we could remove the SubstituteEnvironmentValueProvider , because GraalVM substitutions are inherently brittle.

Would the CI-Pipeline pick it up, if we introduce a regression by removing the patch?

Copy link
Member

@gsmet gsmet left a comment

Choose a reason for hiding this comment

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

I think it's worth trying to drop the substitution and see how it goes.

One thing we need to do is to check if the quickstarts work: https://github.com/quarkusio/quarkus-quickstarts . You need to get the develop branch so that the quickstart points to 999-SNAPSHOT and run the specific liquibase quickstart with -Dnative. It has been failing for a while and I wonder if your patch would fix it: https://github.com/quarkusio/quarkus-quickstarts/actions/runs/10087017755/job/27890486199 .

If not, it's probably worth investigating. It won't block this PR though as I really want it in soon.

As for testing your patch on Windows, you could add the liquibase IT there: https://github.com/quarkusio/quarkus/blob/main/.github/native-tests.json#L135-L140 and it would then be run on Windows too (we don't run all the native tests on Windows).

@@ -105,10 +113,11 @@ IndexDependencyBuildItem indexLiquibase() {
@BuildStep(onlyIf = NativeOrNativeSourcesBuild.class)
@Record(STATIC_INIT)
void nativeImageConfiguration(
LiquibaseRecorder recorder,
LiquibaseRecorder ignored,
Copy link
Member

Choose a reason for hiding this comment

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

I think you can drop this parameter and the @Record annotation if we don't need them.

@gsmet
Copy link
Member

gsmet commented Jul 25, 2024

FWIW, someone just complained about the issue we see in the quickstarts: https://quarkusio.zulipchat.com/#narrow/stream/187038-dev/topic/Native.20Image.20Issue.20with.20quarkus-liquibase .

@quarkus-bot

This comment has been minimized.

@gcw-it
Copy link
Contributor Author

gcw-it commented Jul 25, 2024

One thing we need to do is to check if the quickstarts work

Sorry, that I wasn't really clear. I already built the liquibase-quickstart successfully on windows, without the substitution. I just wasn't sure, if there could be other problematic areas.

I will remove the recorder, and add the liquibase IT.

Would you prefer the commits being squashed, or separate for now?

@gsmet
Copy link
Member

gsmet commented Jul 25, 2024

I think you can add two more semantic commits for these two changes as they are not entirely related to your changes.

@quarkus-bot quarkus-bot bot added the area/infra-automation anything related to CI, bots, etc. that are used to automated our infrastructure label Jul 25, 2024
@gsmet
Copy link
Member

gsmet commented Jul 25, 2024

@gcw-it
Copy link
Contributor Author

gcw-it commented Jul 25, 2024

I wonder, if in a next step it would be a good idea, to extract the functionality, to automatically find the resource paths in a dependency, to a utility class.

At least the liquibase-mongodb extension seems to suffer from a similar problem as the liquibase extension and could benefit from it. Maybe there are other extensions as well?

@gsmet
Copy link
Member

gsmet commented Jul 25, 2024

Yeah so I can see how the Liquibase MongoDB extension would suffer from the same issue and probably needs the same fix.

I wouldn't generalize things too much though and use this approach when it's not risky at all (typically, versioned XSD resources makes perfect sense, blinding adding all services might not be what we want to do).

Let's get this in first though.

@gcw-it
Copy link
Contributor Author

gcw-it commented Jul 25, 2024

I agree with you, that we should concentrate on this fix first.

My proposal wasn't intended to be included in this PR, but further down the road

I also don't want to automate registering resources for a native build, that should remain the prerogative of the extension.
What a utility class could offer, is that given dependency coordinates and a base path, it returns a list of available resource paths at the given location, to be included in the native image at the extensions discretion.

This would simply extract some common functionality to avoid code duplication.

@gsmet
Copy link
Member

gsmet commented Jul 25, 2024

Yes, it makes perfect sense.

@gsmet gsmet added the triage/waiting-for-ci Ready to merge when CI successfully finishes label Jul 25, 2024
@quarkus-bot
Copy link

quarkus-bot bot commented Jul 25, 2024

Status for workflow Quarkus CI

This is the status report for running Quarkus CI on commit a75588a.

✅ The latest workflow run for the pull request has completed successfully.

It should be safe to merge provided you have a look at the other checks in the summary.

You can consult the Develocity build scans.


Flaky tests - Develocity

⚙️ JVM Tests - JDK 17

📦 integration-tests/opentelemetry

io.quarkus.it.opentelemetry.OpenTelemetryInjectionsTest.testOTelInjections - History

  • Condition with Lambda expression in io.quarkus.it.opentelemetry.OpenTelemetryInjectionsTest was not fulfilled within 5 seconds. - org.awaitility.core.ConditionTimeoutException
org.awaitility.core.ConditionTimeoutException: Condition with Lambda expression in io.quarkus.it.opentelemetry.OpenTelemetryInjectionsTest was not fulfilled within 5 seconds.
	at org.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:167)
	at org.awaitility.core.CallableCondition.await(CallableCondition.java:78)
	at org.awaitility.core.CallableCondition.await(CallableCondition.java:26)
	at org.awaitility.core.ConditionFactory.until(ConditionFactory.java:1006)
	at org.awaitility.core.ConditionFactory.until(ConditionFactory.java:975)
	at io.quarkus.it.opentelemetry.OpenTelemetryInjectionsTest.reset(OpenTelemetryInjectionsTest.java:26)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)

⚙️ JVM Tests - JDK 21

📦 integration-tests/opentelemetry

io.quarkus.it.opentelemetry.OpenTelemetryInjectionsTest.testOTelInjections - History

  • Condition with Lambda expression in io.quarkus.it.opentelemetry.OpenTelemetryInjectionsTest was not fulfilled within 5 seconds. - org.awaitility.core.ConditionTimeoutException
org.awaitility.core.ConditionTimeoutException: Condition with Lambda expression in io.quarkus.it.opentelemetry.OpenTelemetryInjectionsTest was not fulfilled within 5 seconds.
	at org.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:167)
	at org.awaitility.core.CallableCondition.await(CallableCondition.java:78)
	at org.awaitility.core.CallableCondition.await(CallableCondition.java:26)
	at org.awaitility.core.ConditionFactory.until(ConditionFactory.java:1006)
	at org.awaitility.core.ConditionFactory.until(ConditionFactory.java:975)
	at io.quarkus.it.opentelemetry.OpenTelemetryInjectionsTest.reset(OpenTelemetryInjectionsTest.java:26)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)

⚙️ JVM Tests - JDK 17 Windows

📦 integration-tests/grpc-hibernate

com.example.grpc.hibernate.BlockingRawTest.shouldAdd - History

  • Condition with Lambda expression in com.example.grpc.hibernate.BlockingRawTestBase was not fulfilled within 30 seconds. - org.awaitility.core.ConditionTimeoutException
org.awaitility.core.ConditionTimeoutException: Condition with Lambda expression in com.example.grpc.hibernate.BlockingRawTestBase was not fulfilled within 30 seconds.
	at org.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:167)
	at org.awaitility.core.CallableCondition.await(CallableCondition.java:78)
	at org.awaitility.core.CallableCondition.await(CallableCondition.java:26)
	at org.awaitility.core.ConditionFactory.until(ConditionFactory.java:1006)
	at org.awaitility.core.ConditionFactory.until(ConditionFactory.java:975)
	at com.example.grpc.hibernate.BlockingRawTestBase.shouldAdd(BlockingRawTestBase.java:59)
	at java.base/java.lang.reflect.Method.invoke(Method.java:569)

@gsmet gsmet merged commit abdb621 into quarkusio:main Jul 25, 2024
52 checks passed
@quarkus-bot quarkus-bot bot added kind/bugfix and removed triage/waiting-for-ci Ready to merge when CI successfully finishes labels Jul 25, 2024
@quarkus-bot quarkus-bot bot added this to the 3.14 - main milestone Jul 25, 2024
@gsmet
Copy link
Member

gsmet commented Jul 25, 2024

And merged, thanks a lot for this fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/infra-automation anything related to CI, bots, etc. that are used to automated our infrastructure area/liquibase kind/bugfix triage/flaky-test
Projects
None yet
3 participants