Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
<netty.version>4.1.130.Final</netty.version>
<brotli4j.version>1.16.0</brotli4j.version>
<reactive-streams.version>1.0.4</reactive-streams.version>
<jboss-logging.version>3.6.2.Final</jboss-logging.version>
<jboss-logging.version>3.6.3.Final</jboss-logging.version>
<mutiny.version>3.1.1</mutiny.version>
<jctools-core.version>4.0.5</jctools-core.version>
<kafka.version>4.1.1</kafka.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import io.quarkus.bootstrap.BootstrapConstants;
import io.quarkus.bootstrap.model.ApplicationModel;
import io.quarkus.gradle.tasks.EffectiveConfig;
import io.quarkus.gradle.tasks.EffectiveConfigProvider;
import io.quarkus.gradle.tasks.QuarkusPluginExtensionView;
import io.quarkus.gradle.tooling.ToolingUtils;
Expand Down Expand Up @@ -63,8 +64,10 @@ public void execute(Task t) {
final Path serializedModel = applicationModelPath.get().getAsFile().toPath();
ApplicationModel applicationModel = ToolingUtils.deserializeAppModel(serializedModel);

SmallRyeConfig config = effectiveProvider().buildEffectiveConfiguration(applicationModel, new HashMap<>())
.getConfig();
EffectiveConfig effectiveConfig = effectiveProvider().buildEffectiveConfiguration(applicationModel,
new HashMap<>());
SmallRyeConfig config = effectiveConfig.getConfig();
props.putAll(effectiveConfig.getQuarkusValues());
config.getOptionalValue(TEST.getProfileKey(), String.class)
.ifPresent(value -> props.put(TEST.getProfileKey(), value));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@
import io.quarkus.deployment.pkg.PackageConfig;
import io.quarkus.runtime.configuration.ConfigUtils;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.DefaultValuesConfigSource;
import io.smallrye.config.Expressions;
import io.smallrye.config.PropertiesConfigSource;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SysPropConfigSource;
import io.smallrye.config.source.yaml.YamlConfigSourceLoader;

/**
Expand Down Expand Up @@ -118,45 +120,67 @@ private Map<String, String> asStringMap(Map<String, ?> map) {

@VisibleForTesting
static Map<String, String> generateFullConfigMap(SmallRyeConfig config) {
Set<String> defaultNames = new HashSet<>();
defaultNames.addAll(configClass(PackageConfig.class).getProperties().keySet());
defaultNames.addAll(configClass(NativeConfig.class).getProperties().keySet());
Set<String> excludeNames = new HashSet<>();
excludeNames.addAll(configClass(PackageConfig.class).getProperties().keySet());
excludeNames.addAll(configClass(NativeConfig.class).getProperties().keySet());
return Expressions.withoutExpansion(new Supplier<Map<String, String>>() {
@Override
public Map<String, String> get() {
Map<String, String> properties = new HashMap<>();
for (String propertyName : config.getPropertyNames()) {
ConfigValue configValue = config.getConfigValue(propertyName);
// Remove defaults coming from PackageConfig and NativeConfig, as this Map as passed as
// system properties to Gradle workers and, we loose the ability to determine if it was set by
// the user to evaluate deprecated configuration
if (configValue.getValue() != null && (!defaultNames.contains(configValue.getName())
|| !configValue.isDefault())) {
properties.put(propertyName, configValue.getValue());
if (configValue.getValue() != null) {
// Exclude defaults coming from PackageConfig and NativeConfig, as this Map as passed as
// system properties to Gradle workers and, we loose the ability to determine if it was set by
// the user to evaluate deprecated configuration
if (!excludeNames.contains(configValue.getName()) || !configValue.isDefault()) {
properties.put(propertyName, configValue.getValue());
}
}
}
return unmodifiableMap(properties);
}
});
}

/**
* Constructs a Map with the list of Quarkus property names that must be propagated to the Gradle workers.
* <p>
* This only takes into account the configuration that is not already available in Quarkus, including properties
* provided by Gradle tasks or files. System Properties are also included, since Gradle workers run on a separate
* VM that does not have access to the original System Properties set by the process.
* <p>
* Environment Variables do not require propagation, since all workers can the Environment. Configuration files
* like {@code application.properties} are already available in Quarkus, so we can skip them as well.
*/
static Map<String, String> generateQuarkusConfigMap(SmallRyeConfig config) {
Set<String> defaultNames = new HashSet<>();
defaultNames.addAll(configClass(PackageConfig.class).getProperties().keySet());
defaultNames.addAll(configClass(NativeConfig.class).getProperties().keySet());
Set<String> excludeNames = new HashSet<>();
excludeNames.addAll(configClass(PackageConfig.class).getProperties().keySet());
excludeNames.addAll(configClass(NativeConfig.class).getProperties().keySet());
Set<String> propagateSources = new HashSet<>();
propagateSources.add("PropertiesConfigSource[source=forcedProperties]");
propagateSources.add("PropertiesConfigSource[source=taskProperties]");
propagateSources.add("PropertiesConfigSource[source=quarkusBuildProperties]");
propagateSources.add("PropertiesConfigSource[source=projectProperties]");
propagateSources.add("PropertiesConfigSource[source=platformProperties]");
propagateSources.add(SysPropConfigSource.NAME);
// It may look weird to include default values, but we do it because of EffectiveConfigProvider#buildEffectiveConfiguration
propagateSources.add(DefaultValuesConfigSource.NAME);
return Expressions.withoutExpansion(new Supplier<Map<String, String>>() {
@Override
public Map<String, String> get() {
Map<String, String> properties = new HashMap<>();
for (String propertyName : config.getPropertyNames()) {
if (propertyName.startsWith("quarkus.") || propertyName.startsWith("platform.quarkus.")) {
ConfigValue configValue = config.getConfigValue(propertyName);
// Remove defaults coming from PackageConfig and NativeConfig, as this Map as passed as
// system properties to Gradle workers and, we loose the ability to determine if it was set by
// the user to evaluate deprecated configuration
if (configValue.getValue() != null && (!defaultNames.contains(configValue.getName())
|| !configValue.isDefault())) {
properties.put(propertyName, configValue.getValue());
// Only propagate properties from sources not available in Quarkus
if (configValue.getValue() != null && propagateSources.contains(configValue.getConfigSourceName())) {
// Exclude defaults coming from PackageConfig and NativeConfig, as this Map as passed as
// system properties to Gradle workers and, we loose the ability to determine if it was set by
// the user to evaluate deprecated configuration
if (!excludeNames.contains(configValue.getName()) || !configValue.isDefault()) {
properties.put(propertyName, configValue.getValue());
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions docs/src/main/asciidoc/dev-mcp.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ BuildTimeActionBuildItem createBuildTimeActions() {
<3> Set a human‑readable description.
<4> Provide the runtime value returned by your recorder.

By default this resource will be disabled, and the user has to enable it in Dev UI. You can change this default by adding `.enableMcpFuctionByDefault()` in the builder method.
By default this resource will be disabled, and the user has to enable it in Dev UI. You can change this default by adding `.enableMcpFunctionByDefault()` in the builder method.

=== MCP tools

Expand Down Expand Up @@ -159,7 +159,7 @@ BuildTimeActionBuildItem createBuildTimeActions() {

The code in the `function` runs on the deployment classpath. The function can return a plain value, a `CompletionStage` or `CompletableFuture` for asynchronous work.

By default this tool will be disabled, and the user has to enable it in Dev UI. You can change this default by adding `.enableMcpFuctionByDefault()` in the builder method.
By default this tool will be disabled, and the user has to enable it in Dev UI. You can change this default by adding `.enableMcpFunctionByDefault()` in the builder method.

=== JSON‑RPC usage

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,19 @@ public ActionBuilder usage(EnumSet<Usage> usage) {
return this;
}

public ActionBuilder enableMcpFuctionByDefault() {
public ActionBuilder enableMcpFunctionByDefault() {
this.mcpEnabledByDefault = true;
return this;
}

/**
* @deprecated Use {@link #enableMcpFunctionByDefault()} instead.
*/
@Deprecated(forRemoval = true)
public ActionBuilder enableMcpFuctionByDefault() {
return enableMcpFunctionByDefault();
}

public <T> ActionBuilder function(Function<Map<String, String>, T> function) {
if (this.runtimeValue != null || this.assistantFunction != null)
throw new IllegalStateException("Only one of runtimeValue, function or assistantFunction is allowed");
Expand Down Expand Up @@ -245,11 +253,19 @@ public SubscriptionBuilder usage(EnumSet<Usage> usage) {
return this;
}

public SubscriptionBuilder enableMcpFuctionByDefault() {
public SubscriptionBuilder enableMcpFunctionByDefault() {
this.mcpEnabledByDefault = true;
return this;
}

/**
* @deprecated Use {@link #enableMcpFunctionByDefault()} instead.
*/
@Deprecated(forRemoval = true)
public SubscriptionBuilder enableMcpFuctionByDefault() {
return enableMcpFunctionByDefault();
}

public <T> SubscriptionBuilder function(Function<Map<String, String>, T> function) {
this.function = function;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void registerBuildTimeActions(BuildProducer<BuildTimeActionBuildItem> buildTimeA
RuntimeUpdatesProcessor.INSTANCE.doScan(true, true);
return Map.of();
})
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();

keyStrokeActions.actionBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ void registerBuildTimeActions(
updateConfig(name, value, profile, target);
return true;
})
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();

configActions.actionBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ private void registerStartMethod(LaunchModeBuildItem launchModeBuildItem, BuildT
throw new RuntimeException(e);
}
})
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();
}

Expand All @@ -139,7 +139,7 @@ private void registerStopMethod(LaunchModeBuildItem launchModeBuildItem, BuildTi
throw new RuntimeException(e);
}
})
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();
}

Expand All @@ -160,7 +160,7 @@ private void registerRunAllMethod(LaunchModeBuildItem launchModeBuildItem, Build
throw new RuntimeException(e);
}
})
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();
}

Expand Down Expand Up @@ -262,7 +262,7 @@ private void registerGetStatusMethod(LaunchModeBuildItem launchModeBuildItem, Bu
throw new RuntimeException(e);
}
})
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();
}

Expand All @@ -282,7 +282,7 @@ private void registerGetResultsMCPMethod(LaunchModeBuildItem launchModeBuildItem
actions.actionBuilder()
.methodName("getTestResults")
.description("Get the results of a Continuous testing test run")
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.function(ignored -> {
TestRunResults continuousTestingResults = continuousTestingResults(launchModeBuildItem);
if (continuousTestingResults != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ private void getDevServices(BuildTimeActionBuildItem buildTimeActions,
.function(ignored -> CompletableFuture.supplyAsync(() -> getServices(devServiceDescriptions, otherDevServices)))
.description(
"Get all the DevServices started by this Quarkus app, including information on container (if any) and the config that is being set automatically")
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ private void listInstallableExtensions(BuildTimeActionBuildItem buildTimeActions
return filtered;
});
})
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();
}

Expand Down Expand Up @@ -221,7 +221,7 @@ private void removeExtension(BuildTimeActionBuildItem buildTimeActions) {
}
});
})
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();
}

Expand All @@ -247,7 +247,7 @@ private void addExtension(BuildTimeActionBuildItem buildTimeActions) {
}
});
})
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ void createBuildTimeActions(Optional<WorkspaceBuildItem> workspaceBuildItem,
.function((t) -> {
return workspaceBuildItem.get().getWorkspaceItems();
})
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();

buildItemActions.actionBuilder()
Expand Down Expand Up @@ -251,7 +251,7 @@ void createBuildTimeActions(Optional<WorkspaceBuildItem> workspaceBuildItem,
}
return null;
})
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();

buildItemActions.actionBuilder()
Expand All @@ -270,7 +270,7 @@ void createBuildTimeActions(Optional<WorkspaceBuildItem> workspaceBuildItem,
}
return new SavedResult(null, false, "Invalid input");
})
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build();

buildTimeActionProducer.produce(buildItemActions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,18 +248,25 @@ private boolean isEmptyValue(String value) {
}

private String getBuildTimeDataConstValue(String jsContent, String constName) {
String patternString = "export const " + Pattern.quote(constName) + "\\s*=\\s*([^;]+);";
Pattern pattern = Pattern.compile(patternString, Pattern.DOTALL);
// Match the full value including any semicolons inside JSON strings.
// Values are always on a single physical line (newlines are escaped in JSON strings).
String patternString = "export const " + Pattern.quote(constName) + "\\s*=\\s*(.+)";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(jsContent);

if (matcher.find()) {
return matcher.group(1).trim();
String value = matcher.group(1).trim();
// Strip the trailing semicolon
if (value.endsWith(";")) {
value = value.substring(0, value.length() - 1).trim();
}
return value;
}

return "Error: Data not found for " + constName;
}

private static final Pattern BTD_PATTERN = Pattern.compile("export const (\\w+)\\s*=\\s*([^;]+);", Pattern.DOTALL);
private static final Pattern BTD_PATTERN = Pattern.compile("export const (\\w+)\\s*=\\s*(.+)");

private static final String URI_SCHEME = "quarkus://resource/";
private static final String SUB_SCHEME_BUILD_TIME = "build-time/";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ RouteBuildItem defineRoute(InfoBuildTimeConfig buildTimeConfig,
"Information about the environment where this Quarkus application is running. "
+ "Things like Operating System, Java version Git information and application details is available")
.runtime(finalBuildInfo)
.enableMcpFuctionByDefault()
.enableMcpFunctionByDefault()
.build());

return RouteBuildItem.newManagementRoute(buildTimeConfig.path())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class SmallryeJwtDevModeProcessor {
private static final Logger LOGGER = Logger.getLogger(SmallryeJwtDevModeProcessor.class);

public static final String MP_JWT_VERIFY_PUBLIC_KEY = "mp.jwt.verify.publickey";
public static final String SMALLRYE_JWT_VERIFY_KEY_LOCATION = "smallrye.jwt.verify.key.location";
private static final String MP_JWT_VERIFY_ISSUER = "mp.jwt.verify.issuer";
private static final String SMALLRYE_JWT_DECRYPT_KEY = "smallrye.jwt.decrypt.key"; // no MP equivalent
private static final String MP_JWT_DECRYPT_KEY_LOCATION = "mp.jwt.decrypt.key.location";
Expand All @@ -54,6 +55,7 @@ public class SmallryeJwtDevModeProcessor {

private static final Set<String> JWT_SIGN_KEY_PROPERTIES = Set.of(
MP_JWT_VERIFY_KEY_LOCATION,
SMALLRYE_JWT_VERIFY_KEY_LOCATION,
MP_JWT_VERIFY_PUBLIC_KEY,
SMALLRYE_JWT_DECRYPT_KEY,
MP_JWT_DECRYPT_KEY_LOCATION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.test.QuarkusUnitTest;

public class SmallryeJwtLocationDevModeTest {
public class SmallryeJwtEncryptLocationDevModeTest {

@RegisterExtension
static QuarkusUnitTest unitTest = new QuarkusUnitTest()
Expand Down
Loading
Loading