Chapter 09Lesson 02~160 minutes

Rules, Rule Types, Severities, Quality Profiles, and Customization: Guided Hands-On Workflow

Run a bounded same-revision experiment: extend Python Sonar way, lower one S3776 threshold in a project-specific child profile, prove the rule-specific issue delta, then revert to parent policy.

S3776Sonar way childSame revisionBefore / afterRollback

Learning objectives

  • Create a synthetic Python fixture and least-privilege analysis token.
  • Record instance mode, S3776 metadata and baseline profile assignment.
  • Create a disposable child profile without changing the language default.
  • Override one rule parameter and correlate analysis to CE/issue/gate evidence.
  • Revert the override and clean up credentials safely.

1. Preflight and safety boundaries

Use only the private/local Community Build server from earlier chapters. Scanner execution uses a project-analysis token; profile changes use an interactive account with Administer Quality Profiles permission. Do not scan with an administrator token.

Do not change: the instance mode, Python language default profile, global exclusions, Quality Gate, plugins, unrelated projects, database/search state or production source. The only policy object created is Academy Python Guardrails, associated only with academy-sonarqube-p09.
export SONAR_HOST_URL='http://127.0.0.1:9000'
sonar-scanner --version
git --version
curl -fsS "$SONAR_HOST_URL/api/system/status" || true

2. Create the disposable fixture

rm -rf sonar-p09
mkdir -p sonar-p09/src sonar-p09/tests
cd sonar-p09
git init
git config user.name 'Academy Learner'
git config user.email 'learner@example.invalid'
cat > src/routing.py <<'PYCODE'
def route(score, premium, active):
    if active:
        if premium:
            if score > 80:
                return "priority"
            return "premium"
        if score > 50:
            return "standard-plus"
    return "standard"
PYCODE
cat > tests/test_routing.py <<'PYTEST'
from src.routing import route

def test_route():
    assert route(90, True, True) == "priority"
PYTEST
cat > sonar-project.properties <<'PROPS'
sonar.projectKey=academy-sonarqube-p09
sonar.projectName=Academy SonarQube P09 Rule Policy Lab
sonar.sources=src
sonar.tests=tests
sonar.sourceEncoding=UTF-8
PROPS
git add . && git commit -m 'p09 controlled rule fixture'
git rev-parse HEAD | tee revision.txt

The function is deliberately below the normal Python S3776 default threshold of 15 but complex enough to cross a much smaller experimental threshold. Record the actual complexity reported by your installed analyzer rather than assuming it.

3. Inspect current policy before mutation

  1. Record Administration → Configuration → Mode; do not switch it.
  2. In Rules, filter Python and retrieve python:S3776.
  3. Record its repository/key, status, tags, current mode-specific classification and configurable threshold. Current guidance uses 15 as the Python default; the installed analyzer is authoritative.
  4. In Quality Profiles → Python, record Sonar way's BUILT-IN/DEFAULT status and active/deprecated counts.
  5. In the disposable project's Quality Profiles settings, record the current Python profile.

4. Baseline scan

read -rsp 'Project-analysis token: ' SONAR_TOKEN; echo
export SONAR_TOKEN
sonar-scanner -X -Dsonar.host.url="$SONAR_HOST_URL" 2>&1 | tee baseline-debug.log
cp .scannerwork/report-task.txt baseline-report-task.txt
grep -E '^(ceTaskId|dashboardUrl|serverUrl|projectKey)=' baseline-report-task.txt

Wait for the referenced Compute Engine task to finish. Record the S3776 issue search and Quality Gate separately. Scanner success, CE success and gate status are three distinct states.

5. Extend Sonar way and associate only the lab project

  1. Quality Profiles → Python → Sonar way → Extend.
  2. Name the child Academy Python Guardrails.
  3. Verify Sonar way is the parent and rules are inherited.
  4. Do not set it as the Python default.
  5. Associate only academy-sonarqube-p09 with the child.

Prediction 1: project-policy state changes while source revision, scanner binary and indexed files stay unchanged. Verify the association independently before changing a rule.

6. Change one inherited parameter

  1. Open the child profile's active rule list and retrieve python:S3776.
  2. Record the inherited threshold and current mode classification.
  3. Select Change and set only the Cognitive Complexity threshold to 3.
  4. Leave severity/impact, the Quality Gate and all other rules unchanged.
  5. Confirm the rule is now shown as overridden.

Prediction 2: the child effective rule configuration changes; Sonar way remains unchanged. If the current analyzer rejects 3, use the smallest valid positive threshold below the measured fixture complexity and record the deviation.

7. Reanalyze the exact same revision

test -z "$(git status --porcelain)" || { git status --short; exit 1; }
git rev-parse HEAD | tee revision-overridden.txt
sonar-scanner -X -Dsonar.host.url="$SONAR_HOST_URL" 2>&1 | tee overridden-debug.log
cp .scannerwork/report-task.txt overridden-report-task.txt

After CE success, filter Issues by python:S3776. Expected evidence is a new cognitive-complexity issue caused by the stricter child threshold. Because the revision is unchanged, the profile override is the causal variable. Preserve the issue's actual measured complexity and allowed threshold.

8. Revert to parent definition

  1. Return to S3776 in the child profile.
  2. Select Revert to Parent Definition.
  3. Keep the project associated with the child for one restore scan so only one variable changes.
sonar-scanner -X -Dsonar.host.url="$SONAR_HOST_URL" 2>&1 | tee restored-debug.log
cp .scannerwork/report-task.txt restored-report-task.txt

Verify that the override marker is gone and the stricter-threshold issue is no longer newly raised under parent policy. Preserve history rather than deleting it.

9. Required evidence

manifest.md — server/scanner/mode/analyzer assumptions
revision.txt — identical revision for all comparisons
rule-before.md — S3776 key/status/classification/threshold
profile-before.md — Sonar way/default/project association
baseline-report-task.txt + CE/issue/gate state
profile-change.md — child parent + threshold old→new + actor/rationale
overridden-report-task.txt + CE/issue/gate state
rollback.md — Revert to Parent Definition proof
restored-report-task.txt + CE/issue state
credentials.md — token metadata only, never the value

10. Cleanup

  1. Revoke the project-analysis token and unset SONAR_TOKEN.
  2. Remove the explicit project/profile association after rollback evidence is complete.
  3. Delete the child profile only after proving no project uses it and preserving its backup/change record.
  4. Delete the lab project/fixture only after evidence is copied.
  5. Leave Sonar way, language defaults, shared caches and server/database/search state untouched.

11. Challenge: choose the correct layer

A teammate wants to loosen the Quality Gate because threshold 3 produces a new maintainability issue. Explain why that changes the wrong layer: this experiment is evaluating a rule parameter in a quality profile. Gate changes alter downstream pass/fail policy and would confound the policy experiment.

Knowledge check

Why use a project-analysis token instead of an admin token for scanning?

Why hold the source revision constant?

Why extend Sonar way?

What proves the override affected analysis?

Why revert the rule before removing the project association?

Next lesson

Design profiles that scale

Lesson 3 compares Extend, Copy and blank profiles, team variants, parameter changes versus issue exceptions, default blast radius and plugin/analyzer provenance.

Official references and version notes

Version and compatibility note

Rechecked on 2026-09-07. Mandatory examples target private/local SonarQube Community Build 26.9.0.129388 and SonarScanner CLI 8.1.0.6389. Current Community Build baseline is 26.9.0.129388; current commercial SonarQube Server baseline is 2026 Release 4.1 with 2026.1.5 as the current 2026 LTA patch line. New Community Build instances use MQR Mode by default, but every lab records the actual mode and never switches it. MQR uses Blocker/High/Medium/Low/Info severities on software-quality impacts; Standard Experience uses Bug/Vulnerability/Code Smell/Security Hotspot types with Blocker/Critical/Major/Minor/Info severity. Sonar way is built-in and immutable. The hands-on experiment extends Python Sonar way and tunes python:S3776; verify installed rule metadata before changing it because analyzer behavior can evolve. No third-party plugin, commercial edition, CI provider, enterprise identity, SonarQube Cloud account, branch/PR analysis or production source is required.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.