index.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. Automatic Quality Assurance checks
  2. ==================================
  3. The GeoServer builds on Github Actions and `https://build.geoserver.org/ <https://build.geoserver.org/>`__ apply
  4. `PMD <https://pmd.github.io/>`_ and `Error Prone <https://errorprone.info/>`_ checks on the code base
  5. and will fail the build in case of rule violation.
  6. In case you want to just run the build with the full checks locally, use the following command:
  7. .. code-block:: bash
  8. mvn clean install -Dqa
  9. Add extra parameters as you see fit, like ``-T1C -nsu`` to speed up the build:
  10. .. code-block:: bash
  11. mvn install -Prelease -Dqa -T1C -nsu -fae
  12. Flags documented below can be used to shut off individual QA checks when trouble shooting.
  13. PMD checks
  14. ----------
  15. The `PMD <https://pmd.github.io/>`__ checks are based on source code analysis for common errors, we have configured :command:`PMD` to check for common mistakes and bad practices such as accidentally including debug ``System.out.println()`` statements in your commit.
  16. .. literalinclude:: /../../../../src/pom.xml
  17. :language: xml
  18. :start-at: <artifactId>maven-pmd-plugin</artifactId>
  19. :end-before: </plugin>
  20. :dedent: 12
  21. Rules are configured in our build `build/qa/pmd-ruleset.xml <https://github.com/geoserver/geoserver/blob/main/build/qa/pmd-ruleset.xml>`_:
  22. .. literalinclude:: /../../../../build/qa/pmd-ruleset.xml
  23. :language: xml
  24. :start-after: </description>
  25. :end-before: </ruleset>
  26. In order to activate the :command:`PMD` checks, use the ``-Ppmd`` profile:
  27. .. code-block:: bash
  28. mvn verify -Ppmd
  29. Or run `pmd:check` (requires use of ``initialize`` to locate `geoserverBaseDir/build/qa/pmd-ruleset.xml`):
  30. .. code-block:: bash
  31. mvn initialize pmd:check -Ppmd
  32. :command:`PMD` will fail the build in case of violation, reporting the specific errors before the build
  33. error message, and a reference to a XML file with the same information after it (example taken from GeoTools)::
  34. 7322 [INFO] --- maven-pmd-plugin:3.11.0:check (default) @ gt-main ---
  35. 17336 [INFO] PMD Failure: org.geotools.data.DataStoreAdaptor:98 Rule:SystemPrintln Priority:2 System.out.println is used.
  36. 17336 [INFO] PMD Failure: org.geotools.data.DataStoreAdaptor:98 Rule:SystemPrintln Priority:2 System.out.println is used.
  37. 17337 [INFO] ------------------------------------------------------------------------
  38. 17337 [INFO] BUILD FAILURE
  39. 17337 [INFO] ------------------------------------------------------------------------
  40. 17338 [INFO] Total time: 16.727 s
  41. 17338 [INFO] Finished at: 2018-12-29T11:34:33+01:00
  42. 17338 [INFO] ------------------------------------------------------------------------
  43. 17340 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-pmd-plugin:3.11.0:check (default) on project gt-main: You have 1 PMD violation. For more details see: /home/yourUser/devel/git-gt/modules/library/main/target/pmd.xml -> [Help 1]
  44. 17340 [ERROR]
  45. In case of parallel build, the specific error messages will be in the body of the build output, while the XML file reference will be at the end, search for ``PMD Failure`` in the build logs to find the specific code issues.
  46. If you do have a :command:`PMD` failure it is worth checking the pmd website which offers quite clear suggestions:
  47. * `Java Rules <https://pmd.github.io/latest/pmd_rules_java_bestpractices.html>`__
  48. PMD false positive suppression
  49. """"""""""""""""""""""""""""""
  50. Occasionally PMD will report a false positive failure, for those it's possible to annotate the method
  51. or the class in question with a SuppressWarnings using ``PMD.<RuleName``, e.g. if the above error
  52. was actually a legit use of ``System.out.println`` it could have been annotated with:
  53. .. code-block:: java
  54. @SuppressWarnings("PMD.SystemPrintln")
  55. public void methodDoingPrintln(...) {
  56. PMD CloseResource checks
  57. """"""""""""""""""""""""
  58. PMD can check for Closeable that are not getting property closed by the code, and report about it.
  59. PMD by default only checks for SQL related closeables, like "Connection,ResultSet,Statement", but it
  60. can be instructed to check for more by configuration (do check the PMD configuration in
  61. ``build/qa/pmd-ruleset.xml``.
  62. The check is a bit fragile, in that there are multiple ways to close an object between direct calls,
  63. utilities and delegate methods. The configuration lists the type of methods, and the eventual
  64. prefix, that will be used to perform the close, for example:
  65. .. code-block:: xml
  66. <rule ref="category/java/errorprone.xml/CloseResource" >
  67. <properties>
  68. <property name="closeTargets" value="releaseConnection,store.releaseConnection,closeQuietly,closeConnection,closeSafe,store.closeSafe,dataStore.closeSafe,getDataStore().closeSafe,close,closeResultSet,closeStmt"/>
  69. </properties>
  70. </rule>
  71. For closing delegates that use an instance object instead of a class static method, the variable
  72. name is included in the prefix, so some uninformity in variable names is required.
  73. Error Prone
  74. -----------
  75. The `Error Prone <https://errorprone.info/>`_ checker runs a compiler plugin.
  76. In order to activate the Error Prone checks, use the "-Perrorprone":
  77. .. literalinclude:: /../../../../src/pom.xml
  78. :language: xml
  79. :start-at: <id>errorprone</id>
  80. :end-before: </profile>
  81. :dedent: 6
  82. Any failure to comply with the "Error Prone" rules will show up as a compile error in the build output, e.g. (example taken from GeoTools)::
  83. 9476 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project gt-coverage: Compilation failure
  84. 9476 [ERROR] /home/user/devel/git-gt/modules/library/coverage/src/main/java/org/geotools/image/ImageWorker.java:[380,39] error: [IdentityBinaryExpression] A binary expression where both operands are the same is usually incorrect; the value of this expression is equivalent to `255`.
  85. 9477 [ERROR] (see https://errorprone.info/bugpattern/IdentityBinaryExpression)
  86. 9477 [ERROR]
  87. 9477 [ERROR] -> [Help 1]
  88. org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project gt-coverage: Compilation failure
  89. /home/user/devel/git-gt/modules/library/coverage/src/main/java/org/geotools/image/ImageWorker.java:[380,39] error: [IdentityBinaryExpression] A binary expression where both operands are the same is usually incorrect; the value of this expression is equivalent to `255`.
  90. (see https://errorprone.info/bugpattern/IdentityBinaryExpression)
  91. In case Error Prone is reporting an invalid error, the method or class in question can be annotated
  92. with SuppressWarnings with the name of the rule, e.g., to get rid of the above the following annotation could be used::
  93. @SuppressWarnings("IdentityBinaryExpression")
  94. Spotbugs
  95. --------
  96. The `Spotbugs <https://spotbugs.github.io/>`_ checker runs as a post-compile bytecode analyzer.
  97. .. literalinclude:: /../../../../src/pom.xml
  98. :language: xml
  99. :start-at: <groupId>com.github.spotbugs</groupId>
  100. :end-before: </plugin>
  101. :dedent: 12
  102. Any failure to comply with the rules will show up as a compile error, e.g.::
  103. 33630 [ERROR] page could be null and is guaranteed to be dereferenced in org.geotools.swing.wizard.JWizard.setCurrentPanel(String) [org.geotools.swing.wizard.JWizard, org.geotools.swing.wizard.JWizard, org.geotools.swing.wizard.JWizard, org.geotools.swing.wizard.JWizard] Dereferenced at JWizard.java:[line 278]Dereferenced at JWizard.java:[line 269]Null value at JWizard.java:[line 254]Known null at JWizard.java:[line 255] NP_GUARANTEED_DEREF
  104. It is also possible to run the spotbugs:gui goal to have a Swing based issue explorer, e.g.:
  105. .. code-block:: bash
  106. mvn spotbugs:gui -Pspotbugs -f wms
  107. In case an invalid report is given, an annotation on the class/method/variable can be added to ignore it:
  108. .. code-block:: java
  109. @SuppressFBWarnings("NP_GUARANTEED_DEREF")
  110. or if it's a general one that should be ignored, the `build/qa/spotbugs-exclude.xml <https://github.com/geoserver/geoserver/blob/main/build/qa/spotbugs-exclude.xml>`__ file can be modified.
  111. .. literalinclude:: /../../../../build/qa/spotbugs-exclude.xml
  112. :language: xml
  113. Spotless
  114. --------
  115. Spotless is used as a fast way to check that the google-java-format is being applied to the codebase.
  116. .. literalinclude:: /../../../../src/pom.xml
  117. :language: xml
  118. :start-at: <groupId>com.diffplug.spotless</groupId>
  119. :end-before: </plugin>
  120. :dedent: 8
  121. This has been setup for incremental checking, with hidden :file:`.spotless-index` files used determine
  122. when files were last checked.
  123. To run the plugin directly:
  124. .. code-block:: bash
  125. mvn spotless:apply
  126. When using ``check`` any failure to comply with the rules will show up as a compiler error in the build output.
  127. .. code-block:: bash
  128. mvn spotless:check
  129. When verifying ``spotless.action`` is used to choose ``apply`` or ``check`` (defaults to ``apply``):
  130. .. code-block:: bash
  131. mvn verify -Dqa -Dspotless.action=check
  132. Property ``spotless.apply.skip`` is used to skip spotless plugin when running ``qa`` build:
  133. .. code-block:: bash
  134. mvn clean install -Dqa -Dspotless.apply.skip=true
  135. Sortpom
  136. -------
  137. Sortpom is used to keep the :file:`pom.xml` files formatting consistent:
  138. .. literalinclude:: /../../../../src/pom.xml
  139. :language: xml
  140. :start-at: <groupId>com.github.ekryd.sortpom</groupId>
  141. :end-before: </plugin>
  142. :dedent: 8
  143. The plugin is attached to verification phase to sort :file:`pom.xml` files.
  144. To run the plugin directly:
  145. .. code-block:: bash
  146. mvn sortpom:sort
  147. Verification checks if (ignoring whitespace changes) is the current :file:`pom.xml` in the correct order:
  148. mvn sortpom:verify
  149. Property ``pom.fmt.action`` is used to choose ``sort`` or ``verify`` (defaults to ``sort``):
  150. .. code-block:: bash
  151. mvn verify -Dqa -Dpom.fmt.action=verify
  152. Property ``pom.fmt.skip`` used to skip sortpom plugin when running ``qa`` build (defaults to ``spotless.apply.skip`` setting):
  153. .. code-block:: bash
  154. mvn clean install -Dqa -Dpom.fmt.skip=true
  155. Checkstyle
  156. ----------
  157. Spotless is already in use to keep the code formatted, so `maven checkstyle plugin <https://maven.apache.org/plugins/maven-checkstyle-plugin/>`__ is used mainly to verify javadocs errors
  158. and presence of copyright headers, which none of the other tools can cover.
  159. .. literalinclude:: /../../../../src/pom.xml
  160. :language: xml
  161. :start-at: <artifactId>maven-checkstyle-plugin</artifactId>
  162. :end-before: </plugin>
  163. :dedent: 12
  164. The checkstyle ruleset checks the following:
  165. .. literalinclude:: /../../../../build/qa/checkstyle.xml
  166. :language: xml
  167. :start-at: <module name="Checker">
  168. To run the plugin directly:
  169. .. code-block:: bash
  170. mvn initialize checkstyle:check