@salesforce/afv-skills 1.65.1 → 1.67.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 +2 -4
- package/skills/agentforce-offline-experimentation-run/SKILL.md +29 -43
- package/skills/agentforce-offline-experimentation-run/scripts/sfap_replay.py +3 -245
- package/skills/commerce-react-storefront-create/SKILL.md +350 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +2 -2
- package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +28 -16
- package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +18 -1
- package/skills/dx-devops-work-item-manage/SKILL.md +34 -17
- package/skills/dx-devops-work-item-manage/examples/common-workflows.md +49 -0
- package/skills/dx-devops-work-item-manage/references/commit-api.md +116 -0
- package/skills/education-cloud-domain-configure/SKILL.md +21 -23
- package/skills/education-cloud-domain-configure/references/dependent-features.md +9 -0
- package/skills/education-cloud-domain-configure/references/domain-features.md +15 -0
- package/skills/education-cloud-domain-configure/references/gotchas-extended.md +8 -0
- package/skills/education-cloud-domain-configure/references/setup-widgets.md +123 -0
- package/skills/experience-lwc-widget-assess/SKILL.md +79 -0
- package/skills/experience-lwc-widget-migrate/SKILL.md +50 -0
- package/skills/experience-search-coordinate/SKILL.md +2 -2
- package/skills/experience-search-coordinate/references/media-route.md +30 -4
- package/skills/experience-ui-bundle-features-generate/SKILL.md +1 -1
- package/skills/experience-ui-bundle-mfa-configure/SKILL.md +1 -1
- package/skills/platform-metadata-deploy/README.md +1 -1
- package/skills/platform-metadata-deploy/SKILL.md +114 -15
- package/skills/platform-metadata-deploy/references/agent-deployment-guide.md +3 -4
- package/skills/platform-metadata-deploy/references/orchestration.md +2 -3
- package/skills/platform-role-hierarchy-apply/SKILL.md +177 -0
- package/skills/platform-value-set-generate/SKILL.md +19 -19
- package/skills/platform-widget-generate/SKILL.md +59 -68
- package/skills/platform-widget-generate/examples/formulas.json +19 -2
- package/skills/platform-widget-generate/examples/localized-labels.json +57 -0
- package/skills/platform-widget-generate/references/widget-actions.md +29 -0
- package/skills/platform-widget-generate/references/widget-bundle-validation.md +15 -0
- package/skills/platform-widget-generate/references/widget-formulas.md +24 -7
- package/skills/platform-widget-generate/references/widget-gotchas.md +10 -0
- package/skills/platform-widget-generate/references/widget-labels.md +78 -0
- package/skills/platform-widget-generate/references/widget-styling.md +12 -0
- package/skills/sales-call-scoring-configure/SKILL.md +17 -10
- package/skills/sales-call-scoring-configure/scripts/enable-call-scoring.sh +55 -33
- package/skills/service-agentforce-contact-center-coordinate/SKILL.md +1 -1
- package/skills/service-agentforce-contact-center-coordinate/references/number_management_api.md +11 -1
- package/skills/service-agentforce-contact-center-coordinate/scripts/fetch-numbers.sh +12 -6
- package/skills/service-agentforce-contact-center-coordinate/scripts/lib.sh +16 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/procure-number.sh +2 -1
- package/skills/service-concierge-portal-generate/references/portal-deploy-runbook.md +24 -11
- package/skills/service-digital-engagement-channel-configure/SKILL.md +29 -16
- package/skills/service-digital-engagement-channel-configure/references/channel_settings.md +13 -2
- package/skills/service-digital-engagement-channel-configure/references/onboarding_contract.md +143 -0
- package/skills/service-digital-engagement-deployment-configure/SKILL.md +65 -79
- package/skills/service-digital-engagement-deployment-configure/assets/esd_web_update_template.xml +83 -8
- package/skills/service-digital-engagement-deployment-configure/examples/esd_web_prechat_fields.xml +74 -0
- package/skills/service-digital-engagement-deployment-configure/references/connect_api_creation.md +26 -7
- package/skills/service-digital-engagement-deployment-configure/references/deployment_settings.md +13 -78
- package/skills/service-digital-engagement-deployment-configure/references/onboarding_contract.md +145 -0
- package/skills/service-digital-engagement-deployment-configure/references/prechat_forms.md +245 -0
- package/skills/service-itsm-agentic-setup-incident-management/SKILL.md +166 -112
- package/skills/service-itsm-agentic-setup-incident-management/examples/output-templates.md +61 -37
- package/skills/service-itsm-agentic-setup-incident-management/references/audit-tracking.md +42 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/broadcast-communications.md +23 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/email-to-incident.md +23 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/incident-dashboards.md +25 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/incident-persona-psg.md +30 -145
- package/skills/service-itsm-agentic-setup-incident-management/references/incident-preferences.md +32 -137
- package/skills/service-itsm-agentic-setup-incident-management/references/major-incident-management.md +32 -155
- package/skills/service-itsm-agentic-setup-incident-management/references/manage-incidents-with-ai.md +45 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/priority-matrix.md +32 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/service-mgmt-privilege.md +30 -140
- package/skills/service-itsm-agentic-setup-incident-management/references/sla-milestones.md +110 -0
- package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +34 -25
- package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +1 -1
- package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +90 -86
- package/skills/service-itsm-agentic-setup-incident-sla-configure/references/workflow.md +63 -38
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: commerce-react-storefront-create
|
|
3
|
+
description: "Stand up the commerce-b2b-headless reference React storefront in a Salesforce B2B Commerce org, end to end — discover the org's WebStores, pick one, fill the four org-specific values (WebStore Id, BuyerGroup Id, buyer permission set group, Vite org alias), build + deploy the UI Bundle, assign the site guest user the auth permission set, and hand back the live Experience Cloud storefront URL. Use whenever the user says \"create a react storefront in my org\", \"set up the headless B2B storefront\", \"deploy commerce-b2b-headless\", \"stand up a React storefront for <org-alias>\", \"get me a hosted headless commerce storefront\", or points at a cloned commerce-b2b-headless repo and wants it running against their org."
|
|
4
|
+
metadata:
|
|
5
|
+
relatedSkills:
|
|
6
|
+
- experience-ui-bundle-deploy
|
|
7
|
+
version: "1.0"
|
|
8
|
+
minApiVersion: "65.0"
|
|
9
|
+
domains:
|
|
10
|
+
- "Commerce"
|
|
11
|
+
- "Experience"
|
|
12
|
+
cliTools:
|
|
13
|
+
- tool:
|
|
14
|
+
- "git"
|
|
15
|
+
semver: ">=2.0"
|
|
16
|
+
- tool:
|
|
17
|
+
- "jq"
|
|
18
|
+
semver: ">=1.6.0"
|
|
19
|
+
- tool:
|
|
20
|
+
- "npm"
|
|
21
|
+
semver: ">=8.0.0"
|
|
22
|
+
- tool:
|
|
23
|
+
- "sf"
|
|
24
|
+
semver: ">=2.130.0"
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# create-react-storefront
|
|
28
|
+
|
|
29
|
+
## What this does
|
|
30
|
+
|
|
31
|
+
Deploys the **commerce-b2b-headless** reference React storefront (a React 19 + Vite `UIBundle`
|
|
32
|
+
served from the Experience Cloud Site Container) into a user's B2B Commerce org and returns the
|
|
33
|
+
hosted storefront URL. The repo is a *reference implementation* — it ships four org-specific
|
|
34
|
+
values as `<…_Placeholder>` strings that throw at runtime until replaced. This skill's whole job
|
|
35
|
+
is to resolve those four values against the target org, then drive build → deploy → guest-user
|
|
36
|
+
entitlement so the storefront actually renders.
|
|
37
|
+
|
|
38
|
+
The repo's `scripts/org-setup.mjs` (`npm run setup`) automates login → build → deploy → permset →
|
|
39
|
+
dev-server, but it does **not** discover the WebStore, replace the placeholders, or entitle the
|
|
40
|
+
site's guest user (the README's own "Limitations" say there is no auto-discovery). Those
|
|
41
|
+
gaps are exactly the manual work below — do them, and the deploy is reliable.
|
|
42
|
+
|
|
43
|
+
**Requires:** Node 22+, `sf` CLI 2.130+, and a target org with B2B Commerce + Multi-framework React
|
|
44
|
+
enabled (API version `67.0+`). Only work against orgs the user owns or is authorized to modify — deploy,
|
|
45
|
+
Apex edits, and permission-set assignment are real, side-effecting writes.
|
|
46
|
+
|
|
47
|
+
## Fixed facts about the repo (don't re-derive these)
|
|
48
|
+
|
|
49
|
+
| Thing | Value |
|
|
50
|
+
|---|---|
|
|
51
|
+
| Repo clone URL | `https://github.com/trailheadapps/commerce-b2b-headless.git` (ask for an existing clone first; a new clone goes to a user-confirmed path under the cwd — Step 3) |
|
|
52
|
+
| UI Bundle dir (`$BUNDLE`) | `force-app/main/default/uiBundles/commerceb2bheadless` |
|
|
53
|
+
| WebStore config file | `$BUNDLE/src/config/commerce.ts` |
|
|
54
|
+
| Registration Apex | `UIBundleRegistration.cls` (in the repo's Apex classes folder) |
|
|
55
|
+
| Vite config | `$BUNDLE/vite.config.ts` |
|
|
56
|
+
| Auth permission set | `UIBundleApexAccess` (grants the 6 auth Apex classes) |
|
|
57
|
+
| Site name | `commerceb2bheadless` — also the storefront URL path: `https://<site-domain>/commerceb2bheadless` |
|
|
58
|
+
| Connect `urlPathPrefix` | `commerceb2bheadlessvforcesite` (internal match key for Step 7 — **not** the URL path) |
|
|
59
|
+
| Default API version | `v67.0` (leave unless the org runs a different version) |
|
|
60
|
+
|
|
61
|
+
## The four values you must set
|
|
62
|
+
|
|
63
|
+
Everything else in the repo is portable. These four are environment-specific — resolve each against
|
|
64
|
+
the target org, then write it into the file. Steps 4a–4d below do this.
|
|
65
|
+
|
|
66
|
+
| # | Value | File / symbol | Prefix |
|
|
67
|
+
|---|---|---|---|
|
|
68
|
+
| 1 | WebStore Id | `commerce.ts` → `WEBSTORE_ID` | `0ZE` |
|
|
69
|
+
| 2 | Default BuyerGroup Id | `UIBundleRegistration.cls` → `DEFAULT_BUYER_GROUP_ID` | `0ZI` |
|
|
70
|
+
| 3 | Buyer permission set group | `UIBundleRegistration.cls` → `BUYER_PERMISSION_SET_GROUP` (DeveloperName) | — |
|
|
71
|
+
| 4 | Vite org alias (optional) | `vite.config.ts` → `salesforce({ orgAlias: '…' })` | — |
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Workflow
|
|
76
|
+
|
|
77
|
+
Narrow with `sf` queries before you ask the user anything, and don't ask what a query can answer.
|
|
78
|
+
Two choices are always the user's to make, even when there is only one option: **which store**
|
|
79
|
+
(Step 2) and **where the repo lives** (Step 3). Confirm the plan (which org, which store, what will
|
|
80
|
+
be written and deployed) before the first write.
|
|
81
|
+
|
|
82
|
+
### Step 1 — Resolve the target org
|
|
83
|
+
|
|
84
|
+
If the user gave an org alias, use it. Otherwise list what's connected and ask which one:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
sf org list --json | jq -r '.result.nonScratchOrgs[]?.alias, .result.scratchOrgs[]?.alias'
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Confirm it's reachable: `sf org display --target-org <alias>`. If not connected, log in:
|
|
91
|
+
`sf org login web --alias <alias> --instance-url https://<my-domain>.my.salesforce.com`.
|
|
92
|
+
|
|
93
|
+
### Step 2 — Discover the org's WebStores, let the user pick
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
sf data query --target-org <alias> \
|
|
97
|
+
--query "SELECT Id, Name, Type FROM WebStore WHERE Type = 'B2B' ORDER BY Name"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The storefront is B2B-only, so list only `Type = 'B2B'` stores. **Always ask the user which store
|
|
101
|
+
to deploy against — show every B2B store by Name and let them choose, even when there is only
|
|
102
|
+
one. Never pick a store on the user's behalf**, and don't fold the choice into a later plan
|
|
103
|
+
confirmation: the store decides which catalog, buyer groups, and pricing the deployed storefront
|
|
104
|
+
serves. Capture the chosen store's `Id` (`0ZE…`); this is **value #1** and also scopes the
|
|
105
|
+
BuyerGroup lookup in Step 4b. If the query returns nothing, the org has no B2B store provisioned —
|
|
106
|
+
stop and point the user at the `b2b-commerce-org-setup` plugin to create one first.
|
|
107
|
+
|
|
108
|
+
### Step 3 — Ask where the repo is, or clone it
|
|
109
|
+
|
|
110
|
+
**Ask the user first** — don't probe default locations or assume a path: do they already have a
|
|
111
|
+
clone of `commerce-b2b-headless` (and where is it), or should you clone it from
|
|
112
|
+
`https://github.com/trailheadapps/commerce-b2b-headless.git`?
|
|
113
|
+
|
|
114
|
+
**Existing clone** — set `$REPO` to the path the user gives, then verify it's the right repo:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
ls "$REPO/README.md" "$REPO/force-app/main/default/uiBundles/commerceb2bheadless" >/dev/null && echo OK
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
If the check fails, tell the user what's missing and ask again — don't switch to cloning unasked.
|
|
121
|
+
|
|
122
|
+
**Clone** — the clone goes inside the current working directory. Check that directory's structure
|
|
123
|
+
first, so the clone doesn't silently land inside another git repo or on top of an existing folder:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
pwd && ls -A
|
|
127
|
+
git rev-parse --show-toplevel 2>/dev/null # prints a path ⇒ cwd is inside another git repo
|
|
128
|
+
ls -d commerce-b2b-headless 2>/dev/null # prints a name ⇒ the target folder already exists
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Propose `$(pwd)/commerce-b2b-headless` as the clone path and call out anything the check surfaced
|
|
132
|
+
(cwd is inside another repo; the folder already exists — offer to use it as the existing clone).
|
|
133
|
+
If the cwd looks like the wrong place, ask the user for a path instead of proposing one. Either
|
|
134
|
+
way, **wait for the user to confirm the path or give their own**. Only then clone and verify:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
git clone https://github.com/trailheadapps/commerce-b2b-headless.git "<confirmed-path>"
|
|
138
|
+
ls "<confirmed-path>/force-app/main/default/uiBundles/commerceb2bheadless" >/dev/null && echo OK
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
If the clone fails with "Repository not found" or an auth prompt, the user's GitHub account can't
|
|
142
|
+
see the repo — don't stop; ask for a URL they can reach (e.g. their fork) or an existing local
|
|
143
|
+
clone, and continue from there. Set `$REPO` to the confirmed path.
|
|
144
|
+
|
|
145
|
+
Either way, the repo is a **reference implementation you adapt**, not a drop-in — the placeholder
|
|
146
|
+
edits below are mandatory. Skim `$REPO/README.md` to
|
|
147
|
+
confirm you're on a compatible version if anything looks different from the Fixed-facts table.
|
|
148
|
+
|
|
149
|
+
### Step 4 — Fill the four org-specific values
|
|
150
|
+
|
|
151
|
+
Use `Edit` to replace each placeholder in place. Do **not** deploy with any `<…Placeholder>` string
|
|
152
|
+
still present — the app throws at runtime and buyers hit `INSUFFICIENT_ACCESS`.
|
|
153
|
+
|
|
154
|
+
**4a — WebStore Id** → `$BUNDLE/src/config/commerce.ts`
|
|
155
|
+
Replace `WEBSTORE_ID: "<Webstore_Id_Placeholder>"` with the `0ZE…` Id from Step 2.
|
|
156
|
+
|
|
157
|
+
**4b — Default BuyerGroup Id** → `UIBundleRegistration.cls` `DEFAULT_BUYER_GROUP_ID`
|
|
158
|
+
Prefer the BuyerGroup actually bound to the chosen store; fall back to listing all:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Preferred — the BuyerGroup(s) entitled to this store:
|
|
162
|
+
sf data query --target-org <alias> \
|
|
163
|
+
--query "SELECT BuyerGroupId, BuyerGroup.Name FROM WebStoreBuyerGroup WHERE WebStoreId = '<0ZE…>'"
|
|
164
|
+
# Fallback — all BuyerGroups:
|
|
165
|
+
sf data query --target-org <alias> --query "SELECT Id, Name FROM BuyerGroup"
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
If more than one, show the names and let the user pick. Replace `<Buyer_Group_Id_Placeholder>` with
|
|
169
|
+
the `0ZI…` Id. New self-registered buyers get enrolled here so the store entitlement applies.
|
|
170
|
+
|
|
171
|
+
**4c — Buyer permission set group** → `UIBundleRegistration.cls` `BUYER_PERMISSION_SET_GROUP`
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
sf data query --target-org <alias> \
|
|
175
|
+
--query "SELECT Id, DeveloperName, MasterLabel FROM PermissionSetGroup ORDER BY DeveloperName"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
This must match the PSG the store hands buyers at **Commerce App → your store → Buyer Access →
|
|
179
|
+
Self-Registration**. Show the list, let the user confirm which one, and replace
|
|
180
|
+
`<Buyer_permission_set_group>` with its **DeveloperName**. Wrong/missing group ⇒ registration
|
|
181
|
+
succeeds but order placement fails with `INSUFFICIENT_ACCESS`.
|
|
182
|
+
|
|
183
|
+
**4d — Vite org alias (optional but recommended)** → `$BUNDLE/vite.config.ts`
|
|
184
|
+
If the machine has more than one org, pin the build to this one so the SDK's CSRF endpoint matches
|
|
185
|
+
the org's API version. Change `salesforce()` to `salesforce({ orgAlias: '<alias>' })`. Skipping it
|
|
186
|
+
falls back to `65.0`, which mismatches newer orgs and 401s every authenticated request.
|
|
187
|
+
|
|
188
|
+
### Step 5 — Build the UI Bundle, then hand off the deploy
|
|
189
|
+
|
|
190
|
+
The `dist/` is what gets shipped, and the WebStore Id (Step 4a) is baked into it at build time. Build from
|
|
191
|
+
inside the bundle, deleting any existing `dist/` first — if the build fails partway, a leftover
|
|
192
|
+
`dist/` from an earlier build (old or placeholder values baked in) would otherwise deploy silently.
|
|
193
|
+
Confirm the chosen WebStore Id made it into the bundle before deploying:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
cd $REPO && npm install
|
|
197
|
+
cd $BUNDLE && npm install && rm -rf dist && npm run build # tsc -b && vite build → fresh dist/
|
|
198
|
+
grep -l '<0ZE…>' dist/assets/*.js >/dev/null && echo "WebStore Id baked"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Before the deploy, flag the guest Chatter setting.** The repo's metadata is a demo-org
|
|
202
|
+
configuration: `force-app/main/default/networks/commerceb2bheadless.network-meta.xml` ships
|
|
203
|
+
`<enableGuestChatter>true</enableGuestChatter>`, which exposes Chatter to unauthenticated guest
|
|
204
|
+
users. Tell the user before deploying and offer to set it to `false`; change it only if they agree.
|
|
205
|
+
On a production org (or if the user isn't sure), don't deploy until they confirm they've reviewed
|
|
206
|
+
the README's "Review all org, site & network settings before production" section, which lists the
|
|
207
|
+
other network, site, profile, and permission-set flags to check.
|
|
208
|
+
|
|
209
|
+
#### Deploy — delegate
|
|
210
|
+
|
|
211
|
+
```yaml
|
|
212
|
+
id: deploy-source
|
|
213
|
+
purpose: delegate
|
|
214
|
+
delegates_to: experience-sites-ui-framework/experience-ui-bundle-deploy
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The shared `experience-ui-bundle-deploy` skill owns UI Bundle deploys, so this skill keeps no deploy
|
|
218
|
+
recipe of its own. Use the installed skill if this client has it; otherwise `describe`
|
|
219
|
+
`experience-ui-bundle-deploy` and follow its served guidance — its helper scripts, including the
|
|
220
|
+
source-root resolver, are served with it. Point it at `$REPO` as the project and `<alias>` as the
|
|
221
|
+
target org, and run **only its "Deploy metadata" step** (its org-auth precondition no-ops, since
|
|
222
|
+
Step 1 already connected the org). Let it resolve the source root itself. The reference repo ships
|
|
223
|
+
no `org-setup.config.json`, so that step's self-registration pre-check doesn't apply.
|
|
224
|
+
|
|
225
|
+
Tell the user which of its other steps you are not running, and why: its build (done above, with
|
|
226
|
+
the stale-`dist/` delete it lacks), and its permission-set, role, self-registration, social-login,
|
|
227
|
+
data-import, and GraphQL steps. Step 6 here entitles the guest user, and the storefront needs
|
|
228
|
+
nothing else from that sequence.
|
|
229
|
+
|
|
230
|
+
The deploy ships the Apex, the UIBundle (with the fresh `dist/`), the Site/Network/digitalExperiences,
|
|
231
|
+
the `UIBundleApexAccess` permission set, and the buyer profile in one shot. Only if neither the
|
|
232
|
+
installed skill nor a `describe` of it is available, report the deploy handoff as blocked. Tell the
|
|
233
|
+
user it needs `experience-ui-bundle-deploy`, or offer the One-command alternative below as their
|
|
234
|
+
choice — don't improvise a deploy.
|
|
235
|
+
|
|
236
|
+
### Step 6 — Entitle the site's guest user (auth permission set)
|
|
237
|
+
|
|
238
|
+
The app puts every storefront route — home, category, search, product, cart, checkout, orders,
|
|
239
|
+
profile — behind login: an anonymous visitor is redirected to `/login`. So the site's **guest user**
|
|
240
|
+
only ever serves the login / register / forgot-password / reset-password pages, and the one thing it
|
|
241
|
+
needs is `UIBundleApexAccess` for the auth Apex classes. Find the guest user and the permset:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
sf data query --target-org <alias> \
|
|
245
|
+
--query "SELECT Id, Name, GuestUserId FROM Site WHERE Name = 'commerceb2bheadless'"
|
|
246
|
+
sf data query --target-org <alias> \
|
|
247
|
+
--query "SELECT Id FROM PermissionSet WHERE Name = 'UIBundleApexAccess'"
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Assign it (without it, `/login` 403s "no access to UIBundleLogin"):
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
sf data create record --target-org <alias> --sobject PermissionSetAssignment \
|
|
254
|
+
--values "AssigneeId=<GuestUserId> PermissionSetId=<UIBundleApexAccessId>"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
A `DUPLICATE_VALUE` error means the assignment already exists from an earlier run — treat it as done.
|
|
258
|
+
Either way, confirm it landed (expect one row; zero means redo the assignment):
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
sf data query --target-org <alias> \
|
|
262
|
+
--query "SELECT Id FROM PermissionSetAssignment WHERE AssigneeId = '<GuestUserId>' AND PermissionSet.Name = 'UIBundleApexAccess'"
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Don't give the guest user a commerce permission set** — for example, by mirroring an LWR store
|
|
266
|
+
guest's permset. Anonymous browsing isn't reachable in this app, so there's nothing for it to
|
|
267
|
+
unlock (and an LWR store's guest often holds no such permset). If the
|
|
268
|
+
user later removes the login guard to allow guest browsing, B2B guest access is configured on the
|
|
269
|
+
store — `WebStore.OptionsGuestBrowsingEnabled`, the guest buyer profile, and a guest buyer group (the
|
|
270
|
+
`merchant-storefront-guest-access` skill) — and the WebStore likely also needs binding to the
|
|
271
|
+
headless site's Network (`WebStoreNetwork`). That path is unverified for this app, so flag it rather
|
|
272
|
+
than attempt it.
|
|
273
|
+
|
|
274
|
+
### Step 7 — Resolve and hand back the hosted storefront URL
|
|
275
|
+
|
|
276
|
+
The app is served at `https://<site-domain>/commerceb2bheadless`. Get the authoritative live URL from
|
|
277
|
+
the Connect communities endpoint, matching on the site's internal `urlPathPrefix` (which differs from
|
|
278
|
+
the URL path):
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
sf api request rest '/services/data/v67.0/connect/communities' --target-org <alias> \
|
|
282
|
+
| jq -r '.communities[] | select(.urlPathPrefix=="commerceb2bheadlessvforcesite") | "\(.name)\t\(.status)\t\(.siteUrl)"'
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Report the `siteUrl` as **"here is your hosted React Storefront"**. If `status` is not `Live`, the
|
|
286
|
+
site needs publishing — direct the user to **Setup → Digital Experiences → All Sites →
|
|
287
|
+
commerceb2bheadless → Publish** (Experience Builder), then re-fetch the URL. If the endpoint returns
|
|
288
|
+
nothing, construct the fallback `https://<my-domain>.my.site.com/commerceb2bheadless` — the path is
|
|
289
|
+
the site name, not the `vforcesite` prefix. Get `<my-domain>` from `sf org display`'s instance URL;
|
|
290
|
+
non-production instances use a different site-domain suffix, so tell the user to verify the URL in
|
|
291
|
+
All Sites.
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## One-command alternative
|
|
296
|
+
|
|
297
|
+
If the four values are already set (Step 4 done), the repo's own orchestrator does build → deploy →
|
|
298
|
+
permset in one go:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
cd $REPO && npm run setup -- --target-org <alias> --skip-dev --skip-data
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Caveats — it does **not** replace the placeholders and it assigns `UIBundleApexAccess` to the
|
|
305
|
+
**current user**, not the guest user, so you **still** run Step 4 before it and Step 6 (the guest
|
|
306
|
+
assignment) after it. Drop `--skip-dev` only if the user wants the local Vite dev server
|
|
307
|
+
(`localhost:5173`) instead of / in addition to the hosted site. If the bundle has no GraphQL
|
|
308
|
+
codegen wired, add `--skip-graphql`.
|
|
309
|
+
|
|
310
|
+
## Troubleshooting (from the repo README)
|
|
311
|
+
|
|
312
|
+
- **`/login` returns 403 "no access to UIBundleLogin"** — guest user missing `UIBundleApexAccess`; redo Step 6.
|
|
313
|
+
- **Anonymous visitors land on `/login`** — by design; every storefront route requires login (Step 6). Register or log in as a buyer to browse.
|
|
314
|
+
- **`/commerce/...` returns 404 from the Site Container** — org is older than API version `67.0` (no Site Container support); upgrade the org.
|
|
315
|
+
- **Storefront shows no products** — the buyer's Account isn't in a BuyerGroup with active price book entries for the catalog.
|
|
316
|
+
- **Every authenticated request 401s** — Vite fell back to API `65.0`; set the org alias (Step 4d) and rebuild.
|
|
317
|
+
- **Order placement fails `INSUFFICIENT_ACCESS`** — wrong/missing buyer PSG (Step 4c).
|
|
318
|
+
- **Storefront still shows old or placeholder values after a redeploy** — a stale `dist/` shipped; delete it and rebuild (Step 5).
|
|
319
|
+
|
|
320
|
+
## Notes
|
|
321
|
+
|
|
322
|
+
- **Dual-network:** the headless storefront runs on its own Network, coexisting with the legacy LWR store's Network. Both stay in the org.
|
|
323
|
+
- **Don't rename** the Apex classes, `UIBundleApexAccess`, or the site URL prefix — they're cross-referenced by the React app, the permission set, and this skill's queries.
|
|
324
|
+
- This is a live-org workflow: name the org, the store, and every write before doing it, and never deploy against an org the user hasn't authorized.
|
|
325
|
+
|
|
326
|
+
<!-- skill-validate: ignore-start -->
|
|
327
|
+
<!-- codey:operations start -->
|
|
328
|
+
## Operations Reference
|
|
329
|
+
|
|
330
|
+
Operations this skill uses — routing and dependency reference.
|
|
331
|
+
|
|
332
|
+
| Operation | Purpose | Status | Call | Depends on |
|
|
333
|
+
|-----------|---------|--------|------|------------|
|
|
334
|
+
| `list-webstores` | read | — | `GET /services/data/v67.0/query` | — |
|
|
335
|
+
| `write-webstore-id-placeholder` | write | — | — | `list-webstores` |
|
|
336
|
+
| `list-buyer-groups-for-store` | read | — | `GET /services/data/v67.0/query` | `list-webstores` |
|
|
337
|
+
| `list-buyer-groups-all` | read | — | `GET /services/data/v67.0/query` | `list-buyer-groups-for-store` |
|
|
338
|
+
| `write-buyer-group-id-placeholder` | write | — | — | `list-buyer-groups-for-store`, `list-buyer-groups-all` |
|
|
339
|
+
| `list-permission-set-groups` | read | — | `GET /services/data/v67.0/query` | — |
|
|
340
|
+
| `write-psg-placeholder` | write | — | — | `list-permission-set-groups` |
|
|
341
|
+
| `write-vite-org-alias` | write | — | — | — |
|
|
342
|
+
| `build-ui-bundle` | write | — | — | `write-webstore-id-placeholder`, `write-buyer-group-id-placeholder`, `write-psg-placeholder`, `write-vite-org-alias` |
|
|
343
|
+
| `deploy-source` | delegate | — | → `experience-sites-ui-framework/experience-ui-bundle-deploy` | `build-ui-bundle` |
|
|
344
|
+
| `find-site-and-guest-user` | read | — | `GET /services/data/v67.0/query` | `deploy-source` |
|
|
345
|
+
| `find-uibundleapexaccess-permset` | read | — | `GET /services/data/v67.0/query` | `deploy-source` |
|
|
346
|
+
| `assign-auth-permset-to-guest` | write | — | `POST /services/data/v67.0/sobjects/PermissionSetAssignment` | `find-site-and-guest-user`, `find-uibundleapexaccess-permset` |
|
|
347
|
+
| `resolve-storefront-url` | read | — | `GET /services/data/v67.0/connect/communities` | `deploy-source` |
|
|
348
|
+
| `verify-guest-permset-assignment` | verify | — | `GET /services/data/v67.0/query` | `assign-auth-permset-to-guest` |
|
|
349
|
+
<!-- codey:operations end -->
|
|
350
|
+
<!-- skill-validate: ignore-end -->
|
|
@@ -77,7 +77,7 @@ Every Apex call is `${PREFIX_DOT}ClassName.method(...)`; every SOQL object/field
|
|
|
77
77
|
|
|
78
78
|
Run these and stop on the first failure.
|
|
79
79
|
|
|
80
|
-
1. `sf --version`; `node --version` (only if running shipped scripts).
|
|
80
|
+
1. `sf --version`; `node --version` (only if running shipped scripts). Also `export SF_SKIP_NEW_VERSION_CHECK=true` once at session start so a stale CLI's update banner cannot leak onto stdout and break any `sf … --json | jq …` pipe downstream (see `references/smoke-and-verify.md` "parse caveat" for the alternate `sed` strip).
|
|
81
81
|
2. `sf org display --target-org <alias> --json` — confirm reachable; capture `instanceUrl` + org id (display/logging only). REST calls use `sf api request rest` on the CLI's stored session — the skill never extracts the access token.
|
|
82
82
|
3. Validate sales org locally: length 4, uppercase, non-blank (mirrors `TPMSetupData.validateSalesOrg`). Fail fast.
|
|
83
83
|
4. **TPM entitlement (Permission Set License)** — the `CGCRetailAndTPMMgmtPsl` PSL assignment on the running user. SOQL + warn/stop routing in `references/preflight-and-seed-queries.md` Step 4.
|
|
@@ -165,7 +165,7 @@ Say "use the SetCommentValue reference" for a worked example.
|
|
|
165
165
|
| jq -r '.fields[] | select(.updateable == true and .createable == true) | .name'
|
|
166
166
|
```
|
|
167
167
|
Any `outputWrites` field must appear here; otherwise stop and ask for a different one (FLS is caller-scoped).
|
|
168
|
-
4. **Confirm the plan** (recap Class/Entity/Workflows/Reads/Writes/Sort/Description → "Deploy + wire? [y/N]"). If `workflows` includes `copy`, flag
|
|
168
|
+
4. **Confirm the plan** (recap Class/Entity/Workflows/Reads/Writes/Sort/Description → "Deploy + wire? [y/N]"). If `workflows` includes `copy`, flag TWO copy-only preconditions up front so neither surfaces as a runtime surprise: (a) per-child input values come from the source promotion — `outputWrites` still fires but `<inputPaths>` values are ignored (only top-level fields like `Slogan` propagate); (b) the running `User.Sales_Org__c` MUST equal the source template's `Sales_Org__c` (preflighted in Phase 1 step 7 + re-checked before every Phase 6 ingest; a mid-flow drift fails `copy` with `TransformationError: The User and the Promotion Template must have the same Sales org` — fix on the user record, do not mutate mid-flow; see `references/conventions-and-payload-rules.md` R6). `n`/blank → save answers to `./.promotion-bo-api-deploy/interview.json` and exit. `y` → Phase 5a.
|
|
169
169
|
|
|
170
170
|
## Phases 5a / 5b — Generate + deploy, register + wire
|
|
171
171
|
|
|
@@ -25,7 +25,29 @@ Both phases run only on a green Phase 4 and a confirmed Phase 5 interview.
|
|
|
25
25
|
for the running user. Any failure → stop, print the failing field + FLS
|
|
26
26
|
remediation.
|
|
27
27
|
|
|
28
|
-
3. **
|
|
28
|
+
3. **Clean the deploy staging directory (mandatory on every invocation).**
|
|
29
|
+
Before writing the new `<stepName>.cls` to
|
|
30
|
+
`./.promotion-bo-api-deploy/force-app/main/default/classes/`, delete every
|
|
31
|
+
`*.cls` and `*.cls-meta.xml` already in that directory. This runs on EVERY
|
|
32
|
+
invocation, not just the second one — the generated class is the only
|
|
33
|
+
artifact that should live under `classes/` for the next deploy. Rationale:
|
|
34
|
+
a leftover `.cls` from a prior step run that is no longer known to the
|
|
35
|
+
source-tracking manifest makes `sf project deploy start` (step 6) evaluate
|
|
36
|
+
the deploy with `rollbackOnError: true` and silently roll back the *entire*
|
|
37
|
+
batch — including the new class — while the CLI still surfaces
|
|
38
|
+
`"created": true` for the intended component. The user sees apparent
|
|
39
|
+
success; the class is not actually in the org. Do NOT wipe `setup-data/`
|
|
40
|
+
under the same staging root (Phase 3a's retrieved read-only static resource
|
|
41
|
+
lives there) and do NOT wipe `sfdx-project.json` or `interview.json`.
|
|
42
|
+
Concretely:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
mkdir -p ./.promotion-bo-api-deploy/force-app/main/default/classes
|
|
46
|
+
find ./.promotion-bo-api-deploy/force-app/main/default/classes \
|
|
47
|
+
-maxdepth 1 -type f \( -name '*.cls' -o -name '*.cls-meta.xml' \) -delete
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
4. **Generate the Apex class from the interview.** The generator takes the
|
|
29
51
|
schema captured in the interview (Phase 5.1) and emits a namespace-agnostic
|
|
30
52
|
Callable in the same shape as the reference example
|
|
31
53
|
(`references/reference-example-set-comment-value.md`). Rules (do not deviate):
|
|
@@ -50,19 +72,9 @@ Both phases run only on a green Phase 4 and a confirmed Phase 5 interview.
|
|
|
50
72
|
<stepName>.cls-meta.xml
|
|
51
73
|
```
|
|
52
74
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
`.cls-meta.xml` left behind in `force-app/main/default/classes/` is picked
|
|
57
|
-
up by `sf project deploy start` in step 5 below. If that stale file is no
|
|
58
|
-
longer known to the source-tracking manifest, MDAPI evaluates the deploy
|
|
59
|
-
with `rollbackOnError: true` and rolls back the *entire* batch — including
|
|
60
|
-
the new class — while the CLI still surfaces `"created": true` for the
|
|
61
|
-
intended component. The user sees an apparent success; the class is not
|
|
62
|
-
actually in the org. Before writing the new step, delete every
|
|
63
|
-
`*.cls`/`*.cls-meta.xml` under `./.promotion-bo-api-deploy/force-app/main/default/classes/`
|
|
64
|
-
that is not the class about to be generated. Do NOT wipe `setup-data/`
|
|
65
|
-
(Phase 3a's retrieved read-only static resource lives there).
|
|
75
|
+
The staging-dir cleanup (step 3 above) must have already run — the new
|
|
76
|
+
`.cls` is the only artifact that should land under `classes/` for the next
|
|
77
|
+
deploy.
|
|
66
78
|
|
|
67
79
|
`sfdx-project.json`:
|
|
68
80
|
```json
|
|
@@ -81,13 +93,13 @@ Both phases run only on a green Phase 4 and a confirmed Phase 5 interview.
|
|
|
81
93
|
</ApexClass>
|
|
82
94
|
```
|
|
83
95
|
|
|
84
|
-
|
|
96
|
+
5. **Show the user the generated class + confirm.** Print the full
|
|
85
97
|
`<stepName>.cls` body and ask "Deploy this? [y/N]". `n` → save to
|
|
86
98
|
`./.promotion-bo-api-deploy/` and exit; the user can hand-edit and re-run
|
|
87
99
|
with `--interview-file` pointing at their tweaked answers, or drop their own
|
|
88
100
|
`.cls` into the temp tree before re-invoking. `y` → deploy.
|
|
89
101
|
|
|
90
|
-
|
|
102
|
+
6. **Deploy:**
|
|
91
103
|
|
|
92
104
|
```bash
|
|
93
105
|
sf project deploy start \
|
|
@@ -28,7 +28,7 @@ on top of the derived contract:
|
|
|
28
28
|
|
|
29
29
|
- **R1** — force `DateFrom`, `DateThru`, `Slogan` into the create payload. If the user gave duration-in-weeks intent, compute `DateThru = DateFrom + weeks*7 - 1` client-side.
|
|
30
30
|
- **R2** — poll for `Status__c = 'Calculated'` (NOT `Processed`, which does not exist in the picklist).
|
|
31
|
-
- **R3** —
|
|
31
|
+
- **R3** — `ProductFilter` is a **top-level** promotion sibling of `Slogan`/`DateFrom`/`Tactics`, **NOT** nested under `Tactics[]` — nesting is schema-valid at ingest but fails downstream with the misleading "You must select at least one Category to the Promotion" (see R3a). Keys are level NAMES (`Category`, `Brand`, …), NOT Product2 field API names. Values are external ids (`<prefix>__Consumer_Goods_External_Product_Id__c`), NOT display `Name`/label (passing a Name fails with the misleading `TransformationError: Could not find Products: <Name>` — see R3b).
|
|
32
32
|
- **R4** — pre-flight the anchor account has a `Plan` `Account_Extension__c` row valid for `DateFrom..DateThru` in this sales org.
|
|
33
33
|
- **R5** — restrict `ManualInputs[].KPI` values to `editable` / `editable_calculated` `KPI_Definition__c.Name` on the template's `KPI_Set__c`.
|
|
34
34
|
- **R6** — for `copy`, derive requireds the same way, then layer the Apex-only preconditions (`Is_Copyable__c`, template type, anchor).
|
|
@@ -95,6 +95,23 @@ credential exposure (S1). Do **not** add `--json` to `sf api request rest` — t
|
|
|
95
95
|
raw stdout body is already JSON. `${URL_NS}` is the namespace segment from
|
|
96
96
|
Phase 1 (`/cgcloud` / `/cgcloud_dev` / empty); the endpoint is instance-relative.
|
|
97
97
|
|
|
98
|
+
**`sf … --json | jq …` parse caveat.** `sf` occasionally prints a plain-text
|
|
99
|
+
update-availability banner (e.g. `› Warning: @salesforce/cli update available
|
|
100
|
+
from X to Y.`) ahead of the JSON body on stdout, which silently breaks a direct
|
|
101
|
+
`| jq` pipe (jq hits the banner line first and errors with `invalid numeric
|
|
102
|
+
literal` / `parse error`). Two defenses — pick one and use it consistently
|
|
103
|
+
across every `sf … --json | jq` pipe in this phase:
|
|
104
|
+
|
|
105
|
+
- Export `SF_SKIP_NEW_VERSION_CHECK=true` for the session (suppresses the
|
|
106
|
+
banner at the source; preferred for a single-session smoke run).
|
|
107
|
+
- Strip pre-JSON noise before piping: `sf … --json | sed -n '/^[\[{]/,$p' | jq .`
|
|
108
|
+
(keeps everything from the first `{` or `[` onward; works even if the banner
|
|
109
|
+
grows to multiple lines).
|
|
110
|
+
|
|
111
|
+
The same caveat applies to the `sf data query --target-org <alias> --json` SOQL
|
|
112
|
+
calls elsewhere in this skill — a stale CLI emits the banner on arbitrary
|
|
113
|
+
invocations, not just the first one.
|
|
114
|
+
|
|
98
115
|
**Smoke-time re-check of running user's `${PREFIX_UNDER}Sales_Org__c`.** Phase 1
|
|
99
116
|
step 7 gated the whole invocation on this, but Phase 6 can be minutes/hours later
|
|
100
117
|
and the user record may have drifted (a parallel admin edit, a session on a
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dx-devops-work-item-manage
|
|
3
|
-
description: "Use this skill to manage the full lifecycle of DevOps Center work items — list, create, update, commit changes, perform status transitions, and create pull requests. Update fields like subject, description, and status. Commit
|
|
3
|
+
description: "Use this skill to manage the full lifecycle of DevOps Center work items — list, create, update, commit changes, perform status transitions, and create pull requests. Update fields like subject, description, and status. Commit changes to work item branches, through the DevOps Center commit API or git. Create pull requests for work item branches via DevOps Center API. Invoke when the user wants to track, find, create, or update a work item, commit changes to a work item branch, advance a work item's status through the pipeline, or create a pull request for code review. Consolidates sf devops work-item and review operations. DO NOT TRIGGER for promotion or deployment operations, or conflict detection."
|
|
4
4
|
metadata:
|
|
5
5
|
relatedSkills:
|
|
6
6
|
- "dx-devops-promote"
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.1"
|
|
8
8
|
domains: ["Developer Experience"]
|
|
9
9
|
minApiVersion: "58.0"
|
|
10
10
|
cliTools:
|
|
@@ -34,7 +34,7 @@ Gather or infer before proceeding:
|
|
|
34
34
|
- **Operation type**: list, create, update, commit, or create-review
|
|
35
35
|
- **For list**: project ID (required) — obtain via `sf devops project list --json` if not provided
|
|
36
36
|
- **For create**: project ID (required), subject (required), description (optional)
|
|
37
|
-
- **For commit**: work item name or ID (required)
|
|
37
|
+
- **For commit**: work item name or ID (required), commit message, and either the files to commit (git path) or the components to commit (API path). Optional: **dev org alias** — the org that holds the changes. When provided, try the DevOps Center commit API first (see step 5); otherwise use git
|
|
38
38
|
- **For update**: work item name (e.g., WI-000001) or work item ID (required), fields to update (subject, description, status)
|
|
39
39
|
- **For create-review**: work item name (e.g., WI-000001) or work item ID (required)
|
|
40
40
|
|
|
@@ -48,7 +48,7 @@ If the user provides a clear request ("list work items for Project Alpha", "crea
|
|
|
48
48
|
|
|
49
49
|
## Workflow
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
Operations use `sf devops work-item` CLI commands with `--json` output; the API commit path also uses `sf api request rest` and `sf data query`.
|
|
52
52
|
|
|
53
53
|
### Phase 1 — Identify Operation
|
|
54
54
|
|
|
@@ -71,6 +71,7 @@ All operations use `sf devops work-item` CLI commands with `--json` output for s
|
|
|
71
71
|
```
|
|
72
72
|
- Verify the authenticated org has DevOps Center enabled by attempting to list projects
|
|
73
73
|
- If the user wants to target a specific org, use `--target-org <alias>` on all subsequent commands
|
|
74
|
+
- For the API commit path, run `sf org display --target-org <alias> --json` for **both** the dev org and the hub org
|
|
74
75
|
|
|
75
76
|
3. **List work items** — when the user wants to see existing work items:
|
|
76
77
|
```bash
|
|
@@ -102,9 +103,21 @@ All operations use `sf devops work-item` CLI commands with `--json` output for s
|
|
|
102
103
|
- Capture the returned work item name (e.g., WI-000001), branch name, and environment from JSON output for future operations
|
|
103
104
|
- Idempotent: if the user attempts to create a duplicate (same subject + project), check via list first and return the existing work item
|
|
104
105
|
|
|
105
|
-
5. **Execute commit operation** — when operation type is commit:
|
|
106
|
-
-
|
|
107
|
-
-
|
|
106
|
+
5. **Execute commit operation** — when operation type is commit. Choose the path first:
|
|
107
|
+
- **API path** — only when the user gave a dev org alias AND the changes are already deployed in that dev org (if unsure, ask: deploy with `sf project deploy start`, or use git). Dev org alias: `commitChanges`, `DevopsRequestInfo`. Hub alias: `sf devops` and `WorkItemComponentList`. DevOps Center retrieves the named components from the dev org and commits them as `DevOps Center <noreply@salesforce.com>`.
|
|
108
|
+
- **Git path** — everything else. If the changes exist only in the dev org, run `sf project retrieve start --target-org <dev-org>` first.
|
|
109
|
+
|
|
110
|
+
**API path** (commands, body, error codes and polling in `references/commit-api.md`):
|
|
111
|
+
1. Preflight `GET /connect/devops/doceConnectionType` on the dev org; a failed call (non-zero exit or error body) or `isCore` not `true` means use the git path.
|
|
112
|
+
2. `sf devops project list` → project id, then `sf devops work-item list --project-id <id> --target-org <hub>` → work item id and name. Status must be New, In Progress, In Review or Ready to Promote.
|
|
113
|
+
3. `POST /connect/devops/commitChanges` on the **dev org**; the body is the inner object (no `commitChanges` wrapper).
|
|
114
|
+
4. A failed call, or `status: "ERROR"` with `reqId` = `CODE:message`: surface it and stop.
|
|
115
|
+
5. If the POST `status` is `SUCCESS` (accepted only), poll `DevopsRequestInfo WHERE RequestToken = '<reqId>'` on the dev org every 10 seconds until `Status` is `SUCCESS` or `ERROR` (report `Message`/`ErrorDetails`), 12-minute deadline. Past it the request is stuck; report it and do not retry automatically.
|
|
116
|
+
6. Confirm a new `WorkItemComponentList` exists on the hub before creating a review.
|
|
117
|
+
|
|
118
|
+
**Git path:**
|
|
119
|
+
- If the work item is New, first set it to In Progress (step 6); the hub ignores pushes made while it is New
|
|
120
|
+
- Use the work item's `branch` field as the branch
|
|
108
121
|
- Standard git workflow:
|
|
109
122
|
```bash
|
|
110
123
|
git checkout <branch-name>
|
|
@@ -112,8 +125,7 @@ All operations use `sf devops work-item` CLI commands with `--json` output for s
|
|
|
112
125
|
git commit -m "<commit-message>"
|
|
113
126
|
git push origin <branch-name>
|
|
114
127
|
```
|
|
115
|
-
- The
|
|
116
|
-
- Changes must be committed before the work item can be marked "Ready to Promote" or before creating a PR
|
|
128
|
+
- The hub registers the push asynchronously; re-check it before creating a PR
|
|
117
129
|
|
|
118
130
|
6. **Update work item** — when the user wants to change subject, description, or status:
|
|
119
131
|
```bash
|
|
@@ -162,7 +174,8 @@ All operations use `sf devops work-item` CLI commands with `--json` output for s
|
|
|
162
174
|
8. **Verify operation success**:
|
|
163
175
|
- **For list**: confirm the CLI returned status 0, parse the JSON `.result[]` array, and verify it contains work items (or is empty if no matches). If the user specified a project by name, confirm the resolved project ID matches.
|
|
164
176
|
- **For create**: verify the CLI returned status 0 and the JSON output contains `.result.name` (work item ID like WI-000001), `.result.branch` (branch name), and `.result.environment` fields.
|
|
165
|
-
- **For commit**: verify each git command returned exit code 0. If `git push` succeeds, the commit is saved to the work item branch.
|
|
177
|
+
- **For commit (git path)**: verify each git command returned exit code 0. If `git push` succeeds, the commit is saved to the work item branch; the hub registers it asynchronously.
|
|
178
|
+
- **For commit (API path)**: verify the POST `status`, then `DevopsRequestInfo.Status`, are `SUCCESS`, and that a new `WorkItemComponentList` with a `CommitReference` exists on the hub. A new list with an empty `CommitReference` means nothing new was committed; report that, not a clean success.
|
|
166
179
|
- **For update (general fields)**: verify the CLI returned status 0 and compare the returned JSON fields against the user's requested changes. If updating subject, confirm `.result.subject` matches the new value.
|
|
167
180
|
- **For update (status transition)**: verify the CLI returned status 0, then **explicitly confirm the status transition** by checking `.result.status` in the JSON response matches the target status (e.g., "Ready to Promote"). If the response doesn't include the status field, re-run `sf devops work-item list` filtered to this work item and verify the status persisted.
|
|
168
181
|
- **For create-review**: verify the CLI returned status 0 and the JSON output contains `.result.pullRequestUrl` (the PR URL) and `.result.status` (should be "open" or equivalent). If VCS credentials are missing, the CLI returns an error — surface this to the user.
|
|
@@ -170,7 +183,7 @@ All operations use `sf devops work-item` CLI commands with `--json` output for s
|
|
|
170
183
|
9. **Report results**:
|
|
171
184
|
- **List**: present work items in a readable format showing work item name, subject, status, branch, and environment. If filtering by status was requested, show only matching work items.
|
|
172
185
|
- **Create**: return the work item name (e.g., WI-000001), branch name, environment, and confirm "Work item created successfully."
|
|
173
|
-
- **Commit**: confirm which files were staged, the commit SHA (from git output), and "Changes committed and pushed to branch <branch-name>."
|
|
186
|
+
- **Commit**: git path — confirm which files were staged, the commit SHA (from git output), and "Changes committed and pushed to branch <branch-name>." API path — confirm the `reqId`, components committed and hub `CommitReference` (author is DevOps Center)
|
|
174
187
|
- **Update (general)**: confirm which fields changed with before/after values (e.g., "Subject updated from 'X' to 'Y'").
|
|
175
188
|
- **Status transition**: explicitly state the transition with old → new status (e.g., "Status updated: In Progress → Ready to Promote").
|
|
176
189
|
- **Create-review**: return the PR URL and confirm "Pull request created successfully. Status: open. URL: <url>"
|
|
@@ -187,7 +200,9 @@ All operations use `sf devops work-item` CLI commands with `--json` output for s
|
|
|
187
200
|
| At least one update field required | Update command fails if no `--subject`, `--description`, or `--status` flag is provided |
|
|
188
201
|
| Status values must be exact strings | "In Progress" and "Ready to Promote" (with spaces, proper capitalization); other values fail |
|
|
189
202
|
| Idempotent create operations | Check for existing work item with same subject + project before creating duplicates |
|
|
190
|
-
|
|
|
203
|
+
| Commit before creating a PR | Commit first and confirm a component list exists on the hub before `review create` |
|
|
204
|
+
| API commit only sends components already in the dev org | The API retrieves from the dev org, not from local disk; deploy local-only edits first (`sf project deploy start`) or use the git path |
|
|
205
|
+
| Check `status` in the commit API response | Errors are returned as HTTP 200 with `status: "ERROR"` |
|
|
191
206
|
| PR creation requires VCS credentials in org | DevOps Center API uses stored VCS credentials; no local git auth needed |
|
|
192
207
|
| Never use interactive prompts | Skills run in headless environments; all inputs must be via CLI flags |
|
|
193
208
|
|
|
@@ -205,6 +220,8 @@ All operations use `sf devops work-item` CLI commands with `--json` output for s
|
|
|
205
220
|
| **Invalid status value** | Only "In Progress" and "Ready to Promote" are valid (exact strings with spaces); check spelling and capitalization |
|
|
206
221
|
| **Project not found** | User provided invalid project ID; run `sf devops project list --json` to show available projects |
|
|
207
222
|
| **Duplicate work item subject** | Idempotent create check should catch this; return existing work item name instead of creating duplicate |
|
|
223
|
+
| **Commit pushed while work item is New** | The hub ignores external pushes for New work items; set In Progress first and, if already pushed, re-check after the status change |
|
|
224
|
+
| **API commit still in progress past the deadline** | Report it as stuck; do not retry automatically (a new request could race it) |
|
|
208
225
|
| **Git push fails - no commits or branch not found** | Verify files are staged with `git status` and branch name retrieved from work item via list command |
|
|
209
226
|
| **PR creation fails - VCS credentials** | VCS credentials not configured in DevOps Center UI; instruct user to configure in Setup → DevOps Center → VCS Credentials |
|
|
210
227
|
|
|
@@ -216,7 +233,7 @@ Deliverables vary by operation:
|
|
|
216
233
|
|
|
217
234
|
- **List**: JSON array of work items with work item name (WI-######), subject, branch, environment, repository details
|
|
218
235
|
- **Create**: Work item name (e.g., WI-000001), ID, branch name, and environment of the newly created work item
|
|
219
|
-
- **Commit**: Confirmation of git commit and push success
|
|
236
|
+
- **Commit**: Confirmation of git commit and push success with commit SHA, or for the API path the `reqId`, final request status and `CommitReference`
|
|
220
237
|
- **Update**: Confirmation of updated fields (old value → new value for subject/description, or status change)
|
|
221
238
|
- **Create-review**: Pull request URL, PR number, and status
|
|
222
239
|
|
|
@@ -247,10 +264,9 @@ Before reporting results to the user:
|
|
|
247
264
|
- [ ] Was `--project-id` provided (or obtained via project list)?
|
|
248
265
|
|
|
249
266
|
### Commit Operation Checks
|
|
250
|
-
- [ ]
|
|
251
|
-
- [ ]
|
|
252
|
-
- [ ]
|
|
253
|
-
- [ ] Did `git push` succeed with exit code 0?
|
|
267
|
+
- [ ] API path: preflight passed, POST `status` checked, `DevopsRequestInfo` polled to `SUCCESS`, new `WorkItemComponentList` with `CommitReference` seen on the hub?
|
|
268
|
+
- [ ] Git path: was the work item In Progress, and the branch name retrieved?
|
|
269
|
+
- [ ] Git path: did `git add`, `git commit` and `git push` all exit 0?
|
|
254
270
|
|
|
255
271
|
### Update Operation Checks
|
|
256
272
|
- [ ] Was work item identifier provided (name or ID)?
|
|
@@ -269,5 +285,6 @@ Before reporting results to the user:
|
|
|
269
285
|
|
|
270
286
|
| File | When to read |
|
|
271
287
|
|------|-------------|
|
|
288
|
+
| `references/commit-api.md` | When committing through the DevOps Center API: request body, response and error codes, polling, preflight |
|
|
272
289
|
| `references/cli-commands.md` | When you need detailed CLI flag documentation, JSON output schemas, or error handling patterns |
|
|
273
290
|
| `examples/common-workflows.md` | When the user's request matches a common pattern (bulk updates, reassignment, idempotent creation, sequential transitions) |
|