Skip to content

Commit

Permalink
An option to resolve only the runtime part of the ApplicationModel
Browse files Browse the repository at this point in the history
  • Loading branch information
aloubyansky committed Oct 29, 2024
1 parent 4b6211c commit 227776a
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ public class DependencySbomMojo extends AbstractMojo {
@Parameter(property = "quarkus.dependency.sbom.schema-version")
String schemaVersion;

/**
* Whether to limit application dependencies to only those that are included in the runtime
*/
@Parameter(property = "quarkus.dependency.sbom.runtime-only")
boolean runtimeOnly;

protected MavenArtifactResolver resolver;

@Override
Expand Down Expand Up @@ -111,7 +117,8 @@ private ApplicationModel resolveApplicationModel()
project.getVersion());
final BootstrapAppModelResolver modelResolver;
try {
modelResolver = new BootstrapAppModelResolver(getResolver());
modelResolver = new BootstrapAppModelResolver(getResolver())
.setRuntimeModelOnly(runtimeOnly);
if (mode != null) {
if (mode.equalsIgnoreCase("test")) {
modelResolver.setTest(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ public class DependencyTreeMojo extends AbstractMojo {
@Parameter(property = "appendOutput", required = false, defaultValue = "false")
boolean appendOutput;

/**
* Whether to log only the runtime dependencies of the Quarkus application
*/
@Parameter(property = "runtimeOnly")
boolean runtimeOnly;

protected MavenArtifactResolver resolver;

@Override
Expand Down Expand Up @@ -134,7 +140,8 @@ private void logTree(final Consumer<String> log) throws MojoExecutionException {
project.getVersion());
final BootstrapAppModelResolver modelResolver;
try {
modelResolver = new BootstrapAppModelResolver(resolver());
modelResolver = new BootstrapAppModelResolver(resolver())
.setRuntimeModelOnly(runtimeOnly);
if (mode != null) {
if (mode.equalsIgnoreCase("test")) {
modelResolver.setTest(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.quarkus.maven;

import io.quarkus.bootstrap.resolver.TsArtifact;
import io.quarkus.bootstrap.resolver.TsQuarkusExt;

public class ConditionalDependencyTreeMojoRuntimeOnlyTest extends DependencyTreeMojoTestBase {
@Override
protected String mode() {
return "prod";
}

@Override
protected boolean isIncubatingModelResolver() {
return true;
}

@Override
protected boolean isRuntimeOnly() {
return true;
}

@Override
protected void initRepo() {

final TsQuarkusExt coreExt = new TsQuarkusExt("test-core-ext");

var tomatoExt = new TsQuarkusExt("quarkus-tomato").addDependency(coreExt);
var mozzarellaExt = new TsQuarkusExt("quarkus-mozzarella").addDependency(coreExt);
var basilExt = new TsQuarkusExt("quarkus-basil").addDependency(coreExt);

var oilJar = TsArtifact.jar("quarkus-oil");

var capreseExt = new TsQuarkusExt("quarkus-caprese")
.setDependencyCondition(tomatoExt, mozzarellaExt, basilExt)
.addDependency(coreExt);
capreseExt.getDeployment().addDependency(oilJar);
capreseExt.install(repoBuilder);

var saladExt = new TsQuarkusExt("quarkus-salad")
.setConditionalDeps(capreseExt)
.addDependency(coreExt);

app = TsArtifact.jar("app-with-conditional-deps")
.addDependency(tomatoExt)
.addDependency(mozzarellaExt)
.addDependency(basilExt)
.addDependency(saladExt)
.addDependency(oilJar);

appModel = app.getPomModel();
app.install(repoBuilder);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ protected boolean isIncubatingModelResolver() {
return false;
}

protected boolean isRuntimeOnly() {
return false;
}

@Test
public void test() throws Exception {

Expand All @@ -81,6 +85,7 @@ public void test() throws Exception {
mojo.resolver = mvnResolver;
mojo.mode = mode();
mojo.graph = isGraph();
mojo.runtimeOnly = isRuntimeOnly();

final Path mojoLog = workDir.resolve(getClass().getName() + ".log");
final PrintStream defaultOut = System.out;
Expand All @@ -92,8 +97,12 @@ public void test() throws Exception {
System.setOut(defaultOut);
}

String expectedFileName = app.getArtifactFileName() + "." + mode();
if (isRuntimeOnly()) {
expectedFileName += ".rt";
}
assertThat(mojoLog).hasSameTextualContentAs(
Path.of("").normalize().toAbsolutePath()
.resolve("target").resolve("test-classes").resolve(app.getArtifactFileName() + "." + mode()));
.resolve("target").resolve("test-classes").resolve(expectedFileName));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[info] Quarkus application PROD mode build dependency tree:
[info] io.quarkus.bootstrap.test:app-with-conditional-deps:pom:1
[info] ├─ io.quarkus.bootstrap.test:quarkus-tomato:1 (compile)
[info] │ └─ io.quarkus.bootstrap.test:test-core-ext:1 (compile)
[info] ├─ io.quarkus.bootstrap.test:quarkus-mozzarella:1 (compile)
[info] ├─ io.quarkus.bootstrap.test:quarkus-basil:1 (compile)
[info] ├─ io.quarkus.bootstrap.test:quarkus-salad:1 (compile)
[info] │ └─ io.quarkus.bootstrap.test:quarkus-caprese:1 (compile)
[info] └─ io.quarkus.bootstrap.test:quarkus-oil:1 (compile)
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package io.quarkus.bootstrap.resolver.test;

import io.quarkus.bootstrap.resolver.BootstrapAppModelResolver;
import io.quarkus.bootstrap.resolver.CollectDependenciesBase;
import io.quarkus.bootstrap.resolver.TsArtifact;
import io.quarkus.bootstrap.resolver.TsQuarkusExt;
import io.quarkus.bootstrap.resolver.maven.workspace.LocalProject;
import io.quarkus.maven.dependency.DependencyFlags;

public class RuntimeOnlyApplicationModelTestCase extends CollectDependenciesBase {

private static final boolean runtimeOnly = true;

@Override
protected BootstrapAppModelResolver newAppModelResolver(LocalProject currentProject) throws Exception {
var resolver = super.newAppModelResolver(currentProject);
resolver.setIncubatingModelResolver(false);
resolver.setRuntimeModelOnly(runtimeOnly);
return resolver;
}

@Override
protected void setupDependencies() {

final TsQuarkusExt extA = new TsQuarkusExt("ext-a");
install(extA, false);
if (!runtimeOnly) {
addCollectedDeploymentDep(extA.getDeployment());
}

installAsDep(extA.getRuntime(),
DependencyFlags.DIRECT
| DependencyFlags.RUNTIME_EXTENSION_ARTIFACT
| DependencyFlags.TOP_LEVEL_RUNTIME_EXTENSION_ARTIFACT);

final TsQuarkusExt extB = new TsQuarkusExt("ext-b");
install(extB, false);

final TsQuarkusExt extC = new TsQuarkusExt("ext-c");
extC.setDependencyCondition(extB);
install(extC, false);

final TsQuarkusExt extD = new TsQuarkusExt("ext-d");
install(extD, false);
installAsDep(extD.getRuntime(),
DependencyFlags.DIRECT
| DependencyFlags.RUNTIME_EXTENSION_ARTIFACT
| DependencyFlags.TOP_LEVEL_RUNTIME_EXTENSION_ARTIFACT);
if (!runtimeOnly) {
addCollectedDeploymentDep(extD.getDeployment());
}

final TsArtifact libE = TsArtifact.jar("lib-e");
install(libE, true);
final TsArtifact libEBuildTIme = TsArtifact.jar("lib-e-build-time");
install(libEBuildTIme);
if (!runtimeOnly) {
addCollectedDeploymentDep(libEBuildTIme);
}

final TsQuarkusExt extE = new TsQuarkusExt("ext-e");
extE.setDependencyCondition(extD);
extE.getRuntime().addDependency(libE);
extE.getDeployment().addDependency(libEBuildTIme);
install(extE, false);
addCollectedDep(extE.getRuntime(), DependencyFlags.RUNTIME_EXTENSION_ARTIFACT);
if (!runtimeOnly) {
addCollectedDeploymentDep(extE.getDeployment());
}

final TsQuarkusExt extF = new TsQuarkusExt("ext-f");
extF.setConditionalDeps(extC, extE);
install(extF, false);
installAsDep(extF.getRuntime(),
DependencyFlags.DIRECT
| DependencyFlags.RUNTIME_EXTENSION_ARTIFACT
| DependencyFlags.TOP_LEVEL_RUNTIME_EXTENSION_ARTIFACT);
if (!runtimeOnly) {
addCollectedDeploymentDep(extF.getDeployment());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public class BootstrapAppModelResolver implements AppModelResolver {
protected boolean test;
private boolean collectReloadableDeps = true;
private boolean incubatingModelResolver;
private boolean runtimeModelOnly;

public BootstrapAppModelResolver(MavenArtifactResolver mvn) {
this.mvn = mvn;
Expand Down Expand Up @@ -110,6 +111,11 @@ public BootstrapAppModelResolver setCollectReloadableDependencies(boolean collec
return this;
}

public BootstrapAppModelResolver setRuntimeModelOnly(boolean runtimeModelOnly) {
this.runtimeModelOnly = runtimeModelOnly;
return this;
}

public void addRemoteRepositories(List<RemoteRepository> repos) {
mvn.addRemoteRepositories(repos);
}
Expand Down Expand Up @@ -371,6 +377,7 @@ private ApplicationModel buildAppModel(ResolvedDependencyBuilder appArtifact,
.setCollectReloadableModules(collectReloadableDeps && reloadableModules.isEmpty())
.setCollectCompileOnly(filteredProvidedDeps)
.setDependencyLogging(depLogConfig)
.setRuntimeModelOnly(runtimeModelOnly)
.resolve(collectRtDepsRequest);
} else {
ApplicationDependencyTreeResolver.newInstance()
Expand All @@ -379,6 +386,7 @@ private ApplicationModel buildAppModel(ResolvedDependencyBuilder appArtifact,
.setCollectReloadableModules(collectReloadableDeps && reloadableModules.isEmpty())
.setCollectCompileOnly(filteredProvidedDeps)
.setBuildTreeConsumer(depLogConfig == null ? null : depLogConfig.getMessageConsumer())
.setRuntimeModelOnly(runtimeModelOnly)
.resolve(collectRtDepsRequest);
}
if (logTime) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public static Artifact getRuntimeArtifact(DependencyNode dep) {
private boolean collectReloadableModules;
private Consumer<String> buildTreeConsumer;
private List<Dependency> collectCompileOnly;
private boolean runtimeModelOnly;

public ApplicationDependencyTreeResolver setArtifactResolver(MavenArtifactResolver resolver) {
this.resolver = resolver;
Expand Down Expand Up @@ -139,6 +140,11 @@ public ApplicationDependencyTreeResolver setCollectCompileOnly(List<Dependency>
return this;
}

public ApplicationDependencyTreeResolver setRuntimeModelOnly(boolean runtimeModelOnly) {
this.runtimeModelOnly = runtimeModelOnly;
return this;
}

public void resolve(CollectRequest collectRtDepsRequest) throws AppModelResolverException {

this.managedDeps = collectRtDepsRequest.getManagedDependencies();
Expand Down Expand Up @@ -202,13 +208,15 @@ public void resolve(CollectRequest collectRtDepsRequest) throws AppModelResolver
}
}

for (ExtensionDependency extDep : topExtensionDeps) {
injectDeploymentDependencies(extDep);
}
if (!runtimeModelOnly) {
for (ExtensionDependency extDep : topExtensionDeps) {
injectDeploymentDependencies(extDep);
}

if (!activatedConditionalDeps.isEmpty()) {
for (ConditionalDependency cd : activatedConditionalDeps) {
injectDeploymentDependencies(cd.getExtensionDependency());
if (!activatedConditionalDeps.isEmpty()) {
for (ConditionalDependency cd : activatedConditionalDeps) {
injectDeploymentDependencies(cd.getExtensionDependency());
}
}
}

Expand All @@ -231,7 +239,9 @@ public void resolve(CollectRequest collectRtDepsRequest) throws AppModelResolver
}

collectPlatformProperties();
collectCompileOnly(collectRtDepsRequest, root);
if (!runtimeModelOnly) {
collectCompileOnly(collectRtDepsRequest, root);
}
}

/**
Expand Down Expand Up @@ -886,7 +896,7 @@ void activate() {
return;
}
activated = true;
clearWalkingFlag(COLLECT_TOP_EXTENSION_RUNTIME_NODES);
clearWalkingFlag((byte) (COLLECT_DIRECT_DEPS | COLLECT_TOP_EXTENSION_RUNTIME_NODES));
final ExtensionDependency extDep = getExtensionDependency();
final DependencyNode originalNode = collectDependencies(info.runtimeArtifact, extDep.exclusions,
extDep.runtimeNode.getRepositories());
Expand Down
Loading

0 comments on commit 227776a

Please sign in to comment.