@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,153 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# validate-config.sh
|
|
3
|
+
# Validates a code-analyzer.yml configuration file.
|
|
4
|
+
# Usage: bash <skill_dir>/scripts/validate-config.sh [config-file]
|
|
5
|
+
#
|
|
6
|
+
# If no config file is specified, looks for code-analyzer.yml in current directory.
|
|
7
|
+
#
|
|
8
|
+
# Exit codes:
|
|
9
|
+
# 0 = Config is valid
|
|
10
|
+
# 1 = Config has errors
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
CONFIG_FILE="${1:-code-analyzer.yml}"
|
|
15
|
+
|
|
16
|
+
echo "Validating: ${CONFIG_FILE}"
|
|
17
|
+
echo ""
|
|
18
|
+
|
|
19
|
+
# Check file exists
|
|
20
|
+
if [ ! -f "$CONFIG_FILE" ]; then
|
|
21
|
+
echo "ERROR: Config file not found: ${CONFIG_FILE}"
|
|
22
|
+
echo ""
|
|
23
|
+
echo "Expected locations:"
|
|
24
|
+
echo " - ./code-analyzer.yml"
|
|
25
|
+
echo " - ./code-analyzer.yaml"
|
|
26
|
+
echo ""
|
|
27
|
+
echo "Generate one with: sf code-analyzer config --output-file code-analyzer.yml"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Check file is not empty
|
|
32
|
+
if [ ! -s "$CONFIG_FILE" ]; then
|
|
33
|
+
echo "ERROR: Config file is empty: ${CONFIG_FILE}"
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# Basic YAML syntax check (if python3 available)
|
|
38
|
+
if command -v python3 &> /dev/null; then
|
|
39
|
+
echo "Checking YAML syntax..."
|
|
40
|
+
if python3 -c "
|
|
41
|
+
import yaml, sys
|
|
42
|
+
try:
|
|
43
|
+
with open('${CONFIG_FILE}', 'r') as f:
|
|
44
|
+
config = yaml.safe_load(f)
|
|
45
|
+
if config is None:
|
|
46
|
+
print('WARNING: Config file is empty or contains only comments')
|
|
47
|
+
sys.exit(0)
|
|
48
|
+
if not isinstance(config, dict):
|
|
49
|
+
print('ERROR: Config must be a YAML mapping (dictionary)')
|
|
50
|
+
sys.exit(1)
|
|
51
|
+
print('YAML syntax: OK')
|
|
52
|
+
except yaml.YAMLError as e:
|
|
53
|
+
print(f'ERROR: Invalid YAML syntax')
|
|
54
|
+
print(f' {e}')
|
|
55
|
+
sys.exit(1)
|
|
56
|
+
" 2>&1; then
|
|
57
|
+
echo ""
|
|
58
|
+
else
|
|
59
|
+
echo ""
|
|
60
|
+
echo "Fix YAML syntax errors before proceeding."
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
else
|
|
64
|
+
echo "WARNING: python3 not found — skipping YAML syntax validation (install python3 for full checks)"
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Validate known field names
|
|
68
|
+
echo "Checking known fields..."
|
|
69
|
+
VALID_TOP_LEVEL="config_root log_folder log_level rules engines ignores suppressions"
|
|
70
|
+
|
|
71
|
+
if command -v python3 &> /dev/null; then
|
|
72
|
+
python3 -c "
|
|
73
|
+
import yaml, sys
|
|
74
|
+
|
|
75
|
+
with open('${CONFIG_FILE}', 'r') as f:
|
|
76
|
+
config = yaml.safe_load(f)
|
|
77
|
+
|
|
78
|
+
if config is None:
|
|
79
|
+
sys.exit(0)
|
|
80
|
+
|
|
81
|
+
valid_fields = set('${VALID_TOP_LEVEL}'.split())
|
|
82
|
+
unknown = set(config.keys()) - valid_fields
|
|
83
|
+
if unknown:
|
|
84
|
+
print(f'WARNING: Unknown top-level fields: {sorted(unknown)}')
|
|
85
|
+
print(' Valid fields: config_root, log_folder, log_level, rules, engines, ignores, suppressions')
|
|
86
|
+
else:
|
|
87
|
+
print('Known fields: OK')
|
|
88
|
+
|
|
89
|
+
# Check engines section
|
|
90
|
+
if 'engines' in config and config['engines']:
|
|
91
|
+
valid_engines = {'pmd', 'cpd', 'eslint', 'regex', 'retire-js', 'flow', 'sfge', 'apexguru'}
|
|
92
|
+
configured_engines = set(config['engines'].keys())
|
|
93
|
+
unknown_engines = configured_engines - valid_engines
|
|
94
|
+
if unknown_engines:
|
|
95
|
+
print(f'WARNING: Unknown engine names: {sorted(unknown_engines)}')
|
|
96
|
+
print(f' Valid engines: {sorted(valid_engines)}')
|
|
97
|
+
else:
|
|
98
|
+
print(f'Engines configured: {sorted(configured_engines)}')
|
|
99
|
+
|
|
100
|
+
# Check ignores section
|
|
101
|
+
if 'ignores' in config and config['ignores']:
|
|
102
|
+
if 'files' not in config['ignores']:
|
|
103
|
+
print('WARNING: ignores section should contain a \"files\" list')
|
|
104
|
+
elif not isinstance(config['ignores']['files'], list):
|
|
105
|
+
print('ERROR: ignores.files must be a list of glob patterns')
|
|
106
|
+
sys.exit(1)
|
|
107
|
+
else:
|
|
108
|
+
print(f'Ignore patterns: {len(config[\"ignores\"][\"files\"])} patterns configured')
|
|
109
|
+
|
|
110
|
+
# Check rules section
|
|
111
|
+
if 'rules' in config and config['rules']:
|
|
112
|
+
for engine, rules in config['rules'].items():
|
|
113
|
+
if rules and isinstance(rules, dict):
|
|
114
|
+
for rule_name, overrides in rules.items():
|
|
115
|
+
if overrides and isinstance(overrides, dict):
|
|
116
|
+
if 'severity' in overrides:
|
|
117
|
+
sev = overrides['severity']
|
|
118
|
+
valid_sevs = [1, 2, 3, 4, 5, 'Critical', 'High', 'Moderate', 'Low', 'Info']
|
|
119
|
+
if sev not in valid_sevs:
|
|
120
|
+
print(f'WARNING: rules.{engine}.{rule_name}.severity = {sev} (expected 1-5 or Critical/High/Moderate/Low/Info)')
|
|
121
|
+
|
|
122
|
+
print('')
|
|
123
|
+
" 2>&1
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
# Run sf code-analyzer config validation (if sf CLI available)
|
|
127
|
+
echo ""
|
|
128
|
+
echo "Running Code Analyzer validation..."
|
|
129
|
+
if command -v sf &> /dev/null; then
|
|
130
|
+
if sf plugins --core 2>&1 | grep -qi "code-analyzer"; then
|
|
131
|
+
if sf code-analyzer config --config-file "$CONFIG_FILE" > /dev/null 2>&1; then
|
|
132
|
+
echo "Code Analyzer validation: PASSED"
|
|
133
|
+
echo ""
|
|
134
|
+
echo "Configuration is valid and ready to use."
|
|
135
|
+
exit 0
|
|
136
|
+
else
|
|
137
|
+
echo "Code Analyzer validation: FAILED"
|
|
138
|
+
echo ""
|
|
139
|
+
echo "Running with verbose output:"
|
|
140
|
+
sf code-analyzer config --config-file "$CONFIG_FILE" 2>&1 || true
|
|
141
|
+
exit 1
|
|
142
|
+
fi
|
|
143
|
+
else
|
|
144
|
+
echo "SKIP: Code Analyzer plugin not installed (cannot run full validation)"
|
|
145
|
+
echo "Install: sf plugins install @salesforce/plugin-code-analyzer"
|
|
146
|
+
fi
|
|
147
|
+
else
|
|
148
|
+
echo "SKIP: sf CLI not available (cannot run full validation)"
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
echo ""
|
|
152
|
+
echo "Basic validation passed. Install Code Analyzer for full validation."
|
|
153
|
+
exit 0
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: configuring-quality-gate
|
|
3
|
+
description: "Creates a DevOps Center quality gate with associated rules (PASS_PERCENTAGE, SEVERITY, ESSENTIAL) and links it to a pipeline-stage suite assignment, after showing a mandatory impact preview and obtaining explicit confirmation. Use this skill when a user wants to set or configure a quality gate, change a coverage threshold, or establish testing benchmarks on a pipeline stage. TRIGGER when: the user wants to set/configure a quality gate, change a coverage threshold, or set testing benchmarks on a stage. DO NOT TRIGGER when: only re-running an existing gate (use running-devops-test-suite in retrigger mode)."
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0"
|
|
6
|
+
minApiVersion: "67.0"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
Load `checking-devops-prerequisites` first — Prerequisites 1–4 AND Prerequisite 5 (stage). You need `doce-org-alias`, `pipelineId`, `stageId`, and the target `DevopsTestSuiteStage` record Id.
|
|
12
|
+
|
|
13
|
+
## Inputs required
|
|
14
|
+
|
|
15
|
+
| Input | Source |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `name` | User-provided name for the quality gate |
|
|
18
|
+
| `rules` | List of `{type, threshold?}` — see rule types below |
|
|
19
|
+
| `doce-org-alias` | Established in Prereq 1 |
|
|
20
|
+
| `testSuiteStageId` | Target `DevopsTestSuiteStage` record Id (Prereq 5) |
|
|
21
|
+
|
|
22
|
+
## Rule types
|
|
23
|
+
|
|
24
|
+
| Type | Description | Threshold |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `PASS_PERCENTAGE` | Minimum % of tests that must pass | Required (0–100) |
|
|
27
|
+
| `SEVERITY` | Maximum allowed severity level of failures | Required (numeric, e.g. 1–5) |
|
|
28
|
+
| `ESSENTIAL` | All essential tests must pass | Not required |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## MANDATORY IMPACT PREVIEW
|
|
33
|
+
|
|
34
|
+
**Before executing any commands**, show the user this preview and wait for explicit confirmation:
|
|
35
|
+
|
|
36
|
+
> "Here's what this quality gate will enforce on `<stageName>`:
|
|
37
|
+
> - Rule: `<type>` — `<description>`
|
|
38
|
+
> - Threshold: `<value>`
|
|
39
|
+
> - Affected pipelines: `<list>`
|
|
40
|
+
>
|
|
41
|
+
> Confirm to apply?"
|
|
42
|
+
|
|
43
|
+
**Never proceed past this point without showing the impact preview first and receiving explicit confirmation.**
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Confirmation gate
|
|
48
|
+
|
|
49
|
+
Only proceed with the steps below after the user has explicitly confirmed (e.g., "yes", "confirm", "go ahead"). If the user declines or does not confirm, stop and do not execute any commands.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Step 1 — Create the gate record
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
sf api request rest \
|
|
57
|
+
"/services/data/v67.0/connect/devopstesting/qualityGate" \
|
|
58
|
+
--method POST \
|
|
59
|
+
--body '{"name": "<gateName>"}' \
|
|
60
|
+
--target-org <doce-org-alias>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Extract `qualityGateId` from the response.
|
|
64
|
+
|
|
65
|
+
## Step 2 — Create each rule as a sObject record
|
|
66
|
+
|
|
67
|
+
Rules are not accepted in the Connect API payload — create them as `DevopsQualityGateRule` records directly. Only create rules the user has requested. `ESSENTIAL` has no threshold.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
sf data create record \
|
|
71
|
+
--sobject DevopsQualityGateRule \
|
|
72
|
+
--values "DevopsQualityGateId='<qualityGateId>' Rule='PASS_PERCENTAGE' Threshold=<value>" \
|
|
73
|
+
--target-org <doce-org-alias> --json
|
|
74
|
+
|
|
75
|
+
sf data create record \
|
|
76
|
+
--sobject DevopsQualityGateRule \
|
|
77
|
+
--values "DevopsQualityGateId='<qualityGateId>' Rule='ESSENTIAL'" \
|
|
78
|
+
--target-org <doce-org-alias> --json
|
|
79
|
+
|
|
80
|
+
sf data create record \
|
|
81
|
+
--sobject DevopsQualityGateRule \
|
|
82
|
+
--values "DevopsQualityGateId='<qualityGateId>' Rule='SEVERITY' Threshold=<value>" \
|
|
83
|
+
--target-org <doce-org-alias> --json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Step 3 — Link the gate to the suite stage
|
|
87
|
+
|
|
88
|
+
Update the `DevopsTestSuiteStage` record to link the new gate:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
sf data update record \
|
|
92
|
+
--sobject DevopsTestSuiteStage \
|
|
93
|
+
--record-id <testSuiteStageId> \
|
|
94
|
+
--values "IsQualityGateEnabled=true DevopsQualityGateId='<qualityGateId>'" \
|
|
95
|
+
--target-org <doce-org-alias> --json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## On success
|
|
101
|
+
|
|
102
|
+
Confirm to the user:
|
|
103
|
+
> "Quality gate `<gateName>` created with `<N>` rule(s) and assigned to `<suiteName>` on `<stageName>`."
|
|
104
|
+
|
|
105
|
+
## Error handling
|
|
106
|
+
|
|
107
|
+
Never expose raw API errors. Use the following responses:
|
|
108
|
+
|
|
109
|
+
| Status | Response |
|
|
110
|
+
|---|---|
|
|
111
|
+
| 400 | "The quality gate configuration is invalid. Check that all rule types and thresholds are correct." |
|
|
112
|
+
| 403 | "You don't have permission to configure quality gates on this org." |
|
|
113
|
+
| 500 | "A server error occurred. Try again in a few minutes." |
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Related skills
|
|
118
|
+
|
|
119
|
+
- To re-run a gate after meeting threshold, use `running-devops-test-suite` (retrigger mode).
|
|
120
|
+
- To assign or map suites to stages, use `managing-suite-assignments`.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: configuring-test-provider
|
|
3
|
+
description: "Configures an available test provider (e.g. Apex Unit Tests, Code Analyzer, Flow Tests, Provar) on a DevOps Center pipeline via the Connect API, after explicit user confirmation, so the provider's test suites become available for assignment to pipeline stages. Takes a pipelineId and a testProviderId. Use this skill when a provider is available on the pipeline but not yet configured and the user wants to enable it. TRIGGER when: the user wants to configure, enable, set up, or add a test provider on a pipeline, or wants a not-yet-configured provider's suites to become available. DO NOT TRIGGER when: re-syncing an already-configured provider to pick up new suites (use syncing-test-providers), or assigning existing suites to a stage (use managing-suite-assignments)."
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0"
|
|
6
|
+
minApiVersion: "67.0"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Configuring a Test Provider
|
|
10
|
+
|
|
11
|
+
Configures an available test provider on a DevOps Center pipeline, making its test suites available for assignment to pipeline stages.
|
|
12
|
+
|
|
13
|
+
**Confirmation required:** Yes — explicit confirmation before the provider is configured.
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
Load `checking-devops-prerequisites` first — Prerequisites 1–4 (org login, Agentforce DX plugin, DevOps Center org auth, pipeline identified). Prerequisite 5 (stage) is **not** required: providers are configured at the pipeline level, not the stage level.
|
|
18
|
+
|
|
19
|
+
| Variable | Source |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `doce-org-alias` | Established in Prerequisite 1 |
|
|
22
|
+
| `pipelineId` | Identified in Prerequisite 4 (pipeline selection) |
|
|
23
|
+
| `testProviderId` | Resolved by fetching the pipeline's test providers (below) |
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Step 1 — Fetch test providers to resolve the provider ID
|
|
28
|
+
|
|
29
|
+
Get all test providers for the pipeline so you can resolve the `testProviderId` and confirm which providers are still available to configure:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
sf api request rest \
|
|
33
|
+
"/services/data/v67.0/connect/devopstesting/pipeline/<pipelineId>/testProviders?status=all" \
|
|
34
|
+
--target-org <doce-org-alias>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Each provider entry includes `testProviderId`, `testProviderName`, and a status (Configured vs. Available). Present a short summary grouped by status:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
Test providers for <pipelineName>:
|
|
41
|
+
|
|
42
|
+
✓ Configured:
|
|
43
|
+
- Code Analyzer (63 suites)
|
|
44
|
+
- Apex Unit Tests (5 suites)
|
|
45
|
+
|
|
46
|
+
Available (not yet configured):
|
|
47
|
+
- Flow Tests
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- **Only an Available provider can be configured.** If the pipeline has no available providers, report that and stop — do NOT fabricate a provider or ID.
|
|
51
|
+
|
|
52
|
+
### If the named provider is already Configured
|
|
53
|
+
|
|
54
|
+
Do **not** present the confirmation gate and do **not** POST to the configure endpoint (Steps 2–3) — that would create a duplicate `DevopsPipelineTestProvider`. Instead:
|
|
55
|
+
|
|
56
|
+
1. State plainly that the provider is already configured, including its synced suite count and last-sync time if returned (e.g. *"Flow Tests is already configured on `<pipelineName>` with 3 suites synced (last sync 2026-06-23)."*).
|
|
57
|
+
2. Diagnose the user's actual goal and redirect **by name**:
|
|
58
|
+
- If the user says the provider's **suites don't appear when assigning tests to a stage**, this is a **stage-assignment gap, not a provider-configuration gap** — the suites already exist at the pipeline level; they just need to be linked to the stage. Redirect to **`managing-suite-assignments`**.
|
|
59
|
+
- If the user expects **newly created suites** that aren't yet synced, redirect to **`syncing-test-providers`** (re-sync via `POST /connect/devops/sync`) to pull them in.
|
|
60
|
+
3. Do not loop back to configuring — finish cleanly after the explanation and redirect.
|
|
61
|
+
|
|
62
|
+
## Step 2 — Confirmation gate
|
|
63
|
+
|
|
64
|
+
**Required — do not call the API before the user confirms.**
|
|
65
|
+
|
|
66
|
+
> "I'll configure `<testProviderName>` on the `<pipelineName>` pipeline. This will make its suites available for assignment to stages. Confirm?"
|
|
67
|
+
|
|
68
|
+
Do not proceed until the user gives an affirmative response.
|
|
69
|
+
|
|
70
|
+
## Step 3 — Configure the provider
|
|
71
|
+
|
|
72
|
+
On confirmation, call the configure endpoint with the provider ID:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
sf api request rest \
|
|
76
|
+
"/services/data/v67.0/connect/devops/pipeline/<pipelineId>/testProvider" \
|
|
77
|
+
--method POST \
|
|
78
|
+
--body '{"testProviderId": "<testProviderId>"}' \
|
|
79
|
+
--target-org <doce-org-alias>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## On success
|
|
83
|
+
|
|
84
|
+
> "Provider `<testProviderName>` is now configured on the `<pipelineName>` pipeline. Its suites are available for assignment to stages."
|
|
85
|
+
|
|
86
|
+
Newly configured suites can then be assigned to stages with `managing-suite-assignments`.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Critical gotcha
|
|
91
|
+
|
|
92
|
+
This `POST .../pipeline/<pipelineId>/testProvider` endpoint **creates a new provider configuration record** (`DevopsPipelineTestProvider`). Use it ONLY to configure a provider for the first time. To re-sync an already-configured provider for new suites, use `syncing-test-providers` (`POST /connect/devops/sync`) — calling this configure endpoint on an already-configured provider produces **duplicate** `DevopsPipelineTestProvider` records.
|
|
93
|
+
|
|
94
|
+
## Error Handling
|
|
95
|
+
|
|
96
|
+
Never expose raw API error messages, stack traces, or JSON payloads to the user. Map response status codes to plain-language messages:
|
|
97
|
+
|
|
98
|
+
| Status | User-facing message |
|
|
99
|
+
|---|---|
|
|
100
|
+
| 400 | "The request was invalid. Check that the provider ID and pipeline ID are correct." |
|
|
101
|
+
| 403 | "You don't have permission to configure test providers on this pipeline." |
|
|
102
|
+
| 404 | "The pipeline or test provider was not found." |
|
|
103
|
+
| 409 | "That provider appears to already be configured on this pipeline. To pick up new suites, re-sync it instead." |
|
|
104
|
+
| 500 | "A server error occurred. Try again in a few minutes." |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Related skills
|
|
109
|
+
|
|
110
|
+
- **`checking-devops-prerequisites`** — loaded first to establish org and pipeline context.
|
|
111
|
+
- **`syncing-test-providers`** — once a provider is configured, use this to re-sync it later and pull in newly added suites.
|
|
112
|
+
- **`managing-suite-assignments`** — after configuring a provider, use this to assign or map its suites to a pipeline stage.
|
|
113
|
+
- **`recommending-devops-tests`** — to recommend which of the newly available suites to run.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: creating-fix-work-item
|
|
3
|
+
description: "Creates a DevOps Center WorkItem to track a fix for a test failure or Code Analyzer violation. Before creating anything, it shows a subject/assignee/project preview and requires explicit confirmation. Use this skill when you want to create a fix work item, track a remediation task, or assign a test or analysis failure to a developer. TRIGGER when: the user wants to create a fix work item, log a remediation, or assign a failure to a developer for resolution. DO NOT TRIGGER when: writing the fix code itself (use generating-apex)."
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0"
|
|
6
|
+
minApiVersion: "67.0"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
Load `checking-devops-prerequisites` first — Prerequisites 1–4. You need `doce-org-alias`, the `DevopsProjectId` to file under, and an `OwnerId` (assignee). If no DevopsProject exists, surface that the work item cannot be created until a project exists.
|
|
12
|
+
|
|
13
|
+
## Inputs required before creating
|
|
14
|
+
|
|
15
|
+
| Input | How to obtain |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `DevopsProjectId` | From the pipeline's associated project — query `DevopsProject WHERE Name = '<projectName>'` on the doce org if not already known |
|
|
18
|
+
| `Subject` | Derived from failure analysis — e.g. "Fix: Missing code-analyzer-v5.yml workflow in blitz-10-06 repository" |
|
|
19
|
+
| `OwnerId` | User ID of the developer to assign to — query `SELECT Id, Name FROM User WHERE Username = '<username>'` on the doce org if not known. Ask the user if the username is unknown. |
|
|
20
|
+
| `doce-org-alias` | Established in Prerequisites |
|
|
21
|
+
|
|
22
|
+
## Confirmation gate
|
|
23
|
+
|
|
24
|
+
Before creating the work item, show a summary and wait for explicit confirmation:
|
|
25
|
+
|
|
26
|
+
> "I'll create a fix work item with the following details:
|
|
27
|
+
> - **Subject:** `<subject>`
|
|
28
|
+
> - **Assigned to:** `<assigneeName>`
|
|
29
|
+
> - **Project:** `<projectName>`
|
|
30
|
+
>
|
|
31
|
+
> Shall I create it?"
|
|
32
|
+
|
|
33
|
+
Do not proceed until the user confirms.
|
|
34
|
+
|
|
35
|
+
## Creating the work item
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
sf data create record \
|
|
39
|
+
--sobject WorkItem \
|
|
40
|
+
--values "Subject='<subject>' DevopsProjectId='<DevopsProjectId>' OwnerId='<OwnerId>'" \
|
|
41
|
+
--target-org <doce-org-alias> \
|
|
42
|
+
--json
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
> **Important:** Use `WorkItem` (no namespace) — `DevopsWorkItem` is not a supported sObject in this org version.
|
|
46
|
+
|
|
47
|
+
## On success
|
|
48
|
+
|
|
49
|
+
Parse the returned `id` from the result and confirm:
|
|
50
|
+
|
|
51
|
+
> "Fix work item created (`<id>`): `<subject>`. Assigned to `<assigneeName>` in the `<projectName>` project."
|
|
52
|
+
|
|
53
|
+
## Error handling
|
|
54
|
+
|
|
55
|
+
Never expose raw API error messages. Map errors to plain-language responses:
|
|
56
|
+
|
|
57
|
+
| Error | Response |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `FIELD_INTEGRITY_EXCEPTION` | "The assignee ID is invalid. Let me look up the correct user ID — what's the developer's username?" |
|
|
60
|
+
| `REQUIRED_FIELD_MISSING` | "A required field is missing. Check that `Subject` and `DevopsProjectId` are both provided." |
|
|
61
|
+
| `INSUFFICIENT_ACCESS` | "Your user doesn't have permission to create work items in this project." |
|
|
62
|
+
| Any other error | "The work item could not be created. Error: `<plain summary>`. Try again or create it manually in DevOps Center." |
|
|
63
|
+
|
|
64
|
+
## Related skills
|
|
65
|
+
|
|
66
|
+
- `analyzing-test-failures` — provides the failure analysis and improvement suggestions that motivate creating a fix work item
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: managing-cdc-enablement
|
|
3
|
+
description: "Use to enable Salesforce Change Data Capture (CDC) on a standard or custom object, configure a custom event channel, set a filter expression, or add enrichment fields. TRIGGER broadly on any of: 'enable CDC', 'enable Change Data Capture', 'turn on CDC', 'subscribe X to change events', 'only emit events for', 'filter change events', 'enrich change events', 'create a custom event channel'; or any mention of CDC, change events, PlatformEventChannel, PlatformEventChannelMember, EnrichedField, ChangeEvents channel, enrichment fields, change event filter; or when the user wants a downstream system to receive Salesforce data changes; or when the user touches .platformEventChannelMember-meta.xml / .platformEventChannel-meta.xml files. SKIP when publishing platform events, Pub/Sub API or REST/SOAP (use building-sf-integrations), or ManagedEventSubscription (out of scope for CDC). Always use this skill for CDC channel-membership metadata."
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Managing Change Data Capture Enablement
|
|
9
|
+
|
|
10
|
+
Generate the metadata that subscribes Salesforce objects to Change Data Capture: `PlatformEventChannelMember` files for the default `ChangeEvents` channel or a custom channel, and `PlatformEventChannel` files for new custom channels. Covers enrichment fields, filter expressions, and the canonical naming and value formats that the Metadata API actually accepts (which differ from values that appear in many internal test fixtures and code-search hits).
|
|
11
|
+
|
|
12
|
+
## Scope
|
|
13
|
+
|
|
14
|
+
- **In scope**: Generating `PlatformEventChannelMember` and `PlatformEventChannel` metadata for CDC. Subscribing standard objects, custom objects, or both. Configuring enrichment fields. Configuring filter expressions. Defining custom data channels.
|
|
15
|
+
- **Out of scope**: Publishing custom platform events (PE) — that's a different metadata type (`PlatformEvent`). Pub/Sub API or external Kafka/Bayeux configuration. Pricing/limits guidance — refer the user to the [CDC Developer Guide](https://developer.salesforce.com/docs/atlas.en-us.change_data_capture.meta/change_data_capture/). Programmatic event-bus subscribers in Apex.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Clarifying Questions
|
|
20
|
+
|
|
21
|
+
Before generating, confirm with the user if not already clear:
|
|
22
|
+
|
|
23
|
+
- Which entity (or entities) need CDC enablement? Standard, custom, or both?
|
|
24
|
+
- Default channel (`ChangeEvents`) or a custom channel? If custom, what's the channel label?
|
|
25
|
+
- Any enrichment fields needed? (Lookup IDs that the consumer needs even when they didn't change.)
|
|
26
|
+
- Any filter expression needed? (A SOQL-WHERE-clause body that gates which change events emit.)
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Required Inputs
|
|
31
|
+
|
|
32
|
+
Gather or infer before proceeding:
|
|
33
|
+
|
|
34
|
+
- **Source entity API name(s)** — e.g. `Account`, `Lead`, `Order__c`. The skill internally translates this to the **ChangeEvent entity name** (see Workflow step 2).
|
|
35
|
+
- **Channel** — either `ChangeEvents` (default) or the developer name of a custom channel ending in `__chn`.
|
|
36
|
+
- **Enrichment fields (optional)** — list of field API names on the source object whose values should be included in every change event.
|
|
37
|
+
- **Filter expression (optional)** — a predicate over fields on the change event payload (e.g. `Status__c != null`).
|
|
38
|
+
|
|
39
|
+
Defaults unless specified:
|
|
40
|
+
- Channel: `ChangeEvents` (the default CDC channel — no path prefix).
|
|
41
|
+
- Enrichment fields: none.
|
|
42
|
+
- Filter expression: none.
|
|
43
|
+
|
|
44
|
+
If the user provides a clear, complete request, generate immediately without unnecessary back-and-forth.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Workflow
|
|
49
|
+
|
|
50
|
+
All steps are sequential. Do not skip or reorder.
|
|
51
|
+
|
|
52
|
+
**Before generating anything, know the only valid CDC metadata types:** CDC is expressed entirely through `PlatformEventChannelMember` (one per subscribed entity) and `PlatformEventChannel` (only for custom channels). Do NOT use `<ChangeDataCapture>`, `.changeDataCapture-meta.xml`, `changeDataCapture/` directories, `EnableChangeDataCapture`, or `ManagedEventSubscription` — these are not in scope for CDC. If you find yourself writing any of them, stop and use a `PlatformEventChannelMember` file instead.
|
|
53
|
+
|
|
54
|
+
1. **Identify the channel** — if the user names a custom channel, you'll generate a `PlatformEventChannel` file (see step 4). Otherwise use the literal value `ChangeEvents` for the default channel.
|
|
55
|
+
|
|
56
|
+
2. **Translate source entity to ChangeEvent entity name** — `<selectedEntity>` is the **ChangeEvent** type, NOT the source object:
|
|
57
|
+
|
|
58
|
+
| Source object | `<selectedEntity>` value |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `Account` | `AccountChangeEvent` |
|
|
61
|
+
| `Lead` | `LeadChangeEvent` |
|
|
62
|
+
| `Contact` | `ContactChangeEvent` |
|
|
63
|
+
| `Order__c` (custom) | `Order__ChangeEvent` |
|
|
64
|
+
| `MyThing__c` (custom) | `MyThing__ChangeEvent` |
|
|
65
|
+
|
|
66
|
+
For standard objects: append `ChangeEvent`. For custom objects: replace the trailing `__c` with `__ChangeEvent` (the double-underscore is preserved).
|
|
67
|
+
|
|
68
|
+
3. **Generate the channel-member file** — one file per `(entity, channel)` pair. **The filename and fullName always use a SINGLE underscore between the entity stem and `ChangeEvent`** — this is independent of how `selectedEntity` is formatted in the XML body. For custom objects, drop the `__c` from the source name when forming the filename:
|
|
69
|
+
|
|
70
|
+
| Source object | Filename (and fullName) | `<selectedEntity>` (in XML) |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `Account` | `Account_ChangeEvent.platformEventChannelMember-meta.xml` | `AccountChangeEvent` |
|
|
73
|
+
| `Lead` | `Lead_ChangeEvent.platformEventChannelMember-meta.xml` | `LeadChangeEvent` |
|
|
74
|
+
| `Order__c` | `Order_ChangeEvent.platformEventChannelMember-meta.xml` (NOT `Order__ChangeEvent`) | `Order__ChangeEvent` |
|
|
75
|
+
| `MyThing__c` | `MyThing_ChangeEvent.platformEventChannelMember-meta.xml` (NOT `MyThing__ChangeEvent`) | `MyThing__ChangeEvent` |
|
|
76
|
+
|
|
77
|
+
The custom-object case is the easiest place to slip — the filename uses single underscore, the `selectedEntity` keeps its double underscore. Read `assets/PlatformEventChannelMember-template.xml` as the structural template.
|
|
78
|
+
|
|
79
|
+
4. **For a custom channel**, generate a `PlatformEventChannel` file — required if any member references a non-default channel. Derive a DeveloperName from the user's label: strip spaces and non-alphanumeric characters, convert to CamelCase, then **always** append the literal suffix `__chn`. The filename and the channel's `<eventChannel>` reference must use this exact form, otherwise the deploy fails with `Invalid channel name`:
|
|
80
|
+
|
|
81
|
+
| User says | DeveloperName | Filename |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `Partner Sync` | `PartnerSync__chn` | `PartnerSync__chn.platformEventChannel-meta.xml` (NOT `Partner_Sync...` or `PartnerSync...`) |
|
|
84
|
+
| `Order Updates` | `OrderUpdates__chn` | `OrderUpdates__chn.platformEventChannel-meta.xml` |
|
|
85
|
+
| `data sync` | `DataSync__chn` | `DataSync__chn.platformEventChannel-meta.xml` |
|
|
86
|
+
|
|
87
|
+
Members on this channel reference it by the same DeveloperName: `<eventChannel>PartnerSync__chn</eventChannel>`. Read `assets/PlatformEventChannel-template.xml`.
|
|
88
|
+
|
|
89
|
+
5. **Add enrichment fields** if requested — repeat the `<enrichedFields><name>FIELD_API_NAME</name></enrichedFields>` block for each field. The name must be a **single-hop API name on the source entity** — verified working with: standard lookup IDs (`OwnerId`, `ParentId`), custom lookup fields (`MyLookup__c`), and custom non-relationship fields (`Region__c`, `Status__c`). Relationship traversals like `Owner.Name` or `Parent.Account.Industry` are rejected by deploy with "The selected field, X.Y, isn't valid".
|
|
90
|
+
|
|
91
|
+
6. **Add a filter expression** if requested — wrap the predicate in `<filterExpression>...</filterExpression>`. The body is a WHERE-clause body without the `WHERE` keyword (e.g. `Status__c != null`, not `WHERE Status__c != null`). For supported operators, field types, and pitfalls, read `references/filter-expressions.md`.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Rules / Constraints
|
|
96
|
+
|
|
97
|
+
| Constraint | Rationale |
|
|
98
|
+
|---|---|
|
|
99
|
+
| `<selectedEntity>` is the ChangeEvent type name, not the source object name | The Metadata API binds the member to a ChangeEvent entity — passing `Account` directly fails with "invalid event in selectedEntity". |
|
|
100
|
+
| Member fullName uses **single** underscore: `Account_ChangeEvent` | The double-underscore form (`Account__ChangeEvent`) is parsed as `<namespace>__<name>` and rejected: "Cannot create a new component with the namespace: Account". |
|
|
101
|
+
| Default channel value is exactly `ChangeEvents` — no path prefix | Older fixtures and some docs show `data/ChangeEvents`; the deploy returns "Unable to find the specified channel" for that value. |
|
|
102
|
+
| Enrichment field names are single-hop API names on the source entity | Standard (`OwnerId`), custom lookup (`MyLookup__c`), and custom non-relationship (`Region__c`) all validate. Traversals like `Owner.Name` are rejected: "The selected field, X.Y, isn't valid". |
|
|
103
|
+
| `<filterExpression>` body has no `WHERE` keyword | Deploy returns "filter expression has syntax errors: unexpected token: 'WHERE'". |
|
|
104
|
+
| Filter cannot reference `IsDeleted` or do relationship traversal (`Owner.Username`) | Deploy rejects with "field is invalid". |
|
|
105
|
+
| DateTime fields support **only equality** in filters (`=`, `!=`) — not `<` / `>` | Deploy returns "Only equality operators are supported for this field type or value". Use a named date literal: `LastModifiedDate = TODAY`. |
|
|
106
|
+
| Filter RHS must be a literal — no field-to-field comparison | `BillingCity = ShippingCity` returns "unexpected token: 'ShippingCity'". |
|
|
107
|
+
| Compound fields (e.g. `BillingAddress`) require dotted component access in filter | `BillingAddress.City = 'X'` deploys; flat `BillingCity` is rejected as "field is invalid"; raw `BillingAddress` is rejected as "has to be used with a component field". Note this is the OPPOSITE of `<enrichedFields>`, which uses flat names. |
|
|
108
|
+
| Custom channel filename ends with `__chn` before the meta-xml suffix | Salesforce's MDAPI naming convention; mismatch causes deploy ambiguity. |
|
|
109
|
+
| Custom channel XML must include `<channelType>data</channelType>` | Without `data`, the channel is rejected for CDC (other types exist for streaming/event channels). |
|
|
110
|
+
| Source custom objects must already exist (or be deployed in the same transaction) | The ChangeEvent entity for `Foo__c` doesn't exist until `Foo__c` does; member deploy fails otherwise. |
|
|
111
|
+
| Never generate a `PlatformEventChannel` file for the default `ChangeEvents` channel | The default channel is system-provided. Reference it via `<eventChannel>ChangeEvents</eventChannel>` on members, but only custom (`__chn`) channels need a channel-meta file. |
|
|
112
|
+
| `PlatformEventChannelMember` accepts ONLY four elements: `<enrichedFields>`, `<eventChannel>`, `<filterExpression>`, `<selectedEntity>` | Adding `<description>`, `<isActive>`, `<masterLabel>`, or any other element fails XML schema validation: "Element {...} invalid at this location". Stick to the four documented elements. |
|
|
113
|
+
| `PlatformEventChannel` accepts ONLY two elements: `<channelType>` and `<label>` | Adding `<masterLabel>`, `<description>`, etc. produces "Element {...}masterLabel invalid at this location in type PlatformEventChannel". Use `<label>`, not `<masterLabel>`. |
|
|
114
|
+
| Generated metadata files only — never run `sf project deploy start` from this skill | This skill produces artifacts; deployment is a separate lifecycle concern. |
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Gotchas
|
|
119
|
+
|
|
120
|
+
| Issue | Resolution |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `Unable to find the specified channel` | Set `<eventChannel>ChangeEvents</eventChannel>` (no `data/` prefix). |
|
|
123
|
+
| `The PlatformEventChannelMember can't be created because it references an invalid event in the "selectedEntity" field` | Use the ChangeEvent name, not the source object: `AccountChangeEvent`, not `Account`. |
|
|
124
|
+
| `Cannot create a new component with the namespace: <Object>` | Rename the file to use a single underscore: `Account_ChangeEvent...`, not `Account__ChangeEvent...`. |
|
|
125
|
+
| `The selected field, X.Y, isn't valid` (in `<enrichedFields>`) | Replace `Owner.Name` with `OwnerId`. CDC enriches the lookup automatically; only single-hop field API names validate. |
|
|
126
|
+
| `filter expression has syntax errors: unexpected token: 'WHERE'` | Remove the `WHERE` keyword. The body is the predicate only. |
|
|
127
|
+
| `The BillingCity field in the filter expression is invalid` (or any flat Address component) | Use the compound dotted form: `BillingAddress.City`, not `BillingCity`. See `references/filter-expressions.md` for the full compound-field matrix. |
|
|
128
|
+
| Custom-object member fails with "ChangeEvent doesn't exist" | The source object isn't deployed yet. Ensure the `Foo__c` object metadata is in the same deploy or already in the org. |
|
|
129
|
+
| `DUPLICATE_VALUE` on second deploy | The member is already subscribed. Either delete first or skip — CDC doesn't support upsert on members directly. |
|
|
130
|
+
| `sf infra error (TypeInferenceError, DeployMetadata): Could not infer a metadata type` for a `.changeDataCapture-meta.xml` file | That file extension and metadata type don't exist. Replace the `changeDataCapture/<Entity>.changeDataCapture-meta.xml` file with a `platformEventChannelMembers/<Entity>_ChangeEvent.platformEventChannelMember-meta.xml` file. |
|
|
131
|
+
| User says "subscribe Order__c" but means standard `Order` | Confirm — `OrderChangeEvent` (standard) and `Order__ChangeEvent` (custom) are different entities. |
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Output Expectations
|
|
136
|
+
|
|
137
|
+
Deliverables:
|
|
138
|
+
- One `force-app/.../platformEventChannelMembers/<Entity>_ChangeEvent.platformEventChannelMember-meta.xml` per subscribed entity.
|
|
139
|
+
- One `force-app/.../platformEventChannels/<DevName>__chn.platformEventChannel-meta.xml` per custom channel (if any).
|
|
140
|
+
|
|
141
|
+
File structure follows the templates in `assets/`.
|
|
142
|
+
|
|
143
|
+
After receiving the generated files, the user can verify them with `sf project deploy start --dry-run -d <path> --target-org <alias>` before deploying. If a dry-run surfaces an unfamiliar error, `references/deploy-troubleshooting.md` maps the common deploy errors to their metadata-side fixes.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Cross-Skill Integration
|
|
148
|
+
|
|
149
|
+
| Need | Delegate to |
|
|
150
|
+
|---|---|
|
|
151
|
+
| Generate the source custom object | `generating-custom-object` skill |
|
|
152
|
+
| Generate custom fields referenced by enrichment or filter | `generating-custom-field` skill |
|
|
153
|
+
| Build a permission set for users who consume change events | `generating-permission-set` skill |
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Reference File Index
|
|
158
|
+
|
|
159
|
+
| File | When to read |
|
|
160
|
+
|---|---|
|
|
161
|
+
| `assets/PlatformEventChannelMember-template.xml` | Step 3 — starting structure for a channel member |
|
|
162
|
+
| `assets/PlatformEventChannel-template.xml` | Step 4 — starting structure for a custom channel |
|
|
163
|
+
| `references/filter-expressions.md` | Step 6 — for the supported operators and field-type matrix when writing a filter expression |
|
|
164
|
+
| `references/deploy-troubleshooting.md` | When a user reports a dry-run deploy error and asks for help diagnosing it |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<PlatformEventChannelMember xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
3
|
+
<!-- Optional: add one <enrichedFields><name>FIELD_API_NAME</name></enrichedFields> per field. Single-hop API names only (e.g. OwnerId, ParentId, MyLookup__c, Region__c). -->
|
|
4
|
+
|
|
5
|
+
<!-- Default CDC channel: ChangeEvents (no path prefix). For a custom channel, use its DeveloperName, e.g. PartnerSync__chn. -->
|
|
6
|
+
<eventChannel>ChangeEvents</eventChannel>
|
|
7
|
+
<!-- Optional: add <filterExpression>YOUR_PREDICATE</filterExpression> if needed (predicate body only, no WHERE keyword). -->
|
|
8
|
+
|
|
9
|
+
<!-- ChangeEvent entity name. Standard: <Object>ChangeEvent. Custom: replace __c with __ChangeEvent. -->
|
|
10
|
+
<selectedEntity>AccountChangeEvent</selectedEntity>
|
|
11
|
+
</PlatformEventChannelMember>
|