Skip to content

Commit

Permalink
Adds diffLink macro to core. Fix #1539. (#1540)
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreaLaGrotteria authored Oct 29, 2024
1 parent bbcc6cd commit ff50863
Show file tree
Hide file tree
Showing 37 changed files with 307 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -613,10 +613,9 @@ class GuideAsciidocGenerator {
}

private static String buildDiffLink(String line, GuidesOption guidesOption, Guide metadata) {

String appName = extractAppName(line) ?: DEFAULT_APP_NAME
App app = metadata.apps().find { it.name() == appName }
String link = 'https://micronaut.io/launch?' +
return 'https://micronaut.io/launch?' +
featureNames(line, app, guidesOption).collect { 'features=' + it }.join('&') +
'&lang=' + guidesOption.language.name() +
'&build=' + guidesOption.buildTool.name() +
Expand All @@ -625,10 +624,7 @@ class GuideAsciidocGenerator {
'&type=' + app.applicationType().name() +
'&package=example.micronaut' +
'&activity=diff' +
'[view the dependency and configuration changes from the specified features, window="_blank"]'

"NOTE: If you have an existing Micronaut application and want to add the functionality described here, you can " +
link + " and apply those changes to your application."
'[Diff, window="_blank"]'
}

private static String processGuideLink(String line) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package io.micronaut.guides.core;

import io.micronaut.guides.core.asciidoc.AsciidocMacro;
import io.micronaut.guides.core.asciidoc.Attribute;
import io.micronaut.http.uri.UriBuilder;
import io.micronaut.starter.application.ApplicationType;
import jakarta.inject.Singleton;
import java.net.URI;
import java.util.*;
import static io.micronaut.guides.core.MacroUtils.*;

@Singleton
public class BuildDiffLinkSubstitution implements MacroSubstitution {
private static final String QUERY_PARAMLANG = "lang";
private static final String QUERY_PARAM_BUILD = "build";
private static final String QUERY_PARAM_TEST = "test";
private static final String QUERY_PARAM_NAME = "name";
private static final String QUERY_PARAM_TYPE = "type";
private static final String QUERY_PARAM_PACKAGE = "package";
private static final String QUERY_PARAM_ACTIVITY = "activity";
private static final String QUERY_PARAM_FEATURES = "features";
public static final String MACRO_DIFF_LINK = "diffLink";
private static final String ATTRIBUTE_FEATURES = "features";
private static final String ATTRIBUTE_EXCLUDE_FEATURES = "featureExcludes";
private final GuidesConfiguration guidesConfiguration;

public BuildDiffLinkSubstitution(GuidesConfiguration config) {
this.guidesConfiguration = config;
}

@Override
public String substitute(String str, Guide guide, GuidesOption option) {
for(String line : findMacroLines(str, MACRO_DIFF_LINK)) {
Optional<AsciidocMacro> asciidocMacroOptional = AsciidocMacro.of(MACRO_DIFF_LINK, line);
if (asciidocMacroOptional.isEmpty()) {
continue;
}
AsciidocMacro asciidocMacro = asciidocMacroOptional.get();
String res = buildDiffLink(asciidocMacro, guide, option).toString() + "[Diff]";
str = str.replace(line,res);
}
return str;
}

private URI buildDiffLink(AsciidocMacro asciidocMacro, Guide guide, GuidesOption option) {
String appName = appName(asciidocMacro);
App app = app(guide, asciidocMacro);
Set<String> features = features(app, asciidocMacro, option);
UriBuilder uriBuilder = UriBuilder.of(guidesConfiguration.getProjectGeneratorUrl())
.queryParam(QUERY_PARAMLANG, option.getLanguage().name())
.queryParam(QUERY_PARAM_BUILD, option.getBuildTool().name())
.queryParam(QUERY_PARAM_TEST, option.getTestFramework().name())
.queryParam(QUERY_PARAM_NAME, appName.equals(guidesConfiguration.getDefaultAppName()) ? "micronautguide" : appName)
.queryParam(QUERY_PARAM_TYPE, app != null ? app.applicationType().name() : ApplicationType.DEFAULT.name())
.queryParam(QUERY_PARAM_PACKAGE, guidesConfiguration.getPackageName())
.queryParam(QUERY_PARAM_ACTIVITY, "diff");
features.forEach(f -> uriBuilder.queryParam(QUERY_PARAM_FEATURES, f));
return uriBuilder.build();
}

private static Set<String> features(App app, AsciidocMacro asciidocMacro, GuidesOption option) {
Set<String> features = new HashSet<>();
if (app != null) {
features.addAll(GuideUtils.getAppVisibleFeatures(app, option.getLanguage()));
}
asciidocMacro.attributes().stream()
.filter(attribute -> attribute.key().equals(ATTRIBUTE_FEATURES))
.map(Attribute::values)
.forEach(features::addAll);
asciidocMacro.attributes().stream()
.filter(attribute -> attribute.key().equals(ATTRIBUTE_EXCLUDE_FEATURES))
.map(Attribute::values)
.forEach(features::removeAll);
return features;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@Singleton
public class DependencyMacroSubstitution implements MacroSubstitution{
@Override
public String substitute(String str, String slug, GuidesOption option) {
public String substitute(String str, Guide guide, GuidesOption option) {
for(String block : findMacroGroups(str, "dependencies")){
List<String> lines = DependencyLines.asciidoc(block.replace(":dependencies:","").strip().lines().toList(), option.getBuildTool(), option.getLanguage());
str = str.replace(block,String.join("\n", lines));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ public interface GuidesConfiguration {
String getTitle();
String getLicensePath();
String getPackageName();
String getDefaultAppName();
String getProjectGeneratorUrl();
List<String> getFilesWithHeader();
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public class GuidesConfigurationProperties implements GuidesConfiguration {
private String licensePath = DEFAULT_LICENSEHEADER;
private String packageName = DEFAULT_PACKAGE_NAME;
private List<String> sourceFilesExtensions = List.of("java", "kotlin", "groovy");
private static final String DEFAULT_APP_NAME = "default";
private static final String HOMEPAGE_URL = "https://micronaut.io";
private static final String LAUNCHER_URL = HOMEPAGE_URL + "/launch";

@Override
public String getPackageName() {
Expand Down Expand Up @@ -52,6 +55,14 @@ public void setTitle(String title) {
this.title = title;
}

@Override
public String getDefaultAppName() {
return DEFAULT_APP_NAME;
}

@Override
public String getProjectGeneratorUrl() { return LAUNCHER_URL; }

@Override
public List<String> getFilesWithHeader() {
return sourceFilesExtensions;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
package io.micronaut.guides.core;

import io.micronaut.core.annotation.NonNull;
import io.micronaut.guides.core.asciidoc.AsciidocMacro;
import io.micronaut.guides.core.asciidoc.Attribute;

public interface MacroSubstitution {
String APP = "app";
String APP_NAME_DEFAULT = "default";

@NonNull
String substitute(@NonNull String str, @NonNull String slug, @NonNull GuidesOption option);
String substitute(@NonNull String str, @NonNull Guide guide, @NonNull GuidesOption option);

default App app(Guide guide, AsciidocMacro asciidocMacro) {
final String appName = appName(asciidocMacro);
return guide.apps().stream()
.filter(a -> a.name().equals(appName))
.findFirst()
.orElseThrow(() -> new RuntimeException("app not found for app name" + appName));
}

default String appName(AsciidocMacro asciidocMacro) {
return asciidocMacro.attributes().stream()
.filter(attribute -> attribute.key().equals(APP))
.map(Attribute::values)
.filter(l -> !l.isEmpty())
.map(l -> l.get(0))
.findFirst()
.orElse(APP_NAME_DEFAULT);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.micronaut.guides.core;

import io.micronaut.core.annotation.NonNull;

import java.util.ArrayList;
import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.jetbrains.annotations.NotNull;

import java.nio.file.Path;
import java.util.List;
import java.util.Optional;

import static io.micronaut.guides.core.MacroUtils.*;
Expand Down Expand Up @@ -35,18 +36,13 @@ public GuidesConfiguration getGuidesConfiguration() {
}

@Override
public String substitute(String str, String slug, GuidesOption option) {
public String substitute(String str, Guide guide, GuidesOption option) {
String slug = guide.slug();
for (String line : findMacroLines(str, getMacroName())) {
Optional<AsciidocMacro> asciidocMacroOptional = AsciidocMacro.of(getMacroName(), line);
if (asciidocMacroOptional.isPresent()) {
AsciidocMacro asciidocMacro = asciidocMacroOptional.get();
String appName = asciidocMacro.attributes().stream()
.filter(attribute -> attribute.key().equals(APP))
.map(Attribute::values)
.filter(l -> !l.isEmpty())
.map(l -> l.get(0))
.findFirst()
.orElse(APP);
String appName = appName(asciidocMacro);

String condensedTarget = condensedTarget(asciidocMacro, option);
String[] arr;
Expand Down Expand Up @@ -105,7 +101,7 @@ protected String sourceTitle(
Classpath classpath,
String language,
String packageName) {
return (appName.equals(MacroSubstitution.APP) ? "" : (appName + "/")) + sourceConventionFolder(classpath, language) + "/"
return (appName.equals(MacroSubstitution.APP_NAME_DEFAULT) ? "" : (appName + "/")) + sourceConventionFolder(classpath, language) + "/"
+ (getFileType() == FileType.CODE ? (packageName.replace(".", "/") + "/") : "")
+ condensedTarget;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package io.micronaut.guides.core;

import io.micronaut.core.beans.BeanIntrospection;
import io.micronaut.core.io.ResourceLoader;
import io.micronaut.http.uri.UriBuilder;
import io.micronaut.json.JsonMapper;
import io.micronaut.starter.api.TestFramework;
import io.micronaut.starter.options.BuildTool;
import io.micronaut.starter.options.Language;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;

import java.io.InputStream;
import java.net.URI;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

@MicronautTest(startApplication = false)
class BuildDiffLinkSubstitutionTest {
@Inject
BuildDiffLinkSubstitution buildDiffLinkSubstitution;

@Inject
JsonMapper jsonMapper;

@Inject
ResourceLoader resourceLoader;

@Test
void testSubstitute(){
assertDoesNotThrow(() -> BeanIntrospection.getIntrospection(Guide.class));
Optional<InputStream> inputStreamOptional = resourceLoader.getResourceAsStream("classpath:metadata-diff.json");
assertTrue(inputStreamOptional.isPresent());
final InputStream inputStreamBase = inputStreamOptional.get();
Guide guide = assertDoesNotThrow(() -> jsonMapper.readValue(inputStreamBase, Guide.class));
String str = "diffLink:[app=cli]";
String resJava = buildDiffLinkSubstitution.substitute(str, guide, new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.JUNIT));
URI expectedURI = UriBuilder.of("https://micronaut.io")
.path("launch")
.queryParam("lang", "JAVA")
.queryParam("build", "GRADLE")
.queryParam("test", "JUNIT")
.queryParam("name", "cli")
.queryParam("type", "CLI")
.queryParam("package", "example.micronaut")
.queryParam("activity", "diff")
.queryParam("features", "awaitility")
.queryParam("features", "graalvm")
.queryParam("features", "mqtt")
.queryParam("features", "yaml")
.build();
String expectedJava = expectedURI.toString() + "[Diff]";
assertEquals(expectedJava, resJava);

str = "diffLink:[app=cli,featureExcludes=graalvm]";
resJava = buildDiffLinkSubstitution.substitute(str, guide, new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.JUNIT));
expectedURI = UriBuilder.of("https://micronaut.io")
.path("launch")
.queryParam("lang", "JAVA")
.queryParam("build", "GRADLE")
.queryParam("test", "JUNIT")
.queryParam("name", "cli")
.queryParam("type", "CLI")
.queryParam("package", "example.micronaut")
.queryParam("activity", "diff")
.queryParam("features", "awaitility")
.queryParam("features", "mqtt")
.queryParam("features", "yaml")
.build();
expectedJava = expectedURI.toString() + "[Diff]";
assertEquals(expectedJava, resJava);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void testSubstitute(){
dependency:micronaut-security-session[groupId=io.micronaut.security]
""";

String resJava = dependencyMacroSubstitution.substitute(str, "micronaut-jaxrs", new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.SPOCK));
String resJava = dependencyMacroSubstitution.substitute(str, GuideTestUtils.guideWithSlug("micronaut-jaxrs"), new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.SPOCK));
String expectedJava = """
==== Dependencies
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.micronaut.guides.core;

import java.util.List;
import java.util.Map;

public final class GuideTestUtils {
private GuideTestUtils() {
}

public static Guide guideWithSlug(String slug) {
return new Guide("", "", List.of(), List.of(), null, 0, 0, null, null, null, "", List.of(), List.of(), List.of(), null, List.of(), slug, null, "", Map.of(), List.of());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void testSubstitute() {
rawTest:HomePage[]
""";
String resJava = rawTestMacroSubstitution.substitute(str, "micronaut-security-jwt-cookie", new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.SPOCK));
String resJava = rawTestMacroSubstitution.substitute(str, GuideTestUtils.guideWithSlug("micronaut-security-jwt-cookie"), new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.SPOCK));
String expectedJava = """
Create three pages:
Expand All @@ -32,7 +32,7 @@ void testSubstitute() {
----
""";
assertEquals(expectedJava, resJava);
String resKotlin = rawTestMacroSubstitution.substitute(str, "micronaut-security-jwt-cookie", new GuidesOption(BuildTool.GRADLE, Language.KOTLIN, TestFramework.SPOCK));
String resKotlin = rawTestMacroSubstitution.substitute(str, GuideTestUtils.guideWithSlug("micronaut-security-jwt-cookie"), new GuidesOption(BuildTool.GRADLE, Language.KOTLIN, TestFramework.SPOCK));
String expectedKotlin = """
Create three pages:
Expand All @@ -43,7 +43,7 @@ void testSubstitute() {
----
""";
assertEquals(expectedKotlin, resKotlin);
String resGroovy = rawTestMacroSubstitution.substitute(str, "micronaut-security-jwt-cookie", new GuidesOption(BuildTool.GRADLE, Language.GROOVY, TestFramework.SPOCK));
String resGroovy = rawTestMacroSubstitution.substitute(str, GuideTestUtils.guideWithSlug("micronaut-security-jwt-cookie"), new GuidesOption(BuildTool.GRADLE, Language.GROOVY, TestFramework.SPOCK));
String expectedGroovy = """
Create three pages:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ResourceMacroSubstitutionTest {
@Test
void testSubstitute() {
String str = "resource:../../../ttfr.sh[]";
String resJava = resourceMacroSubstitution.substitute(str, "executable-jar", new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.JUNIT));
String resJava = resourceMacroSubstitution.substitute(str, GuideTestUtils.guideWithSlug("executable-jar"), new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.JUNIT));
String expectedJava = """
[source,sh]
.ttfr.sh
Expand All @@ -31,7 +31,7 @@ void testSubstitute() {
@Test
void testSubstituteWithTags() {
String str = "resource:application.yml[tag=endpoints]";
String resJava = resourceMacroSubstitution.substitute(str, "adding-commit-info", new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.JUNIT));
String resJava = resourceMacroSubstitution.substitute(str, GuideTestUtils.guideWithSlug("adding-commit-info"), new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.JUNIT));
String expectedJava = """
[source,yaml]
.src/main/resources/application.yml
Expand All @@ -52,7 +52,7 @@ void testMultiLineInput(){
resource:test.yml[tag=security,app=testApp]
""";
String resJava = resourceMacroSubstitution.substitute(str, "adding-commit-info", new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.JUNIT));
String resJava = resourceMacroSubstitution.substitute(str, GuideTestUtils.guideWithSlug("adding-commit-info"), new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.JUNIT));
String expectedJava = """
The `git.properties` file that is generated by the `gradle-git-properties` plugin
will not be accessible from the native executable unless access to the file is
Expand Down
Loading

0 comments on commit ff50863

Please sign in to comment.