Structure101 Build and the Structure101 SonarQube plugin can be incorporated into your existing Jenkins CI process. This post describes the necessary configuration. [Build 14507 and later of the Structure101 SonarQube plugin]
Structure101 Build performs architectural checks and can publish a snapshot and the architectural diagrams to a Structure101 repository. The Check Key Measures and Check Spec operations can be configured to fail the build directly, by throwing a run time exception, or indirectly using Jenkins build steps to set the build status.
- Packages should not be Fat
- Classes should not be Fat
- Methods should not be Fat
- Packages should not contain tangled sub-packages
- Dependencies should comply with the Structure Spec
- Items should not exist in a specified scope unless they are included in the Structure Spec
- Dependencies should comply with all enforced Architecture Diagrams
Installing and Configuring the SonarQube Plugin
The Structure101 SonarQube plugin jar file should be copied into the extensions/plugins folder of the SonarQube installation. Any previous version of the Structure101 plugin should be removed and the SonarQube instance restarted.
Create a new Quality Profile with language Java
Change the parent to your existing Java quality profile
Click Activate More to add the Structure101 rules
Filter the rules using Java language and Structure101 repository
Activate each of the rules setting the desired severity
Jenkins Prerequisites
The examples described use several Jenkins plugins that are not installed by default. Check your Jenkins configuration and install any that are missing.
- Fail The Build Plugin
- Run Condition Extras Plugin
- Text Finder Run Condition Plugin
- Conditional BuildStep Plugin
- Build Cause Run Condition Plugin
- Maven Integration Plugin
Overview of the Build Steps
The build steps are: –
- Execute the compile/test phase
- If the build is successful
- Update the Structure101 Build configuration file with the label of the current build
- Run the Structure101 Build process
- Check Key Measures
- Check Spec
- Publish
- Report Summary
- Run the SonarQube Scanner
- If Check Key Measures or Spec Check failed
- Mark the build unstable/failed
- If the build is successful
- Update the Structure101 Build configuration baseline property
- Commit/push the updated Build configuration file
The baseline property in the check-key-measures and check-spec operations is always set to the label of the last build that did not fail the checks. This allows the snapshot to be published on every build, even those that fail the checks. The snapshots capture the model and diagrams for each build and allow visual comparisons between them.
Initial Publish of Snapshot
The Structure101 project must be published to the Structure101 Repository before the Jenkins driven publish operation can run. The label used for this initial snapshot should be added to the structure101-build-config.xml file in the baseline property of the check-key-measures, check-spec and check-architecture operations.
For multiple branches either use different Structure101 project names for each branch or use the same project name and a branch identifier in the label argument of the publish operation.
Build Steps in Detail – Maven
This first example uses the Maven Integration plugin
This plugin adds a Maven Build Step with Pre and Post Steps. No Pre Steps are used in the example. The Post Steps are configured to run only if the build succeeds.
The first of the post steps is an execute shell command
This step runs the Structure101 Build process passing in the label using -Ds101.label. (In this example, a concatenation of the system variables GIT_BRANCH and BUILD_ID separated by an underscore)
java -Ds101.label="${GIT_BRANCH}_$BUILD_ID" -jar /opt/structure101-build-java-all-5.0.14435/structure101-java-build.jar structure101-build-config.xml -licenseDir=/opt/structure101-build-license
(NOTE that any of the arguments can be provided at runtime with -Ds101.<argument name>)
The second step runs the SonarQube scanner using the Maven goal in an Invoke top-level Maven targets step. Note that the new SonarQube plugin does not require any property definition in the Maven pom.xml. But the plugin does require a system property to be set that provides the path to the output file of the check-key-measures operation run in the previous step. This property is available to the Structure101 plugin when SonarQube invokes its scan.
The path must match that set in the structure101-build-config.xml file
<operation type="check-key-measures"> <argument name="output-file" value="const(THIS_FILE)/target/structure101/key-measures.xml"/> <argument name="output-file-for-snapshot" value="const(THIS_FILE)/s101working/structure101report/snapshot-key-measures.xml"/> <argument name="baseline" value="14"/> <argument name="useProjectFileSpec" value="true"/> <argument name="useProjectFileDiagrams" value="true"/> <argument name="fail-on-architecture-violations" value="false"/> <argument name="fail-on-fat-package" value="false"/> <argument name="fail-on-fat-class" value="false"/> <argument name="fail-on-fat-method" value="false"/> <argument name="fail-on-feedback-dependencies" value="false"/> <argument name="fail-on-spec-violation-dependencies" value="false"/> <argument name="fail-on-total-problem-dependencies" value="false"/> <argument name="fail-on-spec-item-violations" value="false"/> <argument name="fail-on-biggest-class-tangle" value="false"/> <argument name="fail-on-tangled-package" value="false"/> <argument name="fail-on-architecture-violations" value="false"/> <argument name="identifier-on-violation" value="S101 key measure violation"/> </operation>
The next step is a Conditional step (single) that uses Text Finder to check the console output for failure messages from the check-key-measures operation and the Set the build result step to set the build status if any are found. In this example the build is set to failed if any of the messages are detected using a simple OR’d regex
The messages are: –
FAIL! fat0 has increased by FAIL! fat1 has increased by FAIL! fat2 has increased by FAIL! feedbackDependencies has increased by FAIL! specViolationDependencies has increased by FAIL! totalProblemDependencies has increased by FAIL! specItemViolations has increased by FAIL! biggestClassTangles has increased by FAIL! tangledDesign has increased by FAIL! numViolations has increased by
if desired a different build status can be set for the messages by creating multiple Text Finder steps.
The next step is also a single conditional that only runs if the build is successful. It executes a shell command that updates the baseline argument of the check-key-measures, check-spec and check-architecture operations in the structure101-build-config.xml file and then commits the changes.
The awk command replaces the line containing the baseline argument with the content of the baseline_tag variable. This should be identical to the variable used to set the label argument.
awk -v baseline_tag="\<argument name\=\"baseline\" value\=\"${GIT_BRANCH}_$BUILD_ID\"/\>" '{gsub("\<argument name=\"baseline\" value\=\".*", baseline_tag)}1' structure101-build-config.xml > baseline-structure101-build-config.xml mv -f baseline-structure101-build-config.xml structure101-build-config.xml git commit -am "Increment baseline label"
Finally the Git Publisher Post-build Action is used to push the baseline change to the repository.
Build Steps in Detail – Gradle
The gradle example uses a Freestyle project. The steps are all configured as Build Steps.
The Invoke Gradle Script step is followed by a Conditional step (single) that runs only if the build is successful.
This step runs the Structure101 Build process passing in the label using -Ds101.label. (In this example, a concatenation of the system variables GIT_BRANCH and BUILD_ID separated by an underscore)
java -Ds101.label="${GIT_BRANCH}_$BUILD_ID" -jar /opt/structure101-build-java-all-5.0.14435/structure101-java-build.jar structure101-build-config.xml -licenseDir=/opt/structure101-build-license
(NOTE that any of the arguments can be provided at runtime with -Ds101.<argument name>)
The next step runs the SonarQube scanner using an Invoke Gradle script step. Note that the new SonarQube plugin does not require any property definition in the build.gradle file. But the plugin does require a system property to be set that provides the path to the output file of the check-key-measures operation run in the previous step. This property is available to the Structure101 plugin when SonarQube invokes its scan.
The path must match that set in the structure101-build-config.xml file
<operation type="check-key-measures"> <argument name="output-file" value="const(THIS_FILE)/target/structure101/key-measures.xml"/> <argument name="output-file-for-snapshot" value="const(THIS_FILE)/s101working/structure101report/snapshot-key-measures.xml"/> <argument name="baseline" value="14"/> <argument name="useProjectFileSpec" value="true"/> <argument name="useProjectFileDiagrams" value="true"/> <argument name="fail-on-architecture-violations" value="false"/> <argument name="fail-on-fat-package" value="false"/> <argument name="fail-on-fat-class" value="false"/> <argument name="fail-on-fat-method" value="false"/> <argument name="fail-on-feedback-dependencies" value="false"/> <argument name="fail-on-spec-violation-dependencies" value="false"/> <argument name="fail-on-total-problem-dependencies" value="false"/> <argument name="fail-on-spec-item-violations" value="false"/> <argument name="fail-on-biggest-class-tangle" value="false"/> <argument name="fail-on-tangled-package" value="false"/> <argument name="fail-on-architecture-violations" value="false"/> <argument name="identifier-on-violation" value="S101 key measure violation"/> </operation>
The next step is a Conditional step (single) that uses Text Finder to check the console output for failure messages from the check-key-measures operation and the Set the build result step to set the build status if any are found. In this example the build is set to failed if any of the messages are detected using a simple OR’d regex.
The messages are: –
FAIL! fat0 has increased by FAIL! fat1 has increased by FAIL! fat2 has increased by FAIL! feedbackDependencies has increased by FAIL! specViolationDependencies has increased by FAIL! totalProblemDependencies has increased by FAIL! specItemViolations has increased by FAIL! biggestClassTangles has increased by FAIL! tangledDesign has increased by FAIL! numViolations has increased by
if desired a different build status can be set for the messages by creating multiple Text Finder steps.
The next step is also a single conditional that only runs if the build is successful. It executes a shell command that updates the baseline argument of the check-key-measures, check-spec and check-architecture operations in the structure101-build-config.xml file and then commits the changes.
The awk command replaces the line containing the baseline argument with the content of the baseline_tag variable. This should be identical to the variable used to set the label argument.
awk -v baseline_tag="\<argument name\=\"baseline\" value\=\"$BRANCH_NAME$BUILD_ID\"/\>" '{gsub("\<argument name=\"baseline\" value\=\".*", baseline_tag)}1' structure101-build-config.xml > baseline-structure101-build-config.xml mv -f baseline-structure101-build-config.xml structure101-build-config.xml git commit -am "Increment baseline label"
Finally the Git Publisher Post-build Action is used to push the baseline change to the repository.
Process Considerations
The automated update of the baseline version is critical to the success of the process. For this reason it is suggested that that updates to the structure101-build-config.xml file are carefully controlled. After the initial publish further manual publishing of snapshots to the Structure101 repository is not recommended.
Forcing Success for a Build Failing the Structure101 Checks
It may be necessary to force the success of a failing build. This can be achieved by manually updating the baseline arguments in the structure101-build-config.xml file to the label of the last failed build. The violations causing the failure will no longer be treated as new and the build will succeed.
Updating the Structure Spec or Diagrams
The process for updating (or creating new) architecture diagrams or structure spec is simply to commit the modifed java.hsp file to source control. The next Jenkins build will check out the updated file and perform the check operations using the local spec and architecture diagrams in the Structure101 project file. The properties useProjectFileSpec and useProjectFileDiagrams force this behaviour.
Potential Problems
The Structure101 Groups are not displaying in the Measures Page
The Structure101 Quality Profile is not configured for the SonarQube project. Update the project configuration.
The SonarQube scanner is not configured with the structure101.reportdir system property or it does not match the output-file property of the check-key-measures operation. Check the build log for error messages and update the build config file and Jenkins SonarQube step to use the same path.
Leave a Reply