diff --git a/docs/src/main/asciidoc/extension-metadata.adoc b/docs/src/main/asciidoc/extension-metadata.adoc index 37eac75061fbe..3c66b792d8ad2 100644 --- a/docs/src/main/asciidoc/extension-metadata.adoc +++ b/docs/src/main/asciidoc/extension-metadata.adoc @@ -84,12 +84,13 @@ metadata: artifact: "io.quarkus:quarkus-project-core-extension-codestarts::jar:999-SNAPSHOT" config: - "quarkus.rest." - built-with-quarkus-core: "999-SNAPSHOT" <1> - capabilities: <2> + built-with-quarkus-core: "3.8.5" <1> + requires-quarkus-core: "[3.8,)" <2> + capabilities: <3> provides: - "io.quarkus.rest" - "io.quarkus.resteasy.reactive" - extension-dependencies: <3> + extension-dependencies: <4> - "io.quarkus:quarkus-rest-common" - "io.quarkus:quarkus-mutiny" - "io.quarkus:quarkus-smallrye-context-propagation" @@ -101,17 +102,18 @@ metadata: - "io.quarkus:quarkus-jsonp" description: "A Jakarta REST implementation utilizing build time processing and Vert.x.\ \ This extension is not compatible with the quarkus-resteasy extension, or any of\ - \ the extensions that depend on it." <4> -scm-url: "https://github.com/quarkusio/quarkus" <5> -sponsor: A Sponsoring Organisation <6> + \ the extensions that depend on it." <5> +scm-url: "https://github.com/quarkusio/quarkus" <6> +sponsor: A Sponsoring Organisation <7> ---- <1> Quarkus version the extension was built with -<2> https://quarkus.io/guides/capabilities[Capabilities] this extension provides -<3> Direct dependencies on other extensions -<4> Description that can be displayed to users. In this case, the description was copied from the `pom.xml` of the extension module but it could also be provided in the template file. -<5> The source code repository of this extension. Optional, and will often be set automatically using the `` information in the pom. In GitHub Actions builds, it will be inferred from the CI environment. For other GitHub repositories, it can be controlled by setting a `GITHUB_REPOSITORY` environment variable. -<6> The sponsor(s) of this extension. Optional, and will sometimes be determined automatically from commit history. +<2> The Quarkus version range this extension requires. Optional, and will be set automatically by using the `built-with-quarkus-core` as the minimum range. +<3> https://quarkus.io/guides/capabilities[Capabilities] this extension provides +<4> Direct dependencies on other extensions +<5> Description that can be displayed to users. In this case, the description was copied from the `pom.xml` of the extension module but it could also be provided in the template file. +<6> The source code repository of this extension. Optional, and will often be set automatically by using the `` information in the pom. In GitHub Actions builds, it will be inferred from the CI environment. For other GitHub repositories, it can be controlled by setting a `GITHUB_REPOSITORY` environment variable. +<7> The sponsor(s) of this extension. Optional, and will sometimes be determined automatically from commit history. [[quarkus-extension-properties]] == META-INF/quarkus-extension.properties diff --git a/independent-projects/extension-maven-plugin/src/main/java/io/quarkus/maven/ExtensionDescriptorMojo.java b/independent-projects/extension-maven-plugin/src/main/java/io/quarkus/maven/ExtensionDescriptorMojo.java index 0ae05193c4cb1..61fdffab18d13 100644 --- a/independent-projects/extension-maven-plugin/src/main/java/io/quarkus/maven/ExtensionDescriptorMojo.java +++ b/independent-projects/extension-maven-plugin/src/main/java/io/quarkus/maven/ExtensionDescriptorMojo.java @@ -20,6 +20,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.execution.MavenSession; import org.apache.maven.model.Scm; import org.apache.maven.plugin.AbstractMojo; @@ -243,6 +244,12 @@ public static class RemovedResources { @Parameter(defaultValue = "${maven.compiler.release}", readonly = true) String minimumJavaVersion; + /** + * The Quarkus core version range that this extension requires + */ + @Parameter(property = "requiresQuarkusCore") + String requiresQuarkusCore; + ArtifactCoords deploymentCoords; CollectResult collectedDeploymentDeps; DependencyResult runtimeDeps; @@ -290,6 +297,9 @@ public void execute() throws MojoExecutionException { } } + String quarkusCoreVersion = findQuarkusCoreVersion(); + String quarkusCoreVersionRange = requiresQuarkusCore == null ? toVersionRange(quarkusCoreVersion) : requiresQuarkusCore; + final Properties props = new Properties(); props.setProperty(BootstrapConstants.PROP_DEPLOYMENT_ARTIFACT, deployment); @@ -386,6 +396,9 @@ public void execute() throws MojoExecutionException { props.put(ApplicationModelBuilder.LESSER_PRIORITY_ARTIFACTS, val); } + if (quarkusCoreVersionRange != null) { + props.put("requires-quarkus-version", quarkusCoreVersionRange); + } final Path output = outputDirectory.toPath().resolve(BootstrapConstants.META_INF); try { Files.createDirectories(output); @@ -457,7 +470,8 @@ public void execute() throws MojoExecutionException { extObject.put("description", project.getDescription()); } - setBuiltWithQuarkusCoreVersion(extObject); + setBuiltWithQuarkusCoreVersion(quarkusCoreVersion, extObject); + setRequiresQuarkusCoreVersion(quarkusCoreVersionRange, extObject); addJavaVersion(extObject); addCapabilities(extObject); addSource(extObject); @@ -477,6 +491,21 @@ public void execute() throws MojoExecutionException { } } + private void setRequiresQuarkusCoreVersion(String compatibilityRange, ObjectNode extObject) { + ObjectNode metadata = getMetadataNode(extObject); + if (!metadata.has("requires-quarkus-core") && compatibilityRange != null) { + metadata.put("requires-quarkus-core", compatibilityRange); + } + } + + private static String toVersionRange(String version) { + if (version == null) { + return null; + } + DefaultArtifactVersion dav = new DefaultArtifactVersion(version); + return "[" + dav.getMajorVersion() + "." + dav.getMinorVersion() + ",)"; + } + private void ensureArtifactCoords(ObjectNode extObject) { String groupId = null; String artifactId = null; @@ -606,7 +635,16 @@ private static void appendCapability(CapabilityConfig capability, StringBuilder } } - private void setBuiltWithQuarkusCoreVersion(ObjectNode extObject) throws MojoExecutionException { + private void setBuiltWithQuarkusCoreVersion(String coreVersion, ObjectNode extObject) throws MojoExecutionException { + if (coreVersion != null) { + ObjectNode metadata = getMetadataNode(extObject); + metadata.put("built-with-quarkus-core", coreVersion); + } else if (!ignoreNotDetectedQuarkusCoreVersion) { + throw new MojoExecutionException("Failed to determine the Quarkus core version used to build the extension"); + } + } + + private String findQuarkusCoreVersion() throws MojoExecutionException { final QuarkusCoreDeploymentVersionLocator coreVersionLocator = new QuarkusCoreDeploymentVersionLocator(); final DependencyNode root; try { @@ -617,13 +655,7 @@ private void setBuiltWithQuarkusCoreVersion(ObjectNode extObject) throws MojoExe throw new MojoExecutionException("Failed to collect runtime dependencies of " + project.getArtifact(), e); } root.accept(coreVersionLocator); - if (coreVersionLocator.coreVersion != null) { - ObjectNode metadata = getMetadataNode(extObject); - metadata.put("built-with-quarkus-core", coreVersionLocator.coreVersion); - } else if (!ignoreNotDetectedQuarkusCoreVersion) { - throw new MojoExecutionException("Failed to determine the Quarkus core version used to build the extension"); - } - + return coreVersionLocator.coreVersion; } private void addExtensionDependencies(ObjectNode extObject) throws MojoExecutionException { @@ -845,9 +877,9 @@ private void validateExtensionDeps() throws MojoExecutionException { if (buf.length() > 0) { buf.append(System.lineSeparator()); } - buf.append("The deployment artifact " + rootDeploymentGact - + " depends on the following Quarkus extension runtime artifacts that weren't found among the dependencies of " - + project.getArtifact() + ":"); + buf.append("The deployment artifact ").append(rootDeploymentGact).append( + " depends on the following Quarkus extension runtime artifacts that weren't found among the dependencies of ") + .append(project.getArtifact()).append(":"); for (ArtifactKey a : unexpectedRtDeps) { buf.append(' ').append(a); } @@ -861,9 +893,9 @@ private void validateExtensionDeps() throws MojoExecutionException { if (buf.length() > 0) { buf.append(System.lineSeparator()); } - buf.append("The deployment artifact " + rootDeploymentGact - + " depends on the following Quarkus extension deployment artifacts whose corresponding runtime artifacts were not found among the dependencies of " - + project.getArtifact() + ":"); + buf.append("The deployment artifact ").append(rootDeploymentGact).append( + " depends on the following Quarkus extension deployment artifacts whose corresponding runtime artifacts were not found among the dependencies of ") + .append(project.getArtifact()).append(":"); for (ArtifactKey a : unexpectedDeploymentDeps) { buf.append(' ').append(a); } @@ -908,9 +940,7 @@ private void highlightInTree(int depth, DependencyNode node, Collection collectMissingDeploymentDeps(Log log) { collected.add(n.gact); } buf.append(' '); - for (int i = 0; i < depth; ++i) { - buf.append(" "); - } + buf.append(" ".repeat(Math.max(0, depth))); buf.append(n.gact); log1.error(buf.toString()); }); @@ -1276,9 +1304,7 @@ List collectDeploymentsOnRtCp(Log log) { collected.add(n.gact); } buf.append(' '); - for (int i = 0; i < depth; ++i) { - buf.append(" "); - } + buf.append(" ".repeat(Math.max(0, depth))); buf.append(n.gact); log1.error(buf.toString()); }); @@ -1297,7 +1323,7 @@ private void handleChildren(Log log, int depth, List collected, Nod } } - private static interface NodeHandler { + private interface NodeHandler { void handle(Log log, int depth, Node n, List collected); }