@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,73 @@
|
|
|
1
|
+
# CDC Deploy Troubleshooting
|
|
2
|
+
|
|
3
|
+
Errors observed during real org dry-runs while authoring this skill, with the metadata-side fix.
|
|
4
|
+
|
|
5
|
+
## "Unable to find the specified channel"
|
|
6
|
+
|
|
7
|
+
The `<eventChannel>` value doesn't match a channel known to the org.
|
|
8
|
+
|
|
9
|
+
- For the default channel, the value must be exactly `ChangeEvents`. NOT `data/ChangeEvents`, NOT `/data/ChangeEvents`, NOT `data/ChangeEvent`.
|
|
10
|
+
- For a custom channel, the value must match the channel's DeveloperName **including the `__chn` suffix** — e.g. `PartnerSync__chn`.
|
|
11
|
+
- If the custom channel is in the same deploy, ensure it's in the same package directory so MDAPI orders the deploy correctly.
|
|
12
|
+
|
|
13
|
+
## "...invalid event in the 'selectedEntity' field"
|
|
14
|
+
|
|
15
|
+
`<selectedEntity>` must be the ChangeEvent entity, not the source object.
|
|
16
|
+
|
|
17
|
+
| Source | Wrong | Right |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| `Account` | `Account` | `AccountChangeEvent` |
|
|
20
|
+
| `Lead` | `Lead` | `LeadChangeEvent` |
|
|
21
|
+
| `Order__c` | `Order__c` | `Order__ChangeEvent` |
|
|
22
|
+
| `Custom__c` | `Custom__c` | `Custom__ChangeEvent` |
|
|
23
|
+
|
|
24
|
+
For custom objects, swap the trailing `__c` for `__ChangeEvent` — the double underscore separator is preserved.
|
|
25
|
+
|
|
26
|
+
## "Cannot create a new component with the namespace: <Object>"
|
|
27
|
+
|
|
28
|
+
The member's fullName has two underscores between the entity and `ChangeEvent`. Salesforce parses `Foo__Bar` as `<namespace>__<name>` and rejects creation outside the org's own namespace.
|
|
29
|
+
|
|
30
|
+
- Member fullName format: `<Entity>_ChangeEvent` (single underscore).
|
|
31
|
+
- File name: `<Entity>_ChangeEvent.platformEventChannelMember-meta.xml`.
|
|
32
|
+
|
|
33
|
+
This applies even when the source object has `__c` — the member fullName drops the `__c` and uses single underscore: file `Order_ChangeEvent.platformEventChannelMember-meta.xml`, fullName `Order_ChangeEvent`.
|
|
34
|
+
|
|
35
|
+
## "The selected field, X.Y, isn't valid" (enrichedFields)
|
|
36
|
+
|
|
37
|
+
Enrichment fields must be **single-hop API names on the source entity**. Field type doesn't matter — standard lookup IDs, custom lookups, and custom non-relationship fields all work. The rejection is specifically for relationship-traversal syntax (`X.Y`, `__r.Y`).
|
|
38
|
+
|
|
39
|
+
Verified working in dry-run:
|
|
40
|
+
|
|
41
|
+
| Field | Type | Result |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| `OwnerId` | standard lookup ID | ✓ deploys |
|
|
44
|
+
| `ParentId` | standard lookup ID | ✓ deploys |
|
|
45
|
+
| `MyAccountManager__c` | custom Lookup → User | ✓ deploys |
|
|
46
|
+
| `Region__c` | custom Text | ✓ deploys |
|
|
47
|
+
| `Status__c` | custom Picklist | ✓ deploys |
|
|
48
|
+
|
|
49
|
+
Verified rejected:
|
|
50
|
+
|
|
51
|
+
| Field | Why |
|
|
52
|
+
|---|---|
|
|
53
|
+
| `Owner.Name` | relationship traversal |
|
|
54
|
+
| `Parent.Account.Industry` | multi-hop traversal |
|
|
55
|
+
| `MyLookup__r.Name` | relationship traversal (custom) |
|
|
56
|
+
|
|
57
|
+
When the user says "include the owner's name in every event," the metadata stores `OwnerId` — CDC enriches the lookup automatically and the consumer resolves the related record from the ID.
|
|
58
|
+
|
|
59
|
+
## "filter expression has syntax errors: unexpected token: 'WHERE'"
|
|
60
|
+
|
|
61
|
+
The body of `<filterExpression>` is a SOQL WHERE-clause body — without the `WHERE` keyword.
|
|
62
|
+
|
|
63
|
+
| Wrong | Right |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `WHERE Status__c != null` | `Status__c != null` |
|
|
66
|
+
| `WHERE Industry IN ('Tech', 'Finance')` | `Industry IN ('Tech', 'Finance')` |
|
|
67
|
+
|
|
68
|
+
## ChangeEvent entity doesn't exist (for custom objects)
|
|
69
|
+
|
|
70
|
+
`Foo__ChangeEvent` only exists if `Foo__c` exists. If both are being deployed in the same dry-run, the dry-run validator may flag the member because it validates entity references against the *current* org state, not the post-deploy state. Mitigations:
|
|
71
|
+
|
|
72
|
+
- Deploy the source object first, then the channel member in a second deploy.
|
|
73
|
+
- Or accept that dry-run will flag this case but a real (non-dry-run) deploy succeeds because MDAPI orders the components correctly.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Filter Expression Reference
|
|
2
|
+
|
|
3
|
+
The `<filterExpression>` body is a SOQL-WHERE-clause-body — predicate only, no `WHERE` keyword. The platform supports a subset of SOQL grammar for CDC filters; this reference documents what the dry-run deploy verifies.
|
|
4
|
+
|
|
5
|
+
## Operators by field type
|
|
6
|
+
|
|
7
|
+
| Field type | Supported operators | Notes |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| Text | `=`, `!=`, `IN`, `NOT IN`, `LIKE` | `LIKE` accepts `%` wildcard. Quote string literals with single quotes. |
|
|
10
|
+
| Number / Currency / Percent | `=`, `!=`, `<`, `<=`, `>`, `>=` | Numeric literals unquoted. |
|
|
11
|
+
| Boolean (Checkbox) | `=`, `!=` | Use `true` / `false` literal — no quotes. |
|
|
12
|
+
| Date | `=`, `!=` | Named literals (`TODAY`, `THIS_WEEK`, `LAST_N_DAYS:7`) and ISO date strings work. |
|
|
13
|
+
| DateTime | `=`, `!=` only | **Range operators (`>`, `<`) are rejected** — "Only equality operators are supported for this field type or value". |
|
|
14
|
+
| Reference (lookup ID) | `=`, `!=`, `IN`, `NOT IN` | Use the 18-character ID in single quotes: `OwnerId = '005000000000000AAA'`. |
|
|
15
|
+
| Picklist | `=`, `!=`, `IN`, `NOT IN` | Quote the value as a string. |
|
|
16
|
+
|
|
17
|
+
## Compound expressions
|
|
18
|
+
|
|
19
|
+
`AND`, `OR`, and parentheses all work. There's no documented limit on nesting depth.
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
(Industry = 'Technology' OR Industry = 'Finance') AND AnnualRevenue > 0 AND Phone != null
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Null checks
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
Phone = null
|
|
29
|
+
Phone != null
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`null` is a literal — no quotes.
|
|
33
|
+
|
|
34
|
+
`ISBLANK()` and `ISNULL()` are **not** valid filter operators — they parse-fail with "unexpected token". They work in formulas but not in CDC filter expressions. Use `Field = null` / `Field != null` instead.
|
|
35
|
+
|
|
36
|
+
## Functions
|
|
37
|
+
|
|
38
|
+
`LOWER(Name) = 'acme'` deploys successfully. Other SOQL functions probably work, but only `LOWER` has been verified in this skill's dataset. Test before relying on `UPPER`, `CONVERTCURRENCY`, etc.
|
|
39
|
+
|
|
40
|
+
## What the filter cannot do
|
|
41
|
+
|
|
42
|
+
| Pattern | Deploy error |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `WHERE Industry = 'Tech'` | "filter expression has syntax errors: unexpected token: 'WHERE'" — drop the keyword. |
|
|
45
|
+
| `IsDeleted = false` | "The IsDeleted field in the filter expression is invalid." Soft-deleted records still emit ChangeEvent; you cannot filter them out via this mechanism. |
|
|
46
|
+
| `Owner.Username = 'foo@bar.com'` | "The Owner.Username field in the filter expression is invalid." Relationship traversal works in `<enrichedFields>` rejection messages but NOT in filter expressions either — single-hop only. |
|
|
47
|
+
| `LastModifiedDate > LAST_N_DAYS:30` | "Only equality operators are supported for this field type or value." DateTime is equality-only; for "recent changes" semantics, use `LastModifiedDate = LAST_N_DAYS:N` (which compares to the *day*, not the timestamp). |
|
|
48
|
+
|
|
49
|
+
## Field-to-field comparison: not supported
|
|
50
|
+
|
|
51
|
+
The right-hand side of a comparison must be a **literal**. Field references are rejected.
|
|
52
|
+
|
|
53
|
+
| Wrong | Deploy error |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `BillingCity = ShippingCity` | "syntax errors: unexpected token: 'ShippingCity'" |
|
|
56
|
+
| `NumberOfEmployees > AnnualRevenue` | "unexpected token: 'AnnualRevenue'" |
|
|
57
|
+
|
|
58
|
+
If the user wants "records where two fields differ," that logic must live downstream of the change event consumer, not in the filter.
|
|
59
|
+
|
|
60
|
+
## Composite (compound) fields like Address: dotted-component is the only valid form
|
|
61
|
+
|
|
62
|
+
Counterintuitively, the opposite rule applies for composite fields like `BillingAddress` vs. relationship traversals like `Owner.Name`. Compound fields **require** dot-notation; flat component names are rejected.
|
|
63
|
+
|
|
64
|
+
| Pattern | Result |
|
|
65
|
+
|---|---|
|
|
66
|
+
| `BillingAddress.City = 'San Francisco'` | ✓ deploys — required form for compound fields |
|
|
67
|
+
| `BillingAddress = null` | ✗ "Compound field BillingAddress has to be used with a component field in a filter expression" |
|
|
68
|
+
| `BillingCity = 'San Francisco'` (flat component) | ✗ "The BillingCity field in the filter expression is invalid" |
|
|
69
|
+
| `BillingState`, `BillingPostalCode`, `BillingCountry`, `BillingLatitude` (flat) | ✗ all rejected as invalid |
|
|
70
|
+
|
|
71
|
+
So, for the same `BillingAddress` field, the accepted form differs by location:
|
|
72
|
+
|
|
73
|
+
| Location | `BillingAddress` (compound) | `BillingAddress.City` (dotted) | `BillingCity` (flat component) |
|
|
74
|
+
|---|---|---|---|
|
|
75
|
+
| `<filterExpression>` | ✗ "has to be used with a component field" | ✓ deploys (required form) | ✗ "field is invalid" |
|
|
76
|
+
| `<enrichedFields>` | ✓ deploys | ✗ "isn't valid" (dots never allowed) | ✗ "isn't valid" (components not exposed at this layer) |
|
|
77
|
+
|
|
78
|
+
Rules per location:
|
|
79
|
+
|
|
80
|
+
- **Filter expression**: address components are reachable only via dotted form on the compound (`BillingAddress.City`). Both the compound itself (no component) and the flat component name are rejected.
|
|
81
|
+
- **Enrichment field**: takes a top-level field API name only. The compound `BillingAddress` is a top-level field and works; dotted forms are never valid here regardless of whether the dot would be a compound-component select or a relationship traversal; flat components like `BillingCity` are not top-level enrichable fields and are rejected.
|
|
82
|
+
- **Relationship traversal** (`Owner.Name`, `Parent.Industry`) is rejected in both locations.
|
|
83
|
+
|
|
84
|
+
The mental model: compound fields are a single physical column with sub-components; relationships are joins. The filter parser supports dotted access into compound sub-components but never into joins. The enrichment list takes top-level field names only and never accepts dots; the platform handles compound-vs-component decomposition itself when emitting the change event payload.
|
|
85
|
+
|
|
86
|
+
## What's NOT yet verified
|
|
87
|
+
|
|
88
|
+
- Aggregate functions or subqueries — almost certainly unsupported.
|
|
89
|
+
- Operators on Long Text, Rich Text, Encrypted, Geolocation field types.
|
|
90
|
+
- Filter on a custom field that doesn't exist (deploy-time error vs runtime).
|
|
91
|
+
- Custom-object-specific picklist with locale-sensitive values.
|
|
92
|
+
|
|
93
|
+
If the user requests one of these and the deploy succeeds — update this file. If it fails — capture the error here.
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: managing-suite-assignments
|
|
3
|
+
description: "Manages all forms of test suite assignment for DevOps Center pipeline stages via the Connect API testSuiteStages endpoint. Covers three modes: (A) attaching a single suite to a stage as a one-off add, (B) bulk-mapping multiple suites to a stage as a testing strategy with a mandatory impact-preview table before any changes, and (C) adding or removing individual test classes within a suite assignment with governance rules that exclude rejected tests and re-present the final list before committing. TRIGGER when: a suite is found unlinked from a pipeline stage and the user wants to assign it; the user wants to configure suite-to-stage mappings across a pipeline or assign multiple suites to stages as part of a testing strategy; the user wants to add or remove tests in a suite, sync reviewed tests into a suite, or promote tests to a suite. DO NOT TRIGGER when: authoring new test classes (use generating-apex-test) or running tests directly (use running-apex-tests)."
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0"
|
|
6
|
+
minApiVersion: "67.0"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Managing Suite Assignments
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
Load `checking-devops-prerequisites` first — Prerequisites 1–4 AND Prerequisite 5 (stage). You need `doce-org-alias`, `pipelineId`, and `stageId` before proceeding in any mode.
|
|
14
|
+
|
|
15
|
+
| Variable | Description |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `doce-org-alias` | Established in Prerequisite 1 |
|
|
18
|
+
| `pipelineId` | Identified in Prerequisite 4 (pipeline selection) |
|
|
19
|
+
| `stageId` | Identified in Prerequisite 5 (stage selection) |
|
|
20
|
+
| `event` | `Pre-Promote`, `Post-Promote`, or `Review` |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Mode A — Assign a single suite to a stage
|
|
25
|
+
|
|
26
|
+
Use this mode when a relevant test suite already exists but is not yet linked to a pipeline stage and the user wants to add it as a single one-off assignment.
|
|
27
|
+
|
|
28
|
+
**Additional inputs required:**
|
|
29
|
+
|
|
30
|
+
| Variable | Description |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `testSuiteId` | ID of the suite to assign |
|
|
33
|
+
| `testSuiteName` | Name of the suite (for display in confirmation) |
|
|
34
|
+
|
|
35
|
+
**Confirmation gate**
|
|
36
|
+
|
|
37
|
+
**Confirmation required before any API call is made.**
|
|
38
|
+
|
|
39
|
+
Present the following prompt to the user and wait for an affirmative response:
|
|
40
|
+
|
|
41
|
+
> "The suite `<testSuiteName>` is not currently assigned to the `<stageName>` stage (`<event>`). Would you like me to assign it now?"
|
|
42
|
+
|
|
43
|
+
Do not proceed until the user confirms.
|
|
44
|
+
|
|
45
|
+
**On success**
|
|
46
|
+
|
|
47
|
+
Report to the user:
|
|
48
|
+
|
|
49
|
+
> "Suite `<testSuiteName>` has been assigned to the `<stageName>` stage (`<event>`)."
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Mode B — Map multiple suites to a stage
|
|
54
|
+
|
|
55
|
+
Use this mode when configuring suite-to-stage mappings across a pipeline or assigning multiple suites to stages as part of a testing strategy.
|
|
56
|
+
|
|
57
|
+
**Additional inputs required:**
|
|
58
|
+
|
|
59
|
+
| Input | Description |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `testSuiteOperations` | List of `{testSuiteId, action: "add"\|"remove"}` |
|
|
62
|
+
|
|
63
|
+
**MANDATORY IMPACT PREVIEW — Required Before Any Changes**
|
|
64
|
+
|
|
65
|
+
**Do not call the API until the user has confirmed the preview below.**
|
|
66
|
+
|
|
67
|
+
Present the full mapping summary and wait for explicit confirmation:
|
|
68
|
+
|
|
69
|
+
> "Here's the suite mapping I'll apply:
|
|
70
|
+
>
|
|
71
|
+
> | Suite | Stage | Event | Action |
|
|
72
|
+
> |---|---|---|---|
|
|
73
|
+
> | `<suiteName>` | `<stageName>` | `<event>` | Add |
|
|
74
|
+
> | `<suiteName2>` | `<stageName>` | `<event>` | Remove |
|
|
75
|
+
>
|
|
76
|
+
> Confirm to apply all changes?"
|
|
77
|
+
|
|
78
|
+
Only proceed after the user explicitly confirms.
|
|
79
|
+
|
|
80
|
+
**On success**
|
|
81
|
+
|
|
82
|
+
> "Suite mapping applied. `<N>` suite(s) updated for the `<stageName>` stage."
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Mode C — Add/remove test classes in a suite
|
|
87
|
+
|
|
88
|
+
Use this mode when the user wants to add or remove individual test classes within an existing suite assignment, sync reviewed tests into a suite, or promote tests to a suite.
|
|
89
|
+
|
|
90
|
+
**Additional inputs required:**
|
|
91
|
+
|
|
92
|
+
| Input | Source |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `testSuiteOperations` | List of `{testSuiteId, action: "add"\|"remove"}` |
|
|
95
|
+
|
|
96
|
+
**Governance rules**
|
|
97
|
+
|
|
98
|
+
- **Never call this without explicit approval.** AI-reviewed or modified tests must be re-presented to the user before this call is made.
|
|
99
|
+
- Rejected tests must be EXCLUDED from the payload — do not include them even if they were previously in the suite.
|
|
100
|
+
- If tests were modified during review, re-present the final list of tests before requesting confirmation.
|
|
101
|
+
|
|
102
|
+
**Confirmation gate**
|
|
103
|
+
|
|
104
|
+
**REQUIRED — do not skip.** Show the user the full list of changes before calling:
|
|
105
|
+
|
|
106
|
+
> "I'm about to sync the following changes to the test suite:
|
|
107
|
+
> - **Add:** `<testSuiteName1>`, `<testSuiteName2>`
|
|
108
|
+
> - **Remove:** `<testSuiteName3>`
|
|
109
|
+
> - Stage: `<stageName>` | Event: `<event>`
|
|
110
|
+
>
|
|
111
|
+
> Confirm?"
|
|
112
|
+
|
|
113
|
+
Only proceed after receiving explicit confirmation.
|
|
114
|
+
|
|
115
|
+
**On success**
|
|
116
|
+
|
|
117
|
+
Confirm to the user:
|
|
118
|
+
> "Test suite updated successfully for the `<stageName>` stage."
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## The system call
|
|
123
|
+
|
|
124
|
+
All three modes use the same endpoint. Substitute all `<placeholder>` values before executing.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
sf api request rest "/services/data/v67.0/connect/devopstesting/pipeline/<pipelineId>/testSuiteStages" --method POST --body '{"pipelineStageId":"<stageId>","event":"<event>","assignments":[{"testSuiteId":"<id>","action":"add|remove"}]}' --target-org <doce-org-alias>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Full payload schema:
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"pipelineStageId": "<stageId>",
|
|
135
|
+
"event": "<event>",
|
|
136
|
+
"assignments": [
|
|
137
|
+
{"testSuiteId": "<suiteId1>", "action": "add"},
|
|
138
|
+
{"testSuiteId": "<suiteId2>", "action": "remove"}
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Error handling**
|
|
144
|
+
|
|
145
|
+
Never expose raw API error messages to the user. Map response status codes to the following user-facing messages:
|
|
146
|
+
|
|
147
|
+
| Status | User-facing message |
|
|
148
|
+
|---|---|
|
|
149
|
+
| 400 | "The request was invalid. Check that all suite and stage IDs are correct and the event type is valid." |
|
|
150
|
+
| 403 | "You don't have permission to modify suite assignments on this pipeline." |
|
|
151
|
+
| 404 | "The pipeline or stage was not found." |
|
|
152
|
+
| 500 | "A server error occurred. Try again in a few minutes." |
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Related skills
|
|
157
|
+
|
|
158
|
+
- **`syncing-test-providers`** — use when the suite you want to assign doesn't appear yet; re-syncing the provider pulls in newly added suites.
|
|
159
|
+
- **`recommending-devops-tests`** — use when a suite has not yet been identified and you need a recommendation for which suite to assign.
|
|
160
|
+
- **`configuring-quality-gate`** — use to configure a quality gate on the stage after mapping suites.
|
|
161
|
+
- **`analyzing-test-failures`** — use for failure analysis and suggested improvements to the tests within a suite.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: polling-test-results
|
|
3
|
+
description: "Polls a DevOps Center async test execution by runId until it completes, fails, or times out — using read-only SOQL on the execution record at provider-specific intervals (Apex 15s/5m, Code Analyzer 10s/3m, Provar UI 60s/20m, Flow 20s/8m) — then surfaces results. Use this skill when a test suite run is in progress and the user is waiting on results, or immediately after running a suite. TRIGGER when: a test suite run is in progress and the user is waiting on results, or immediately after running a suite and a runId is available. DO NOT TRIGGER when: there is no active runId."
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0"
|
|
6
|
+
minApiVersion: "67.0"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# polling-test-results
|
|
10
|
+
|
|
11
|
+
**Confirmation required:** No — polling is automatic and read-only. No user confirmation gate is needed.
|
|
12
|
+
|
|
13
|
+
**What it does:** Polls the DevOps Center org for the status of an async test execution until it completes, times out, or fails.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
You need an active `runId` (returned by the `running-devops-test-suite` skill) and the confirmed `doce-org-alias`. If org context is not yet established, load `checking-devops-prerequisites` first (Prerequisites 1–3).
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Inputs required
|
|
24
|
+
|
|
25
|
+
| Input | Source |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `runId` | Returned by the `running-devops-test-suite` skill |
|
|
28
|
+
| `testType` | Derived from the suite's test provider (Apex, Code Analyzer, UI/Provar, Flow) |
|
|
29
|
+
| `doce-org-alias` | Established via `checking-devops-prerequisites` |
|
|
30
|
+
|
|
31
|
+
## Polling configuration
|
|
32
|
+
|
|
33
|
+
| Test type | Poll interval | Max wait | Timeout action |
|
|
34
|
+
|---|---|---|---|
|
|
35
|
+
| Apex unit tests | 15 seconds | 5 minutes | Surface runId, offer retry |
|
|
36
|
+
| Code Analyzer | 10 seconds | 3 minutes | Surface runId, offer retry |
|
|
37
|
+
| UI tests (Provar) | 60 seconds | 20 minutes | Surface runId, mark as pending |
|
|
38
|
+
| Flow tests | 20 seconds | 8 minutes | Surface runId, offer retry |
|
|
39
|
+
|
|
40
|
+
## Poll query
|
|
41
|
+
|
|
42
|
+
Query the execution record by `runId` on each interval:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
sf data query \
|
|
46
|
+
--query "SELECT Id, Status, TestsRan, TestsPassed, TestsFailed, CoveragePercentage FROM DevopsTestExecution WHERE Id = '<runId>' LIMIT 1" \
|
|
47
|
+
--target-org <doce-org-alias> \
|
|
48
|
+
--json
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Check the `Status` field on each poll:
|
|
52
|
+
- `Queued` / `Running` → wait and poll again
|
|
53
|
+
- `Completed` → proceed to result analysis
|
|
54
|
+
- `Failed` → surface error and offer retry or skip
|
|
55
|
+
|
|
56
|
+
## On timeout
|
|
57
|
+
|
|
58
|
+
Surface the `runId` to the user:
|
|
59
|
+
> "The test run is taking longer than expected. Your run ID is `<runId>`. You can check the status manually in DevOps Center, or I can keep waiting — what would you prefer?"
|
|
60
|
+
|
|
61
|
+
Do not automatically retry after timeout. Wait for user instruction.
|
|
62
|
+
|
|
63
|
+
## On completion
|
|
64
|
+
|
|
65
|
+
Pass the full result payload to the `analyzing-test-failures` skill for reasoning. Surface `Coverage`, `SuccessCount`, `FailureCount`, and `QualityGateStatus` inline. Do not surface raw JSON to the user.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Related skills
|
|
70
|
+
|
|
71
|
+
- Runs are started by `running-devops-test-suite` (including its retrigger mode)
|
|
72
|
+
- Failure analysis is handled by `analyzing-test-failures`
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: recommending-devops-tests
|
|
3
|
+
description: "Analyzes a commit diff and available DevOps Center test suite metadata to recommend the most relevant existing test suites, then flags coverage gaps where no suite covers a new method — via pure reasoning, no system calls beyond the prerequisite queries. Use this skill when a developer wants to know which test suites to run for a specific commit or diff, what tests cover their changes, or wants suite recommendations at commit time. TRIGGER when: the user asks which test suites to run for a commit/diff, asks what tests cover their changes, or asks for suite recommendations before promoting. DO NOT TRIGGER when: authoring new tests (use generating-apex-test) or running sf apex run test directly (use running-apex-tests)."
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0"
|
|
6
|
+
minApiVersion: "67.0"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Recommending DevOps Tests
|
|
10
|
+
|
|
11
|
+
**Type:** Pure reasoning — no system calls beyond the prerequisite data-fetch queries documented below.
|
|
12
|
+
|
|
13
|
+
**What it does:** Analyzes the commit diff and available suite metadata to recommend the most relevant existing test suites assigned to the Review pipeline stage. Flags coverage gaps where no suite covers a new method.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
Load and follow the `checking-devops-prerequisites` skill first (Prerequisites 1–4). This skill needs a confirmed DevOps Center org alias and pipeline Id before it can proceed.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Step 1 — Fetch suite metadata
|
|
24
|
+
|
|
25
|
+
Before reasoning can begin, fetch the test suite metadata assigned to the Review pipeline stage. This requires two queries.
|
|
26
|
+
|
|
27
|
+
**1a — Find the Review pipeline stage trigger:**
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
sf data query \
|
|
31
|
+
--query "SELECT Id FROM DevopsPipelineStageTrigger WHERE TriggerType = 'Review' AND RelatedRecordId = '<pipelineId>'" \
|
|
32
|
+
--target-org <doce-org-alias> \
|
|
33
|
+
--json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Record the `Id` returned as `<reviewTriggerId>`.
|
|
37
|
+
|
|
38
|
+
**1b — Fetch suites assigned to that trigger:**
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
sf data query \
|
|
42
|
+
--query "SELECT Id, TestSuiteId, TestSuite.Name, IsQualityGateEnabled, DevopsQualityGateId FROM DevopsTestSuiteStage WHERE DevopsPipelineStageTriggerId = '<reviewTriggerId>'" \
|
|
43
|
+
--target-org <doce-org-alias> \
|
|
44
|
+
--json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Each row provides: `TestSuiteId`, `TestSuite.Name`, `IsQualityGateEnabled`, and `DevopsQualityGateId` (when a gate is configured).
|
|
48
|
+
|
|
49
|
+
> Note: Do NOT use the beta `/connect/devops/.../testSuites` endpoint — it returns empty results. Query `DevopsTestSuiteStage` directly as shown above.
|
|
50
|
+
|
|
51
|
+
Never expose raw API errors or raw JSON to the user. If a query fails, report the problem in plain language and stop.
|
|
52
|
+
|
|
53
|
+
The commit diff comes from the user or surrounding context.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Reasoning steps
|
|
58
|
+
|
|
59
|
+
### 1 — Classify the diff by change type
|
|
60
|
+
|
|
61
|
+
Parse the diff file extensions and paths to determine what types of changes were made:
|
|
62
|
+
|
|
63
|
+
| File pattern | Change type |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `*.cls`, `*.trigger` | Apex |
|
|
66
|
+
| `*.flow-meta.xml`, `*.flow` | Flow |
|
|
67
|
+
| `*.java` | Java |
|
|
68
|
+
| `*.js`, `*.html` (LWC paths) | LWC / JavaScript |
|
|
69
|
+
|
|
70
|
+
A single commit may contain multiple change types. Identify all of them.
|
|
71
|
+
|
|
72
|
+
### 2 — Map change types to test providers
|
|
73
|
+
|
|
74
|
+
For each change type identified, match against the `testProviderName` of the fetched suites:
|
|
75
|
+
|
|
76
|
+
| Change type | Match suites whose `testProviderName` contains |
|
|
77
|
+
|---|---|
|
|
78
|
+
| Apex | `Apex` |
|
|
79
|
+
| Flow | `Flow` |
|
|
80
|
+
| Java | `Java` |
|
|
81
|
+
| LWC / JavaScript | `LWC` or `JavaScript` |
|
|
82
|
+
| Code Analyzer (any) | `Code Analyzer` — then sub-filter by suite name convention: `recommended` → Apex/general rules (suggest for Apex and Java changes), `html` → suggest for HTML/LWC template changes, `css` → suggest for CSS changes. If no suite name matches the convention, suggest all Code Analyzer suites and note the ambiguity. |
|
|
83
|
+
|
|
84
|
+
Only recommend suites whose provider matches at least one change type in the diff. Suites from non-matching providers are excluded from the recommendation.
|
|
85
|
+
|
|
86
|
+
### 3 — Rank matched suites
|
|
87
|
+
|
|
88
|
+
Within each matched provider group, rank suites by:
|
|
89
|
+
1. `triggerType` alignment — `Pre-Promote` suites first for commit-time checks
|
|
90
|
+
2. Quality gate presence — suites with a `qualityGateRuleName` are higher priority (they gate promotion)
|
|
91
|
+
3. Suite name relevance — if the suite name contains a term from the modified file names, boost it
|
|
92
|
+
|
|
93
|
+
### 4 — Flag new methods with no suite coverage
|
|
94
|
+
|
|
95
|
+
For any new method added in the diff, flag it as a gap regardless of provider matching:
|
|
96
|
+
> "⚠ `processRefund()` in `OrderService.cls` is a new method. No existing suite can confirm it's covered until tests are authored and linked."
|
|
97
|
+
|
|
98
|
+
### 5 — Return the recommendation list
|
|
99
|
+
|
|
100
|
+
Group recommendations by change type so it's clear why each suite was suggested.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Output format
|
|
105
|
+
|
|
106
|
+
```text
|
|
107
|
+
Recommended suite(s) for this commit:
|
|
108
|
+
|
|
109
|
+
Apex changes detected (OrderService.cls, InvoiceService.cls):
|
|
110
|
+
1. <SuiteName> — Apex Test Provider | Trigger: Pre-Promote | Gate: <gateName or none>
|
|
111
|
+
2. <SuiteName2> — Apex Test Provider | Trigger: Post-Promote | Gate: <gateName or none>
|
|
112
|
+
|
|
113
|
+
Flow changes detected (OrderApproval.flow):
|
|
114
|
+
1. <SuiteName3> — Flow Test Provider | Trigger: Pre-Promote | Gate: <gateName or none>
|
|
115
|
+
|
|
116
|
+
Code Analyzer — Apex rules:
|
|
117
|
+
1. <SuiteName4> — Code Analyzer | Trigger: Pre-Promote | Gate: <gateName or none>
|
|
118
|
+
|
|
119
|
+
No matching suite found for:
|
|
120
|
+
- LWC changes — no LWC test suite is assigned to this stage
|
|
121
|
+
|
|
122
|
+
Coverage gaps (new methods — manual authoring required):
|
|
123
|
+
- `processRefund()` in `OrderService.cls` — new method, not yet covered by any suite
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## v1 constraint
|
|
129
|
+
|
|
130
|
+
Only recommend existing suites. Never suggest generating new tests. If gaps exist, direct the developer to author tests manually and explain exactly which methods need coverage.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Related skills
|
|
135
|
+
|
|
136
|
+
- To analyze failures from a run, use `analyzing-test-failures`.
|
|
137
|
+
- To actually execute a recommended suite, use `running-devops-test-suite`.
|