diff --git a/docs/src/main/asciidoc/deploying-to-kubernetes.adoc b/docs/src/main/asciidoc/deploying-to-kubernetes.adoc index 100ad90fe3abe0..1a88f7badbb5a8 100644 --- a/docs/src/main/asciidoc/deploying-to-kubernetes.adoc +++ b/docs/src/main/asciidoc/deploying-to-kubernetes.adoc @@ -3,9 +3,10 @@ This guide is maintained in the main Quarkus repository and pull requests should be submitted there: https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc //// +[id="deploy-kubernetes"] = Kubernetes extension include::_attributes.adoc[] -:categories: cloud +:categories: cloud, native :summary: This guide covers how to deploy a native application on Kubernetes. Quarkus offers the ability to automatically generate Kubernetes resources based on sane defaults and user-supplied configuration using https://github.com/dekorateio/dekorate/[dekorate]. diff --git a/docs/src/main/asciidoc/deploying-to-openshift.adoc b/docs/src/main/asciidoc/deploying-to-openshift.adoc index 5768aa7f4a0de4..97283afc18cea8 100644 --- a/docs/src/main/asciidoc/deploying-to-openshift.adoc +++ b/docs/src/main/asciidoc/deploying-to-openshift.adoc @@ -3,9 +3,10 @@ This guide is maintained in the main Quarkus repository and pull requests should be submitted there: https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc //// +[id="deploy-openshift"] = Deploying on OpenShift include::_attributes.adoc[] -:categories: cloud +:categories: cloud, native :summary: This guide covers how to deploy a native application on OpenShift. This guide covers generating and deploying OpenShift resources based on sane default and user supplied configuration. diff --git a/docs/src/main/asciidoc/getting-started-testing.adoc b/docs/src/main/asciidoc/getting-started-testing.adoc index 50673af86f6d6e..31421ab89e6f28 100644 --- a/docs/src/main/asciidoc/getting-started-testing.adoc +++ b/docs/src/main/asciidoc/getting-started-testing.adoc @@ -3,9 +3,10 @@ This guide is maintained in the main Quarkus repository and pull requests should be submitted there: https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc //// +[id="testing"] = Testing Your Application include::_attributes.adoc[] -:categories: core +:categories: core, native, tooling :summary: This guide covers testing in JVM mode, native mode, and injection of resources into tests :numbered: :sectnums: diff --git a/docs/src/main/asciidoc/gradle-tooling.adoc b/docs/src/main/asciidoc/gradle-tooling.adoc index 1ee21accf7085c..1c4bbdefc7697f 100644 --- a/docs/src/main/asciidoc/gradle-tooling.adoc +++ b/docs/src/main/asciidoc/gradle-tooling.adoc @@ -3,12 +3,15 @@ This guide is maintained in the main Quarkus repository and pull requests should be submitted there: https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc //// -= Building Quarkus apps with Gradle +[id="gradle-tooling"] += Quarkus and Gradle include::_attributes.adoc[] -:categories: tooling -:summary: This guide covers: Gradle configuration, creating a new project, dealing with extensions, development mode, debugging, import in your IDE, building a native image, and build a container friendly executable +:categories: tooling, native +:summary: Develop and build your Quarkus application with Gradle :devtools-no-maven: +Use Gradle to create a new project, add or remove extensions, launch development mode, debug your application, and build your application into a jar, native executable, or container-friendly executable. Import your project into your favorite IDE using Gradle project metadata. + [[project-creation]] == Creating a new project diff --git a/docs/src/main/asciidoc/maven-tooling.adoc b/docs/src/main/asciidoc/maven-tooling.adoc index 50cfb25486352f..6e4e0abafdd521 100644 --- a/docs/src/main/asciidoc/maven-tooling.adoc +++ b/docs/src/main/asciidoc/maven-tooling.adoc @@ -3,12 +3,15 @@ This guide is maintained in the main Quarkus repository and pull requests should be submitted there: https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc //// -= Building applications with Maven +[id="maven-tooling"] += Quarkus and Maven include::_attributes.adoc[] -:categories: tooling -:summary: This guide covers: Maven configuration, creating a new project, dealing with extensions, development mode, debugging, import in your IDE, building a native image, and build a container friendly executable +:categories: tooling, native +:summary: Develop and build your Quarkus application with Maven :devtools-no-gradle: +Use Maven to create a new project, add or remove extensions, launch development mode, debug your application, and build your application into a jar, native executable, or container-friendly executable. Import your project into your favorite IDE using Maven project metadata. + [[project-creation]] == Creating a new project diff --git a/docs/src/main/asciidoc/native-reference.adoc b/docs/src/main/asciidoc/native-reference.adoc index e1c406f6d05bd9..fe22ee7b82e7f4 100644 --- a/docs/src/main/asciidoc/native-reference.adoc +++ b/docs/src/main/asciidoc/native-reference.adoc @@ -3,8 +3,8 @@ This guide is maintained in the main Quarkus repository and pull requests should be submitted there: https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc //// +[id="native-reference"] = Native Reference Guide - include::_attributes.adoc[] :categories: native diff --git a/docs/src/main/java/io/quarkus/docs/generation/YamlMetadataGenerator.java b/docs/src/main/java/io/quarkus/docs/generation/YamlMetadataGenerator.java index f7b6a52138f0f0..582b5c7b00f244 100644 --- a/docs/src/main/java/io/quarkus/docs/generation/YamlMetadataGenerator.java +++ b/docs/src/main/java/io/quarkus/docs/generation/YamlMetadataGenerator.java @@ -47,7 +47,7 @@ * */ public class YamlMetadataGenerator { - private static Errors errors = new Errors(); + private static Messages messages = new Messages(); final static String INCL_ATTRIBUTES = "include::_attributes.adoc[]\n"; final static String YAML_FRONTMATTER = "---\n"; @@ -117,8 +117,8 @@ public void writeYamlFiles() throws StreamWriteException, DatabindException, IOE om.writeValue(targetDir.resolve("indexByType.yaml").toFile(), index); om.writeValue(targetDir.resolve("indexByFile.yaml").toFile(), metadata); - om.writeValue(targetDir.resolve("errorsByType.yaml").toFile(), errors); - om.writeValue(targetDir.resolve("errorsByFile.yaml").toFile(), errors.messagesByFile); + om.writeValue(targetDir.resolve("errorsByType.yaml").toFile(), messages); + om.writeValue(targetDir.resolve("errorsByFile.yaml").toFile(), messages.allByFile()); } public Index generateIndex() throws IOException { @@ -130,7 +130,7 @@ public Index generateIndex() throws IOException { throw new IllegalStateException( String.format("Target directory (%s) does not exist. Exiting.%n", targetDir.toAbsolutePath())); } - errors.setRoot(srcDir); + messages.setRoot(srcDir); Options options = Options.builder() .docType("book") @@ -147,7 +147,7 @@ public Index generateIndex() throws IOException { try { str = Files.readString(path); } catch (IOException e) { - errors.record("ioexception", path); + messages.record("ioexception", path); return; } @@ -162,11 +162,11 @@ public Index generateIndex() throws IOException { // it should be part of the document header int includeAttr = str.indexOf(INCL_ATTRIBUTES); if (includeAttr < 0) { - errors.record("missing-attributes", path); + messages.record("missing-attributes", path); } else { String prefix = str.substring(0, includeAttr); if (prefix.contains("\n\n")) { - errors.record("detached-attributes", path); + messages.record("detached-attributes", path); } } @@ -174,7 +174,7 @@ public Index generateIndex() throws IOException { int documentHeaderEnd = str.indexOf("\n\n", titlePos); String documentHeader = str.substring(0, documentHeaderEnd); if (documentHeader.contains(":toc:")) { - errors.record("toc", path); + messages.record("toc", path); } String title = doc.getDoctitle(); @@ -200,18 +200,18 @@ public Index generateIndex() throws IOException { if (content.isPresent()) { index.add(new DocMetadata(title, path, summaryString, categories, keywords, id)); } else { - errors.record("empty-preamble", path); + messages.record("empty-preamble", path); index.add(new DocMetadata(title, path, summaryString, categories, keywords, id)); } } else { - errors.record("missing-preamble", path); + messages.record("missing-preamble", path); summaryString = getSummary(summary, Optional.empty()); index.add(new DocMetadata(title, path, summaryString, categories, keywords, id)); } long spaceCount = summaryString.chars().filter(c -> c == (int) ' ').count(); if (spaceCount > 26) { - errors.record("summary-too-long", path); + messages.record("summary-too-long", path); } }); } @@ -297,11 +297,14 @@ public static void addAll(Set set, Object source, Path path) { return; } for (String c : source.toString().split("\\s*,\\s*")) { - try { - Category cat = Category.valueOf(c.toLowerCase().replace("-", "_")); - set.add(cat); - } catch (IllegalArgumentException ex) { - errors.record("unknown-category", path, "Unknown category: " + c); + String lower = c.toLowerCase(); + Optional match = Stream.of(Category.values()) + .filter(cat -> cat.id.equals(lower)) + .findFirst(); + if (match.isEmpty()) { + messages.record("unknown-category", path, "Unknown category: " + c); + } else { + set.add(match.get()); } } } @@ -329,15 +332,17 @@ enum Type { } } - private static class Errors { + private static class Messages { String root; - Map> messagesByFile = new TreeMap<>(); + Map> errorsByFile = new TreeMap<>(); + Map> warningsByFile = new TreeMap<>(); public final Map> errors = new TreeMap<>(); void setRoot(Path root) { this.root = root.toString(); errors.clear(); - messagesByFile.clear(); + errorsByFile.clear(); + warningsByFile.clear(); } void record(String errorKey, Path path) { @@ -349,10 +354,24 @@ void record(String errorKey, Path path, String message) { if (message == null) { message = getMessageforKey(errorKey); } - messagesByFile.computeIfAbsent(filename, k -> new ArrayList<>()).add(message); + + if (isWarning(errorKey)) { + warningsByFile.computeIfAbsent(filename, k -> new ArrayList<>()).add(message); + } else { + errorsByFile.computeIfAbsent(filename, k -> new ArrayList<>()).add(message); + } errors.computeIfAbsent(errorKey, k -> new HashSet<>()).add(filename); } + private boolean isWarning(String errorKey) { + switch (errorKey) { + case "missing-id": + case "not-diataxis-type": + return true; + } + return false; + } + private String getMessageforKey(String errorKey) { switch (errorKey) { case "missing-attributes": @@ -377,8 +396,26 @@ private String getMessageforKey(String errorKey) { return errorKey; } + public Map allByFile() { + Map result = new TreeMap<>(); + errorsByFile.forEach((k, v) -> { + FileMessages mr = result.computeIfAbsent(k, x -> new FileMessages()); + mr.errors = v; + }); + warningsByFile.forEach((k, v) -> { + FileMessages mr = result.computeIfAbsent(k, x -> new FileMessages()); + mr.warnings = v; + }); + + return result; + } + Map> errorsByFile() { - return messagesByFile; + return errorsByFile; + } + + Map> warningsByFile() { + return warningsByFile; } } @@ -407,8 +444,8 @@ public Map metadataByFile() { } // convenience - public Map> errorsByFile() { - return errors.errorsByFile(); + public Map messagesByFile() { + return messages.allByFile(); } } @@ -464,20 +501,20 @@ static class DocMetadata implements Comparable { this.type = Type.reference; } else { this.type = Type.other; - errors.record("not-diataxis-type", path); + messages.record("not-diataxis-type", path); } if (id == null) { - errors.record("missing-id", path); + messages.record("missing-id", path); } else if (type != Type.other && !id.endsWith(type.suffix)) { - errors.record("incorrect-id", path, + messages.record("incorrect-id", path, String.format( "The document id (%s) does not end with the correct suffix, should end with '-%s'%n", id, type.suffix)); } if (this.categories.isEmpty()) { - errors.record("missing-categories", path); + messages.record("missing-categories", path); } } @@ -520,4 +557,25 @@ public int compareTo(DocMetadata that) { return this.title.compareTo(that.title); } } + + @JsonInclude(value = Include.NON_EMPTY) + public static class FileMessages { + Collection errors; + Collection warnings; + + Collection warnings() { + return warnings == null ? List.of() : warnings; + } + + Collection errors() { + return errors == null ? List.of() : errors; + } + + public boolean listAll(StringBuilder sb) { + errors().forEach(e -> sb.append(" [ ERR] ").append(e).append("\n")); + warnings().forEach(e -> sb.append(" [WARN] ").append(e).append("\n")); + sb.append("\n"); + return !errors().isEmpty(); + } + } } diff --git a/docs/src/test/java/io/quarkus/docs/YamlMetadataGeneratorTest.java b/docs/src/test/java/io/quarkus/docs/YamlMetadataGeneratorTest.java index 36ecc3c7cc85bf..d5d99f40d25064 100644 --- a/docs/src/test/java/io/quarkus/docs/YamlMetadataGeneratorTest.java +++ b/docs/src/test/java/io/quarkus/docs/YamlMetadataGeneratorTest.java @@ -2,13 +2,13 @@ import java.nio.file.Path; import java.util.Collection; -import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIfSystemProperty; import io.quarkus.docs.generation.YamlMetadataGenerator; +import io.quarkus.docs.generation.YamlMetadataGenerator.FileMessages; import io.quarkus.docs.generation.YamlMetadataGenerator.Index; public class YamlMetadataGeneratorTest { @@ -39,21 +39,22 @@ public void testAsciidocFiles() throws Exception { // Generate YAML: doc requirements Index index = metadataGenerator.generateIndex(); - Map> metadataErrors = index.errorsByFile(); + Map messages = index.messagesByFile(); + boolean hasErrors = false; StringBuilder sb = new StringBuilder("\n"); - for (String fileName : metadataErrors.keySet()) { - sb.append(fileName).append(": ").append("\n"); - - Collection mErrors = metadataErrors.getOrDefault(fileName, List.of()); - mErrors.forEach(e -> sb.append(" ").append(e).append("\n")); - sb.append("\n"); + for (String fileName : messages.keySet()) { + FileMessages fm = messages.get(fileName); + if (fm != null) { + sb.append(fileName).append(": ").append("\n"); + hasErrors |= fm.listAll(sb); + } } String result = sb.toString().trim(); - if (result.length() > 0) { - System.err.println(result); - // throw new LintException("target/errorsByFile.yaml"); + System.err.println(result); + if (hasErrors) { + throw new LintException("target/errorsByFile.yaml"); } else { System.out.println("🥳 OK"); } diff --git a/docs/src/test/java/io/quarkus/docs/vale/LocalValeLintTest.java b/docs/src/test/java/io/quarkus/docs/vale/LocalValeLintTest.java index d256658fcc192b..f45f2164d9717f 100644 --- a/docs/src/test/java/io/quarkus/docs/vale/LocalValeLintTest.java +++ b/docs/src/test/java/io/quarkus/docs/vale/LocalValeLintTest.java @@ -2,7 +2,6 @@ import java.nio.file.Path; import java.util.Collection; -import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; @@ -11,6 +10,7 @@ import io.quarkus.docs.ChangedFiles; import io.quarkus.docs.LintException; import io.quarkus.docs.generation.YamlMetadataGenerator; +import io.quarkus.docs.generation.YamlMetadataGenerator.FileMessages; import io.quarkus.docs.generation.YamlMetadataGenerator.Index; import io.quarkus.docs.vale.ValeAsciidocLint.ChecksBySeverity; @@ -61,26 +61,28 @@ public void testAsciidocFiles() throws Exception { // Generate YAML: doc requirements Index index = metadataGenerator.generateIndex(); - Map> metadataErrors = index.errorsByFile(); + Map messages = index.messagesByFile(); // Find Vale errors Map lintResults = linter.lintFiles(); // Write vale.yaml - linter.resultsToYaml(lintResults, metadataErrors); + linter.resultsToYaml(lintResults, messages); + boolean hasErrors = false; StringBuilder sb = new StringBuilder("\n"); for (String fileName : lintResults.keySet()) { sb.append(fileName).append(": ").append("\n"); - if (!metadataErrors.isEmpty()) { + FileMessages fm = messages.get(fileName); + if (fm != null) { sb.append("\n metadata\n"); - Collection mErrors = metadataErrors.getOrDefault(fileName, List.of()); - mErrors.forEach(e -> sb.append(" ").append(e).append("\n")); + hasErrors |= fm.listAll(sb); } ChecksBySeverity lErrors = lintResults.get(fileName); if (lErrors != null) { + hasErrors = true; // always fail in this purposeful case lErrors.checksBySeverity.entrySet().forEach(e -> { sb.append("\n ").append(e.getKey()).append("\n"); e.getValue().forEach(c -> sb.append(" ").append(c).append("\n")); @@ -90,8 +92,8 @@ public void testAsciidocFiles() throws Exception { } String result = sb.toString().trim(); - if (result.length() > 0) { - System.err.println(result); + System.err.println(result); + if (hasErrors) { throw new LintException("target/vale.yaml"); } else { System.out.println("🥳 OK"); diff --git a/docs/src/test/java/io/quarkus/docs/vale/ValeAsciidocLint.java b/docs/src/test/java/io/quarkus/docs/vale/ValeAsciidocLint.java index 52d95769af80ec..4ce6a94197ae4d 100644 --- a/docs/src/test/java/io/quarkus/docs/vale/ValeAsciidocLint.java +++ b/docs/src/test/java/io/quarkus/docs/vale/ValeAsciidocLint.java @@ -38,6 +38,8 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; +import io.quarkus.docs.generation.YamlMetadataGenerator.FileMessages; + public class ValeAsciidocLint { public static TypeReference>> typeRef = new TypeReference>>() { }; @@ -125,7 +127,7 @@ public boolean test(String p) { return this; } - public void resultsToYaml(Map lintChecks, Map> metadataErrors) + public void resultsToYaml(Map lintChecks, Map metadataErrors) throws StreamWriteException, DatabindException, IOException { ObjectMapper yaml = new ObjectMapper(new YAMLFactory().enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)); Map> results = lintChecks.entrySet().stream() @@ -133,9 +135,9 @@ public void resultsToYaml(Map lintChecks, Map value = new TreeMap<>(); // sort by key for consistency value.putAll(e.getValue().checksBySeverity); if (metadataErrors != null) { - Collection me = metadataErrors.get(e.getKey()); - if (me != null) { - value.put("metadata", me); + FileMessages fm = metadataErrors.get(e.getKey()); + if (fm != null) { + value.put("metadata", fm); } } return value;