Skip to content

Commit

Permalink
chore: show warning when LC is missing in a DAU build (#20036) (#20039)
Browse files Browse the repository at this point in the history
* chore: show warning when LC is missing in a DAU build

In a DAU build, checks if license-checker will be present at runtime and
prints a warning message with instructions to fix the configuration if
it the dependency is missing.

* Apply suggestions from code review



---------

Co-authored-by: Marco Collovati <marco@vaadin.com>
Co-authored-by: Tomi Virtanen <tltv@vaadin.com>
  • Loading branch information
3 people authored Sep 24, 2024
1 parent c01cdbb commit d641601
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,21 @@
import java.nio.file.Paths;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;

import com.vaadin.flow.component.dependency.JavaScript;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
Expand All @@ -42,15 +53,6 @@
import com.vaadin.flow.server.frontend.installer.Platform;
import com.vaadin.flow.server.frontend.scanner.ClassFinder;
import com.vaadin.flow.theme.Theme;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;

import static com.vaadin.flow.server.Constants.VAADIN_SERVLET_RESOURCES;
import static com.vaadin.flow.server.Constants.VAADIN_WEBAPP_RESOURCES;
Expand Down Expand Up @@ -461,4 +463,10 @@ public boolean isReactEnabled() {
public String applicationIdentifier() {
return project.getGroupId() + ":" + project.getArtifactId();
}

@Override
public boolean checkRuntimeDependency(String groupId, String artifactId,
Consumer<String> missingDependencyMessageConsumer) {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import org.gradle.api.tasks.bundling.War
import java.io.File
import java.net.URI
import java.nio.file.Path
import java.util.function.Consumer

private val servletApiJarRegex = Regex(".*(/|\\\\)(portlet-api|javax\\.servlet-api)-.+jar$")

Expand Down Expand Up @@ -216,4 +217,26 @@ internal class GradlePluginAdapter(
override fun isReactEnabled(): Boolean = config.reactEnable.get()

override fun applicationIdentifier(): String = config.applicationIdentifier.get()

override fun checkRuntimeDependency(
groupId: String,
artifactId: String,
missingDependencyMessageConsumer: Consumer<String>?
): Boolean {
val dependencyAbsent = project.configurations.getByName(config.dependencyScope.get())
.resolvedConfiguration?.resolvedArtifacts?.filter {
groupId == it.moduleVersion.id.group && artifactId == it.moduleVersion.id.name
}?.isEmpty() ?: true
if (dependencyAbsent && missingDependencyMessageConsumer != null) {
missingDependencyMessageConsumer.accept("""
The dependency ${groupId}:${artifactId} has not been found in the project configuration.
Please add the following dependency to your project configuration:
dependencies {
runtimeOnly("${groupId}:${artifactId}")
}
""".trimIndent())
}
return dependencyAbsent
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@

import java.io.File;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
Expand Down Expand Up @@ -233,4 +237,50 @@ public boolean compressBundle() {
return true;
}

@Override
public boolean checkRuntimeDependency(String groupId, String artifactId,
Consumer<String> missingDependencyMessage) {
Objects.requireNonNull(groupId, "groupId cannot be null");
Objects.requireNonNull(artifactId, "artifactId cannot be null");
if (missingDependencyMessage == null) {
missingDependencyMessage = text -> {
};
}

List<Artifact> deps = project.getArtifacts().stream()
.filter(artifact -> groupId.equals(artifact.getGroupId())
&& artifactId.equals(artifact.getArtifactId()))
.toList();
if (deps.isEmpty()) {
missingDependencyMessage.accept(String.format(
"""
The dependency %1$s:%2$s has not been found in the project configuration.
Please add the following dependency to your POM file:
<dependency>
<groupId>%1$s</groupId>
<artifactId>%2$s</artifactId>
<scope>runtime</scope>
</dependency>
""",
groupId, artifactId));
return false;
} else if (deps.stream().noneMatch(artifact -> !artifact.isOptional()
&& artifact.getArtifactHandler().isAddedToClasspath()
&& (Artifact.SCOPE_COMPILE.equals(artifact.getScope())
|| Artifact.SCOPE_PROVIDED.equals(artifact.getScope())
|| Artifact.SCOPE_RUNTIME
.equals(artifact.getScope())))) {
missingDependencyMessage.accept(String.format(
"""
The dependency %1$s:%2$s has been found in the project configuration,
but with a scope that does not guarantee its presence at runtime.
Please check that the dependency has 'compile', 'provided' or 'runtime' scope.
To check the current dependency scope, you can run 'mvn dependency:tree -Dincludes=%1$s:%2$s'
""",
groupId, artifactId));
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,7 @@ public static void updateBuildFile(PluginAdapterBuild adapter,
if (LocalSubscriptionKey.get() != null) {
adapter.logInfo("Daily Active User tracking enabled");
buildInfo.put(Constants.DAU_TOKEN, true);
checkLicenseCheckerAtRuntime(adapter);
}
}
if (isControlCenterAvailable(adapter.getClassFinder())
Expand Down Expand Up @@ -795,6 +796,18 @@ private static boolean isControlCenterAvailable(ClassFinder classFinder) {
}
}

private static void checkLicenseCheckerAtRuntime(
PluginAdapterBuild adapter) {
adapter.checkRuntimeDependency("com.vaadin", "license-checker",
logMessage -> adapter.logWarn(
"""
Vaadin Subscription used to build the application requires
the artifact com.vaadin:license-checker to be present at runtime.
"""
+ logMessage));
}

/**
* Delete the build token file. This is used with dev-bundle build as token
* file should never be added to the package.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
package com.vaadin.flow.plugin.base;

import java.io.File;

import com.vaadin.flow.server.InitParameters;
import java.util.function.Consumer;

/**
* Gives access to plugin-specific implementations and configurations.
Expand Down Expand Up @@ -95,4 +94,28 @@ public interface PluginAdapterBuild extends PluginAdapterBase {
* @return {@code true} if the bundle should be compressed
*/
boolean compressBundle();

/**
* Checks if the artifact defined by given coordinates is a dependency of
* the project, present at runtime.
* <p>
* </p>
* If the dependency is missing or in invalid scope, the method produces a
* message containing the necessary instructions to fix the project and
* notifies the caller by invoking the provided message consumer, if
* present.
*
* @param groupId
* dependency groupId, not {@literal null}.
* @param artifactId
* dependency artifactId, not {@literal null}.
* @param missingDependencyMessageConsumer
* a consumer for missing dependency message produced by the
* adapter.
* @return {@literal true} if the given coordinates identify a project
* dependency present at runtime, otherwise {@literal false}.
*/
boolean checkRuntimeDependency(String groupId, String artifactId,
Consumer<String> missingDependencyMessageConsumer);

}

0 comments on commit d641601

Please sign in to comment.