Browse Source

ESQL: Only generate syntax diagrams locally (#99059)

CI will skip building them. Lot's of CI machines don't have font support
so they can't generate these. But all local machine have a GUI so they
can.

Also, super-lazy initialize the font so CI don't bump into it by
accident.

Closes #99018
Nik Everett 2 years ago
parent
commit
b73cc0c529

+ 1 - 1
docs/reference/esql/functions/signature/ceil.svg

@@ -1 +1 @@
-<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="226" height="43" viewbox="0 0 226 43"><defs><style type="text/css">.c{fill:none;stroke:#222222;}.k{fill:#000000;font-family:Dialog,Sans-serif;font-size:20px;}.s{fill:#e4f4ff;stroke:#222222;}.syn{fill:#8D8D8D;font-family:Dialog,Sans-serif;font-size:20px;}</style></defs><path class="c" d="M0 28h5m64 0h10m28 0h10m66 0h10m28 0h5"/><rect class="s" x="5" y="5" width="64" height="33"/><text class="k" x="15" y="28">CEIL</text><rect class="s" x="79" y="5" width="28" height="33" rx="7"/><text class="syn" x="89" y="28">(</text><rect class="s" x="117" y="5" width="66" height="33" rx="7"/><text class="k" x="127" y="28">arg1</text><rect class="s" x="193" y="5" width="28" height="33" rx="7"/><text class="syn" x="203" y="28">)</text></svg>
+<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="204" height="46" viewbox="0 0 204 46"><defs><style type="text/css">#guide .c{fill:none;stroke:#222222;}#guide .k{fill:#000000;font-family:Roboto Mono,Sans-serif;font-size:20px;}#guide .s{fill:#e4f4ff;stroke:#222222;}#guide .syn{fill:#8D8D8D;font-family:Roboto Mono,Sans-serif;font-size:20px;}</style></defs><path class="c" d="M0 31h5m68 0h10m32 0h10m32 0h10m32 0h5"/><rect class="s" x="5" y="5" width="68" height="36"/><text class="k" x="15" y="31">CEIL</text><rect class="s" x="83" y="5" width="32" height="36" rx="7"/><text class="syn" x="93" y="31">(</text><rect class="s" x="125" y="5" width="32" height="36" rx="7"/><text class="k" x="135" y="31">n</text><rect class="s" x="167" y="5" width="32" height="36" rx="7"/><text class="syn" x="177" y="31">)</text></svg>

+ 1 - 0
docs/reference/esql/functions/signature/left.svg

@@ -0,0 +1 @@
+<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="360" height="46" viewbox="0 0 360 46"><defs><style type="text/css">#guide .c{fill:none;stroke:#222222;}#guide .k{fill:#000000;font-family:Roboto Mono,Sans-serif;font-size:20px;}#guide .s{fill:#e4f4ff;stroke:#222222;}#guide .syn{fill:#8D8D8D;font-family:Roboto Mono,Sans-serif;font-size:20px;}</style></defs><path class="c" d="M0 31h5m68 0h10m32 0h10m68 0h10m32 0h10m68 0h10m32 0h5"/><rect class="s" x="5" y="5" width="68" height="36"/><text class="k" x="15" y="31">LEFT</text><rect class="s" x="83" y="5" width="32" height="36" rx="7"/><text class="syn" x="93" y="31">(</text><rect class="s" x="125" y="5" width="68" height="36" rx="7"/><text class="k" x="135" y="31">arg1</text><rect class="s" x="203" y="5" width="32" height="36" rx="7"/><text class="syn" x="213" y="31">,</text><rect class="s" x="245" y="5" width="68" height="36" rx="7"/><text class="k" x="255" y="31">arg2</text><rect class="s" x="323" y="5" width="32" height="36" rx="7"/><text class="syn" x="333" y="31">)</text></svg>

+ 1 - 1
docs/reference/esql/functions/types/ceil.asciidoc

@@ -1,6 +1,6 @@
 [%header.monospaced.styled,format=dsv,separator=|]
 |===
-arg1 | result
+n | result
 double | double
 integer | integer
 long | long

+ 5 - 0
docs/reference/esql/functions/types/left.asciidoc

@@ -0,0 +1,5 @@
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+arg1 | arg2 | result
+keyword | integer | keyword
+|===

+ 17 - 14
x-pack/plugin/esql/build.gradle

@@ -56,20 +56,23 @@ sourceSets.main.java {
 }
 
 tasks.getByName('test') {
-  dependsOn 'cleanGeneratedDocs'
-}
-
-tasks.register('cleanGeneratedDocs', Delete) {
-  delete "${projectDir}/build/testrun/test/temp/esql/functions"
-}
-
-tasks.register('copyGeneratedDocs', Sync) {
-  dependsOn 'test'
-  from "${projectDir}/build/testrun/test/temp/esql/functions"
-  into "${rootDir}/docs/reference/esql/functions"
-  include '**/*.asciidoc', '**/*.svg'
-  preserve {
-    include '/*.asciidoc'
+  if (BuildParams.isCi() == false) {
+    systemProperty 'generateDocs', true
+    doFirst {
+      project.delete(
+        files("${projectDir}/build/testrun/test/temp/esql/functions")
+      )
+    }
+    doLast {
+      project.sync {
+        from "${projectDir}/build/testrun/test/temp/esql/functions"
+        into "${rootDir}/docs/reference/esql/functions"
+        include '**/*.asciidoc', '**/*.svg'
+        preserve {
+          include '/*.asciidoc'
+        }
+      }
+    }
   }
 }
 

+ 2 - 2
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/package-info.java

@@ -123,8 +123,8 @@
  *         asciidoc ceremony to make the result look right in the rendered docs.
  *     </li>
  *     <li>
- *         Auto-generate a syntax diagram and a table with supported types by running
- *         {@code ./gradlew x-pack:plugin:esql:copyGeneratedDocs}
+ *         Generate a syntax diagram and a table with supported types by running the tests via
+ *         gradle: {@code ./gradlew x-pack:plugin:esql:test}
  *         The generated files can be found here
  *         {@code docs/reference/esql/functions/signature/myfunction.svg }
  *         and here

+ 19 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/AbstractFunctionTestCase.java

@@ -857,6 +857,22 @@ public abstract class AbstractFunctionTestCase extends ESTestCase {
         return EsqlDataTypes.types().stream().filter(EsqlDataTypes::isRepresentable);
     }
 
+    @AfterClass
+    public static void renderSignature() throws IOException {
+        if (System.getProperty("generateDocs") == null) {
+            return;
+        }
+        FunctionDefinition definition = definition();
+        if (definition == null) {
+            LogManager.getLogger(getTestClass()).info("Skipping rendering signature because the function isn't registered");
+            return;
+        }
+
+        String rendered = RailRoadDiagram.functionSignature(definition);
+        LogManager.getLogger(getTestClass()).info("Writing function signature");
+        writeToTempDir("signature", rendered, "svg");
+    }
+
     /**
      * Unique signatures encountered by this test.
      * <p>
@@ -892,6 +908,9 @@ public abstract class AbstractFunctionTestCase extends ESTestCase {
 
     @AfterClass
     public static void renderTypesTable() throws IOException {
+        if (System.getProperty("generateDocs") == null) {
+            return;
+        }
         FunctionDefinition definition = definition();
         if (definition == null) {
             LogManager.getLogger(getTestClass()).info("Skipping rendering types because the function isn't registered");

+ 8 - 9
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/RailRoadDiagram.java

@@ -19,6 +19,7 @@ import net.nextencia.rrdiagram.grammar.rrdiagram.RRDiagramToSVG;
 import net.nextencia.rrdiagram.grammar.rrdiagram.RRElement;
 import net.nextencia.rrdiagram.grammar.rrdiagram.RRText;
 
+import org.elasticsearch.common.util.LazyInitializable;
 import org.elasticsearch.xpack.esql.plan.logical.show.ShowFunctions;
 import org.elasticsearch.xpack.ql.expression.function.FunctionDefinition;
 
@@ -40,9 +41,9 @@ public class RailRoadDiagram {
      * on whatever fonts you have installed. And, since the world can't agree
      * on fonts, that'd be chaos. So, instead, we load Roboto Mono.
      */
-    private static final Font FONT = loadFont().deriveFont(20.0F);
+    private static final LazyInitializable<Font, IOException> FONT = new LazyInitializable<>(() -> loadFont().deriveFont(20.0F));
 
-    static String functionSignature(FunctionDefinition definition) {
+    static String functionSignature(FunctionDefinition definition) throws IOException {
         List<Expression> expressions = new ArrayList<>();
         expressions.add(new SpecialSequence(definition.name().toUpperCase(Locale.ROOT)));
         expressions.add(new Syntax("("));
@@ -68,12 +69,12 @@ public class RailRoadDiagram {
 
         RRDiagramToSVG toSvg = new RRDiagramToSVG();
         toSvg.setSpecialSequenceShape(RRDiagramToSVG.BoxShape.RECTANGLE);
-        toSvg.setSpecialSequenceFont(FONT);
+        toSvg.setSpecialSequenceFont(FONT.getOrCompute());
 
         toSvg.setLiteralFillColor(toSvg.getSpecialSequenceFillColor());
-        toSvg.setLiteralFont(FONT);
+        toSvg.setLiteralFont(FONT.getOrCompute());
 
-        toSvg.setRuleFont(FONT);
+        toSvg.setRuleFont(FONT.getOrCompute());
         /*
          * "Tighten" the styles in the SVG so they beat the styles sitting in the
          * main page. We need this because we're embedding the SVG into the page.
@@ -143,7 +144,7 @@ public class RailRoadDiagram {
         }
     }
 
-    private static Font loadFont() {
+    private static Font loadFont() throws IOException {
         try {
             InputStream woff = RailRoadDiagram.class.getClassLoader()
                 .getResourceAsStream("META-INF/resources/webjars/fontsource__roboto-mono/4.5.7/files/roboto-mono-latin-400-normal.woff");
@@ -152,9 +153,7 @@ public class RailRoadDiagram {
             }
             return Font.createFont(Font.TRUETYPE_FONT, new WoffConverter().convertToTTFOutputStream(woff));
         } catch (FontFormatException e) {
-            throw new RuntimeException(e);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
+            throw new IOException(e);
         }
     }
 }