@salesforce/afv-skills 1.34.0 → 1.35.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.
Files changed (67) hide show
  1. package/package.json +1 -1
  2. package/skills/automation-sandbox-post-copy-config-generate/SKILL.md +239 -0
  3. package/skills/automation-sandbox-post-copy-config-generate/assets/config_template.json +21 -0
  4. package/skills/automation-sandbox-post-copy-config-generate/assets/json_schema.json +90 -0
  5. package/skills/automation-sandbox-post-copy-config-generate/examples/sample_sop_excerpt.md +31 -0
  6. package/skills/automation-sandbox-post-copy-config-generate/examples/sample_sop_to_config.json +50 -0
  7. package/skills/automation-sandbox-post-copy-config-generate/references/configuration_catalog.md +76 -0
  8. package/skills/automation-sandbox-post-copy-config-generate/references/sop_parsing_patterns.md +157 -0
  9. package/skills/automation-sandbox-post-copy-config-generate/references/source_format_handling.md +230 -0
  10. package/skills/dx-apexguru-scan/SKILL.md +403 -0
  11. package/skills/dx-apexguru-scan/examples/README.md +54 -0
  12. package/skills/dx-apexguru-scan/examples/sample-decoded-summary.json +176 -0
  13. package/skills/dx-apexguru-scan/examples/sample-full-no-runtime-response.json +26 -0
  14. package/skills/dx-apexguru-scan/examples/sample-succeeded-response.json +15 -0
  15. package/skills/dx-apexguru-scan/references/api-reference.md +81 -0
  16. package/skills/dx-apexguru-scan/references/authentication.md +134 -0
  17. package/skills/dx-apexguru-scan/references/error-handling.md +56 -0
  18. package/skills/dx-apexguru-scan/references/violation-catalog.md +28 -0
  19. package/skills/dx-apexguru-scan/scripts/build-zip.sh +87 -0
  20. package/skills/dx-apexguru-scan/scripts/decode-report.js +389 -0
  21. package/skills/dx-apexguru-scan/scripts/resolve-token.sh +151 -0
  22. package/skills/dx-apexguru-scan/scripts/run-scan.sh +153 -0
  23. package/skills/dx-apexguru-scan/scripts/scan.sh +96 -0
  24. package/skills/dx-apexguru-scan/scripts/validate-token.js +121 -0
  25. package/skills/dx-devops-pipeline-manage/SKILL.md +263 -0
  26. package/skills/dx-devops-pipeline-manage/examples/common-workflows.md +177 -0
  27. package/skills/dx-devops-pipeline-manage/references/cli-commands.md +298 -0
  28. package/skills/dx-devops-pipeline-manage/references/parsing-patterns.md +134 -0
  29. package/skills/dx-devops-pipeline-manage/scripts/check-activation-ready.sh +34 -0
  30. package/skills/dx-devops-pipeline-manage/scripts/validate-org-type.sh +17 -0
  31. package/skills/dx-devops-pipeline-manage/scripts/verify-operation.sh +82 -0
  32. package/skills/dx-devops-promote/SKILL.md +214 -0
  33. package/skills/dx-devops-promote/examples/promotion-workflows.md +212 -0
  34. package/skills/dx-devops-promote/references/cli-commands.md +303 -0
  35. package/skills/experience-lwc-base-components-integrate/SKILL.md +176 -0
  36. package/skills/experience-lwc-base-components-integrate/references/lbc-expert-guidance.md +127 -0
  37. package/skills/experience-lwc-base-components-integrate/references/lightning-component-index.md +179 -0
  38. package/skills/experience-lwc-base-components-integrate/references/lightning-components.md +5429 -0
  39. package/skills/experience-lwc-base-components-integrate/scripts/extract-component-docs.sh +61 -0
  40. package/skills/experience-lwc-rtl-validate/SKILL.md +149 -0
  41. package/skills/experience-lwc-rtl-validate/references/rtl-expert.md +892 -0
  42. package/skills/experience-lwc-rtl-validate/scripts/scan-rtl-css.sh +206 -0
  43. package/skills/experience-lwc-typescript-migrate/SKILL.md +207 -0
  44. package/skills/experience-lwc-typescript-migrate/assets/dts-template.ts +15 -0
  45. package/skills/experience-lwc-typescript-migrate/assets/type-patterns.ts +44 -0
  46. package/skills/experience-lwc-typescript-migrate/scripts/find-consumers.sh +128 -0
  47. package/skills/experience-ui-bundle-localize/SKILL.md +323 -0
  48. package/skills/experience-ui-bundle-localize/references/gotchas.md +249 -0
  49. package/skills/experience-ui-bundle-localize/references/i18n-setup.md +169 -0
  50. package/skills/experience-ui-bundle-localize/references/interpolation.md +311 -0
  51. package/skills/experience-ui-bundle-localize/references/label-xml.md +282 -0
  52. package/skills/experience-ui-bundle-localize/references/verifying.md +219 -0
  53. package/skills/experience-ui-bundle-localize/scripts/check-i18n-wired.sh +195 -0
  54. package/skills/experience-ui-bundle-localize/scripts/check-manifest-registered.sh +100 -0
  55. package/skills/experience-ui-bundle-localize/scripts/check-org-api-version.sh +40 -0
  56. package/skills/experience-ui-bundle-localize/scripts/detect-bundle-type.sh +57 -0
  57. package/skills/platform-custom-lightning-type-generate/SKILL.md +3 -0
  58. package/skills/platform-custom-lightning-type-generate/assets/primitive-types-and-constraints.md +1 -1
  59. package/skills/platform-mcp-tool-widget-coordinate/SKILL.md +250 -0
  60. package/skills/platform-mcp-tool-widget-coordinate/examples/action-name-source-prompt.md +74 -0
  61. package/skills/platform-mcp-tool-widget-coordinate/examples/apex-invocable-source-prompt.md +90 -0
  62. package/skills/platform-mcp-tool-widget-coordinate/examples/nested-object-source-prompt.md +191 -0
  63. package/skills/platform-mcp-tool-widget-coordinate/examples/pasted-tool-output-prompt.md +85 -0
  64. package/skills/platform-mcp-tool-widget-coordinate/references/build-plan-format.md +74 -0
  65. package/skills/platform-mcp-tool-widget-coordinate/references/mcp-tool-output-discovery.md +184 -0
  66. package/skills/platform-mcp-tool-widget-coordinate/references/two-clt-modeling.md +128 -0
  67. package/skills/platform-mcp-tool-widget-coordinate/references/validation-gates.md +181 -0
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env bash
2
+ # Deterministically verify the result of a pipeline operation by checking the
3
+ # command's JSON status and the relevant post-state fields from `pipeline get`.
4
+ # Usage:
5
+ # scripts/verify-operation.sh status <json-file-or-'-'>
6
+ # -> assert the captured CLI JSON has .status == 0
7
+ # scripts/verify-operation.sh active <pipeline-id> <true|false> [target-org]
8
+ # -> assert .result.isActive matches the expected boolean
9
+ # scripts/verify-operation.sh has-stage <pipeline-id> <stage-name> [target-org]
10
+ # -> assert a stage with that name exists in the chain
11
+ # scripts/verify-operation.sh has-project <pipeline-id> <project-name> [target-org]
12
+ # -> assert a connected project with that name exists
13
+ # Exits 0 when the assertion holds; prints an actionable error and exits 1 otherwise.
14
+
15
+ set -euo pipefail
16
+
17
+ MODE="${1:?Usage: verify-operation.sh <status|active|has-stage|has-project> ...}"
18
+
19
+ # Read a pipeline once and hand back validated JSON on stdout. Distinguishes a
20
+ # failed CLI read / non-zero JSON status from a successful read (whose fields the
21
+ # caller then evaluates), so post-state checks never mistake a read failure for a
22
+ # "not found" result. Exits 2 with an actionable message on any read/JSON error.
23
+ GET_JSON=""
24
+ read_pipeline() {
25
+ local pid="$1" org="$2"
26
+ local flag=() err rc
27
+ [ -n "$org" ] && flag=(--target-org "$org")
28
+ # Capture stdout and stderr separately; do not let pipefail abort silently.
29
+ err=$(mktemp)
30
+ rc=0
31
+ GET_JSON=$(sf devops pipeline get --pipeline-id "$pid" "${flag[@]+"${flag[@]}"}" --json 2>"$err") || rc=$?
32
+ if [ "$rc" -ne 0 ]; then
33
+ echo "ERROR: could not read pipeline '$pid' (sf exited $rc): $(tr '\n' ' ' <"$err")" >&2
34
+ rm -f "$err"; exit 2
35
+ fi
36
+ rm -f "$err"
37
+ local st
38
+ st=$(echo "$GET_JSON" | jq -r '.status // 1' 2>/dev/null || echo 1)
39
+ if [ "$st" != "0" ]; then
40
+ local msg
41
+ msg=$(echo "$GET_JSON" | jq -r '.message // "unknown error"' 2>/dev/null || echo "unparseable response")
42
+ echo "ERROR: 'pipeline get' for '$pid' returned status $st — $msg" >&2
43
+ exit 2
44
+ fi
45
+ }
46
+
47
+ case "$MODE" in
48
+ status)
49
+ SRC="${2:?status mode needs a JSON file path or '-' for stdin}"
50
+ JSON=$([ "$SRC" = "-" ] && cat || cat "$SRC")
51
+ ST=$(echo "$JSON" | jq -r '.status // 1')
52
+ if [ "$ST" = "0" ]; then echo "OK: command status 0"; exit 0; fi
53
+ MSG=$(echo "$JSON" | jq -r '.message // "unknown error"')
54
+ echo "ERROR: command returned status $ST — $MSG" >&2; exit 1
55
+ ;;
56
+ active)
57
+ PID="${2:?}"; WANT="${3:?expected true|false}"; ORG="${4:-}"
58
+ read_pipeline "$PID" "$ORG" # exits 2 on read/JSON error before we evaluate fields
59
+ GOT=$(echo "$GET_JSON" | jq -r '.result.isActive')
60
+ if [ "$GOT" = "$WANT" ]; then echo "OK: isActive == $WANT"; exit 0; fi
61
+ echo "ERROR: expected isActive=$WANT but pipeline '$PID' reports isActive=$GOT" >&2; exit 1
62
+ ;;
63
+ has-stage)
64
+ PID="${2:?}"; NAME="${3:?stage name}"; ORG="${4:-}"
65
+ read_pipeline "$PID" "$ORG"
66
+ if echo "$GET_JSON" | jq -e --arg n "$NAME" '.result.stages[]? | select(.name == $n)' >/dev/null; then
67
+ echo "OK: stage '$NAME' present"; exit 0
68
+ fi
69
+ echo "ERROR: stage '$NAME' not found in pipeline '$PID'" >&2; exit 1
70
+ ;;
71
+ has-project)
72
+ PID="${2:?}"; NAME="${3:?project name}"; ORG="${4:-}"
73
+ read_pipeline "$PID" "$ORG"
74
+ if echo "$GET_JSON" | jq -e --arg n "$NAME" '.result.connectedProjects[]? | select(.name == $n)' >/dev/null; then
75
+ echo "OK: project '$NAME' connected"; exit 0
76
+ fi
77
+ echo "ERROR: project '$NAME' not connected to pipeline '$PID'" >&2; exit 1
78
+ ;;
79
+ *)
80
+ echo "ERROR: unknown mode '$MODE' (expected status|active|has-stage|has-project)" >&2; exit 1
81
+ ;;
82
+ esac
@@ -0,0 +1,214 @@
1
+ ---
2
+ name: dx-devops-promote
3
+ description: "Use this skill to drive the full DevOps Center promotion workflow for work items and pipeline stages — validate preconditions, prepare work items, optionally combine work items that share metadata, promote one or more work items or an entire stage to a target pipeline stage, and complete the promotion to finalize the deployment. TRIGGER when the user wants to promote a work item, advance changes to the next environment or stage, combine work items for a single promotion, or move metadata through the release pipeline. The mandatory validate step runs automatically at the start. DO NOT TRIGGER for work item creation or status updates (use dx-devops-work-item-manage), for conflict detection, or for polling an existing promotion's status."
4
+ metadata:
5
+ version: "1.0"
6
+ minApiVersion: "58.0"
7
+ relatedSkills:
8
+ - "dx-devops-work-item-manage"
9
+ cliTools:
10
+ - tool: ["jq"]
11
+ semver: ">=1.6"
12
+ - tool: ["sf"]
13
+ semver: ">=2.0.0"
14
+ accessCheck:
15
+ - type: "orgPref"
16
+ value: "ALMDevopsCorePref"
17
+ - type: "userPerm"
18
+ value: "UserHasDevOpsCore"
19
+ ---
20
+
21
+ # DevOps Center Promotion
22
+
23
+ Drives the full promotion workflow in DevOps Center — validate, prepare, optionally combine, promote, and complete — moving work items through the release pipeline. Provides headless, `--json`-driven, idempotent operations for autonomous release workflows in CI. Every promotion begins with a mandatory validate step.
24
+
25
+ ## Scope
26
+
27
+ - **In scope**: Validate promotion preconditions, prepare a work item, combine work items that share metadata into one promotion, promote one or more work items or an entire source stage to a target stage, and complete the promotion
28
+ - **Out of scope**: Work item creation/status updates (use `dx-devops-work-item-manage`), conflict detection, polling an existing promotion's status, pipeline or project setup (separate skills)
29
+
30
+ ---
31
+
32
+ ## Required Inputs
33
+
34
+ Gather or infer before proceeding:
35
+
36
+ - **Promotion target**: one or more specific work items, or all approved work items in a source stage
37
+ - **Target stage ID** (required for every promotion command — validate, prepare, combine, promote, and complete): `--target-stage-id` — the pipeline stage to promote to
38
+ - **Work item ID(s)** or **source stage ID** — depending on the promotion target. `sf devops promote` takes `--work-item-id` (repeatable) XOR `--stage-id`
39
+ - **For combined promotion**: a parent work item ID and one or more child work item IDs that share metadata
40
+ - **Target org**: `--target-org <alias>` (required unless the `target-org` config variable is set)
41
+
42
+ Defaults unless specified:
43
+ - Output format: `--json` for headless consumption
44
+ - Test level: omit `--test-level` for development-stage deploys (defaults to `NoTestRun`); use `RunLocalTests` for production-stage deploys with Apex
45
+
46
+ If the user gives a clear request ("promote work item 1fkxx… to stage 1QVxx…", "promote the QA stage to UAT", "combine these work items and promote"), proceed once you have the required IDs.
47
+
48
+ ---
49
+
50
+ ## Workflow
51
+
52
+ All operations use `sf devops` CLI commands with `--json` output. Validate ALWAYS runs first. All promotion commands are keyed on **record IDs**, not work item names — resolve names to IDs first if needed.
53
+
54
+ ### Phase 1 — Authenticate and Validate
55
+
56
+ 1. **Verify org authentication** before any operation:
57
+ ```bash
58
+ sf org display --json
59
+ ```
60
+ - If it fails, instruct the user to run `sf org login web --set-default --alias <alias>`
61
+ - Pass `--target-org <alias>` on every subsequent command (required unless the `target-org` config variable is set)
62
+
63
+ 2. **Run the mandatory validate step** — this is non-negotiable and always runs before prepare/combine/promote. `sf devops promotion validate` requires the target stage (`-t/--target-stage-id`) and one or more `-i/--work-item-id`:
64
+ ```bash
65
+ # Capture the output — Phase 2 derives the combine decision from it deterministically.
66
+ VALIDATE_JSON=$(sf devops promotion validate --work-item-id <id> --target-stage-id <target-stage-id> --target-org <alias> --json)
67
+ ```
68
+ - Validates whether the work item(s) can be promoted to the target stage — checks for VCS and object-permission errors (including the associated-PR requirement) before a promotion is attempted
69
+ - Repeat `--work-item-id` to validate multiple work items in one call
70
+ - **Success:** `status == 0` and `.result.success == true` — proceed
71
+ - **If validation fails** (non-zero exit; e.g. `VCS_ERROR: No pull request exists…`, with `.result.errorType`/`.result.errorDetails` set), STOP. Report the error and do not proceed. If it references metadata overlap, resolve the conflict before retrying
72
+ - **Shared components:** when `.result.combineDetails` is non-null, the work items share metadata — validate returns the parent/child grouping and `suggestions`. This is the authoritative signal for the Phase 2 combine decision (see step 4); do not guess whether to combine — the Phase 2 script reads `.result.combineDetails` from `VALIDATE_JSON`
73
+
74
+ ### Phase 2 — Prepare (and optionally Combine)
75
+
76
+ 3. **Prepare the work item** for promotion:
77
+ ```bash
78
+ sf devops work-item prepare --work-item-id <id> --target-stage-id <target-stage-id> --target-org <alias> --json
79
+ ```
80
+ - `--target-stage-id` is required — the same target stage the work item will be promoted to
81
+ - Idempotent: re-running a prepared work item is safe — treat as success
82
+
83
+ 4. **Combine work items** — ONLY when the Phase 1 validate step reported shared components (`.result.combineDetails` non-null) or the work items otherwise have dependencies and must promote as one unit. Do not eyeball the JSON — derive the decision and the parent/child IDs deterministically from the saved validate output (`VALIDATE_JSON`):
84
+ ```bash
85
+ # COMBINE == "true" only when validate returned a combineDetails block.
86
+ COMBINE=$(printf '%s' "$VALIDATE_JSON" | jq -r '(.result.combineDetails != null)')
87
+ if [ "$COMBINE" = "true" ]; then
88
+ PARENT_ID=$(printf '%s' "$VALIDATE_JSON" | jq -r '.result.combineDetails.parentWorkitemId')
89
+ # one --child-work-item-id arg per child, safe for use as a flag array
90
+ CHILD_ARGS=()
91
+ while IFS= read -r cid; do CHILD_ARGS+=(--child-work-item-id "$cid"); done < <(
92
+ printf '%s' "$VALIDATE_JSON" | jq -r '.result.combineDetails.childWorkitemsId[]')
93
+ fi
94
+ ```
95
+ Then combine using those derived values (skip this command entirely when `COMBINE` is not `"true"`):
96
+ ```bash
97
+ sf devops work-item combine \
98
+ --parent-work-item-id "$PARENT_ID" \
99
+ "${CHILD_ARGS[@]}" \
100
+ --target-stage-id <stage-id> \
101
+ --target-org <alias> \
102
+ --json
103
+ ```
104
+ - `CHILD_ARGS` expands to one `--child-work-item-id <id>` pair per child work item
105
+ - The **parent** work item is the primary item that continues through the pipeline; child changes merge into the parent's branch during promotion
106
+ - After combining, promote the **parent** work item ID in step 5
107
+
108
+ ### Phase 3 — Promote
109
+
110
+ 5. **Promote to the target stage** — exactly one of `--work-item-id` or `--stage-id` must be provided; `--target-stage-id` is always required. **Pass `--skip-validation` ONLY when the Phase 1 validate step completed successfully in the current session for every work item being promoted.** Otherwise, OMIT the flag and let the CLI run its built-in validation:
111
+ - Promote one or more specific work items (repeat `--work-item-id` per item; use the parent's ID for a combined promotion). Include the `--skip-validation` line ONLY if Phase 1 validate passed this session; otherwise drop that line:
112
+ ```bash
113
+ sf devops promote \
114
+ --work-item-id <id> \
115
+ --target-stage-id <target-stage-id> \
116
+ --skip-validation \
117
+ --target-org <alias> \
118
+ --json
119
+ ```
120
+ - Or promote all approved work items from a source stage (again, include the `--skip-validation` line only if Phase 1 validate passed this session):
121
+ ```bash
122
+ sf devops promote \
123
+ --stage-id <source-stage-id> \
124
+ --target-stage-id <target-stage-id> \
125
+ --skip-validation \
126
+ --target-org <alias> \
127
+ --json
128
+ ```
129
+ - **Why conditional:** `sf devops promote`'s built-in pre-promote validation runs the *same* checks as the Phase 1 `sf devops promotion validate` step (including the associated-PR requirement). When the full workflow ran sequentially this session, that validation already passed, so `--skip-validation` only eliminates a redundant re-run. But if the agent resumed mid-workflow, promotion was invoked without a preceding Phase 1 validate, or Phase 1 was not run for every work item being promoted, DO NOT pass `--skip-validation` — bypassing it there would skip validation entirely with no prior guard
130
+ - Add `--deploy-all` to deploy all metadata in the branch rather than only changes not yet in the target stage
131
+ - Add `--test-level RunLocalTests` (or `RunSpecifiedTests --tests <names>`) for production-stage deploys that include Apex
132
+ - The deploy runs asynchronously — capture the returned promotion/deploy identifier from the JSON `.result`
133
+
134
+ ### Phase 4 — Complete and Report
135
+
136
+ 6. **Complete the promotion** to finalize — advances the work items in the target stage:
137
+ ```bash
138
+ sf devops promotion complete --target-stage-id <target-stage-id> --target-org <alias> --json
139
+ ```
140
+ - Run after the promote deploy succeeds to mark the promotion done in the target stage
141
+ - `--target-stage-id` is required (same target stage the work items were promoted to)
142
+
143
+ 7. **Report the outcome**:
144
+ - Confirm the CLI returned status 0 for each step
145
+ - Report the promotion/deploy identifier and note that async deploy completion is tracked separately
146
+ - Do NOT block or busy-wait inside this skill — surface the identifier and return
147
+ - State the promotion clearly: e.g., "Work item promotion initiated (source stage → target stage). Deploy ID: <id>. Poll this ID to confirm deploy completion, then run promotion complete."
148
+
149
+ ---
150
+
151
+ ## Rules / Constraints
152
+
153
+ | Constraint | Rationale |
154
+ |-----------|-----------|
155
+ | Validate ALWAYS runs first | Guarantees preconditions are met before any mutation; skipping it can corrupt pipeline state |
156
+ | All `sf devops` commands must use `--json` | Structured output is required for headless consumption; human-readable output is unreliable to parse |
157
+ | Commands are keyed on record IDs, not names | `--work-item-id`, `--stage-id`, `--target-stage-id`, `--parent/--child-work-item-id` all take IDs; resolve names to IDs first |
158
+ | `--target-stage-id` required for every promotion command (validate, prepare, combine, promote, complete) | The target stage is mandatory; the promotion has no destination without it |
159
+ | Exactly one of `--work-item-id` or `--stage-id` on promote | These flags are mutually exclusive; promote either specific items or a whole source stage |
160
+ | Pass `--skip-validation` on promote ONLY if Phase 1 validate passed this session | The CLI's built-in pre-promote validation runs the same checks (including the associated-PR requirement) as the Phase 1 `promotion validate` step. Skipping is safe only when that validation already ran successfully this session; if the agent resumed mid-workflow or promotion was invoked without a preceding validate, OMIT the flag so the CLI validates |
161
+ | Deploy runs async — capture and report the identifier | The promote deploy does not complete synchronously; completion is tracked separately |
162
+ | Do NOT busy-wait for deploy completion in this skill | Polling is a separate concern; blocking here wastes turns and risks timeouts |
163
+ | Combine only when work items share metadata/dependencies | Combining is for conflict-prone or dependent items, not a default for every multi-item promotion |
164
+ | Prepare is idempotent | Retry-safe for CI; re-running a completed prepare is a no-op |
165
+ | Never use interactive prompts | Skills run headless; all inputs must be CLI flags |
166
+ | Pass IDs as CLI flags, never interpolate into shell strings | Prevents prompt/command injection via crafted identifiers |
167
+
168
+ ---
169
+
170
+ ## Gotchas
171
+
172
+ | Issue | Resolution |
173
+ |-------|------------|
174
+ | **Validation fails** | STOP — do not prepare/combine/promote. Report the non-zero status / error message; if metadata overlap, resolve the conflict before retrying |
175
+ | **No default org set** | Run `sf org display --json`; if it fails, instruct user to run `sf org login web --set-default` |
176
+ | **Passing a work item name instead of an ID** | Promotion commands need record IDs; resolve names via `sf devops work-item list --project-id <id> --json \| jq -r '.result.workItems[] \| select(.subject == "<WI-subject>") \| .id'` |
177
+ | **Both `--work-item-id` and `--stage-id` supplied** | They are mutually exclusive; pick specific work items OR a source stage, not both |
178
+ | **Missing `--target-stage-id`** | Required on every promotion command (validate, prepare, combine, promote, complete); obtain the target stage ID from the pipeline configuration |
179
+ | **Combined promotion promotes the wrong item** | After `work-item combine`, promote the **parent** work item ID — children merge into the parent's branch |
180
+ | **Treating the deploy as synchronous** | The promote deploy is async; capture the identifier and confirm completion before running `promotion complete` |
181
+ | **Production deploy fails on Apex coverage** | Set `--test-level RunLocalTests` (or `RunSpecifiedTests --tests <names>`) for production-stage promotions with Apex |
182
+ | **Deploy fails with conflict** | A conflict slipped past validate; resolve the metadata conflict, then re-validate and retry |
183
+
184
+ ---
185
+
186
+ ## Output Expectations
187
+
188
+ Deliverables vary by operation:
189
+
190
+ - **Validate**: `.result.success` plus, when work items share metadata, `.result.combineDetails` / `.result.suggestions`. A non-zero exit (with `.result.errorType`/`.result.errorDetails`) means the work item cannot be promoted to the target stage
191
+ - **Prepare / combine**: confirmation that the work item(s) are staged (combine returns the parent/child grouping)
192
+ - **Promote**: an async deploy identifier and confirmation that the promotion deploy was initiated
193
+ - **Promotion complete**: confirmation the work items advanced in the target stage
194
+
195
+ Outputs are derived from `sf devops work-item`, `sf devops promote`, and `sf devops promotion complete` CLI commands. Async deploy completion is NOT produced by the promote call — poll the returned identifier separately before completing.
196
+
197
+ ---
198
+
199
+ ## Cross-Skill Integration
200
+
201
+ | When | Action |
202
+ |------|--------|
203
+ | Work item must be created or moved to a promotable status first | Delegate to `dx-devops-work-item-manage` |
204
+ | Validation reports metadata overlap / conflict | Resolve the metadata conflict before retrying |
205
+ | The promote deploy identifier must be polled to confirm completion | Poll the returned identifier separately, then run `sf devops promotion complete` |
206
+
207
+ ---
208
+
209
+ ## Reference File Index
210
+
211
+ | File | When to read |
212
+ |------|-------------|
213
+ | `references/cli-commands.md` | When you need detailed CLI flag documentation, JSON output schemas, or error-handling patterns for validate/prepare/combine/promote/complete |
214
+ | `examples/promotion-workflows.md` | When the user's request matches a common pattern (single work item promotion, combined promotion, whole-stage promotion, validate-first gate) |
@@ -0,0 +1,212 @@
1
+ # Promotion Workflow Examples
2
+
3
+ Common end-to-end promotion patterns. Every pattern begins with the mandatory validate step. All commands are keyed on record IDs — resolve names/subjects to IDs first. The promote step is async and returns a promotion ID that is polled separately before running `promotion complete`.
4
+
5
+ ---
6
+
7
+ ## Example 1 — Promote a single work item
8
+
9
+ **User prompt:** "Promote work item 1fkxx0000000123AAA to the QA stage."
10
+
11
+ ```bash
12
+ # 1. Verify auth
13
+ sf org display --json
14
+
15
+ # 2. Mandatory validate (requires the target stage)
16
+ sf devops promotion validate \
17
+ --work-item-id 1fkxx0000000123AAA \
18
+ --target-stage-id 1QVxx0000000QA0AAA \
19
+ --target-org myorg --json
20
+ # → status 0 and .result.success == true, proceed. On non-zero exit, STOP.
21
+
22
+ # 3. Prepare (target stage is required)
23
+ sf devops work-item prepare --work-item-id 1fkxx0000000123AAA --target-stage-id 1QVxx0000000QA0AAA --target-org myorg --json
24
+
25
+ # 4. Promote (async). --skip-validation: this skill already validated (step 2)
26
+ # and prepared (step 3), so the CLI's built-in pre-promote check is redundant.
27
+ PROMOTION_ID=$(sf devops promote \
28
+ --work-item-id 1fkxx0000000123AAA \
29
+ --target-stage-id 1QVxx0000000QA0AAA \
30
+ --skip-validation \
31
+ --target-org myorg \
32
+ --json | jq -r '.result.promotionId // .result.asyncOperationId')
33
+
34
+ echo "Promotion initiated. Promotion ID: $PROMOTION_ID"
35
+
36
+ # 5. Hand off the promotion ID for status polling (a separate concern —
37
+ # do NOT busy-wait here). Only once the async deploy has CONFIRMED
38
+ # completion should the promotion be finalized:
39
+ # sf devops promotion complete --target-stage-id 1QVxx0000000QA0AAA --target-org myorg --json
40
+ ```
41
+
42
+ **Report:** "Work item promotion initiated (→ QA stage). Promotion ID: `<id>`. Poll this ID to confirm the deploy completed; run `sf devops promotion complete` only after it reports success."
43
+
44
+ ---
45
+
46
+ ## Example 2 — Combine and promote multiple work items
47
+
48
+ **User prompt:** "Combine work items 1fkxx…101 and 1fkxx…102 into 1fkxx…100 and promote them to UAT."
49
+
50
+ ```bash
51
+ # 1. Validate ALL work items against the target stage in one call — if it fails
52
+ # (non-zero exit), STOP. On success, a non-null .result.combineDetails
53
+ # confirms the work items share components and returns the parent/child
54
+ # grouping to use in step 2.
55
+ sf devops promotion validate \
56
+ --work-item-id 1fkxx0000000100AAA \
57
+ --work-item-id 1fkxx0000000101AAA \
58
+ --work-item-id 1fkxx0000000102AAA \
59
+ --target-stage-id 1QVxx000000UAT0AAA \
60
+ --target-org myorg --json
61
+
62
+ # 2. Combine children into the parent (from .result.combineDetails), targeting the destination stage
63
+ sf devops work-item combine \
64
+ --parent-work-item-id 1fkxx0000000100AAA \
65
+ --child-work-item-id 1fkxx0000000101AAA \
66
+ --child-work-item-id 1fkxx0000000102AAA \
67
+ --target-stage-id 1QVxx000000UAT0AAA \
68
+ --target-org myorg \
69
+ --json
70
+
71
+ # 3. Promote the PARENT work item (async). --skip-validation: all work items
72
+ # were validated in step 1 and combining prepared the unit.
73
+ PROMOTION_ID=$(sf devops promote \
74
+ --work-item-id 1fkxx0000000100AAA \
75
+ --target-stage-id 1QVxx000000UAT0AAA \
76
+ --skip-validation \
77
+ --target-org myorg \
78
+ --json | jq -r '.result.promotionId // .result.asyncOperationId')
79
+
80
+ echo "Combined promotion initiated. Promotion ID: $PROMOTION_ID"
81
+
82
+ # 4. Hand off the promotion ID for status polling. Finalize with
83
+ # `sf devops promotion complete --target-stage-id 1QVxx000000UAT0AAA --target-org myorg --json`
84
+ # ONLY after the async deploy has confirmed completion — do not run it here.
85
+ ```
86
+
87
+ **Report:** "Work items combined into parent 1fkxx…100 and promotion initiated (→ UAT). Promotion ID: `<id>`. Poll this ID; run `sf devops promotion complete` only after the deploy reports success."
88
+
89
+ ---
90
+
91
+ ## Example 3 — Promote an entire stage
92
+
93
+ **User prompt:** "Promote everything in the QA stage to Production."
94
+
95
+ ```bash
96
+ # 1. The validate-first gate still applies. `sf devops work-item list` takes
97
+ # --project-id (not a stage flag), so list the project's work items and
98
+ # filter to the approved ones in the QA stage with jq. Validate them against
99
+ # the target stage before promoting — if validation fails, STOP; do not promote.
100
+ #
101
+ # IMPORTANT: capture the list command into a variable with fail-fast checks
102
+ # BEFORE filtering. Do not put `sf devops work-item list | jq` directly in a
103
+ # `for` loop — command substitution in the loop header hides non-zero exits
104
+ # (and an unset/invalid project ID) as an empty iteration, which would skip
105
+ # validation entirely and fall through to `sf devops promote`.
106
+ set -euo pipefail
107
+ PROJECT_ID=1Qg0000000000001
108
+ QA_STAGE_ID=1QVxx0000000QA0AAA
109
+ PROD_STAGE_ID=1QVxx00000PROD0AAA # the target stage promotion validates against
110
+
111
+ if ! WI_LIST_JSON=$(sf devops work-item list --project-id "$PROJECT_ID" --target-org myorg --json); then
112
+ echo "Failed to list work items for project $PROJECT_ID — STOP. Do not promote." >&2
113
+ exit 1
114
+ fi
115
+
116
+ # `sf devops work-item list` returns .result.workItems[]. Filter to the approved
117
+ # work items in the QA stage.
118
+ WI_IDS=$(printf '%s' "$WI_LIST_JSON" \
119
+ | jq -r --arg s "$QA_STAGE_ID" '.result.workItems[] | select(.stageId == $s and .status == "Approved") | .id')
120
+
121
+ if [ -z "$WI_IDS" ]; then
122
+ echo "No approved work items in QA stage $QA_STAGE_ID — STOP. Do not promote." >&2
123
+ exit 1
124
+ fi
125
+
126
+ # Validate all approved work items against the TARGET stage in one call (repeat
127
+ # --work-item-id per item). A non-zero exit means validation failed — STOP.
128
+ VALIDATE_ARGS=()
129
+ for WI_ID in $WI_IDS; do VALIDATE_ARGS+=(--work-item-id "$WI_ID"); done
130
+ if ! sf devops promotion validate "${VALIDATE_ARGS[@]}" \
131
+ --target-stage-id "$PROD_STAGE_ID" --target-org myorg --json; then
132
+ echo "Promotion validation failed — STOP. Do not promote the stage." >&2
133
+ exit 1
134
+ fi
135
+
136
+ # 2. All QA work items validated — promote the whole source stage to the
137
+ # target stage (async). Production deploys with Apex should run tests.
138
+ PROMOTION_ID=$(sf devops promote \
139
+ --stage-id "$QA_STAGE_ID" \
140
+ --target-stage-id "$PROD_STAGE_ID" \
141
+ --test-level RunLocalTests \
142
+ --skip-validation \
143
+ --target-org myorg \
144
+ --json | jq -r '.result.promotionId // .result.asyncOperationId')
145
+
146
+ echo "Stage promotion initiated. Promotion ID: $PROMOTION_ID"
147
+
148
+ # 3. Hand off the promotion ID for status polling. Finalize with
149
+ # `sf devops promotion complete --target-stage-id "$PROD_STAGE_ID" --target-org myorg --json`
150
+ # ONLY after the async deploy has confirmed completion — do not run it here.
151
+ ```
152
+
153
+ **Report:** "QA → Production stage promotion initiated after validating all approved QA work items. Promotion ID: `<id>`. Poll this ID; run `sf devops promotion complete` only after the deploy reports success."
154
+
155
+ ---
156
+
157
+ ## Example 4 — Validate-first gate blocks promotion
158
+
159
+ **User prompt:** "Promote work item 1fkxx0000000200AAA."
160
+
161
+ ```bash
162
+ sf devops promotion validate \
163
+ --work-item-id 1fkxx0000000200AAA \
164
+ --target-stage-id 1QVxx0000000QA0AAA \
165
+ --target-org myorg --json
166
+ ```
167
+
168
+ Response (non-zero exit indicates the work item cannot be promoted):
169
+ ```json
170
+ {
171
+ "status": 1,
172
+ "result": {
173
+ "success": false,
174
+ "errorType": "VCS_ERROR",
175
+ "errorDetails": "No pull request exists for the work item on the source branch."
176
+ },
177
+ "warnings": []
178
+ }
179
+ ```
180
+
181
+ **Action:** STOP. Do NOT prepare/combine/promote/complete. Report the exact blocking issue from `.result.errorType` / `.result.errorDetails` — here a `VCS_ERROR`: no pull request exists for the work item on the source branch. Remediate the reported cause (create/associate the pull request for the work item), then re-validate only after it is resolved.
182
+
183
+ **Report:** "Promotion blocked — validation failed (`VCS_ERROR`): no pull request exists for the work item on the source branch. Create/associate the PR, then re-validate and retry."
184
+
185
+ ---
186
+
187
+ ## Example 5 — Idempotent retry in CI
188
+
189
+ **Scenario:** A CI job re-runs after a transient network failure mid-promotion.
190
+
191
+ ```bash
192
+ # Re-running validate + prepare is safe — prepare is a no-op if already prepared
193
+ sf devops promotion validate \
194
+ --work-item-id 1fkxx0000000300AAA \
195
+ --target-stage-id 1QVxx0000000QA0AAA \
196
+ --target-org myorg --json
197
+ sf devops work-item prepare --work-item-id 1fkxx0000000300AAA --target-stage-id 1QVxx0000000QA0AAA --target-org myorg --json
198
+ # → treat an already-prepared work item as success
199
+
200
+ # Promote again — capture the promotion ID (--skip-validation: validated and
201
+ # prepared above)
202
+ PROMOTION_ID=$(sf devops promote \
203
+ --work-item-id 1fkxx0000000300AAA \
204
+ --target-stage-id 1QVxx0000000QA0AAA \
205
+ --skip-validation \
206
+ --target-org myorg \
207
+ --json | jq -r '.result.promotionId // .result.asyncOperationId')
208
+
209
+ echo "Promotion ID: $PROMOTION_ID"
210
+ ```
211
+
212
+ **Key point:** validate and prepare are idempotent — retries do not create duplicate state or double-prepare.