@salesforce/afv-skills 1.17.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/analyzing-test-failures/SKILL.md +159 -0
- package/skills/building-sf-integrations/SKILL.md +1 -1
- package/skills/checking-devops-prerequisites/SKILL.md +141 -0
- package/skills/configuring-code-analyzer/SKILL.md +482 -0
- package/skills/configuring-code-analyzer/examples/apex-project-config.yml +41 -0
- package/skills/configuring-code-analyzer/examples/ci-github-actions.yml +96 -0
- package/skills/configuring-code-analyzer/examples/fullstack-project-config.yml +46 -0
- package/skills/configuring-code-analyzer/examples/lwc-project-config.yml +26 -0
- package/skills/configuring-code-analyzer/references/ci-cd-templates.md +648 -0
- package/skills/configuring-code-analyzer/references/config-schema.md +257 -0
- package/skills/configuring-code-analyzer/references/diagnostic-flow.md +70 -0
- package/skills/configuring-code-analyzer/references/engine-prerequisites.md +276 -0
- package/skills/configuring-code-analyzer/references/rule-name-resolution.md +67 -0
- package/skills/configuring-code-analyzer/references/troubleshooting.md +298 -0
- package/skills/configuring-code-analyzer/scripts/check-prerequisites.sh +189 -0
- package/skills/configuring-code-analyzer/scripts/generate-config.sh +143 -0
- package/skills/configuring-code-analyzer/scripts/validate-config.sh +153 -0
- package/skills/configuring-quality-gate/SKILL.md +120 -0
- package/skills/configuring-test-provider/SKILL.md +113 -0
- package/skills/creating-fix-work-item/SKILL.md +66 -0
- package/skills/managing-cdc-enablement/SKILL.md +164 -0
- package/skills/managing-cdc-enablement/assets/PlatformEventChannel-template.xml +5 -0
- package/skills/managing-cdc-enablement/assets/PlatformEventChannelMember-template.xml +11 -0
- package/skills/managing-cdc-enablement/references/deploy-troubleshooting.md +73 -0
- package/skills/managing-cdc-enablement/references/filter-expressions.md +93 -0
- package/skills/managing-suite-assignments/SKILL.md +161 -0
- package/skills/polling-test-results/SKILL.md +72 -0
- package/skills/recommending-devops-tests/SKILL.md +137 -0
- package/skills/running-code-analyzer/SKILL.md +264 -267
- package/skills/running-code-analyzer/references/post-scan-workflows.md +286 -0
- package/skills/running-code-analyzer/scripts/describe-rule.js +382 -0
- package/skills/running-code-analyzer/scripts/list-rules.js +260 -0
- package/skills/running-code-analyzer/scripts/query-results.js +230 -0
- package/skills/running-devops-test-suite/SKILL.md +144 -0
- package/skills/syncing-test-providers/SKILL.md +108 -0
- package/skills/using-salesforce-archive/SKILL.md +121 -0
- package/skills/using-salesforce-archive/examples/monitor-failed-jobs.md +47 -0
- package/skills/using-salesforce-archive/references/archive-activity-entity.md +59 -0
- package/skills/using-salesforce-archive/references/connect-api-operations.md +157 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Code Analyzer Configuration — LWC-focused Project
|
|
2
|
+
#
|
|
3
|
+
# This file contains ONLY overrides. Code Analyzer's built-in defaults
|
|
4
|
+
# handle everything else. Only add entries here that intentionally
|
|
5
|
+
# change behavior for your project.
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# Place at project root as code-analyzer.yml
|
|
9
|
+
# Validate: sf code-analyzer config --config-file code-analyzer.yml
|
|
10
|
+
|
|
11
|
+
# Exclude non-project files and test infrastructure
|
|
12
|
+
ignores:
|
|
13
|
+
files:
|
|
14
|
+
- "**/node_modules/**"
|
|
15
|
+
- "**/.sfdx/**"
|
|
16
|
+
- "**/.sf/**"
|
|
17
|
+
- "**/jest-mocks/**"
|
|
18
|
+
- "**/__tests__/**"
|
|
19
|
+
- "**/*.min.js"
|
|
20
|
+
|
|
21
|
+
# Engine tuning
|
|
22
|
+
engines:
|
|
23
|
+
# ESLint: opt-in to use project's existing ESLint config
|
|
24
|
+
# (built-in default is false — Code Analyzer uses its own base configs)
|
|
25
|
+
eslint:
|
|
26
|
+
auto_discover_eslint_config: true
|
|
@@ -0,0 +1,648 @@
|
|
|
1
|
+
# CI/CD Pipeline Templates
|
|
2
|
+
|
|
3
|
+
Ready-to-use templates for integrating Code Analyzer into CI/CD pipelines.
|
|
4
|
+
|
|
5
|
+
## GitHub Actions (using `forcedotcom/run-code-analyzer@v2`)
|
|
6
|
+
|
|
7
|
+
The official GitHub Action for Code Analyzer. It orchestrates the run, uploads artifacts, and optionally creates PR reviews with violation counts.
|
|
8
|
+
|
|
9
|
+
**Action inputs:**
|
|
10
|
+
| Input | Required | Default | Description |
|
|
11
|
+
|-------|----------|---------|-------------|
|
|
12
|
+
| `run-arguments` | No | `--view detail --output-file sfca_results.json` | Flags passed to `sf code-analyzer run` |
|
|
13
|
+
| `results-artifact-name` | No | `salesforce-code-analyzer-results` | Name of the uploaded ZIP artifact |
|
|
14
|
+
| `github-token` | No | *(none)* | Enables PR reviews + `*-in-changed-files` outputs |
|
|
15
|
+
|
|
16
|
+
**Action outputs:** `exit-code`, `num-violations`, `num-sev1-violations` through `num-sev5-violations`, `num-violations-in-changed-files`, `num-sev1-violations-in-changed-files` through `num-sev5-violations-in-changed-files`, `review-id`.
|
|
17
|
+
|
|
18
|
+
**Key `run-arguments` flags:**
|
|
19
|
+
| Flag | Purpose | Example |
|
|
20
|
+
|------|---------|---------|
|
|
21
|
+
| `--workspace` | Root directory to scan (scans all eligible files recursively) | `--workspace .` |
|
|
22
|
+
| `--target` | Specific files/directories to scan (comma-separated or repeated) | `--target force-app/main/default/classes --target force-app/main/default/triggers` |
|
|
23
|
+
| `--rule-selector` | Which rules to run | `Recommended`, `all`, `all:Security`, `pmd`, `"Severity:1,2"` |
|
|
24
|
+
| `--config-file` | Path to `code-analyzer.yml` — **omit if no config file exists** | `--config-file code-analyzer.yml` |
|
|
25
|
+
| `--output-file` | Output file (repeat for multiple formats; format inferred from extension) | `--output-file results.html --output-file results.sarif` |
|
|
26
|
+
| `--view` | Output verbosity | `detail` or `summary` |
|
|
27
|
+
|
|
28
|
+
**`--workspace` vs `--target`:**
|
|
29
|
+
- Use `--workspace .` for full-repo scans (most common in CI)
|
|
30
|
+
- Use `--target <path>` to scan specific directories (monorepos, scoped scans, faster feedback)
|
|
31
|
+
- If both are omitted, defaults to current working directory
|
|
32
|
+
- You can combine: `--workspace . --target force-app/` scans only `force-app/` within the workspace
|
|
33
|
+
|
|
34
|
+
### Basic Quality Gate (Pull Requests)
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
# .github/workflows/code-analyzer.yml
|
|
38
|
+
name: Salesforce Code Analyzer
|
|
39
|
+
|
|
40
|
+
on:
|
|
41
|
+
pull_request:
|
|
42
|
+
branches: [main, develop]
|
|
43
|
+
|
|
44
|
+
jobs:
|
|
45
|
+
code-analysis:
|
|
46
|
+
permissions:
|
|
47
|
+
pull-requests: write
|
|
48
|
+
contents: read
|
|
49
|
+
actions: read
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
- name: Check out files
|
|
53
|
+
uses: actions/checkout@v4
|
|
54
|
+
|
|
55
|
+
- name: Setup Node
|
|
56
|
+
uses: actions/setup-node@v4
|
|
57
|
+
with:
|
|
58
|
+
node-version: '>=20.9.0'
|
|
59
|
+
|
|
60
|
+
- name: Setup Java
|
|
61
|
+
uses: actions/setup-java@v4
|
|
62
|
+
with:
|
|
63
|
+
distribution: 'temurin'
|
|
64
|
+
java-version: '>=11'
|
|
65
|
+
|
|
66
|
+
- name: Install Salesforce CLI
|
|
67
|
+
run: npm install -g @salesforce/cli@latest
|
|
68
|
+
|
|
69
|
+
- name: Install Code Analyzer Plugin
|
|
70
|
+
run: sf plugins install code-analyzer@latest
|
|
71
|
+
|
|
72
|
+
- name: Run Salesforce Code Analyzer
|
|
73
|
+
id: run-code-analyzer
|
|
74
|
+
uses: forcedotcom/run-code-analyzer@v2
|
|
75
|
+
with:
|
|
76
|
+
run-arguments: --workspace . --rule-selector Recommended --output-file sfca_results.html --output-file sfca_results.json
|
|
77
|
+
results-artifact-name: code-analyzer-results
|
|
78
|
+
github-token: ${{ github.token }}
|
|
79
|
+
|
|
80
|
+
- name: Check Quality Gate (Changed Files Only)
|
|
81
|
+
if: |
|
|
82
|
+
steps.run-code-analyzer.outputs.num-sev1-violations-in-changed-files > 0 ||
|
|
83
|
+
steps.run-code-analyzer.outputs.num-sev2-violations-in-changed-files > 0
|
|
84
|
+
run: |
|
|
85
|
+
echo "Critical/High violations found in changed files!"
|
|
86
|
+
echo "Sev1: ${{ steps.run-code-analyzer.outputs.num-sev1-violations-in-changed-files }}"
|
|
87
|
+
echo "Sev2: ${{ steps.run-code-analyzer.outputs.num-sev2-violations-in-changed-files }}"
|
|
88
|
+
exit 1
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Strict Quality Gate (All Files + SARIF)
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
# .github/workflows/code-analyzer-strict.yml
|
|
95
|
+
name: Salesforce Code Analyzer (Strict)
|
|
96
|
+
|
|
97
|
+
on:
|
|
98
|
+
pull_request:
|
|
99
|
+
branches: [main]
|
|
100
|
+
push:
|
|
101
|
+
branches: [main]
|
|
102
|
+
|
|
103
|
+
jobs:
|
|
104
|
+
code-analysis:
|
|
105
|
+
permissions:
|
|
106
|
+
pull-requests: write
|
|
107
|
+
contents: read
|
|
108
|
+
actions: read
|
|
109
|
+
security-events: write
|
|
110
|
+
runs-on: ubuntu-latest
|
|
111
|
+
steps:
|
|
112
|
+
- name: Check out files
|
|
113
|
+
uses: actions/checkout@v4
|
|
114
|
+
|
|
115
|
+
- name: Setup Node
|
|
116
|
+
uses: actions/setup-node@v4
|
|
117
|
+
with:
|
|
118
|
+
node-version: '>=20.9.0'
|
|
119
|
+
|
|
120
|
+
- name: Setup Java
|
|
121
|
+
uses: actions/setup-java@v4
|
|
122
|
+
with:
|
|
123
|
+
distribution: 'temurin'
|
|
124
|
+
java-version: '>=11'
|
|
125
|
+
|
|
126
|
+
- name: Install Salesforce CLI
|
|
127
|
+
run: npm install -g @salesforce/cli@latest
|
|
128
|
+
|
|
129
|
+
- name: Install Code Analyzer Plugin
|
|
130
|
+
run: sf plugins install code-analyzer@latest
|
|
131
|
+
|
|
132
|
+
- name: Run Salesforce Code Analyzer
|
|
133
|
+
id: run-code-analyzer
|
|
134
|
+
uses: forcedotcom/run-code-analyzer@v2
|
|
135
|
+
with:
|
|
136
|
+
run-arguments: --workspace . --rule-selector Recommended --output-file sfca_results.html --output-file sfca_results.json --output-file sfca_results.sarif --config-file code-analyzer.yml
|
|
137
|
+
results-artifact-name: code-analyzer-results
|
|
138
|
+
github-token: ${{ github.token }}
|
|
139
|
+
|
|
140
|
+
- name: Upload SARIF to GitHub Security
|
|
141
|
+
if: always()
|
|
142
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
143
|
+
with:
|
|
144
|
+
sarif_file: sfca_results.sarif
|
|
145
|
+
|
|
146
|
+
- name: Check Quality Gate (All Files)
|
|
147
|
+
if: |
|
|
148
|
+
steps.run-code-analyzer.outputs.exit-code > 0 ||
|
|
149
|
+
steps.run-code-analyzer.outputs.num-sev1-violations > 0 ||
|
|
150
|
+
steps.run-code-analyzer.outputs.num-sev2-violations > 0
|
|
151
|
+
run: |
|
|
152
|
+
echo "Quality gate failed!"
|
|
153
|
+
echo "Total violations: ${{ steps.run-code-analyzer.outputs.num-violations }}"
|
|
154
|
+
echo "Sev1: ${{ steps.run-code-analyzer.outputs.num-sev1-violations }}"
|
|
155
|
+
echo "Sev2: ${{ steps.run-code-analyzer.outputs.num-sev2-violations }}"
|
|
156
|
+
exit 1
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Security-Focused (AppExchange Prep)
|
|
160
|
+
|
|
161
|
+
```yaml
|
|
162
|
+
# .github/workflows/code-analyzer-security.yml
|
|
163
|
+
name: Security Analysis
|
|
164
|
+
|
|
165
|
+
on:
|
|
166
|
+
pull_request:
|
|
167
|
+
branches: [main]
|
|
168
|
+
schedule:
|
|
169
|
+
- cron: '0 6 * * 1' # Weekly Monday 6am
|
|
170
|
+
|
|
171
|
+
jobs:
|
|
172
|
+
security-scan:
|
|
173
|
+
permissions:
|
|
174
|
+
pull-requests: write
|
|
175
|
+
contents: read
|
|
176
|
+
actions: read
|
|
177
|
+
security-events: write
|
|
178
|
+
runs-on: ubuntu-latest
|
|
179
|
+
steps:
|
|
180
|
+
- name: Check out files
|
|
181
|
+
uses: actions/checkout@v4
|
|
182
|
+
|
|
183
|
+
- name: Setup Node
|
|
184
|
+
uses: actions/setup-node@v4
|
|
185
|
+
with:
|
|
186
|
+
node-version: '>=20.9.0'
|
|
187
|
+
|
|
188
|
+
- name: Setup Java
|
|
189
|
+
uses: actions/setup-java@v4
|
|
190
|
+
with:
|
|
191
|
+
distribution: 'temurin'
|
|
192
|
+
java-version: '>=11'
|
|
193
|
+
|
|
194
|
+
- name: Install Salesforce CLI
|
|
195
|
+
run: npm install -g @salesforce/cli@latest
|
|
196
|
+
|
|
197
|
+
- name: Install Code Analyzer Plugin
|
|
198
|
+
run: sf plugins install code-analyzer@latest
|
|
199
|
+
|
|
200
|
+
- name: Run Security Scan
|
|
201
|
+
id: run-code-analyzer
|
|
202
|
+
uses: forcedotcom/run-code-analyzer@v2
|
|
203
|
+
with:
|
|
204
|
+
run-arguments: --workspace . --rule-selector "all:Security" --output-file security-results.html --output-file security-results.json --output-file security-results.sarif --config-file code-analyzer.yml
|
|
205
|
+
results-artifact-name: security-scan-results
|
|
206
|
+
github-token: ${{ github.token }}
|
|
207
|
+
|
|
208
|
+
- name: Upload SARIF to GitHub Security
|
|
209
|
+
if: always()
|
|
210
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
211
|
+
with:
|
|
212
|
+
sarif_file: security-results.sarif
|
|
213
|
+
|
|
214
|
+
- name: Fail on Any Security Violations
|
|
215
|
+
if: steps.run-code-analyzer.outputs.num-sev1-violations > 0
|
|
216
|
+
run: |
|
|
217
|
+
echo "Critical security violations found!"
|
|
218
|
+
echo "Sev1: ${{ steps.run-code-analyzer.outputs.num-sev1-violations }}"
|
|
219
|
+
exit 1
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### With Path Filters (Faster Feedback)
|
|
223
|
+
|
|
224
|
+
Use `paths:` to only trigger the workflow when relevant source files change. This avoids running scans on README edits, CI config changes, etc.
|
|
225
|
+
|
|
226
|
+
```yaml
|
|
227
|
+
# .github/workflows/code-analyzer-filtered.yml
|
|
228
|
+
name: Salesforce Code Analyzer
|
|
229
|
+
|
|
230
|
+
on:
|
|
231
|
+
pull_request:
|
|
232
|
+
branches: [main, develop]
|
|
233
|
+
paths:
|
|
234
|
+
- 'force-app/**'
|
|
235
|
+
- '**/*.cls'
|
|
236
|
+
- '**/*.trigger'
|
|
237
|
+
- '**/*.js'
|
|
238
|
+
- '**/*.ts'
|
|
239
|
+
- '**/*.html'
|
|
240
|
+
- '**/*.flow-meta.xml'
|
|
241
|
+
- 'code-analyzer.yml'
|
|
242
|
+
|
|
243
|
+
jobs:
|
|
244
|
+
code-analysis:
|
|
245
|
+
permissions:
|
|
246
|
+
pull-requests: write
|
|
247
|
+
contents: read
|
|
248
|
+
actions: read
|
|
249
|
+
runs-on: ubuntu-latest
|
|
250
|
+
steps:
|
|
251
|
+
- name: Check out files
|
|
252
|
+
uses: actions/checkout@v4
|
|
253
|
+
|
|
254
|
+
- name: Setup Node
|
|
255
|
+
uses: actions/setup-node@v4
|
|
256
|
+
with:
|
|
257
|
+
node-version: '>=20.9.0'
|
|
258
|
+
|
|
259
|
+
- name: Setup Java
|
|
260
|
+
uses: actions/setup-java@v4
|
|
261
|
+
with:
|
|
262
|
+
distribution: 'temurin'
|
|
263
|
+
java-version: '>=11'
|
|
264
|
+
|
|
265
|
+
- name: Install Salesforce CLI
|
|
266
|
+
run: npm install -g @salesforce/cli@latest
|
|
267
|
+
|
|
268
|
+
- name: Install Code Analyzer Plugin
|
|
269
|
+
run: sf plugins install code-analyzer@latest
|
|
270
|
+
|
|
271
|
+
- name: Run Salesforce Code Analyzer
|
|
272
|
+
id: run-code-analyzer
|
|
273
|
+
uses: forcedotcom/run-code-analyzer@v2
|
|
274
|
+
with:
|
|
275
|
+
run-arguments: --workspace . --rule-selector Recommended --output-file sfca_results.html --output-file sfca_results.json
|
|
276
|
+
results-artifact-name: code-analyzer-results
|
|
277
|
+
github-token: ${{ github.token }}
|
|
278
|
+
|
|
279
|
+
- name: Check Quality Gate
|
|
280
|
+
if: |
|
|
281
|
+
steps.run-code-analyzer.outputs.num-sev1-violations-in-changed-files > 0 ||
|
|
282
|
+
steps.run-code-analyzer.outputs.num-sev2-violations-in-changed-files > 0
|
|
283
|
+
run: exit 1
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**When to use path filters:**
|
|
287
|
+
- Use when the repo contains non-Salesforce code (docs, scripts, infra) that shouldn't trigger scans
|
|
288
|
+
- Always include `code-analyzer.yml` in paths so config changes trigger a validation run
|
|
289
|
+
- Don't use if you want every PR to get a scan regardless of what changed
|
|
290
|
+
|
|
291
|
+
### With Flow Engine (Python Required)
|
|
292
|
+
|
|
293
|
+
If the project contains `.flow-meta.xml` files and uses the Flow engine, Python 3.10+ must be installed:
|
|
294
|
+
|
|
295
|
+
```yaml
|
|
296
|
+
- name: Setup Python (required for Flow engine)
|
|
297
|
+
uses: actions/setup-python@v5
|
|
298
|
+
with:
|
|
299
|
+
python-version: '>=3.10'
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Insert this step after the Java setup step. If you're unsure whether the project uses Flows, include it — it adds ~5s and avoids a partial scan failure.
|
|
303
|
+
|
|
304
|
+
### Monorepo / Scoped Scan
|
|
305
|
+
|
|
306
|
+
For monorepos where Salesforce code lives in a subdirectory, use `--target` to scope the scan:
|
|
307
|
+
|
|
308
|
+
```yaml
|
|
309
|
+
- name: Run Salesforce Code Analyzer
|
|
310
|
+
id: run-code-analyzer
|
|
311
|
+
uses: forcedotcom/run-code-analyzer@v2
|
|
312
|
+
with:
|
|
313
|
+
run-arguments: --workspace . --target packages/salesforce-app/force-app --rule-selector Recommended --output-file sfca_results.html --output-file sfca_results.json
|
|
314
|
+
results-artifact-name: code-analyzer-results
|
|
315
|
+
github-token: ${{ github.token }}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
For multiple packages:
|
|
319
|
+
```
|
|
320
|
+
--target packages/app-a/force-app --target packages/app-b/force-app
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Without a Config File
|
|
324
|
+
|
|
325
|
+
If the project has no `code-analyzer.yml`, simply omit `--config-file`. Code Analyzer uses built-in defaults:
|
|
326
|
+
|
|
327
|
+
```yaml
|
|
328
|
+
- name: Run Salesforce Code Analyzer
|
|
329
|
+
id: run-code-analyzer
|
|
330
|
+
uses: forcedotcom/run-code-analyzer@v2
|
|
331
|
+
with:
|
|
332
|
+
run-arguments: --workspace . --rule-selector Recommended --output-file sfca_results.html --output-file sfca_results.json
|
|
333
|
+
results-artifact-name: code-analyzer-results
|
|
334
|
+
github-token: ${{ github.token }}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
To conditionally use a config file if it exists:
|
|
338
|
+
```yaml
|
|
339
|
+
- name: Check for config file
|
|
340
|
+
id: config-check
|
|
341
|
+
run: |
|
|
342
|
+
if [ -f "code-analyzer.yml" ]; then
|
|
343
|
+
echo "config-flag=--config-file code-analyzer.yml" >> $GITHUB_OUTPUT
|
|
344
|
+
else
|
|
345
|
+
echo "config-flag=" >> $GITHUB_OUTPUT
|
|
346
|
+
fi
|
|
347
|
+
|
|
348
|
+
- name: Run Salesforce Code Analyzer
|
|
349
|
+
id: run-code-analyzer
|
|
350
|
+
uses: forcedotcom/run-code-analyzer@v2
|
|
351
|
+
with:
|
|
352
|
+
run-arguments: --workspace . --rule-selector Recommended --output-file sfca_results.html --output-file sfca_results.json ${{ steps.config-check.outputs.config-flag }}
|
|
353
|
+
results-artifact-name: code-analyzer-results
|
|
354
|
+
github-token: ${{ github.token }}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Jenkins
|
|
358
|
+
|
|
359
|
+
### Jenkinsfile (Declarative Pipeline)
|
|
360
|
+
|
|
361
|
+
```groovy
|
|
362
|
+
// Jenkinsfile
|
|
363
|
+
pipeline {
|
|
364
|
+
agent {
|
|
365
|
+
docker {
|
|
366
|
+
image 'node:20'
|
|
367
|
+
args '-v /usr/local/share/java:/usr/local/share/java'
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
environment {
|
|
372
|
+
JAVA_HOME = '/usr/lib/jvm/java-11-openjdk-amd64'
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
stages {
|
|
376
|
+
stage('Setup') {
|
|
377
|
+
steps {
|
|
378
|
+
sh 'npm install -g @salesforce/cli@latest'
|
|
379
|
+
sh 'sf plugins install code-analyzer@latest'
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
stage('Code Analysis') {
|
|
384
|
+
steps {
|
|
385
|
+
sh '''
|
|
386
|
+
sf code-analyzer run \
|
|
387
|
+
--workspace . \
|
|
388
|
+
--rule-selector Recommended \
|
|
389
|
+
--output-file results.json \
|
|
390
|
+
--output-file results.html \
|
|
391
|
+
--config-file code-analyzer.yml 2>&1 | tee sfca_output.txt
|
|
392
|
+
'''
|
|
393
|
+
script {
|
|
394
|
+
def output = readFile('results.json')
|
|
395
|
+
def json = new groovy.json.JsonSlurper().parseText(output)
|
|
396
|
+
def sev1Count = json.violations?.count { it.severity == 1 } ?: 0
|
|
397
|
+
def sev2Count = json.violations?.count { it.severity == 2 } ?: 0
|
|
398
|
+
if (sev1Count > 0 || sev2Count > 0) {
|
|
399
|
+
error("Quality gate failed! Sev1: ${sev1Count}, Sev2: ${sev2Count}")
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
post {
|
|
404
|
+
always {
|
|
405
|
+
archiveArtifacts artifacts: 'results.*', allowEmptyArchive: true
|
|
406
|
+
publishHTML(target: [
|
|
407
|
+
reportName: 'Code Analyzer Report',
|
|
408
|
+
reportDir: '.',
|
|
409
|
+
reportFiles: 'results.html'
|
|
410
|
+
])
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
post {
|
|
417
|
+
failure {
|
|
418
|
+
echo 'Code analysis found violations above severity threshold!'
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## GitLab CI
|
|
425
|
+
|
|
426
|
+
```yaml
|
|
427
|
+
# .gitlab-ci.yml
|
|
428
|
+
code-analysis:
|
|
429
|
+
image: node:20
|
|
430
|
+
stage: test
|
|
431
|
+
before_script:
|
|
432
|
+
- apt-get update && apt-get install -y openjdk-11-jdk python3
|
|
433
|
+
- export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
|
|
434
|
+
- npm install -g @salesforce/cli@latest
|
|
435
|
+
- sf plugins install code-analyzer@latest
|
|
436
|
+
script:
|
|
437
|
+
- |
|
|
438
|
+
sf code-analyzer run \
|
|
439
|
+
--workspace . \
|
|
440
|
+
--rule-selector Recommended \
|
|
441
|
+
--output-file results.json \
|
|
442
|
+
--output-file results.html \
|
|
443
|
+
--config-file code-analyzer.yml
|
|
444
|
+
- |
|
|
445
|
+
# Quality gate: fail on sev1 or sev2 violations
|
|
446
|
+
SEV1=$(cat results.json | python3 -c "import sys,json; d=json.load(sys.stdin); print(sum(1 for v in d.get('violations',[]) if v.get('severity')==1))")
|
|
447
|
+
SEV2=$(cat results.json | python3 -c "import sys,json; d=json.load(sys.stdin); print(sum(1 for v in d.get('violations',[]) if v.get('severity')==2))")
|
|
448
|
+
echo "Sev1: $SEV1, Sev2: $SEV2"
|
|
449
|
+
if [ "$SEV1" -gt 0 ] || [ "$SEV2" -gt 0 ]; then
|
|
450
|
+
echo "Quality gate failed!"
|
|
451
|
+
exit 1
|
|
452
|
+
fi
|
|
453
|
+
artifacts:
|
|
454
|
+
paths:
|
|
455
|
+
- results.json
|
|
456
|
+
- results.html
|
|
457
|
+
reports:
|
|
458
|
+
codequality: results.json
|
|
459
|
+
rules:
|
|
460
|
+
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
|
461
|
+
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
## Bitbucket Pipelines
|
|
465
|
+
|
|
466
|
+
```yaml
|
|
467
|
+
# bitbucket-pipelines.yml
|
|
468
|
+
pipelines:
|
|
469
|
+
pull-requests:
|
|
470
|
+
'**':
|
|
471
|
+
- step:
|
|
472
|
+
name: Code Analysis
|
|
473
|
+
image: node:20
|
|
474
|
+
script:
|
|
475
|
+
- apt-get update && apt-get install -y openjdk-11-jdk
|
|
476
|
+
- export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
|
|
477
|
+
- npm install -g @salesforce/cli@latest
|
|
478
|
+
- sf plugins install code-analyzer@latest
|
|
479
|
+
- |
|
|
480
|
+
sf code-analyzer run \
|
|
481
|
+
--workspace . \
|
|
482
|
+
--rule-selector Recommended \
|
|
483
|
+
--output-file results.json \
|
|
484
|
+
--output-file results.html \
|
|
485
|
+
--config-file code-analyzer.yml
|
|
486
|
+
- |
|
|
487
|
+
# Quality gate: fail on sev1 or sev2 violations
|
|
488
|
+
SEV1=$(cat results.json | python3 -c "import sys,json; d=json.load(sys.stdin); print(sum(1 for v in d.get('violations',[]) if v.get('severity')==1))")
|
|
489
|
+
SEV2=$(cat results.json | python3 -c "import sys,json; d=json.load(sys.stdin); print(sum(1 for v in d.get('violations',[]) if v.get('severity')==2))")
|
|
490
|
+
echo "Sev1: $SEV1, Sev2: $SEV2"
|
|
491
|
+
if [ "$SEV1" -gt 0 ] || [ "$SEV2" -gt 0 ]; then
|
|
492
|
+
echo "Quality gate failed!"
|
|
493
|
+
exit 1
|
|
494
|
+
fi
|
|
495
|
+
artifacts:
|
|
496
|
+
- results.json
|
|
497
|
+
- results.html
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
## Configuration Tips for CI/CD
|
|
501
|
+
|
|
502
|
+
### Quality Gating Strategy
|
|
503
|
+
|
|
504
|
+
With `forcedotcom/run-code-analyzer@v2`, you control the quality gate via output checks:
|
|
505
|
+
|
|
506
|
+
| Strategy | Condition | Use Case |
|
|
507
|
+
|----------|-----------|----------|
|
|
508
|
+
| Block on critical only | `num-sev1-violations > 0` | Permissive — only block security vulnerabilities |
|
|
509
|
+
| Block on critical + high | `num-sev1-violations > 0 \|\| num-sev2-violations > 0` | Recommended for most teams |
|
|
510
|
+
| Block on changed files only | `num-sev1-violations-in-changed-files > 0` | Great for legacy codebases — don't block on pre-existing issues |
|
|
511
|
+
| Block on total count | `num-violations > 10` | Budget approach — allow some violations but cap total |
|
|
512
|
+
| Zero tolerance | `num-violations > 0` | For new greenfield projects only |
|
|
513
|
+
|
|
514
|
+
For non-GitHub platforms (Jenkins, GitLab, Bitbucket), parse `results.json` to count violations by severity and fail the pipeline accordingly.
|
|
515
|
+
|
|
516
|
+
### Output Formats
|
|
517
|
+
|
|
518
|
+
Specify multiple `--output-file` flags (format inferred from extension):
|
|
519
|
+
|
|
520
|
+
| Format | Extension | Best For |
|
|
521
|
+
|--------|-----------|----------|
|
|
522
|
+
| SARIF | `.sarif` | GitHub Code Scanning integration (requires `security-events: write` permission) |
|
|
523
|
+
| JSON | `.json` | Programmatic processing, quality gating scripts, custom dashboards |
|
|
524
|
+
| HTML | `.html` | Human-readable reports in artifacts |
|
|
525
|
+
| CSV | `.csv` | Spreadsheet analysis |
|
|
526
|
+
| XML | `.xml` | Legacy tool integration |
|
|
527
|
+
|
|
528
|
+
### Caching for Faster CI
|
|
529
|
+
|
|
530
|
+
```yaml
|
|
531
|
+
# GitHub Actions: Cache sf CLI plugins
|
|
532
|
+
- uses: actions/cache@v4
|
|
533
|
+
with:
|
|
534
|
+
path: ~/.local/share/sf/
|
|
535
|
+
key: sf-plugins-${{ hashFiles('**/code-analyzer.yml') }}
|
|
536
|
+
restore-keys: sf-plugins-
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### Recommended PR Workflow
|
|
540
|
+
|
|
541
|
+
1. **On PR open/update:** Use `forcedotcom/run-code-analyzer@v2` with `github-token` — gate on changed-files outputs only
|
|
542
|
+
2. **On merge to main:** Full scan with SARIF upload to GitHub Security tab
|
|
543
|
+
3. **Weekly schedule:** Full security scan with `--rule-selector "all:Security"`
|
|
544
|
+
|
|
545
|
+
### When to Use Path Filters
|
|
546
|
+
|
|
547
|
+
| Situation | Use Path Filters? | Reasoning |
|
|
548
|
+
|-----------|-------------------|-----------|
|
|
549
|
+
| Mixed repo (docs, infra, salesforce code) | Yes | Avoid wasting CI minutes on non-code PRs |
|
|
550
|
+
| Pure Salesforce project | Optional | Every PR likely touches scannable files anyway |
|
|
551
|
+
| You want config changes to trigger a scan | Yes, include `code-analyzer.yml` | Validates config changes don't break the scan |
|
|
552
|
+
| Monorepo with multiple apps | Yes, scope to your package path | Avoid scanning unrelated packages |
|
|
553
|
+
|
|
554
|
+
---
|
|
555
|
+
|
|
556
|
+
## Composition & Adaptation Guide
|
|
557
|
+
|
|
558
|
+
When a user's request doesn't match an existing template exactly, compose from these building blocks:
|
|
559
|
+
|
|
560
|
+
### Prerequisites Block (always required)
|
|
561
|
+
```yaml
|
|
562
|
+
# ALWAYS include these — the action does NOT install them
|
|
563
|
+
- uses: actions/setup-node@v4 # Node >= 20.9.0
|
|
564
|
+
- uses: actions/setup-java@v4 # Java >= 11 (for PMD/CPD/SFGE)
|
|
565
|
+
- uses: actions/setup-python@v5 # Python >= 3.10 (ONLY if project has .flow-meta.xml files)
|
|
566
|
+
- run: npm install -g @salesforce/cli@latest
|
|
567
|
+
- run: sf plugins install code-analyzer@latest
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
### Composing `run-arguments`
|
|
571
|
+
|
|
572
|
+
Build the `run-arguments` string by combining these independent flags as needed:
|
|
573
|
+
|
|
574
|
+
| Need | Flag to Add |
|
|
575
|
+
|------|-------------|
|
|
576
|
+
| Scan the whole repo | `--workspace .` |
|
|
577
|
+
| Scan specific directory | `--target force-app/main/default/classes` |
|
|
578
|
+
| Scan multiple directories | `--target dir1 --target dir2` |
|
|
579
|
+
| Use recommended rules | `--rule-selector Recommended` |
|
|
580
|
+
| Use all rules | `--rule-selector all` |
|
|
581
|
+
| Security rules only | `--rule-selector "all:Security"` |
|
|
582
|
+
| Specific engine only | `--rule-selector pmd` or `--rule-selector eslint` |
|
|
583
|
+
| Specific severity filter | `--rule-selector "Severity:1,2"` |
|
|
584
|
+
| Combined selector | `--rule-selector "pmd:Security:(1,2)"` |
|
|
585
|
+
| Apply custom config | `--config-file code-analyzer.yml` |
|
|
586
|
+
| No custom config | *(omit --config-file entirely)* |
|
|
587
|
+
| HTML output | `--output-file results.html` |
|
|
588
|
+
| JSON output | `--output-file results.json` |
|
|
589
|
+
| SARIF for GitHub Security | `--output-file results.sarif` |
|
|
590
|
+
| Multiple formats | `--output-file a.html --output-file b.json --output-file c.sarif` |
|
|
591
|
+
| Verbose output | `--view detail` |
|
|
592
|
+
|
|
593
|
+
### Permissions Required
|
|
594
|
+
|
|
595
|
+
| Feature | Permission Needed |
|
|
596
|
+
|---------|------------------|
|
|
597
|
+
| PR review comments | `pull-requests: write` |
|
|
598
|
+
| Upload SARIF to Security tab | `security-events: write` |
|
|
599
|
+
| Private repo checkout | `contents: read` |
|
|
600
|
+
| Download artifacts | `actions: read` |
|
|
601
|
+
|
|
602
|
+
### Decision Tree for Template Selection
|
|
603
|
+
|
|
604
|
+
```
|
|
605
|
+
User wants CI/CD for Code Analyzer
|
|
606
|
+
├── Platform?
|
|
607
|
+
│ ├── GitHub Actions → Use forcedotcom/run-code-analyzer@v2
|
|
608
|
+
│ ├── Jenkins → Use Jenkinsfile template + JSON parsing for quality gate
|
|
609
|
+
│ ├── GitLab → Use .gitlab-ci.yml template + script-based quality gate
|
|
610
|
+
│ └── Bitbucket → Use bitbucket-pipelines.yml template + script-based quality gate
|
|
611
|
+
├── Scope?
|
|
612
|
+
│ ├── Full repo → --workspace .
|
|
613
|
+
│ ├── Specific folder → --target <path>
|
|
614
|
+
│ └── Changed files only → use github-token + *-in-changed-files outputs (GitHub only)
|
|
615
|
+
├── Strictness?
|
|
616
|
+
│ ├── Block on sev1 only → check num-sev1-violations
|
|
617
|
+
│ ├── Block on sev1+sev2 → check both (RECOMMENDED DEFAULT)
|
|
618
|
+
│ ├── Block on any violation → check num-violations
|
|
619
|
+
│ └── Legacy codebase → use *-in-changed-files to avoid blocking on old debt
|
|
620
|
+
├── Has config file?
|
|
621
|
+
│ ├── Yes → add --config-file code-analyzer.yml
|
|
622
|
+
│ ├── No → omit --config-file
|
|
623
|
+
│ └── Maybe → use conditional check pattern
|
|
624
|
+
├── Has Flow files?
|
|
625
|
+
│ ├── Yes → add actions/setup-python step
|
|
626
|
+
│ └── No → skip Python setup
|
|
627
|
+
└── Wants GitHub Security integration?
|
|
628
|
+
├── Yes → add --output-file *.sarif + upload-sarif step + security-events: write
|
|
629
|
+
└── No → skip SARIF
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### Common User Requests → Modifications
|
|
633
|
+
|
|
634
|
+
| User Says | What to Change |
|
|
635
|
+
|-----------|---------------|
|
|
636
|
+
| "Only scan on PRs to main" | Set `on: pull_request: branches: [main]` |
|
|
637
|
+
| "Scan only Apex classes" | Use `--target force-app/main/default/classes` |
|
|
638
|
+
| "Don't fail on existing violations" | Use `*-in-changed-files` outputs for quality gate |
|
|
639
|
+
| "I want to see results in GitHub Security tab" | Add `--output-file *.sarif` + `upload-sarif` step + `security-events: write` |
|
|
640
|
+
| "Run a nightly full scan" | Add `schedule: - cron: '0 0 * * *'` trigger |
|
|
641
|
+
| "We don't have a config file" | Remove `--config-file` from run-arguments |
|
|
642
|
+
| "Only run security rules" | Change `--rule-selector` to `"all:Security"` |
|
|
643
|
+
| "Block the PR if there are more than 5 violations" | Change gate to `num-violations > 5` |
|
|
644
|
+
| "We have Flows in our project" | Add `actions/setup-python@v5` with `python-version: '>=3.10'` |
|
|
645
|
+
| "Scan only what changed in the PR" | Use `github-token` + gate on `*-in-changed-files` outputs |
|
|
646
|
+
| "We're a monorepo" | Use `--target packages/my-sf-app/force-app` instead of `--workspace .` |
|
|
647
|
+
| "Cache the plugin install" | Add `actions/cache@v4` step for `~/.local/share/sf/` |
|
|
648
|
+
| "I want an HTML report I can download" | Add `--output-file results.html` (auto-uploaded via results-artifact-name) |
|