diff --git a/.github/workflows/pr_build_code.yml b/.github/workflows/pr_build_code.yml index 26c112f4302..f1e99ab487c 100644 --- a/.github/workflows/pr_build_code.yml +++ b/.github/workflows/pr_build_code.yml @@ -95,6 +95,28 @@ jobs: run: mvn spotless:check -Dgib.disable=$GIB_DISABLE -Dgib.buildUpstream=false - name: Build with Maven run: MAVEN_OPTS="-XX:+TieredCompilation -XX:TieredStopAtLevel=1"; mvn clean install -T 1C -B -C -e -fae -V -Dmaven.compiler.fork=true -Dsurefire.rerunFailingTestsCount=2 -Dassemblies=false -Dmodule.zips=false -Djacoco.skip=true -Dgib.disable=$GIB_DISABLE --file pom.xml + # The build regenerates the configuration perspective's option tables from the + # @ConfigPlugin and @GuiWidgetElement annotations. If that leaves the working tree + # dirty, the committed page no longer matches the code it documents. + - name: Configuration documentation is up to date + run: | + CONFIG_DOCS=docs/hop-user-manual/modules/ROOT/partials/config + # --porcelain, not diff: a newly added configuration plugin writes a new .adoc, and an + # untracked file is invisible to git diff. + if [ -n "$(git status --porcelain -- $CONFIG_DOCS)" ]; then + echo "The configuration perspective's generated option tables are out of date." + echo "A configuration option was added, removed or changed without regenerating" + echo "the page that documents it." + echo + echo "To fix, from a full build of your branch:" + echo " mvn clean install -DskipTests" + echo "and commit the result under $CONFIG_DOCS." + echo + git status --short -- $CONFIG_DOCS + git diff -- $CONFIG_DOCS + exit 1 + fi + echo "Generated configuration documentation matches the code." # Add a UI and run the UI tests only ui-tests: diff --git a/config-doc/pom.xml b/config-doc/pom.xml new file mode 100644 index 00000000000..02250f12bef --- /dev/null +++ b/config-doc/pom.xml @@ -0,0 +1,208 @@ + + + + 4.0.0 + + + org.apache.hop + hop + 2.20.0-SNAPSHOT + + + hop-config-doc + jar + Hop Configuration Documentation Generator + Regenerates the AsciiDoc tables describing the options in the configuration perspective. + A build tool: it is not part of any assembly and ships with nothing. + + + ${project.basedir}/../docs/hop-user-manual/modules/ROOT/partials/config + + + + + io.smallrye + jandex + ${jandex.version} + + + + + org.apache.hop + hop-misc-git + ${project.version} + provided + + + + * + * + + + + + org.apache.hop + hop-misc-lint + ${project.version} + provided + + + + * + * + + + + + org.apache.hop + hop-misc-projects + ${project.version} + provided + + + + * + * + + + + + org.apache.hop + hop-tech-ai + ${project.version} + provided + + + + * + * + + + + + org.apache.hop + hop-tech-azure + ${project.version} + provided + + + + * + * + + + + + org.apache.hop + hop-tech-calcite + ${project.version} + provided + + + + * + * + + + + + org.apache.hop + hop-tech-dropbox + ${project.version} + provided + + + + * + * + + + + + org.apache.hop + hop-tech-google + ${project.version} + provided + + + + * + * + + + + + org.apache.hop + hop-ui + ${project.version} + provided + + + + * + * + + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.5.0 + + + generate-config-docs + + + exec + + package + + + ${java.home}/bin/java + + compile + + -classpath + + org.apache.hop.config.doc.ConfigDocGenerator + ${project.basedir}/.. + ${docs.partials.directory} + + + + + + + + diff --git a/config-doc/src/main/java/org/apache/hop/config/doc/ConfigDocGenerator.java b/config-doc/src/main/java/org/apache/hop/config/doc/ConfigDocGenerator.java new file mode 100644 index 00000000000..4d88928202f --- /dev/null +++ b/config-doc/src/main/java/org/apache/hop/config/doc/ConfigDocGenerator.java @@ -0,0 +1,548 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hop.config.doc; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.TreeMap; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.Index; +import org.jboss.jandex.IndexReader; + +/** + * Generates one AsciiDoc partial per configuration plugin from the annotations the configuration + * perspective already builds its widgets from. Build time only: it reads the Jandex indexes the + * build writes into every module and the message bundles next to the classes, and instantiates only + * the plain configuration objects, never Hop itself. + */ +public class ConfigDocGenerator { + + static final DotName CONFIG_PLUGIN = + DotName.createSimple("org.apache.hop.core.config.plugin.ConfigPlugin"); + static final DotName GUI_WIDGET = + DotName.createSimple("org.apache.hop.core.gui.plugin.GuiWidgetElement"); + static final DotName GUI_PLUGIN = + DotName.createSimple("org.apache.hop.core.gui.plugin.GuiPlugin"); + static final String PARENT_ID = "EnterOptionsDialog-GuiWidgetsParent"; + static final String JANDEX_INDEX = "META-INF/jandex.idx"; + static final String AGGREGATE = "all-plugins.adoc"; + + /** First line of every page this generator owns, and how it tells them from hand-written ones. */ + static final String GENERATED_MARKER = + "// Generated from the @ConfigPlugin and @GuiWidgetElement annotations."; + + static final String LICENSE = + """ + //// + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + //// + """; + + record Option( + String order, String label, String toolTip, String type, boolean variables, String dflt) {} + + record Plugin( + String id, String description, String name, String configKey, List