ci: migrate Sonar analysis to @3 tasks and Java 21#589
Conversation
SonarQube Cloud no longer supports Java 17. The vendored Sonar templates
used the old SonarCloud{Prepare,Analyze,Publish}@1 tasks, which have no
JDK-selection input, so the scanner ran on the agent's default Java 17.
Bump all three tasks to @3 and pass jdkversion: JAVA_HOME_21_X64 to the
Analyze task, matching the @common templates. Covers all activity packs
via the shared stage.sonar.yml.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The @1 -> @3 task bump alone was insufficient: SonarCloudPrepare@3 publishes v3-namespaced variables that this repo's cross-stage (Build -> PublishSonar) scanner handoff did not carry. - upload/download: probe and republish the v3 scanner-path variables (SONAR_SCANNER_DOTNET_EXE/DLL) alongside the legacy names. - upload setSonarVariables + stage.sonar.yml: transfer the v3 task-state variables across the stage boundary using the names the @3 tasks actually read/require (SONAR_SCANNER_MODE, SONAR_ENDPOINT, SONAR_SCANNER_REPORTTASKFILE, SONAR_SERVER_VERSION; SONARQUBE_SCANNER_PARAMS keeps its legacy name), verified against SonarSource's v3 TaskVariables enum. - stage.sonar.yml: patch SONAR_SCANNER_REPORTTASKFILE to the PublishSonar job's temp path (no isOutput, so the in-job Analyze/Publish tasks read the rewrite). Cross-validated with Codex (4 rounds, final verdict: no findings). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Updates the vendored Azure Pipelines SonarCloud templates to use the SonarCloud v3 (@3) tasks and run analysis with Java 21, while keeping the existing two-stage “prepare in Build / analyze+publish in PublishSonar” split working by propagating the renamed v3 SONAR_* variables and patching the report-task file path.
Changes:
- Migrate SonarCloud tasks from
@1to@3across prepare/analyze/publish templates. - Run Sonar analysis on Java 21 via
SonarCloudAnalyze@3jdkversion: JAVA_HOME_21_X64. - Update cross-stage artifact/variable ferrying for v3 (
SONAR_*variables, scanner-path env var probing) and patchSONAR_SCANNER_REPORTTASKFILEin the PublishSonar job.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| Activities/.pipelines/templates/stage.sonar.yml | Imports v3 Sonar variables from Build stage outputs and patches SONAR_SCANNER_REPORTTASKFILE for the PublishSonar agent temp directory. |
| Activities/.pipelines/templates/Sonar/upload-sonar-build-output.yml | Extends scanner-path discovery to support both v1 and v3 env var names; exports v3 SONAR_* variables plus original temp path as outputs. |
| Activities/.pipelines/templates/Sonar/download-sonar-build-output.yml | Restores scanner-path variables in the PublishSonar job for both v1 and v3 env var names. |
| Activities/.pipelines/templates/Sonar/publish-sonar-coverage.yml | Switches Quality Gate publish task to SonarCloudPublish@3. |
| Activities/.pipelines/templates/Sonar/prepare-sonar-coverage.yml | Switches prepare task to SonarCloudPrepare@3. |
| Activities/.pipelines/templates/Sonar/analyze-sonar-coverage.yml | Switches analyze task to SonarCloudAnalyze@3 and selects Java 21. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Address PR review: replace non-terminating Write-Error with throw in the upload/download scanner-path steps so the job aborts with a clear message instead of continuing into an empty Copy-Item / missing-scanner secondary failure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SonarScanner for .NET 10.x auto-provisions its own JRE on the Build agent at
'begin' and bakes that agent-local path into <JavaExePath> in
SonarQubeAnalysisConfig.xml. The config is relocated to the separate RunSonar
agent, where the path does not exist, so the scanner's JAVA_HOME check failed at
'end' ("JAVA_HOME ... does not point to a valid Java home folder").
Repoint <JavaExePath> at the RunSonar agent's local JDK 21 (JAVA_HOME_21_X64,
pre-installed on windows-latest) before the analyze task. Mirrors the fix merged
in UiPath/Activities#38694.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pin SonarCloudPrepare/Analyze/Publish to the reviewed version 3.4.3 instead of the floating @3. Floating major-version tags auto-adopt future 3.x releases without review, which is the supply-chain exposure flagged by GitHub Advanced Security (azurepipelines:S7637). Consistent with the existing PatchSonarQubeTask@0.7921.14273 pin. Note: these pins must be bumped in lockstep when the AzDO SonarQube Cloud extension is updated, or the pipeline fails to compile ("A task is missing"). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Non-blocking architectural observation: repeated ad hoc path-patching across split Prepare/Analyze/Publish jobs Not a defect in this PR — just a pattern worth flagging for the team to weigh, since it keeps recurring. This pipeline splits Sonar work across separate jobs/agents: "Prepare" runs on one agent (downloading the scanner, generating config files with that agent's local paths baked in), while "Analyze" and "Publish" run later on a different agent. Whenever the generated config references an agent-specific path, it breaks across that agent boundary, and the fix so far has been a bespoke find/replace "patch" step per broken path. This PR adds two more such patches in Functionally this is fine and the PR's fixes look reasonable on their own. Just flagging that every future SonarScanner/SonarCloud extension change that bakes in a new agent-local path will likely need patch #4, #5, etc. It might be worth a future discussion on whether running prepare/analyze/publish in the same job/agent (or another way of avoiding the cross-agent path issue at the source) would be more sustainable than continuing to add patches — but that's an architectural call for the team, not something this PR needs to solve. |
LiviuPonova
left a comment
There was a problem hiding this comment.
Approving — the overall direction (fixing the JDK-21/agent mismatch and hardening the scanner-path lookup) is solid, and I left 6 review comments (5 inline + 1 general) with suggested follow-ups.
One item is worth calling out explicitly before merge: the new fail-fast throw in upload-sonar-build-output.yml (missing Sonar Scanner directory) currently sits inside a step marked continueOnError: true, so it can never actually fail the job — the intended hardening doesn't take effect yet. Please take a look at that one in particular; the rest are lower-severity cleanup/maintainability notes (hardcoded task version repeated across files, a duplicated env-var alias list, JDK version hardcoded in two places) plus one non-blocking architectural observation about the growing number of ad hoc path patches across the split Prepare/Analyze/Publish jobs.
Approving on the basis that these get addressed before/at merge.
- stage.sonar.yml: gate the report-task-file patch behind RunAnalysis (like its sibling steps) and guard the .Replace() against an empty OriginalTempPath, which would otherwise throw ArgumentException and fail the job. - upload-sonar-build-output.yml: add a separate "Verify Sonar scanner was staged" step without continueOnError, so a missing scanner actually fails the job (the copy step's throw was neutralized by its pre-existing continueOnError: true). - Hoist the SonarCloud task version to a single source of truth: sonarTaskVersion in stage.start.yml, threaded to prepare/analyze/publish, instead of repeating the literal 3.4.3 in four places. Bump one spot on future extension updates. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Fixed in 36ad237: added a separate Verify Sonar scanner was staged step (without |
Address two further review findings on duplicated literals: - JDK env-var name (JAVA_HOME_21_X64) was in the analyze jdkVersion default and again in the stage.sonar.yml JavaExePath patch step. Hoisted to sonarJdkVersion in stage.start.yml, threaded to both. - The 8 scanner-path variable names were hand-synced between the upload probe and the download republish. Hoisted to sonarScannerVarsDll/sonarScannerVarsExe in stage.start.yml; both templates now derive their lists from these. Each value is now a single literal in stage.start.yml. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…8263)
The single-source hoist interpolated ${{ parameters.* }} directly into inline
PowerShell blocks, which SonarCloud flags as BLOCKER script-injection
vulnerabilities (azurepipelines:S7630 / S8263) - pipeline parameters are treated
as untrusted input. This gave new code an E security rating and failed the gate.
Pass the parameters through each step's env: mapping and read them as $env:*
inside the scripts (the rule's sanctioned mitigation). The values still come from
the single source in stage.start.yml; only the delivery channel changed. The
task-version reference is unaffected (not a script block).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Context
The activity packs run SonarCloud analysis through vendored pipeline templates under
Activities/.pipelines/templates/(not the shared@commonrepo). The scan is split across two stages:SonarCloudPrepare(begin) runs in the Build stage, whileSonarCloudAnalyze/SonarCloudPublish(end) run in a separatePublishSonarjob — homemade upload/download/patch steps ferry the scanner and its state between them. All six packs share this chain viastage.start.yml -> stage.sonar.yml.Problem Statement
SonarQube Cloud no longer supports Java 17 and fails the analysis: "The version of Java (17) ... is deprecated ... upgrade to Java 21 or later." Every pack's Sonar stage is red.
Behavior Before This PR
The Sonar stage runs the legacy
SonarCloud*@1tasks with no JDK selection; the scanner picks the agent's default Java 17 and the end step aborts with the deprecation error. No coverage or quality gate is published.Behavior After This PR
The
@3tasks run the analysis on Java 21 (jdkversion: JAVA_HOME_21_X64); the scanner and its v3 task state cross the Build -> PublishSonar boundary intact, the end step completes, and the quality gate publishes.Implementation
Bumping
@1 -> @3alone was insufficient:SonarCloudPrepare@3moved its cross-task variables to theSONAR_*namespace (SONAR_SCANNER_MODE,SONAR_ENDPOINT,SONAR_SCANNER_REPORTTASKFILE,SONAR_SERVER_VERSION; onlySONARQUBE_SCANNER_PARAMSkept its old name) and its scanner-path vars (SONAR_SCANNER_DOTNET_EXE/DLL). Because this repo splits the tasks across stages, the upload/download/transfer steps were updated to carry the v3 names —Analyze@3hard-fails withoutSONAR_SCANNER_MODE,Publish@3withoutSONAR_ENDPOINT. Names verified against SonarSource'ssonarcloud-v3TaskVariablesenum. The report-task-file is re-pointed to the PublishSonar job's temp dir withoutisOutput, so the same-job tasks read the rewrite.Caveats / Potential Issues
@3tasks require the SonarQube Cloud (v3) AzDO extension installed org-wide, or the pipeline fails to compile ("A task is missing").PatchSonarQubeTask@0.7921.14273pin (stage.sonar.yml) is unchanged — confirm it stays valid against the installed extension payload.SONAR_ENDPOINTcould not be validated statically; it needs a real run.How to Test
Activities/Java/*, or queue it manually) and confirm: (1) the pipeline compiles, and (2) theRunSonarjob's "Run Code Analysis" step completes without the Java-version error and the quality gate publishes.🤖 Generated with Claude Code