|
4 | 4 |  |
5 | 5 |  |
6 | 6 |
|
7 | | -Debug Salesforce deployment failures in seconds — Claude analyses your errors, coverage gaps, and PMD violations together and pinpoints the root cause instantly. |
8 | | -No more manually reading logs across three tools — get a ranked, component-level diagnosis with exact fixes, ready to act on. |
| 7 | +**Debug Salesforce deployment failures in seconds using AI-powered root cause analysis with Claude.** |
| 8 | +When a deployment fails, engineers waste time switching between logs, coverage reports, and static analysis tools to manually piece together what went wrong — this tool does that correlation automatically and tells you exactly what to fix first. |
9 | 9 |
|
10 | 10 | > Salesforce's CLI tools produce structured JSON output that no open source tool currently cross-correlates into a ranked diagnosis. This project fills that gap — there is no equivalent in the Salesforce ecosystem today. |
11 | 11 |
|
12 | 12 | --- |
13 | 13 |
|
14 | 14 | ## Problem |
15 | 15 |
|
16 | | -When a deployment fails, engineers read raw logs, pull coverage reports, and run PMD scans — then manually piece together why it broke across three disconnected tools. |
| 16 | +When a Salesforce deployment fails, the information you need is split across three tools that have no awareness of each other: |
17 | 17 |
|
18 | | -- Deployment logs show *what* failed, not *why* |
19 | | -- Coverage gaps and code violations have no visible connection to the error |
20 | | -- Correlating all three manually is slow, error-prone, and blocks every release |
| 18 | +- The deployment log tells you `OpportunityService` threw a `NullPointerException` — but not why |
| 19 | +- The coverage report shows 62% — but has no connection to the exception |
| 20 | +- PMD flags 120 violations — but doesn't tell you which ones caused the failure |
| 21 | + |
| 22 | +An engineer must open all three, read each output, reason about the connections under pressure, and decide what to fix first. That process is slow, error-prone, and entirely manual. |
| 23 | + |
| 24 | +--- |
| 25 | + |
| 26 | +## Solution |
| 27 | + |
| 28 | +This tool accepts your deployment metrics as a single JSON payload, sends them to Claude with a strict schema contract, and returns a structured diagnosis: |
| 29 | + |
| 30 | +- **Risks** — each issue ranked by severity with the specific component named |
| 31 | +- **Root causes** — the technical reason per component, not a restatement of the error |
| 32 | +- **Recommendations** — ordered P0 → P3, with exact fixes ready to act on |
| 33 | + |
| 34 | +Unlike traditional DevOps tools that surface logs and metrics, this system provides actionable insights and prioritizes fixes using LLM-based reasoning across all three signals simultaneously. |
21 | 35 |
|
22 | 36 | --- |
23 | 37 |
|
24 | | -## How This Differs from Standard DevOps Tools |
| 38 | +## How It Differs from Standard DevOps Tools |
25 | 39 |
|
26 | 40 | | | Traditional tools | This project | |
27 | 41 | |---|---|---| |
28 | 42 | | Output | Raw logs, metrics, violation counts | Root cause, ranked recommendations | |
29 | 43 | | Signal handling | One tool per signal, no cross-referencing | All three signals correlated in one pass | |
30 | 44 | | Next step | Engineer manually interprets and prioritises | Fix order is explicit — P0 first | |
31 | 45 |
|
32 | | -Standard tools report faithfully. This tool reasons — it tells you which signal caused the others and what to fix first. |
33 | | - |
34 | 46 | --- |
35 | 47 |
|
36 | 48 | ## Why Claude |
@@ -99,25 +111,27 @@ python main.py --input input.json --live |
99 | 111 |
|
100 | 112 | ## Risk Scoring |
101 | 113 |
|
102 | | -Coverage below 75% is a hard Salesforce platform blocker with no override — so it carries the highest weight. Active runtime failures block the pipeline immediately. Critical PMD violations are serious but do not prevent deployment on their own. |
| 114 | +Risk is derived from three dimensions that reflect Salesforce deployment reality: |
103 | 115 |
|
104 | | -| Dimension | Max Points | Trigger | |
| 116 | +| Dimension | Max Points | Why it matters | |
105 | 117 | |---|---|---| |
106 | | -| Code coverage | +4 | < 75% — no override possible | |
107 | | -| Deployment failures | +3 | Runtime errors (+2) and failed tests (+1) stack | |
108 | | -| Critical PMD violations | +2 | SOQL in loops, hardcoded IDs — governor limit risk | |
| 118 | +| Code coverage | +4 | Below 75% is a hard platform blocker — no override possible | |
| 119 | +| Deployment failures | +3 | Runtime errors (+2) and failed tests (+1) stack — pipeline stops immediately | |
| 120 | +| Critical PMD violations | +2 | SOQL in loops, hardcoded IDs — governor limit failures under production load | |
109 | 121 |
|
110 | 122 | | Score | Risk Level | |
111 | 123 | |---|---| |
112 | 124 | | 0–2 | 🟢 Low — deployment can proceed | |
113 | 125 | | 3–5 | 🟡 Medium — quality issues, no blockers | |
114 | 126 | | 6–10 | 🔴 High — at least one active blocker | |
115 | 127 |
|
| 128 | +Coverage carries the highest weight because it is the only signal that unconditionally blocks deployment with no workaround. |
| 129 | + |
116 | 130 | --- |
117 | 131 |
|
118 | 132 | ## Example: Debugging a Failed Salesforce Deployment |
119 | 133 |
|
120 | | -A deployment fails during a sprint release. The engineer has three data points: coverage is below threshold, `OpportunityService` threw an exception, and the static analyser flagged violations. |
| 134 | +A deployment fails mid-sprint. The engineer has three data points — coverage below threshold, a `NullPointerException` in `OpportunityService`, and 120 PMD violations — with no obvious connection between them. |
121 | 135 |
|
122 | 136 | ### Input |
123 | 137 |
|
@@ -146,60 +160,58 @@ A deployment fails during a sprint release. The engineer has three data points: |
146 | 160 | "risk_level": "High", |
147 | 161 | "risks": [ |
148 | 162 | { |
149 | | - "issue": "Code coverage at 62% — 13 points below the 75% Salesforce deployment threshold", |
| 163 | + "issue": "Code coverage at 62% — 13 points below the 75% deployment threshold, hard blocker", |
150 | 164 | "severity": "Critical", |
151 | 165 | "component": "Overall Org" |
152 | 166 | }, |
153 | 167 | { |
154 | | - "issue": "NullPointerException in OpportunityService — all 3 dependent test methods failing, pipeline blocked", |
| 168 | + "issue": "NullPointerException in OpportunityService — 3 test methods failing, pipeline cannot proceed", |
155 | 169 | "severity": "Critical", |
156 | 170 | "component": "OpportunityService" |
157 | 171 | }, |
158 | 172 | { |
159 | | - "issue": "15 critical PMD violations — SOQL-in-loop patterns will trigger governor limit failures under production load", |
| 173 | + "issue": "15 critical PMD violations — SOQL-in-loop and hardcoded record IDs confirmed, governor limit failures will occur under bulk record processing", |
160 | 174 | "severity": "High", |
161 | 175 | "component": "OpportunityService" |
162 | 176 | } |
163 | 177 | ], |
164 | 178 | "root_causes": [ |
165 | 179 | { |
166 | | - "cause": "OpportunityService calls opp.Account.Name without a null-guard — Account is null because @TestSetup creates Opportunity records without inserting a parent Account first", |
| 180 | + "cause": "OpportunityService accesses opp.Account.Name without a null-guard — Account is null because @TestSetup inserts Opportunity records without a parent Account, so every method that traverses the relationship throws at runtime", |
167 | 181 | "component": "OpportunityService" |
168 | 182 | }, |
169 | 183 | { |
170 | | - "cause": "The same @TestSetup gap suppresses execution of every method that traverses the Account relationship — this is why coverage dropped to 62%, not a separate coverage problem", |
| 184 | + "cause": "The @TestSetup gap suppresses execution of all methods that depend on related Account data — coverage dropped to 62% as a direct consequence of the test failures, not as a separate problem", |
171 | 185 | "component": "Overall Org" |
172 | 186 | } |
173 | 187 | ], |
174 | 188 | "recommendations": [ |
175 | 189 | { |
176 | | - "action": "In OpportunityService, replace opp.Account.Name with opp.Account?.Name — the safe navigation operator prevents the NullPointerException when Account is not loaded", |
| 190 | + "action": "In OpportunityService, replace opp.Account.Name with opp.Account?.Name — the safe navigation operator prevents the NullPointerException when Account is not populated on the record", |
177 | 191 | "priority": "P0 - Immediate" |
178 | 192 | }, |
179 | 193 | { |
180 | | - "action": "In OpportunityServiceTest @TestSetup, insert an Account record and set AccountId on each Opportunity before any test method runs — this unblocks all 3 failing tests and recovers coverage above 75% automatically", |
| 194 | + "action": "In OpportunityServiceTest @TestSetup, insert an Account record first and assign its Id to AccountId on each Opportunity — this unblocks all 3 failing tests and recovers coverage above 75% automatically", |
181 | 195 | "priority": "P0 - Immediate" |
182 | 196 | }, |
183 | 197 | { |
184 | | - "action": "Run 'sf scanner run --category Performance --target force-app/main/default/classes/OpportunityService.cls' and move all SOQL calls outside loop bodies before the next production release", |
| 198 | + "action": "Run 'sf scanner run --category Performance --target force-app/main/default/classes/OpportunityService.cls' — move all SOQL calls above loop bodies into a single typed query: Map<Id, Account> accountMap = new Map<Id, Account>([SELECT Id, Name FROM Account WHERE Id IN :accountIds])", |
185 | 199 | "priority": "P1 - High" |
| 200 | + }, |
| 201 | + { |
| 202 | + "action": "Add two CI gates on pull requests: (1) 'sf scanner run --severity-threshold 2 --target force-app' to block on critical PMD violations; (2) parse 'sf project deploy start --test-level RunLocalTests --json' output and fail the build if result.numberTestsCompleted / result.numberTestsTotal falls below 0.80", |
| 203 | + "priority": "P2 - Medium" |
186 | 204 | } |
187 | 205 | ] |
188 | 206 | } |
189 | 207 | ``` |
190 | 208 |
|
191 | | -### What this shows |
192 | | - |
193 | | -- **One root cause, three symptoms.** A single `@TestSetup` gap caused the exception, the 3 test failures, and the coverage drop — one fix resolves all of them. |
194 | | -- **Exact fix, not general advice.** P0 recommendations name the specific call to change (`opp.Account.Name` → `opp.Account?.Name`) and exactly what to insert in the test setup. |
195 | | -- **Prioritised.** Two P0 actions unblock the deployment. The P1 SOQL fix is scoped to a specific file and command. |
196 | | - |
197 | 209 | ### Impact |
198 | 210 |
|
199 | | -- **Without this tool:** An engineer opens the deployment log, sees a `NullPointerException`, then separately checks coverage (62% — why?), then runs PMD and gets 120 violations with no clear connection to the runtime error. Correlation is manual, slow, and easy to get wrong. |
| 211 | +- **Without this tool:** An engineer opens the deployment log, sees a `NullPointerException`, then separately checks coverage (62% — why?), then runs PMD and gets 120 violations with no clear connection to the runtime error. Correlation is manual, slow, and easy to get wrong under release pressure. |
200 | 212 | - **With this tool:** One command surfaces that all three issues share a single root cause — a missing `Account` insert in `@TestSetup`. The fix is two lines of code, not three separate investigations. |
201 | | -- **Time saved:** The manual process requires switching between three tools and reasoning about signal relationships under pressure. This tool does that step automatically and returns a prioritised fix list in seconds. |
202 | | -- **Trust:** Every recommendation names the exact component, method, and code change — nothing generic, nothing to interpret before acting. |
| 213 | +- **What Claude identified beyond the raw input:** The input only states `"error": "NullPointerException"` and `"failed_tests": 3`. Nothing in the payload mentions `@TestSetup`, parent records, or the Account relationship. The causal link between the exception and the coverage drop was inferred — not extracted from the data. |
| 214 | +- **Time saved:** The manual correlation step — switching tools, reading outputs, reasoning about signal relationships — is eliminated. The fix list is ready before the editor is opened. |
203 | 215 |
|
204 | 216 | --- |
205 | 217 |
|
@@ -301,7 +313,8 @@ Claude connected the `LimitException` to the SOQL-in-loop PMD violations — ide |
301 | 313 | ## Real-World Applicability |
302 | 314 |
|
303 | 315 | This tool is designed to integrate directly into Salesforce DX workflows and CI/CD pipelines — the input schema maps to the JSON output of `sf project deploy` and `sf scanner run`, so deployment logs and static analysis results can be piped in automatically rather than collected manually. |
304 | | -Native pipeline integration (GitHub Actions, Jenkins, Copado) is on the roadmap; the current CLI interface is the foundation for that. |
| 316 | +Deployment logs and static analysis results are already captured by most pipeline configurations; this tool adds the reasoning layer on top of data teams already have. |
| 317 | +Native pipeline integration (GitHub Actions, Jenkins, Copado) is on the roadmap — the current CLI interface is the foundation for that. |
305 | 318 |
|
306 | 319 | --- |
307 | 320 |
|
|
0 commit comments