{"id":75852,"date":"2025-09-10T12:09:19","date_gmt":"2025-09-10T06:39:19","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=75852"},"modified":"2026-01-02T18:06:24","modified_gmt":"2026-01-02T12:36:24","slug":"end-to-end-code-quality-automation-sonarqube-in-jenkins-with-jira-ticketing-and-aws-sso-integration","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/end-to-end-code-quality-automation-sonarqube-in-jenkins-with-jira-ticketing-and-aws-sso-integration\/","title":{"rendered":"End-to-End Code Quality Automation: SonarQube in Jenkins with JIRA Ticketing and AWS SSO Integration"},"content":{"rendered":"<p>In modern software development, code quality assurance is no longer optional \u2014 it\u2019s a foundational requirement. Delivery teams usually want three things when it comes to code quality:<\/p>\n<ol>\n<li><strong>Consistency<\/strong> \u2013 rules should apply equally across all services.<\/li>\n<li><strong>Governance<\/strong> \u2013 changes to quality standards must be visible and auditable.<\/li>\n<li><strong>Zero manual toil<\/strong>\u00a0\u2013 automation should handle checks, reporting, and enforcement.<\/li>\n<\/ol>\n<p>This blog shows how to achieve all three by wiring <strong>SonarQube<\/strong> into <strong>Jenkins,<\/strong> driving <strong>Quality Gates<\/strong> from service property files, auto-opening JIRA tickets when thresholds are loosened, and securing SonarQube with <strong>AWS SSO (SAML)<\/strong>.<\/p>\n<h3><strong>Objectives<\/strong><\/h3>\n<p>By the end of this guide, you\u2019ll understand how to:<\/p>\n<ul>\n<li>Integrate SonarQube with Jenkins CI\/CD pipelines.<\/li>\n<li>Create Sonar projects and Quality Gates dynamically.<\/li>\n<li>Use service-specific property files to define thresholds.<\/li>\n<li>Run SonarQube analysis inside pipelines.<\/li>\n<li>Automatically create JIRA tickets if standards are weakened.<\/li>\n<li>Secure SonarQube with AWS SSO for enterprise-ready access management.<\/li>\n<\/ul>\n<p><strong>1. Integrating SonarQube with Jenkins<\/strong><\/p>\n<p>The first step is to bring code quality scanning into your CI\/CD pipeline. Jenkins already runs builds, tests, and deployments \u2014 adding SonarQube into the flow ensures every build is analyzed.<\/p>\n<p><strong>Configure Jenkins with SonarQube<\/strong><\/p>\n<ol>\n<li>Install the SonarQube Scanner plugin in Jenkins.<\/li>\n<li>Navigate to Manage Jenkins \u2192 Configure System and add:<\/li>\n<\/ol>\n<ul>\n<li>SonarQube server URL<\/li>\n<li>Authentication Token (generate in SonarQube under your account settings)<\/li>\n<\/ul>\n<p>3. Add a SonarQube Scanner under Global Tool Configuration.<\/p>\n<p>Once configured, simply add a <strong>withSonarQubeEnv<\/strong> stage in your pipeline.<\/p>\n<h3>2. Creating Projects and Quality Gates Dynamically<\/h3>\n<p>In most organizations, there are dozens (sometimes hundreds) of repositories. Manually creating a Sonar project and assigning a Quality Gate for each repo is error-prone.<\/p>\n<p>Instead, we can automate this:<\/p>\n<ul>\n<li>Every Jenkins job creates a matching Sonar project.<\/li>\n<li>A Quality Gate is automatically created with the same name.<\/li>\n<li>The pipeline attaches the gate to the project.<\/li>\n<\/ul>\n<p>Use SonarQube Web APIs to <strong>create<\/strong> the <strong>project<\/strong>, <strong>create<\/strong> a <strong>gate<\/strong> with the same name, and attach it to the project. Doing this on every run is fine as long as you write idempotent calls.<\/p>\n<p><strong>Example<\/strong> :<\/p>\n<p># <em>Create (no-op if exists; handle 4xx gracefully in script):<\/em><\/p>\n<p><span style=\"color: #808080;\"><strong>curl -u &#8220;$SONAR_TOKEN:&#8221; -X POST &#8220;$SONAR_URL\/api\/projects\/create&#8221; -d &#8220;project=${serviceName}&#8221; -d &#8220;name=${serviceName}&#8221;<\/strong><\/span><\/p>\n<p># <em>Create Quality Gate (handle \u201calready exists\u201d):<\/em><\/p>\n<p><span style=\"color: #808080;\"><strong>curl -u &#8220;$SONAR_TOKEN:&#8221; -X POST &#8220;$SONAR_URL\/api\/qualitygates\/create&#8221; -d &#8220;name=${serviceName}&#8221;<\/strong><\/span><\/p>\n<p># <em>Attach gate to project:<\/em><\/p>\n<p><span style=\"color: #808080;\"><strong>curl -u &#8220;$SONAR_TOKEN:&#8221; -X POST &#8220;$SONAR_URL\/api\/qualitygates\/select&#8221; -d &#8220;gateName=${serviceName}&#8221; -d &#8220;projectKey=${serviceName}&#8221;<\/strong><\/span><\/p>\n<p>We can create a single function for executing above API\u2019s which does exactly this: create project \u2192 create gate \u2192 select gate \u2192 then call the reconciliation logic below.This way, developers don\u2019t need to raise tickets or request access \u2014 new services get onboarded to SonarQube automatically.<\/p>\n<p><strong>Benefit<\/strong>: Standardization. Every project follows the same onboarding process, leaving no gaps.<\/p>\n<h3>3. Property-Driven Quality Gates<\/h3>\n<p>One common problem is that quality gates are often <strong>hard-coded<\/strong> or <strong>manually adjusted<\/strong> in the SonarQube UI. This leads to drift: one service has stricter standards, another has weaker ones, and nobody knows why.<\/p>\n<p>The fix? Use a <strong>service property file<\/strong> that declares thresholds in plain text:<\/p>\n<p># qa-service-ordering-managemnet.properties (example):<\/p>\n<p><span style=\"color: #808080;\"><strong>qualitygate.bugs = threshold:0, operator:GT<\/strong><\/span><\/p>\n<p><span style=\"color: #808080;\"><strong>qualitygate.vulnerabilities = threshold:0, operator:GT<\/strong><\/span><\/p>\n<p><span style=\"color: #808080;\"><strong>qualitygate.code_smells = threshold:50, operator:GT<\/strong><\/span><\/p>\n<p><span style=\"color: #808080;\"><strong>qualitygate.coverage = threshold:80, operator:LT<\/strong><\/span><\/p>\n<p><strong>Rules:<\/strong><\/p>\n<ol>\n<li>We can use the key to start with <strong>qualitygate<\/strong>.<\/li>\n<li>Values follow <strong>threshold:&lt;number&gt;, operator:&lt;GT|LT|EQ&gt;<\/strong>.<\/li>\n<\/ol>\n<ul>\n<li>For \u201cmust be at least 80% coverage\u201d use operator:LT with threshold:80 (fail if actual is <strong>less than<\/strong> 80 \u2192 \u201cerror when LT 80\u201d).<\/li>\n<li>For \u201cno more than 0 critical issues\u201d use operator:GT with threshold:0 (fail if actual is <strong>greater than<\/strong> 0).<\/li>\n<\/ul>\n<p><strong>Defaulting behavior<\/strong>: If a service-specific file is missing or malformed, load a global default (e.g., default-quality-gate.properties) from your shared library.<\/p>\n<p><strong>Benefit:<\/strong> Developers control their own quality rules transparently, but governance is centralized.<\/p>\n<h3>4. Reconcile Gate Conditions from Properties (the Important Part)<\/h3>\n<p>Your reconciliation function logic enforces governance:<\/p>\n<ol>\n<li>Parse the property file into { metric \u2192 (threshold, operator) }.<\/li>\n<li>Fetch current conditions:<\/li>\n<\/ol>\n<p><span style=\"color: #808080;\"><strong>curl -s -u &#8220;$SONAR_TOKEN:&#8221; &#8220;$SONAR_URL\/api\/qualitygates\/show?name=${serviceName}&#8221; | jq -c &#8216;.conditions[]&#8217;<\/strong><\/span><\/p>\n<p>3. Delete any existing gate condition whose metric is not in the property file (prevents drift).<\/p>\n<p>4. For each metric:<\/p>\n<ul>\n<li>If threshold is increased \u2192 create JIRA ticket (weakening detected).<\/li>\n<li>If threshold is same \u2192 no action.<\/li>\n<li>If threshold is stricter \u2192 update silently.<\/li>\n<li>If missing \u2192 create it.<\/li>\n<\/ul>\n<p>With this logic the function will fetche current metric conditions, deletes any metrics not in the property file, and then updates\/creates conditions as required. The property file remains the single source of truth for quality rules.<\/p>\n<h3><strong>5. Running Sonar Analysis (Maven Example)<\/strong><\/h3>\n<p>Your pipeline stage should run the Sonar Maven plugin and publish JaCoCo XML coverage(if test cases are written by developers otherwise not required):<\/p>\n<p><span style=\"color: #808080;\"><strong>withSonarQubeEnv(&#8216;sonar&#8217;) {<\/strong><\/span><br \/>\n<span style=\"color: #808080;\"><strong>sh &#8220;&#8221;&#8221;<\/strong><\/span><br \/>\n<span style=\"color: #808080;\"><strong>mvn -f pom.xml org.sonarsource.scanner.maven:sonar-maven-plugin:${env.SONAR_MAVEN_PLUGIN_VERSION}:sonar -Dsonar.projectKey=&#8221;${projectKey}&#8221; -Dsonar.projectName=&#8221;${projectKey}&#8221; -Dsonar.coverage.jacoco.xmlReportPaths=target\/site\/jacoco\/jacoco.xml<\/strong><\/span><br \/>\n<span style=\"color: #808080;\"><strong>&#8220;&#8221;&#8221;<\/strong><\/span><br \/>\n<span style=\"color: #808080;\"><strong>}<\/strong><\/span><\/p>\n<p><strong>Benefit<\/strong>: Code that doesn\u2019t meet agreed standards never reaches production.<\/p>\n<h3>6. Security &amp; Secrets<\/h3>\n<p>Because Jenkins pipelines handle tokens and credentials:<\/p>\n<p>&#8211;&gt; Use Jenkins Credentials for:<\/p>\n<ul>\n<li><span style=\"color: #808080;\">SONAR_TOKEN<\/span><\/li>\n<li><span style=\"color: #808080;\">JIRA_USERNAME \/ JIRA_TOKEN<\/span><\/li>\n<\/ul>\n<p>&#8211;&gt; Parameterize SONAR_URL, JIRA_URL, JIRA_PROJECT_KEY, and default property file names via a shared library properties file<br \/>\n<strong>Benefit<\/strong>: Security is enforced by design, not left to developers.<\/p>\n<h3>7.Auto-Creating JIRA Tickets Only When Standards Are Weakened<\/h3>\n<p>The above logic creates a JIRA ticket only when a threshold increases (i.e., when quality is being relaxed). That\u2019s the right governance move.<\/p>\n<p>Implementation points you nailed (and you should keep):<\/p>\n<ul>\n<li><strong>Issue summary<\/strong> and <strong>description<\/strong> clearly state the metric and the change (old \u2192 new).<\/li>\n<li>Map environment (branch\/type) into a custom field if you have one (e.g., \u201cQA\u201d, \u201cSTAGE\u201d, \u201cPRD\u201d).<\/li>\n<li>After creating, <strong>add the ticket to the active sprint<\/strong> (optional) by fetching the current sprint from a board and posting the issue into it.<\/li>\n<li>Parameterize JIRA project key, board ID, and custom field IDs via a <strong>shared properties file.<\/strong><\/li>\n<\/ul>\n<div id=\"attachment_75850\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-75850\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-75850 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-6.53.08\u202fPM-1024x740.png\" alt=\"Jira Ticket\" width=\"625\" height=\"452\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-6.53.08\u202fPM-1024x740.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-6.53.08\u202fPM-300x217.png 300w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-6.53.08\u202fPM-768x555.png 768w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-6.53.08\u202fPM-1536x1110.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-6.53.08\u202fPM-2048x1480.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-6.53.08\u202fPM-624x451.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-75850\" class=\"wp-caption-text\">Jira Ticket<\/p><\/div>\n<h3>Integrating SonarQube with AWS SSO<\/h3>\n<p>As enterprises grow, managing user access becomes critical. Integrate SonarQube with AWS IAM Identity Center (SSO) via SAML.<\/p>\n<p>1. Prerequisites<\/p>\n<ul>\n<li>AWS IAM Identity Center set up:<\/li>\n<\/ul>\n<p><strong>On AWS IAM Identity Center:<\/strong><\/p>\n<ol>\n<li>Create a new SAML application for SonarQube.<\/li>\n<li>Set the ACS (Assertion Consumer Service) URL and Entity ID to what SonarQube expects (from SonarQube\u2019s SAML config or metadata).<\/li>\n<li>Assign users\/groups and download the IdP metadata or note the SSO URL and certificate.<\/li>\n<\/ol>\n<ul>\n<li>Custom SAML app created for SonarQube<\/li>\n<\/ul>\n<p>2. Configure SonarQube for SAML<\/p>\n<p><strong>On SonarQube (sonar.properties or UI if using SAML plugin):<\/strong><\/p>\n<p>Edit sonar.properties:<\/p>\n<p><span style=\"color: #808080;\">sonar.auth.saml.enabled=true<\/span><\/p>\n<p><span style=\"color: #808080;\">sonar.auth.saml.providerName=AWS-SSO<\/span><\/p>\n<p><span style=\"color: #808080;\">sonar.auth.saml.loginUrl=https:\/\/your-idp.awsapps.com\/start<\/span><\/p>\n<p><span style=\"color: #808080;\">sonar.auth.saml.certificate.secured=[certificate]<\/span><\/p>\n<p><span style=\"color: #808080;\">sonar.auth.saml.user.login=NameID<\/span><\/p>\n<p><span style=\"color: #808080;\">sonar.auth.saml.user.name=Attribute<\/span><\/p>\n<p><span style=\"color: #808080;\">sonar.auth.saml.user.email=Attribute<\/span><\/p>\n<p>3. Configure AWS IAM Identity Center<\/p>\n<ul>\n<li>Create a new application<\/li>\n<li>Upload SonarQube metadata (or manually configure ACS\/Entity ID)<\/li>\n<li>Assign users\/groups<\/li>\n<li>Download the SAML metadata file for SonarQube<\/li>\n<\/ul>\n<div id=\"attachment_75851\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-75851\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-75851 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-7.00.35\u202fPM-1024x646.png\" alt=\"SonarQube Login Page\" width=\"625\" height=\"394\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-7.00.35\u202fPM-1024x646.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-7.00.35\u202fPM-300x189.png 300w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-7.00.35\u202fPM-768x485.png 768w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-7.00.35\u202fPM-624x394.png 624w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-2025-09-07-at-7.00.35\u202fPM.png 1486w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-75851\" class=\"wp-caption-text\">SonarQube LogIn Page<\/p><\/div>\n<h3>Conclusion<\/h3>\n<p>With a few disciplined patterns\u2014consistent naming, property-driven gates, idempotent APIs, and governance on threshold raises\u2014you turn SonarQube from a dashboard into a control system. Jenkins executes; SonarQube evaluates; the property file declares policy; and JIRA provides the change log whenever someone tries to loosen standards.<\/p>\n<p>Add AWS SSO on top, and you\u2019ve got frictionless, compliant access that scales with your org.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In modern software development, code quality assurance is no longer optional \u2014 it\u2019s a foundational requirement. Delivery teams usually want three things when it comes to code quality: Consistency \u2013 rules should apply equally across all services. Governance \u2013 changes to quality standards must be visible and auditable. Zero manual toil\u00a0\u2013 automation should handle checks, [&hellip;]<\/p>\n","protected":false},"author":2053,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":3},"categories":[2348],"tags":[1892,4057,8106],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/75852"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/2053"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=75852"}],"version-history":[{"count":3,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/75852\/revisions"}],"predecessor-version":[{"id":77283,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/75852\/revisions\/77283"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=75852"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=75852"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=75852"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}