@salesforce/afv-skills 1.62.0 → 1.64.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/agentforce-offline-experimentation-run/SKILL.md +253 -0
- package/skills/agentforce-offline-experimentation-run/scripts/build_report.py +796 -0
- package/skills/agentforce-offline-experimentation-run/scripts/resolve-token.sh +111 -0
- package/skills/agentforce-offline-experimentation-run/scripts/sfap_replay.py +1053 -0
- package/skills/automation-sandbox-post-copy-config-generate/SKILL.md +21 -11
- package/skills/automation-sandbox-post-copy-config-generate/assets/config_template.json +10 -0
- package/skills/automation-sandbox-post-copy-config-generate/assets/json_schema.json +33 -1
- package/skills/automation-sandbox-post-copy-config-generate/references/configuration_catalog.md +44 -1
- package/skills/automation-sandbox-post-copy-configure/SKILL.md +132 -124
- package/skills/automation-sandbox-post-copy-configure/references/flow_activation_path.md +151 -0
- package/skills/automation-sandbox-post-copy-configure/references/scheduled_apex_path.md +55 -9
- package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +54 -107
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/copy.json +1 -1
- package/skills/consumer-goods-promotion-bo-api-deploy/references/conventions-and-payload-rules.md +82 -5
- package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +35 -2
- package/skills/consumer-goods-promotion-bo-api-deploy/references/preflight-and-seed-queries.md +149 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +17 -1
- package/skills/dx-devops-conflict-resolve/SKILL.md +1 -5
- package/skills/dx-devops-pipeline-manage/SKILL.md +1 -5
- package/skills/dx-devops-project-manage/SKILL.md +1 -5
- package/skills/dx-devops-promote/SKILL.md +1 -5
- package/skills/dx-devops-request-status/SKILL.md +1 -5
- package/skills/dx-lifecycle-center/SKILL.md +120 -0
- package/skills/dx-lifecycle-center/examples/workflows.md +175 -0
- package/skills/dx-lifecycle-center/references/connect-api.md +123 -0
- package/skills/dx-lifecycle-center/references/connect-org.md +184 -0
- package/skills/dx-lifecycle-center/references/deploy.md +153 -0
- package/skills/dx-lifecycle-center/references/error-handling.md +21 -0
- package/skills/dx-lifecycle-center/references/hub-org.md +37 -0
- package/skills/dx-lifecycle-center/references/list-orgs.md +99 -0
- package/skills/dx-lifecycle-center/references/request-body.md +75 -0
- package/skills/dx-lifecycle-center/references/troubleshooting.md +31 -0
- package/skills/dx-lifecycle-center/scripts/poll-deploy-status.sh +200 -0
- package/skills/dx-lifecycle-center/scripts/resolve-environment.sh +120 -0
- package/skills/dx-org-devhub-configure/SKILL.md +1 -3
- package/skills/dx-org-shape-manage/SKILL.md +1 -5
- package/skills/dx-org-snapshot-manage/SKILL.md +1 -3
- package/skills/education-cloud-academic-calendar-generate/SKILL.md +1 -3
- package/skills/education-cloud-course-catalog-migrate/SKILL.md +1 -3
- package/skills/education-cloud-domain-configure/SKILL.md +1 -3
- package/skills/education-cloud-multi-campus-configure/SKILL.md +1 -3
- package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +1 -5
- package/skills/experience-ui-bundle-2gp-deploy/SKILL.md +1 -3
- package/skills/experience-ui-bundle-features-generate/SKILL.md +1 -5
- package/skills/experience-ui-bundle-mfa-configure/SKILL.md +1 -3
- package/skills/field-service-data-capture-migrate/SKILL.md +1 -3
- package/skills/insurance-brokerage-agency-billing-configure/SKILL.md +1 -3
- package/skills/marketing-message-test/SKILL.md +1 -3
- package/skills/nonprofit-fundraising-configure/SKILL.md +240 -0
- package/skills/nonprofit-fundraising-configure/references/gotchas.md +26 -0
- package/skills/nonprofit-fundraising-configure/references/mcp-invocation.md +678 -0
- package/skills/nonprofit-fundraising-configure/references/permission-targeting.md +35 -0
- package/skills/nonprofit-volunteer-management-model-get/SKILL.md +166 -0
- package/skills/nonprofit-volunteer-management-model-get/references/entities.md +315 -0
- package/skills/nonprofit-volunteer-management-model-get/references/relationships.md +175 -0
- package/skills/nonprofit-volunteer-management-model-get/references/themes.md +143 -0
- package/skills/nonprofit-volunteer-management-records-create/SKILL.md +121 -0
- package/skills/nonprofit-volunteer-management-records-create/references/field-guide.md +284 -0
- package/skills/nonprofit-volunteer-management-records-create/references/mcp-invocation.md +248 -0
- package/skills/nonprofit-volunteer-management-records-create/references/review-format.md +140 -0
- package/skills/nonprofit-volunteer-management-records-create/scripts/expand-series.py +632 -0
- package/skills/nonprofit-volunteer-management-records-create/scripts/render-review-table.py +419 -0
- package/skills/nonprofit-volunteer-management-records-create/scripts/tests/test_expand_series.py +690 -0
- package/skills/nonprofit-volunteer-management-records-create/scripts/tests/test_render_review_table.py +421 -0
- package/skills/nonprofit-volunteer-management-structure-generate/SKILL.md +119 -0
- package/skills/nonprofit-volunteer-management-structure-generate/references/configuration-decisions.md +159 -0
- package/skills/nonprofit-volunteer-management-structure-generate/references/discovery-interview.md +137 -0
- package/skills/nonprofit-volunteer-management-structure-generate/references/edge-cases.md +48 -0
- package/skills/nonprofit-volunteer-management-structure-generate/references/mcp-invocation.md +75 -0
- package/skills/nonprofit-volunteer-management-structure-generate/references/plan-output.md +141 -0
- package/skills/platform-custom-field-generate/SKILL.md +1 -0
- package/skills/platform-custom-field-generate/references/advanced-picklists.md +5 -5
- package/skills/platform-custom-metadata-type-generate/SKILL.md +3 -0
- package/skills/platform-custom-object-generate/SKILL.md +4 -0
- package/skills/platform-custom-setting-generate/SKILL.md +3 -0
- package/skills/platform-datamask-run/SKILL.md +1 -5
- package/skills/platform-permission-set-generate/SKILL.md +3 -0
- package/skills/platform-salesforce-connect-adapter-generate/SKILL.md +1 -3
- package/skills/platform-sandbox-configure/SKILL.md +1 -3
- package/skills/platform-value-set-generate/SKILL.md +3 -0
- package/skills/sales-call-scoring-configure/SKILL.md +1 -5
- package/skills/service-agentforce-channel-configure/SKILL.md +1 -3
- package/skills/service-agentforce-human-escalation-configure/SKILL.md +1 -3
- package/skills/service-catalog-template-coordinate/SKILL.md +1 -3
- package/skills/service-concierge-portal-generate/SKILL.md +1 -3
- package/skills/service-email-to-case-configure/SKILL.md +1 -5
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-agentforce-studio-configure/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-agentforce-studio-validate/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-cmdb-access-assign/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-cmdb-bundle-deploy/SKILL.md +1 -5
- package/skills/service-itsm-agentic-setup-cmdb-configure/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-cmdb-discovery-configure/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-employee-agent-configure/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-incident-management/SKILL.md +1 -0
- package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +1 -0
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-uel-user-create/SKILL.md +1 -9
- package/skills/service-itsm-incident-mgmt-configure/SKILL.md +1 -5
- package/skills/service-itsm-incident-priority-configure/SKILL.md +1 -3
- package/skills/service-itsm-slack-itservice-configure/SKILL.md +1 -3
- package/skills/service-itsm-swarming-configure/SKILL.md +1 -3
- package/skills/service-itsm-teams-configure/SKILL.md +1 -3
- package/skills/service-itsm-teams-debug/SKILL.md +1 -3
- package/skills/service-itsm-teams-employee-agent-configure/SKILL.md +1 -3
- package/skills/service-itsm-teams-itdesk-configure/SKILL.md +1 -3
- package/skills/service-itsm-teams-itservice-configure/SKILL.md +1 -3
- package/skills/service-native-voice-recording-transcription-configure/SKILL.md +1 -3
- package/skills/service-omni-agent-users-create/SKILL.md +1 -3
- package/skills/service-omni-agent-work-sharing-configure/SKILL.md +1 -3
- package/skills/service-omni-attribute-routing-configure/SKILL.md +1 -3
- package/skills/service-omni-base-settings-configure/SKILL.md +1 -3
- package/skills/service-omni-channel-inventory-analyze/SKILL.md +1 -3
- package/skills/service-omni-channel-limits-analyze/SKILL.md +1 -3
- package/skills/service-omni-channel-setup-coordinate/SKILL.md +1 -3
- package/skills/service-omni-command-center-analyze/SKILL.md +1 -3
- package/skills/service-omni-command-center-configure/SKILL.md +1 -3
- package/skills/service-omni-permission-set-assign/SKILL.md +1 -3
- package/skills/service-omni-presence-status-deploy/SKILL.md +1 -3
- package/skills/service-omni-presence-user-config-deploy/SKILL.md +1 -3
- package/skills/service-omni-queue-deploy/SKILL.md +1 -3
- package/skills/service-omni-queue-members-assign/SKILL.md +1 -3
- package/skills/service-omni-queue-routing-config-deploy/SKILL.md +1 -3
- package/skills/service-omni-routing-flow-deploy/SKILL.md +1 -3
- package/skills/service-omni-service-channel-configure/SKILL.md +1 -3
- package/skills/service-omni-sidebar-configure/SKILL.md +1 -3
- package/skills/service-omni-skills-based-routing-configure/SKILL.md +1 -3
- package/skills/service-omni-supervisor-config-deploy/SKILL.md +1 -3
- package/skills/service-omni-supervisor-permset-assign/SKILL.md +1 -3
- package/skills/service-omni-supervisor-surface-deploy/SKILL.md +1 -3
- package/skills/service-omni-supervisor-users-create/SKILL.md +1 -3
- package/skills/service-omni-work-skill-routing-configure/SKILL.md +1 -3
- package/skills/field-service-setup-orchestrator-get/SKILL.md +0 -47
- package/skills/tableau-next-asset-create/README.md +0 -65
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Lifecycle Center Examples
|
|
2
|
+
|
|
3
|
+
Worked prompts, grouped by operation (`SKILL.md`, Operations). Listing, status checks, and polling are **read-only**. Connecting and deploying change an org, so they wait for the user's confirmation first (a validate run does not change the target).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## A. List orgs
|
|
8
|
+
|
|
9
|
+
**A1. "Show the list of connected orgs I can deploy to."**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bash scripts/resolve-environment.sh my-dev-org
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Reply with only the table and the closing sentence (`references/list-orgs.md`, section 4). The Lifecycle Center org is not in it and is not mentioned.
|
|
16
|
+
|
|
17
|
+
**A2. "What org am I in?"**
|
|
18
|
+
|
|
19
|
+
Answer from the `source` block: alias, username, URL, and org id. Nothing else.
|
|
20
|
+
|
|
21
|
+
**A3. The query fails because the session expired.**
|
|
22
|
+
|
|
23
|
+
The script reports "query failed, not an enablement problem". Say the error plainly and tell them to reconnect the source org (Reconnect prompt in Builder Central, or `sf org login web --alias <alias>` on a local CLI), then try again. Never say DX Inspector is disabled.
|
|
24
|
+
|
|
25
|
+
**A4. The query fails because DX Inspector is off.**
|
|
26
|
+
|
|
27
|
+
The script reports "DevOps Center not enabled or no access". Reply only: "DX Inspector isn't enabled for this org or user, so there are no environments to list or deploy to. An admin needs to enable it." Stop.
|
|
28
|
+
|
|
29
|
+
**A5. "Show my DevOps Center orgs."**
|
|
30
|
+
|
|
31
|
+
The phrase is plural, so it is not the Lifecycle Center org. List the environments (A1) and do not mention the hub.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## B. Connect an org
|
|
36
|
+
|
|
37
|
+
**B1. "Connect a new sandbox."**
|
|
38
|
+
|
|
39
|
+
1. Ask for the environment name (letters only). The type is `SANDBOX`; confirm it.
|
|
40
|
+
2. Check the org is not already connected (`references/connect-org.md`, Step 0).
|
|
41
|
+
3. After the user confirms, `POST /connect/devops/environment`.
|
|
42
|
+
4. Give the `redirectUrl` as a clickable link and wait for **done**. Never say a browser was opened.
|
|
43
|
+
5. `PATCH /connect/devops/environment/<id>`, then list again and confirm the new row shows its URL and org id.
|
|
44
|
+
|
|
45
|
+
**B2. "Connect https://mydomain--qa.sandbox.my.salesforce.com."**
|
|
46
|
+
|
|
47
|
+
The host contains `.sandbox.`, so the type is `SANDBOX` without asking. Ask only for the environment name.
|
|
48
|
+
|
|
49
|
+
**B3. "Connect my org."**
|
|
50
|
+
|
|
51
|
+
The type is not decided by anything the user said. Ask: "Is it a sandbox or scratch org, a production org, or an OrgFarm org?" Never default. A scratch org is handled exactly like a sandbox (`SANDBOX`).
|
|
52
|
+
|
|
53
|
+
**B4. "Connect the org I'm already in."**
|
|
54
|
+
|
|
55
|
+
The identifier is the source org. Say it cannot be connected as its own deploy target and ask which other org they mean.
|
|
56
|
+
|
|
57
|
+
**B5. The environment exists but was never finished.**
|
|
58
|
+
|
|
59
|
+
The row shows as not authenticated. Do not POST again. Get a fresh link with `GET /connect/devops/environment/<id>`, wait for **done**, then PATCH once.
|
|
60
|
+
|
|
61
|
+
**B6. What the user sees while connecting.**
|
|
62
|
+
|
|
63
|
+
Sign-in (Step 2):
|
|
64
|
+
|
|
65
|
+
> **Connect `QA`**
|
|
66
|
+
>
|
|
67
|
+
> **[Sign in to `QA` →](https://mydomain--qa.sandbox.my.salesforce.com/services/oauth2/authorize?...)**
|
|
68
|
+
>
|
|
69
|
+
> 1. Sign in with the user DX Inspector should act as, and approve access.
|
|
70
|
+
> 2. Come back here and reply **done**.
|
|
71
|
+
>
|
|
72
|
+
> Link not working? Copy it: `https://mydomain--qa.sandbox.my.salesforce.com/services/oauth2/authorize?...`
|
|
73
|
+
|
|
74
|
+
Connected (Step 5):
|
|
75
|
+
|
|
76
|
+
> **✅ `QA` is connected**
|
|
77
|
+
>
|
|
78
|
+
> | Org | Type | Status |
|
|
79
|
+
> |---|---|---|
|
|
80
|
+
> | `mydomain--qa.sandbox.my.salesforce.com` | Sandbox | Ready to deploy to |
|
|
81
|
+
|
|
82
|
+
The Lifecycle Center org uses the same two layouts with its own heading, button text, and a Hub type column.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## C. Lifecycle Center org
|
|
87
|
+
|
|
88
|
+
**C1. "Connect me to the hub org."**
|
|
89
|
+
|
|
90
|
+
1. "Hub org" is an ambiguous name, so ask: "Do you mean the Lifecycle Center org (the Lifecycle Center hub)?" ("Connect the Lifecycle Center org" is a certain name: skip the question.)
|
|
91
|
+
2. On yes, check the credential. If it is configured, reply only: "The Lifecycle Center org is already configured." Stop.
|
|
92
|
+
3. If it is not configured, confirm, create the credential, and give the login link labeled **Connect to Lifecycle Center org** (`references/connect-org.md`, hub mode).
|
|
93
|
+
|
|
94
|
+
**C5. "connect to lifecyclecenter org", "lifecycle-center", "connect lifecycle_center".**
|
|
95
|
+
|
|
96
|
+
These are spelling variants of the same name. Normalize (lowercase, drop spaces and punctuation), find `lifecyclecenter`, and handle it as C1 without asking which org is meant.
|
|
97
|
+
|
|
98
|
+
**C6. Wording variants of the other operations.**
|
|
99
|
+
|
|
100
|
+
After normalizing, these route the same way as the plain phrase: "Pls push AccountService into my QA-sandbox", "ship my flows to prod", "deployment to org-farm env", "dry run to my sandbox" → **D**. "Hook up a new scratch-org", "add sandbx", "sign in to prod", "set up an orgfarm env" → **B** (scratch and `sandbx` are `SANDBOX`, prod is `PRODUCTION`). "which envs can I use", "show linked orgs", "where can I deploy" → **A**.
|
|
101
|
+
|
|
102
|
+
**C2. "Is the Lifecycle Center org connected?"**
|
|
103
|
+
|
|
104
|
+
Check the credential. Configured: "The Lifecycle Center org is already configured." Not configured: "The Lifecycle Center org is not configured. Want me to connect it?"
|
|
105
|
+
|
|
106
|
+
**C3. "Deploy AccountService to the Lifecycle Center org."**
|
|
107
|
+
|
|
108
|
+
Make no API call. Ask: "Do you mean the Lifecycle Center org, or a different org?" For the Lifecycle Center org, explain that a deploy cannot go there because it is the Lifecycle Center hub, and offer to connect an org as a regular deploy target. For a different org, ask which and continue at `references/deploy.md`, Step 2.
|
|
109
|
+
|
|
110
|
+
**C4. "Why isn't the Lifecycle Center org in my list?"**
|
|
111
|
+
|
|
112
|
+
Say it is the Lifecycle Center hub, kept separate from deploy targets, and is never part of the deploy list.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## D. Deploy
|
|
117
|
+
|
|
118
|
+
**D1. "Deploy AccountService to https://mydomain--mysandbox.sandbox.my.salesforce.com."**
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
bash scripts/resolve-environment.sh my-dev-org https://mydomain--mysandbox.sandbox.my.salesforce.com
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
- `matched` and `selectable`: confirm the row back with name, URL, and org id, build the request, show the Step 4 confirmation, then submit.
|
|
125
|
+
- `not-connected`: say so and offer to connect it, carrying the URL into the connect flow (D2).
|
|
126
|
+
|
|
127
|
+
The same call works with an alias (`my-sandbox`), an org id (`00D5g000001AbCd`), or an environment name (`MySandbox`).
|
|
128
|
+
|
|
129
|
+
**D2. Deploy to an org that is not connected yet.**
|
|
130
|
+
|
|
131
|
+
**User prompt:** "Deploy AccountService to my QA sandbox."
|
|
132
|
+
|
|
133
|
+
1. The lookup says `not-connected`. Offer to connect it. The user agrees.
|
|
134
|
+
2. Run the connect flow (B1). When it finishes, say: "`QA` is now connected. I'll continue deploying `AccountService` to it."
|
|
135
|
+
3. Go straight to the Step 4 confirmation. Nothing is deployed until the user says yes.
|
|
136
|
+
|
|
137
|
+
**D3. "Deploy."**
|
|
138
|
+
|
|
139
|
+
Make no API call. Ask one question: which components to deploy. Then ask for the target.
|
|
140
|
+
|
|
141
|
+
**D4. "Validate AccountService against production," then quick deploy.**
|
|
142
|
+
|
|
143
|
+
State what you will validate, then submit with `"isCheckDeploy": true` (`references/request-body.md`), then:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
bash scripts/poll-deploy-status.sh <requestId> my-dev-org 10 100
|
|
147
|
+
# Exit codes: 0 succeeded, 2 failed or not found, 3 timeout, 1 usage or call error (4 only with --once)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
On success, report the validation id from `metadata.deployId` and offer a quick deploy with it. For the quick deploy, send only `isQuickDeploy` and `checkDeployIdentifier`. If it is still running after 2 minutes, see D9; never resubmit.
|
|
151
|
+
|
|
152
|
+
**D5. "Check request `<requestId>`" or a `requestId` from earlier.**
|
|
153
|
+
|
|
154
|
+
Skip the component and target steps. Poll once:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
bash scripts/poll-deploy-status.sh --once <requestId> my-dev-org
|
|
158
|
+
# Exit 4 means still processing: report the status and step
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**D9. The deploy takes more than 2 minutes.**
|
|
162
|
+
|
|
163
|
+
The poll exits `3`. Reply: "Your deploy is still running. Request id: `<requestId>`. Send me this id and I'll check its status." Stop polling. When the user sends the id, run `bash scripts/poll-deploy-status.sh --once <requestId> my-dev-org` and report the status in plain language.
|
|
164
|
+
|
|
165
|
+
**D8. The user gives only an id starting `0Af`.**
|
|
166
|
+
|
|
167
|
+
It is a validation id, not a `requestId`: never poll it. Ask whether to quick deploy it and to which target, then show the quick-deploy confirmation (`references/deploy.md`, Step 4).
|
|
168
|
+
|
|
169
|
+
**D6. The user names two targets.**
|
|
170
|
+
|
|
171
|
+
Deploy to the first, report, then ask before starting the second. Each target gets its own confirmation.
|
|
172
|
+
|
|
173
|
+
**D7. The target answers `Bad_OAuth_Token` or `TARGET_ORG_SESSION_EXPIRED`.**
|
|
174
|
+
|
|
175
|
+
The stored login for that environment is stale. Say so, reconnect that environment (`references/connect-org.md`, repair path), and ask before trying the deploy again.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# DX Inspector Named Credential Connect API
|
|
2
|
+
|
|
3
|
+
All calls target the **development org** (where DX Inspector runs). This skill requires API v67.0 or later. The caller needs DevOps common API access (`USER_HAS_DEVOPS_COMMON_API_ACCESS`). Portal users are rejected.
|
|
4
|
+
|
|
5
|
+
Both calls are part of the DevOps Center Connect API (v67.0).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## `/connect/devops/environment` (deploy targets)
|
|
10
|
+
|
|
11
|
+
Creates the NC, the EC, **and the `DevopsEnvironment` row** that simple-deploy requires. `setupNamedCredential` never creates the row.
|
|
12
|
+
|
|
13
|
+
Part of the DevOps Center Connect API (v67.0).
|
|
14
|
+
|
|
15
|
+
| Method | Path | Body | Result |
|
|
16
|
+
|---|---|---|---|
|
|
17
|
+
| POST | `/connect/devops/environment` | `{envName, orgType, isDevEnv?, replaceEnvironmentId?}` | `{id, name, namedCredential, externalCredential, redirectUrl, orgType, isDevEnv}` |
|
|
18
|
+
| PATCH | `/connect/devops/environment/{id}` | none | `{id, organizationId, orgUrl, status, message}` after the login. `name` and `namedCredential` are not returned; keep them from the POST |
|
|
19
|
+
| GET | `/connect/devops/environment/{id}` | none | The environment, with a fresh `redirectUrl` pinned to the row's org URL: use it for the repair link |
|
|
20
|
+
| DELETE | `/connect/devops/environment/{id}` | none | Removes the NC/EC and the row |
|
|
21
|
+
|
|
22
|
+
- `envName` and `orgType` are required. `orgType` is `PRODUCTION`, `SANDBOX`, or `ORGFARM`; it maps to `ORG_TO_ORG`, `ORG_TO_SANDBOX_ORG`, `ORG_TO_ORGFARM_ORG`.
|
|
23
|
+
- The NC/EC name is generated as `<letters-of-envName>_<epochMillis>`.
|
|
24
|
+
- POST sets up the NC/EC, builds the OAuth `redirectUrl`, then inserts the row. The user logs in at `redirectUrl`; PATCH then reads `/services/oauth2/userinfo` through the NC, rewrites the callout URL to the real My Domain, and stores `organizationId` and `orgUrl` on the row.
|
|
25
|
+
- Errors are prefixed `TARGET_ORG_ENVIRONMENT_CREATION_FAILED`, `TARGET_ORG_AUTHENTICATION_STATUS_CHECK_FAILED` (401/403), `TARGET_ORG_AUTHENTICATION_TIMEOUT` (408/504), or `TARGET_ORG_UNKNOWN_ERROR`.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## `/connect/devops/setupNamedCredential` (hub)
|
|
30
|
+
|
|
31
|
+
The POST and PATCH take the same flat JSON body:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{ "namedCredentialName": "<name>", "namedCredentialType": "<DevopsAuthType>" }
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Use `ORG_TO_ORG`, `ORG_TO_SANDBOX_ORG`, or `ORG_TO_ORGFARM_ORG`. Any other value returns `400 namedCredentialType is not supported.`
|
|
38
|
+
|
|
39
|
+
### POST: create the credential and get the login URL
|
|
40
|
+
|
|
41
|
+
Server behavior (`setUpNamedCredentialsForDevops`, then `getOAuthCredentialAuthUrl`):
|
|
42
|
+
|
|
43
|
+
1. **External Credential.** If missing, it creates one with:
|
|
44
|
+
- developer name and label set to `<name>`,
|
|
45
|
+
- protocol **OAuth**,
|
|
46
|
+
- `ExternalAuthIdentityProvider` set to the platform standard IdP for the type:
|
|
47
|
+
|
|
48
|
+
| Type | IdP |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `ORG_TO_ORG` | `sfdc.ALMDevOpsOrgStandardIdP` |
|
|
51
|
+
| `ORG_TO_SANDBOX_ORG` | `sfdc.ALMDevOpsSandoxOrgStandardIdp` |
|
|
52
|
+
| `ORG_TO_ORGFARM_ORG` | `sfdc.ALMDevOpsOrgFarmOrgStandardIdp` |
|
|
53
|
+
|
|
54
|
+
- `AdditionalRefreshStatusCode` set to `403`,
|
|
55
|
+
- one **PerUserPrincipal** (sequence 1).
|
|
56
|
+
|
|
57
|
+
The IdP uses the authorization code flow with PKCE. The client id and secret come from the platform secrets store, so no per-org connected app is needed.
|
|
58
|
+
2. **Named Credential.** If missing, it creates a `SecuredEndpoint` NC linked to the EC, with:
|
|
59
|
+
- `generateAuthorizationHeader=true`, `allowMergeFieldsInHeader=true`, `allowMergeFieldsInBody=false`,
|
|
60
|
+
- a **placeholder** callout URL (the login host),
|
|
61
|
+
- headers `target_org_auth_token: Bearer {!$Credential.OAuthToken}` and `x-salesforce-region`.
|
|
62
|
+
3. **Principal access.** Grants the EC principal to the permission set `AccessDevOpsCenterNamedCredentials` ("Access DevOps Center Named Credentials").
|
|
63
|
+
4. **Response.** Returns `{"redirectUrl": "<OAuth start URL>"}`, HTML-escaped, so you must replace `&` with `&`.
|
|
64
|
+
|
|
65
|
+
The POST is **idempotent**: existing NCs and ECs are reused. Errors inside steps 1–3 are **logged and swallowed**, so a "successful" POST can still leave things half-created. Always verify with *Check credential status*. An empty `redirectUrl` means URL generation failed.
|
|
66
|
+
|
|
67
|
+
Error wrapping: `DOCE_AUTHENTICATION_FAILED:<msg>` or `DOCE_AUTH_UNKNOWN_ERROR:<msg>` (500), and `INVALID_INPUT` (400).
|
|
68
|
+
|
|
69
|
+
### PATCH: finalize after the OAuth login
|
|
70
|
+
|
|
71
|
+
Server behavior (`updateNamedCredentialsForDevops`):
|
|
72
|
+
|
|
73
|
+
1. Returns `404 Named credential does not exist: <name>` if the NC is missing.
|
|
74
|
+
2. Calls `callout:<name>/services/oauth2/userinfo` and takes the org URL from `urls.rest`. **This requires the OAuth token from the browser login.**
|
|
75
|
+
3. Pre-warms the remote API version cache (`GET /services/data`).
|
|
76
|
+
4. Rewrites the NC callout URL to the org URL. It keeps the label, type, callout options, and EC link.
|
|
77
|
+
|
|
78
|
+
The response is `{"namedCredentialName": "<name>", "calloutUrl": "<org url>", "redirectUrl": null}`.
|
|
79
|
+
|
|
80
|
+
On failure it returns `DOCE_CONNECTION_UPDATE_FAILED:<msg>` and **also clears the user's saved DX Inspector selections**. Unexpected failures return `DOCE_AUTH_UNKNOWN_ERROR:<msg>`.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Check credential status
|
|
85
|
+
|
|
86
|
+
Use the standard Named Credentials Connect API in the dev org:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# External credential and its per-user principal status
|
|
90
|
+
sf api request rest "/services/data/v<ver>/named-credentials/external-credentials/<name>" \
|
|
91
|
+
--target-org <dev-org-alias>
|
|
92
|
+
# → principals[].principalType == "PerUserPrincipal", principals[].authenticationStatus == "Configured" | "NotConfigured"
|
|
93
|
+
|
|
94
|
+
# Named credential callout URL
|
|
95
|
+
sf api request rest "/services/data/v<ver>/named-credentials/named-credential-setup/<name>" \
|
|
96
|
+
--target-org <dev-org-alias>
|
|
97
|
+
# → calloutUrl (placeholder login host before PATCH, org My Domain after); calloutStatus "Enabled"
|
|
98
|
+
|
|
99
|
+
# List named credentials (diagnostics only; deploy targets come from DevopsEnvironment)
|
|
100
|
+
sf data query --use-tooling-api \
|
|
101
|
+
--query "SELECT DeveloperName FROM NamedCredential ORDER BY CreatedDate DESC" \
|
|
102
|
+
--target-org <dev-org-alias> --json
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Tooling `NamedCredential.Endpoint` is `null` for these `SecuredEndpoint` credentials, so always read `calloutUrl` from the `named-credential-setup` GET. DevOps-created target credentials match `<letters>_<millis>`. Never build the deploy-target list from this query.
|
|
106
|
+
|
|
107
|
+
A missing credential returns `NOT_FOUND` ("We couldn't access the credential(s)... might not exist") on either GET. That means the credential does not exist, or the user lacks access to it. `authenticationStatus` is reported **for the running user**: the token is per user, so another user's login does not count.
|
|
108
|
+
|
|
109
|
+
| EC principal | NC callout URL | State |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| — (404) | — (404) | Not created. Run POST. |
|
|
112
|
+
| `NotConfigured` | login host | Created, but login not done. Run browser login, then PATCH. |
|
|
113
|
+
| `Configured` | login host | Login done, PATCH missing. Run PATCH. |
|
|
114
|
+
| `Configured` | org My Domain | Ready. |
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## How the flows consume the credential
|
|
119
|
+
|
|
120
|
+
| Flow | Dev-org endpoint | Credential use |
|
|
121
|
+
|---|---|---|
|
|
122
|
+
| Deploy | `POST /connect/devops/simple-deploy/deploy` with `{"namedCredential": "<name>", ...}` | Calls `userinfo` through the NC (refreshing the token if needed), then forwards the target token and instance URL to the deploy service. `TARGET_ORG_NAMED_CREDENTIAL_NOT_AUTHENTICATED` means the principal is not configured. |
|
|
123
|
+
| Hub type | `GET /connect/devops/doceConnectionType` | Reads the hub `DevHubSettings` through `ALMDevOpsCenterHub` and returns `CORE` or `MANAGED_PACKAGE`. |
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Connecting an Org (Named Credential Setup)
|
|
2
|
+
|
|
3
|
+
Creates and configures the Named Credential (NC) and External Credential (EC) that DX Inspector uses to call another org, through `/connect/devops/setupNamedCredential`. Use it when the user wants to connect an org, or a deploy needs a target that is not connected yet.
|
|
4
|
+
|
|
5
|
+
The **development org** is the source org, where DX Inspector runs. It holds every credential, so every API call here targets that org (`<dev-org-alias>`). The org being connected to is touched only through the browser login. API shapes and status checks: `connect-api.md`. Failures: `troubleshooting.md`.
|
|
6
|
+
|
|
7
|
+
## Modes
|
|
8
|
+
|
|
9
|
+
| Mode | Used by | NC/EC name | Type field |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| **Deploy target** | Operation B, and Operation D when its target is not connected | Generated by the server: `<EnvName>_<epochMillis>` (letters only in `EnvName`, which must contain at least one letter). Uses the **Environment API**, which also creates the `DevopsEnvironment` row | `orgType` `PRODUCTION`, `SANDBOX`, or `ORGFARM` |
|
|
12
|
+
| **Lifecycle Center org** (the hub) | `hub-org.md` | Fixed: `ALMDevOpsCenterHub` (exact casing). Uses `setupNamedCredential`; no `DevopsEnvironment` row is needed | `ORG_TO_ORG` |
|
|
13
|
+
|
|
14
|
+
**Why two APIs:** `setupNamedCredential` creates only the NC and EC. It never creates a `DevopsEnvironment` row, and deploy needs that row (`targetEnvironmentId`). For a deploy target always use `POST /connect/devops/environment`, which creates the NC, the EC, and the row in one call.
|
|
15
|
+
|
|
16
|
+
Target org to type (deploy mode sends `orgType`; hub mode sends `namedCredentialType`, normally `ORG_TO_ORG` for the hub org):
|
|
17
|
+
|
|
18
|
+
| Target org | `orgType` (deploy) | `namedCredentialType` (hub) |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| Production or Developer Edition (logs in at login.salesforce.com) | `PRODUCTION` | `ORG_TO_ORG` |
|
|
21
|
+
| Sandbox or scratch org (logs in at test.salesforce.com; both are the same type) | `SANDBOX` | `ORG_TO_SANDBOX_ORG` |
|
|
22
|
+
| OrgFarm org | `ORGFARM` | `ORG_TO_ORGFARM_ORG` |
|
|
23
|
+
|
|
24
|
+
The type picks the login page. The API takes no login URL, and the PATCH later discovers the org's real My Domain from the login. If the user gives an org URL instead of a type, map it by host, checking rows top to bottom (first match wins, so an OrgFarm sandbox is a sandbox):
|
|
25
|
+
|
|
26
|
+
| Host pattern | Type |
|
|
27
|
+
|---|---|
|
|
28
|
+
| Contains `.sandbox.` (e.g. `*.sandbox.my.salesforce.com`), or `test.salesforce.com`, or contains `.scratch.` | Sandbox (scratch orgs included) |
|
|
29
|
+
| Starts with `orgfarm-` | OrgFarm |
|
|
30
|
+
| Other `*.my.salesforce.com`, `login.salesforce.com` | Production |
|
|
31
|
+
|
|
32
|
+
Read the type from any common spelling, ignoring case, spaces, and hyphens: sandbox, sbx, sand box, test org, scratch, scratch org, scratchorg → `SANDBOX`; production, prod, prd, live, developer edition, dev edition → `PRODUCTION`; orgfarm, org farm, org-farm → `ORGFARM`. A word that fits none of these is not a type: ask.
|
|
33
|
+
|
|
34
|
+
If the type is still ambiguous (for example only an environment name like "MySandbox", or a vague "connect my org"), **ask the user**; never default. Never infer the type from the environment name: a wrong type sends them to the wrong login host.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Step 0 — Resolve inputs and check for an existing credential
|
|
39
|
+
|
|
40
|
+
1. Resolve `<dev-org-alias>`: the alias the user named, else the default org from `sf org display --json`. Read `result.apiVersion` as `<ver>`; it must be at least `67.0`.
|
|
41
|
+
2. Determine the mode. Hub mode only when reached from `hub-org.md`; every other connect is deploy mode. In deploy mode also determine the target org type and a short environment name.
|
|
42
|
+
3. Check whether a usable credential already exists (`connect-api.md`, *Check credential status*).
|
|
43
|
+
- **Hub mode:** check `ALMDevOpsCenterHub`.
|
|
44
|
+
- **Deploy mode:** run the environment lookup (`list-orgs.md`) using the org's **URL, org id, or local alias only**, never the environment name the user wants to give it. If `sourceMatched` is `true`, say it cannot be connected as its own deploy target and ask for another org. If a row matches, check its `NamedCredential`. A row that matches only by name belongs to another org: that name is taken, so ask for a different one. If the user gave no URL, org id, or alias, there is nothing to match: create.
|
|
45
|
+
|
|
46
|
+
| Finding | Action |
|
|
47
|
+
|---|---|
|
|
48
|
+
| Exists, principal `Configured`, callout URL is the real org (not a login host) | Stop. Already connected; return to the calling flow with the NC name. **Hub, asked for directly by the user:** reply only "The Lifecycle Center org is already configured." with no reconnect offer, org details, or login link. |
|
|
49
|
+
| Exists but `NotConfigured`, or callout URL is still a login host | Repair. **Hub:** re-run Steps 1–4 with the same name (POST is idempotent). **Deploy:** reuse the existing row's `Id`; do **not** POST a second environment. Confirm first: "I'll reconnect `<name>`: this refreshes its credential. Proceed?" Then get a fresh login URL with `GET /connect/devops/environment/<id>` (its `redirectUrl`) and go to Step 2. |
|
|
50
|
+
| Matched row is `expired` | Not repairable. Create a new environment (Steps 1–4) with a new name. |
|
|
51
|
+
| `ambiguous` | Show the matches and ask which one. |
|
|
52
|
+
| Does not exist | Create. Run Steps 1–4. |
|
|
53
|
+
|
|
54
|
+
## Step 1 — Create the credential and get the login URL (POST)
|
|
55
|
+
|
|
56
|
+
**This creates metadata in the dev org. Confirm with the user first:**
|
|
57
|
+
|
|
58
|
+
> "I'll connect `<name>` (`<type>`) to DX Inspector in `<dev-org-alias>`: this creates the environment record and its credential. Proceed?"
|
|
59
|
+
|
|
60
|
+
**Hub mode** has no environment record. Say instead: "I'll connect the Lifecycle Center org to `<dev-org-alias>`: this creates its credential. Proceed?" For a repair, add that a failed finish step clears their saved DX Inspector selections.
|
|
61
|
+
|
|
62
|
+
**Deploy mode** — Environment API (creates NC, EC, and the `DevopsEnvironment` row):
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
sf api request rest "/services/data/v<ver>/connect/devops/environment" \
|
|
66
|
+
--method POST \
|
|
67
|
+
--body '{"envName":"<name>","orgType":"<PRODUCTION|SANDBOX|ORGFARM>","isDevEnv":false}' \
|
|
68
|
+
--target-org <dev-org-alias>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Response: `{id, name, namedCredential, redirectUrl, orgType, ...}`. Keep `id` (the `DevopsEnvironment` Id) and `namedCredential`. Send only `envName`, `orgType`, and `isDevEnv`. A `BAD_REQUEST` naming `Invalid org type` means the value above was wrong.
|
|
72
|
+
|
|
73
|
+
**Hub mode** — `setupNamedCredential`:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
sf api request rest "/services/data/v<ver>/connect/devops/setupNamedCredential" \
|
|
77
|
+
--method POST \
|
|
78
|
+
--body '{"namedCredentialName":"ALMDevOpsCenterHub","namedCredentialType":"ORG_TO_ORG"}' \
|
|
79
|
+
--target-org <dev-org-alias>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Response: `{"redirectUrl": "..."}`. In both modes replace every `&` in `redirectUrl` with `&`.
|
|
83
|
+
|
|
84
|
+
The server **swallows setup errors** and can still return an empty `redirectUrl`. If it is empty, stop and diagnose with `troubleshooting.md`. Do not continue to the PATCH. In deploy mode an environment row may already exist; tell the user and offer to delete it with `DELETE /connect/devops/environment/<id>` (removes the NC/EC too) after confirmation.
|
|
85
|
+
|
|
86
|
+
## Step 2 — User completes the OAuth login via a link
|
|
87
|
+
|
|
88
|
+
This step **requires a human** (authorization code with PKCE, stored per user). The CLI cannot open the user's browser from a chat, so **do not claim a browser was opened** and do not run `sf org open`. Show the sign-in as a button-style link, using exactly this layout (deploy mode shown; `<name>` is the environment name):
|
|
89
|
+
|
|
90
|
+
> **Connect `<name>`**
|
|
91
|
+
>
|
|
92
|
+
> **[Sign in to `<name>` →](<redirectUrl>)**
|
|
93
|
+
>
|
|
94
|
+
> 1. Sign in with the user DX Inspector should act as, and approve access.
|
|
95
|
+
> 2. Come back here and reply **done**.
|
|
96
|
+
>
|
|
97
|
+
> Link not working? Copy it: `<redirectUrl>`
|
|
98
|
+
|
|
99
|
+
Hub mode uses the same layout with the heading **Connect the Lifecycle Center org** and the button text **Connect to Lifecycle Center org →**.
|
|
100
|
+
|
|
101
|
+
Rules for the link:
|
|
102
|
+
- Use the full `redirectUrl` after the `&` fix, unmodified, as the Markdown link, and again in the "Link not working?" line. Show the sign-in once; do not repeat it in other words.
|
|
103
|
+
- Only the newest link works. Each new Step 1 run (hub) or `GET /connect/devops/environment/<id>` (deploy) replaces the previous one, so never run one while the user is still signing in, and never show an older link again. If the user reports it expired or failed, get a fresh one the same way.
|
|
104
|
+
- The user should open it in a browser that is signed in to the dev org as the same user the CLI uses (the final confirmation happens on the dev org). Otherwise the browser lands on that org's login page: tell them to sign in there, then use the link again.
|
|
105
|
+
- Right after showing the layout, wait for the user to reply **done**. Do not run other steps in between.
|
|
106
|
+
|
|
107
|
+
**Hub mode:** the user must log in as someone holding the **DevOps Center User** permission set in the hub org.
|
|
108
|
+
|
|
109
|
+
## Step 3 — Confirm the OAuth token landed
|
|
110
|
+
|
|
111
|
+
When the user says they are done, check the EC principal (`connect-api.md`, *Check credential status*).
|
|
112
|
+
|
|
113
|
+
| Status | Action |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `Configured` | Go to Step 4. |
|
|
116
|
+
| `NotConfigured` | The login did not complete. Ask whether they saw an error and offer to re-run Step 1 for a fresh URL. Do not PATCH. |
|
|
117
|
+
|
|
118
|
+
## Step 4 — Finalize: set the real org URL (PATCH)
|
|
119
|
+
|
|
120
|
+
The NC is created pointing at a placeholder login host. The PATCH calls `/services/oauth2/userinfo` through the NC, rewrites the callout URL to the real My Domain, and (deploy mode) stores the target's org id and URL on the `DevopsEnvironment` row. Until it succeeds, callouts go to the wrong host.
|
|
121
|
+
|
|
122
|
+
**Deploy mode:**
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
sf api request rest "/services/data/v<ver>/connect/devops/environment/<id>" \
|
|
126
|
+
--method PATCH --target-org <dev-org-alias>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Success returns `id`, `organizationId`, `orgUrl`, `status`, and `message`. Keep `namedCredential` from the POST. Verify `orgUrl` is a My Domain URL and **not** `login.salesforce.com` or `test.salesforce.com`.
|
|
130
|
+
|
|
131
|
+
**Hub mode:**
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
sf api request rest "/services/data/v<ver>/connect/devops/setupNamedCredential" \
|
|
135
|
+
--method PATCH \
|
|
136
|
+
--body '{"namedCredentialName":"ALMDevOpsCenterHub","namedCredentialType":"ORG_TO_ORG"}' \
|
|
137
|
+
--target-org <dev-org-alias>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Success returns `{"namedCredentialName": "...", "calloutUrl": "https://<org>.my.salesforce.com", "redirectUrl": null}`. Verify `calloutUrl` the same way.
|
|
141
|
+
|
|
142
|
+
- On failure (`DOCE_CONNECTION_UPDATE_FAILED`, a 404, a userinfo failure, or `TARGET_ORG_*` codes) see `troubleshooting.md`.
|
|
143
|
+
- **Never retry the PATCH in a loop.** **Hub mode only:** a failed PATCH also **clears the user's saved DX Inspector selections**. Tell the user.
|
|
144
|
+
|
|
145
|
+
## Step 5 — Verify and hand off
|
|
146
|
+
|
|
147
|
+
1. Re-run the status check. Expect principal `Configured` and a callout URL equal to the PATCH `calloutUrl`.
|
|
148
|
+
2. **Hub mode only:** optionally record the hub type the way DX Inspector does. A `CORE` or `MANAGED_PACKAGE` response proves the NC works end to end.
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
sf api request rest "/services/data/v<ver>/connect/devops/doceConnectionType" --target-org <dev-org-alias>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
3. Show the result with exactly this layout, no raw JSON, and never the credential name.
|
|
155
|
+
|
|
156
|
+
Deploy mode:
|
|
157
|
+
|
|
158
|
+
> **✅ `<name>` is connected**
|
|
159
|
+
>
|
|
160
|
+
> | Org | Type | Status |
|
|
161
|
+
> |---|---|---|
|
|
162
|
+
> | `<host of orgUrl>` | Sandbox, Production, or OrgFarm | Ready to deploy to |
|
|
163
|
+
|
|
164
|
+
Hub mode (use the `calloutUrl` host; leave out the Hub type column when the type call was skipped or unknown):
|
|
165
|
+
|
|
166
|
+
> **✅ The Lifecycle Center org is connected**
|
|
167
|
+
>
|
|
168
|
+
> | Org | Hub type | Status |
|
|
169
|
+
> |---|---|---|
|
|
170
|
+
> | `<host of calloutUrl>` | Core or Managed package | Connected |
|
|
171
|
+
|
|
172
|
+
Say "Sandbox" for a scratch org too. If the status check in item 1 did not return `Configured`, do not show this layout: say the sign-in is not complete and offer a fresh link.
|
|
173
|
+
4. **Deploy mode:** re-run the environment lookup (`list-orgs.md`) and confirm the row with the `id` from Step 1 is listed, `selectable`, with its `NamedCredential`. Carry that `id` and `namedCredential` forward. If it is missing, do not deploy and do not invent an id; report that the credential is connected but the row was not found.
|
|
174
|
+
5. **If this connect started from a deploy request** (`deploy.md`, Step 2): tell the user in one sentence that `<name>` is connected and that you are continuing the deploy of the components they gave. Then go to `deploy.md`, Step 3 and Step 4. The deploy confirmation is theirs to give; do not submit anything before it. If the connect did not start from a deploy, end here and do not offer anything beyond the result.
|
|
175
|
+
|
|
176
|
+
## Rules
|
|
177
|
+
|
|
178
|
+
- Never fabricate an NC name, callout URL, or `Configured` status. Report only what the org returned.
|
|
179
|
+
- Never print access tokens, and never pass `headerTargetAccessToken` in place of a stored connection.
|
|
180
|
+
- One environment per target org. Do not reuse a deploy NC for a different org; create a new environment.
|
|
181
|
+
- Deploy-target connections always use the Environment API so the `DevopsEnvironment` row exists. Never use `setupNamedCredential` alone for a deploy target.
|
|
182
|
+
- Never tell the user a browser was opened. Give the link.
|
|
183
|
+
- Do not rename `ALMDevOpsCenterHub`. DX Inspector looks it up by that exact name.
|
|
184
|
+
- Only the org-to-org types (`ORG_TO_ORG`, `ORG_TO_SANDBOX_ORG`, `ORG_TO_ORGFARM_ORG`) are used here.
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Deploy, validate, or quick deploy (Operation D)
|
|
2
|
+
|
|
3
|
+
Deploys metadata that already exists in the **source org** (the org the user built in) to a **target environment** connected in DX Inspector. It calls `POST /connect/devops/simple-deploy/deploy`, then polls `GET` until the request reaches a final status.
|
|
4
|
+
|
|
5
|
+
Metadata only. Data (record) deploys are not supported. Needs Salesforce API **v67.0** or later.
|
|
6
|
+
|
|
7
|
+
| Mode | When | Request body |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `deploy` (default) | The user wants the components in the target | `references/request-body.md` |
|
|
10
|
+
| `validate` | The user asks for a check only. For a Production target, recommend it first (Step 3), but never switch the mode without their agreement | `isCheckDeploy: true` |
|
|
11
|
+
| `quickDeploy` | The user has a successful validation id (`0Af…`) to deploy | `isQuickDeploy: true` + `checkDeployIdentifier` |
|
|
12
|
+
|
|
13
|
+
## Before Step 1
|
|
14
|
+
|
|
15
|
+
1. Source org: the alias the user named, else the default org from `sf org display --json`. If it cannot be read, ask which org they build in.
|
|
16
|
+
2. Read `result.apiVersion` from that output. If it is below `67.0`, stop and say the org's API version is too old for this skill.
|
|
17
|
+
3. One target per run. If the user names several, deploy to the first, finish, and ask before starting the next. Each target gets its own confirmation (Step 4).
|
|
18
|
+
|
|
19
|
+
## Step 1: Components
|
|
20
|
+
|
|
21
|
+
Skip this step for `quickDeploy`: it sends no `changes`.
|
|
22
|
+
|
|
23
|
+
Ask: "Which components do you want to deploy? Give the name and type of each (for example `AccountService` ApexClass, `Account.Tier__c` CustomField), and tell me whether each is **new**, **changed**, or **removed**."
|
|
24
|
+
|
|
25
|
+
Map the answer to the wire `operation`: new → `add`, changed → `modify`, removed → `delete`. Anything unclear → `modify`.
|
|
26
|
+
|
|
27
|
+
Build `changes[]` as `{fullName, type, operation}`. All three are required and non-blank. Types are Metadata API type names (`ApexClass`, `CustomObject`, `CustomField`, `Flow`, `LightningComponentBundle`, …). If the user gives a name without a type, ask; do not guess.
|
|
28
|
+
|
|
29
|
+
## Step 2: Target environment
|
|
30
|
+
|
|
31
|
+
Follow `references/list-orgs.md` with the identifier the user gave (sections 1 to 3). Then:
|
|
32
|
+
|
|
33
|
+
| Outcome | Do |
|
|
34
|
+
|---|---|
|
|
35
|
+
| Target is `matched` and `selectable` | Carry `id` and `namedCredential` from that row. Go to Step 3. |
|
|
36
|
+
| No target named yet | Ask which target. Show the list (`list-orgs.md`, section 4) if they want to choose. |
|
|
37
|
+
| `not-connected` | Offer to connect it. If the user agrees, run `references/connect-org.md` (deploy-target mode), then **continue as below**. |
|
|
38
|
+
| `unauthenticated` | Offer to finish connecting it (repair path), then continue as below. |
|
|
39
|
+
| `expired` | Not deployable. Ask for another target or offer to connect a new one. |
|
|
40
|
+
|
|
41
|
+
**Continuing after a connect.** When the connect flow finishes and the environment shows as `selectable`, tell the user in one sentence that `<name>` is now connected, and that you will continue the deploy of `<components>` to it. Then go straight to Step 3 and Step 4. The Step 4 message is the confirmation they give before anything is deployed; connecting an org never deploys by itself.
|
|
42
|
+
|
|
43
|
+
If the user connected the org but gave no components yet, ask for them (Step 1) after the connect.
|
|
44
|
+
|
|
45
|
+
## Step 3: Build the request
|
|
46
|
+
|
|
47
|
+
Write the POST body to a temp file (`BODY=$(mktemp)`; this avoids shell-quoting nested JSON):
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"namedCredential": "<NamedCredential>",
|
|
52
|
+
"targetEnvironmentId": "<DevopsEnvironment Id>",
|
|
53
|
+
"requestBody": {
|
|
54
|
+
"changes": [{"fullName": "AccountService", "type": "ApexClass", "operation": "modify"}],
|
|
55
|
+
"testOptions": {"level": "NoTestRun", "tests": []}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Mode variants and test-level rules: `references/request-body.md`.
|
|
61
|
+
|
|
62
|
+
- **Production target:** recommend a `validate` run first unless the user already has a successful one, and default the test level to `RunLocalTests`. An explicit user choice of test level always wins.
|
|
63
|
+
- **Quick deploy:** the validation id comes from the user or from an earlier `validate` in this conversation (`metadata.deployId`). If you have neither, ask for it. Never invent one. Send only `isQuickDeploy` and `checkDeployIdentifier`, never `changes` or `testOptions`.
|
|
64
|
+
|
|
65
|
+
## Step 4: Confirmation gate
|
|
66
|
+
|
|
67
|
+
**This call changes the target org (except `validate`). Do not proceed without an explicit yes.** Show:
|
|
68
|
+
|
|
69
|
+
> "I'm about to **<deploy | validate | quick deploy>** from `<source-org-alias>` to `<environment Name>` (<OrgType>):
|
|
70
|
+
> - Components: <n> (<first few, with new/changed/removed>)
|
|
71
|
+
> - Test level: <level>
|
|
72
|
+
>
|
|
73
|
+
> Shall I proceed?"
|
|
74
|
+
|
|
75
|
+
For **quick deploy**, replace the components and test-level lines with `- Validation id: <0Af…>`, and use the same target environment the validation ran against. If the user gives only the id, ask which target it was validated against.
|
|
76
|
+
|
|
77
|
+
Call out any `delete` and any Production target explicitly. `validate` does not change the target, so it needs no confirmation, but still state what you are about to validate.
|
|
78
|
+
|
|
79
|
+
## Step 5: Submit
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
sf api request rest \
|
|
83
|
+
"/services/data/v67.0/connect/devops/simple-deploy/deploy" \
|
|
84
|
+
--method POST \
|
|
85
|
+
--body @"$BODY" \
|
|
86
|
+
--target-org <source-org-alias>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Read `response.requestId`. If it is absent, the call failed: use `references/error-handling.md`. Make **one** attempt. Never retry in a loop, never resubmit after a timeout, and never invent a `requestId`.
|
|
90
|
+
|
|
91
|
+
## Step 6: Poll to completion
|
|
92
|
+
|
|
93
|
+
Polling is automatic and read-only. Every check reads **two sources**, and a terminal state from **either** one ends it: the Simple Deploy status endpoint (live `step`, `metadata.deployId`) and the `DevopsRequestInfo` record for the `requestId` (`Status` is `SUCCESS` or `ERROR`; it is the same record commit polling uses).
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
bash scripts/poll-deploy-status.sh <requestId> <source-org-alias> 10 100
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Checks come at 3 s, then 5 s, then every 10 s, for at most **100 seconds**, about 2 minutes in all. Set the shell tool timeout to at least 180 seconds so the run is not killed before it exits. Progress lines (`status=… step=… request-info=…`) go to stderr; relay the current step to the user while waiting. Never say the deploy is "still waiting" after the script has printed a result.
|
|
100
|
+
|
|
101
|
+
On a failed deploy the script also reads the failure detail that Core attaches to the request (the `DEPLOYMENT_COMPLETED` `DevopsActivityLog` row). Core fills it in a few seconds after the failure by calling the target org's Metadata API through the deploy's named credential, so **no login to the target org is needed**. The script waits up to 20 s for it (`DETAIL_WAIT`), and skips the wait when the deploy failed before reaching the target org.
|
|
102
|
+
|
|
103
|
+
The script prints one JSON object when it ends:
|
|
104
|
+
|
|
105
|
+
| Field | Meaning |
|
|
106
|
+
|---|---|
|
|
107
|
+
| `outcome` | `SUCCEEDED`, `FAILED`, `NOT_FOUND`, `TIMEOUT` (poll ran out of time), or `IN_PROGRESS` (`--once` only) |
|
|
108
|
+
| `step`, `status` | Last phase seen (`RETRIEVE_METADATA`, `DEPLOY_METADATA`, `VALIDATE_METADATA`, …) and its status |
|
|
109
|
+
| `deployId` | The target org's deploy id (`0Af…`). For a successful `validate` this is the id for a quick deploy |
|
|
110
|
+
| `message`, `errorDetails`, `activityMessage` | Failure text. For a failure before the target org (retrieve or validation) this already names the problem; for a failed target deploy it is generic ("Metadata deployment failed with status: Failed"). Prefer these over `errorMessage`, which can be HTML-escaped (`'`) |
|
|
111
|
+
| `deployJobLogURL` | Per-component detail, in the target org |
|
|
112
|
+
| `errorDetail` | Core's detail for a failed target deploy: `numberComponentErrors`, `componentFailures[]` (`componentType`, `fileName`, `problem`, `problemType`, `lineNumber`, `columnNumber`), `testFailures[]` (`name`, `methodName`, `message`, `stackTrace`), `errorMessage` (for example a code-coverage shortfall), `truncated` (only the first 5 of each are kept). `null` when none |
|
|
113
|
+
| `errorDetailUnavailable` | `true` when Core recorded that no detail will come |
|
|
114
|
+
| `decidedBy` | `endpoint` or `request-info`: which source reported the final state |
|
|
115
|
+
| `response` | The raw endpoint response |
|
|
116
|
+
|
|
117
|
+
Exit codes: `0` succeeded, `2` failed or not found, `3` timeout, `1` usage error or both sources failed, `4` still processing (`--once` only). `outcome` tells `FAILED` from `NOT_FOUND`.
|
|
118
|
+
|
|
119
|
+
`NOT_FOUND` right after a submit can be transient (the script allows a short grace period, and a `DevopsRequestInfo` row overrides it). If it persists, the id is unknown or older than about 2 days.
|
|
120
|
+
|
|
121
|
+
On timeout (exit `3`, `outcome` `TIMEOUT`, about 2 minutes), stop polling and tell the user, in plain words, that the deploy has not reported a final status yet but may still be running. Give them what they need to check it later:
|
|
122
|
+
|
|
123
|
+
- **Request token (`requestId`)**: "Send me this id and I'll check its status."
|
|
124
|
+
- **Deployment id (`deployId`, starts `0Af`)**, only if the result has one: it is the deploy job in the target org. They can find it in the target org under Setup → Deployment Status, or at `deployJobLogURL`.
|
|
125
|
+
- The `step` it had reached.
|
|
126
|
+
- That the deploy also shows in DX Inspector's activity history for this org.
|
|
127
|
+
|
|
128
|
+
Example: "Your deploy to `<target>` hasn't reported a final status after 2 minutes. It was at `DEPLOY_METADATA` and may still be running. Request token: `<requestId>`. Deployment id: `<deployId>`. Send me the request token any time and I'll check it, or look up the deployment id in `<target>` under Setup → Deployment Status." Never resubmit, and do not keep polling.
|
|
129
|
+
|
|
130
|
+
For a one-off check, put `--once` **first**: `bash scripts/poll-deploy-status.sh --once <requestId> <source-org-alias>`. It exits `4` while the request is still processing: report the current `step` and do not poll again unless the user asks. With `--once` there is no grace period, so `NOT_FOUND` right after a submit may be transient: say the request is not visible yet and check again shortly, not that it failed.
|
|
131
|
+
|
|
132
|
+
If the user gives a `requestId` to check (also when they come back with the id from a timeout), skip Steps 1 to 5 and check it once with `--once`, using the source org alias. If the user asks for the status without an id, use the `requestId` from earlier in this conversation; if there is none, ask for it. Then report as in Step 7.
|
|
133
|
+
|
|
134
|
+
## Step 7: Report
|
|
135
|
+
|
|
136
|
+
Summarize in plain language: what was deployed, from where, to where, and the outcome. No raw JSON.
|
|
137
|
+
|
|
138
|
+
- **Succeeded:** say so, with the completion time (`completedAt`). After a successful `validate`, give `deployId` as the validation id and offer a quick deploy with it.
|
|
139
|
+
- **Failed:** always show the error, never just "failed".
|
|
140
|
+
1. Say which `step` failed. If `errorDetail` is present, use it: list each `errorDetail.componentFailures` entry as `<fileName> (<componentType>), line <lineNumber>: <problem>`, each `testFailures` entry as `<name>.<methodName>: <message>`, and always include `errorDetail.errorMessage` when set (a code-coverage shortfall appears only there, with `numberComponentErrors` at 0). If `truncated` is true, say only the first few are shown and give `deployJobLogURL`.
|
|
141
|
+
2. If `errorDetail` is `null`, quote `activityMessage` (else `errorDetails`, else `message`). A failure at `RETRIEVE_METADATA` or validation, such as "Entity of type 'CustomField' named 'Book__c.Author__c' cannot be found", is complete as is: the component is missing from the source org.
|
|
142
|
+
3. If `errorDetail` is `null` and the message is only the generic "Metadata deployment failed with status: Failed", the detail was not attached in time (or `errorDetailUnavailable` is `true`). Say so, give `deployJobLogURL` (also Setup → Deployment Status in the target org), and offer to check again shortly with `--once`.
|
|
143
|
+
4. Map the error with `references/error-handling.md`, and ask before retrying. Never resubmit on your own.
|
|
144
|
+
|
|
145
|
+
## Gotchas
|
|
146
|
+
|
|
147
|
+
| Gotcha | What to do |
|
|
148
|
+
|---|---|
|
|
149
|
+
| Component not in the source org | The deploy retrieves from the source org. Confirm the name and type exist there before submitting. |
|
|
150
|
+
| Quick deploy with `changes` | Forbidden. Send only `isQuickDeploy` and `checkDeployIdentifier`. |
|
|
151
|
+
| Target equals the source org | Not allowed. Ask for a different target. |
|
|
152
|
+
| An id starting `0Af` | It is a validation id, not a `requestId`. Never poll it. If the user gives one alone, ask whether to quick deploy it, and to which target. |
|
|
153
|
+
| Stale target login | Shows only at deploy time (`Bad_OAuth_Token`, `TARGET_ORG_SESSION_EXPIRED`). Reconnect that environment (`connect-org.md`, repair path), then ask before retrying. |
|