I was also facing this issue, we dont use Jenkins Pipeline jobs so using below stage was not an option for me
stage("Quality gate") {
steps {
waitForQualityGate abortPipeline: true
}
}
And I didn't want to use some custom shell script execution to check using Sonar WEB APIs as its not standard, plus I then had to configure this in multiple jobs and in future for any new Job this has to be remembered so kind of not scalable solution in my opinion.
So, I explored Jenkins plugins to solve the problem. There are few like below however both have known vulnerability of Credentials Transmitting in plain text.

So, further more analysis and I found the right way of doing it. There is a BuildBreaker plugin from SonarQube itself. Read more about this @ https://github.com/adnovum/sonar-build-breaker
This can be installed from the SonarQube market place

Once you opt to install, it will be downloaded and shown as Installation Pending as the installation would reflect on the restart of SonarQube Server
So, you have to connect to SonarQube Server and Restart the Server.
Once done it will by default break the Jenkins build with errors similar to below
10:43:54 INFO: Executing post-job 'Forbidden Configuration Breaker'
10:43:54 INFO: Executing post-job 'Quality Gate Breaker'
10:43:54 INFO: Waiting for report processing to complete...
10:44:04 INFO: Quality gate status: ERROR
10:44:04 ERROR: Reliability Rating on New Code: 3 > 1
10:44:04 ERROR: [BUILD BREAKER] Project did not meet 1 conditions
10:44:05 INFO: ------------------------------------------------------------------------
10:44:05 INFO: EXECUTION FAILURE
10:44:05 INFO: ------------------------------------------------------------------------
10:44:05 INFO: Total time: 59.701s
10:44:05 INFO: Final Memory: 86M/2627M
10:44:05 INFO: ------------------------------------------------------------------------
10:44:05 ERROR: Error during SonarQube Scanner execution
10:44:05 java.lang.IllegalStateException: Project does not pass the quality gate.
Good part is, this behaviour can be controlled by a config which goes in sonar-project.properties. If this is set to true then the build will not break. By default the build will break
sonar.buildbreaker.skip=true
So, this way is more configurable, generic and useful.