@salesforce/afv-skills 1.37.0 → 1.38.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-generate/README.md +20 -3
- package/skills/agentforce-generate/SKILL.md +253 -440
- package/skills/agentforce-generate/assets/agent-spec-template.md +6 -2
- package/skills/agentforce-generate/assets/agents/order-service.agent +16 -12
- package/skills/agentforce-generate/assets/agents/production-faq.agent +4 -4
- package/skills/agentforce-generate/assets/agents/router-first.agent +5 -5
- package/skills/agentforce-generate/assets/agents/template-single-subagent.agent +4 -4
- package/skills/agentforce-generate/assets/agents/verification-gate.agent +8 -6
- package/skills/agentforce-generate/assets/agents/voice-knowledge-grounded.agent +9 -9
- package/skills/agentforce-generate/assets/agents/voice-service-agent.agent +7 -7
- package/skills/agentforce-generate/assets/patterns/README.md +3 -3
- package/skills/agentforce-generate/assets/patterns/action-callbacks.agent +5 -5
- package/skills/agentforce-generate/assets/patterns/advanced-input-bindings.agent +6 -8
- package/skills/agentforce-generate/assets/patterns/bidirectional-routing.agent +11 -13
- package/skills/agentforce-generate/assets/patterns/critical-input-collection.agent +11 -16
- package/skills/agentforce-generate/assets/patterns/lifecycle-events.agent +2 -3
- package/skills/agentforce-generate/assets/patterns/llm-controlled-actions.agent +6 -7
- package/skills/agentforce-generate/assets/patterns/open-gate-routing.agent +3 -3
- package/skills/agentforce-generate/assets/patterns/prompt-template-action.agent +14 -19
- package/skills/agentforce-generate/assets/patterns/system-instruction-overrides.agent +11 -20
- package/skills/agentforce-generate/references/actions-reference.md +2 -2
- package/skills/agentforce-generate/references/agent-audit-and-repair.md +135 -0
- package/skills/agentforce-generate/references/agent-audit-candidate-verification.md +160 -0
- package/skills/agentforce-generate/references/agent-audit-diagnostic-catalog.md +156 -0
- package/skills/agentforce-generate/references/agent-audit-diagnostics-actions-state.md +176 -0
- package/skills/agentforce-generate/references/agent-audit-diagnostics-architecture-evaluation.md +68 -0
- package/skills/agentforce-generate/references/agent-audit-diagnostics-instructions-routing.md +283 -0
- package/skills/agentforce-generate/references/agent-audit-evaluation-loop.md +191 -0
- package/skills/agentforce-generate/references/agent-audit-repair-report.md +143 -0
- package/skills/agentforce-generate/references/agent-audit-scope-path-review.md +180 -0
- package/skills/agentforce-generate/references/agent-design-and-spec-creation.md +105 -59
- package/skills/agentforce-generate/references/agent-script-core-language.md +144 -61
- package/skills/agentforce-generate/references/agent-subagent-map-diagrams.md +33 -23
- package/skills/agentforce-generate/references/agent-validation-and-debugging.md +37 -11
- package/skills/agentforce-generate/references/agentscript-toolchain.md +112 -0
- package/skills/agentforce-generate/references/architecture-patterns.md +81 -18
- package/skills/agentforce-generate/references/common-control-flow-pitfalls.md +255 -0
- package/skills/agentforce-generate/references/control-flow-actions-sequencing.md +198 -0
- package/skills/agentforce-generate/references/control-flow-lifecycle-side-effects.md +87 -0
- package/skills/agentforce-generate/references/examples.md +22 -22
- package/skills/agentforce-generate/references/instruction-resolution.md +123 -83
- package/skills/agentforce-generate/references/known-issues.md +1 -2
- package/skills/agentforce-generate/references/optimization-pattern-1-data-flow.md +4 -0
- package/skills/agentforce-generate/references/optimization-pattern-2-deterministic-logic.md +33 -0
- package/skills/agentforce-generate/references/optimization-pattern-3-reference-syntax.md +32 -3
- package/skills/agentforce-generate/references/optimization-pattern-4-escalation.md +2 -2
- package/skills/agentforce-generate/references/patterns-by-requirement.md +3 -1
- package/skills/agentforce-generate/references/posture-and-determinism.md +103 -22
- package/skills/agentforce-generate/references/reference-map.md +19 -3
- package/skills/agentforce-generate/references/scoring-rubric.md +1 -1
- package/skills/agentforce-generate/references/voice-latency-heuristics.md +4 -0
- package/skills/agentforce-generate/references/voice-modality-reference.md +4 -4
- package/skills/agentforce-generate/references/zen-of-agentscript.md +139 -23
- package/skills/agentforce-generate/scripts/agentscript-sdk-loader.mjs +133 -0
- package/skills/agentforce-generate/scripts/index-agent.mjs +141 -0
- package/skills/agentforce-generate/scripts/setup-agentscript-sdk.mjs +337 -0
- package/skills/automation-sandbox-post-copy-config-generate/SKILL.md +1 -1
- package/skills/automation-sandbox-post-copy-configure/SKILL.md +433 -0
- package/skills/automation-sandbox-post-copy-configure/assets/api_request_templates.json +89 -0
- package/skills/automation-sandbox-post-copy-configure/examples/sample_config_input.json +40 -0
- package/skills/automation-sandbox-post-copy-configure/examples/sample_execution_summary.md +79 -0
- package/skills/automation-sandbox-post-copy-configure/references/api_endpoints.md +273 -0
- package/skills/automation-sandbox-post-copy-configure/references/authentication.md +94 -0
- package/skills/automation-sandbox-post-copy-configure/references/execution_phasing.md +93 -0
- package/skills/automation-sandbox-post-copy-configure/references/rules_gotchas.md +35 -0
- package/skills/automation-sandbox-post-copy-configure/scripts/classify-patch-result.mjs +88 -0
- package/skills/automation-sandbox-post-copy-configure/scripts/map-metadata-key.mjs +98 -0
- package/skills/automation-sandbox-post-copy-configure/scripts/plan-phases.mjs +98 -0
- package/skills/automation-sandbox-post-copy-configure/scripts/resolve-target-org.mjs +56 -0
- package/skills/design-systems-slds-validate/SKILL.md +14 -13
- package/skills/dx-code-analyzer-custom-rule-create/examples/xpath-examples.md +1 -1
- package/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-security.md +1 -1
- package/skills/dx-org-devhub-configure/SKILL.md +268 -0
- package/skills/dx-org-devhub-configure/examples/status-output.md +39 -0
- package/skills/dx-org-devhub-configure/scripts/devhub.sh +650 -0
- package/skills/dx-org-devhub-configure/scripts/test-devhub.sh +116 -0
- package/skills/dx-org-manage/SKILL.md +135 -42
- package/skills/dx-org-manage/assets/derive-alias.sh +95 -0
- package/skills/dx-org-manage/assets/scratch-def.seed.json +6 -0
- package/skills/dx-org-manage/examples/README.md +1 -1
- package/skills/dx-org-manage/examples/scratch-orgs/delete_output.json +8 -0
- package/skills/dx-org-manage/examples/scratch-orgs/display_output.json +23 -0
- package/skills/dx-org-manage/examples/scratch-orgs/list_output.json +58 -0
- package/skills/dx-org-manage/examples/scratch-orgs/resume_output.json +38 -0
- package/skills/dx-org-manage/examples/scratch-orgs/success_definition_file.json +1 -1
- package/skills/dx-org-manage/examples/scratch-orgs/success_edition.json +1 -1
- package/skills/dx-org-manage/examples/scratch-orgs/success_shape.json +41 -0
- package/skills/dx-org-manage/examples/scratch-orgs/success_snapshot.json +1 -1
- package/skills/dx-org-manage/examples/snapshots/error_output.json +3 -3
- package/skills/dx-org-manage/references/creating-scratch-org.md +2 -2
- package/skills/dx-org-manage/references/creating-snapshot.md +1 -2
- package/skills/dx-org-manage/references/definition_file_options.md +24 -0
- package/skills/dx-org-manage/references/edition_types.md +10 -8
- package/skills/dx-org-manage/references/opening-org.md +11 -12
- package/skills/dx-org-manage/references/scratch-org-create.md +303 -0
- package/skills/dx-org-manage/references/scratch-org-operations.md +135 -0
- package/skills/experience-aura-lwc-migrate/SKILL.md +120 -0
- package/skills/experience-aura-lwc-migrate/references/aura-api-expert.md +170 -0
- package/skills/experience-aura-lwc-migrate/references/aura-data-expert.md +172 -0
- package/skills/experience-aura-lwc-migrate/references/aura-migration-guidelines.md +299 -0
- package/skills/experience-aura-lwc-migrate/references/aura-prd-framework.md +79 -0
- package/skills/experience-aura-lwc-migrate/references/aura-redundant-code-expert.md +24 -0
- package/skills/experience-aura-lwc-migrate/references/aura-reference-expert.md +140 -0
- package/skills/experience-aura-lwc-migrate/references/aura-resolver-expert.md +115 -0
- package/skills/experience-aura-lwc-migrate/references/aura-slots-expert.md +67 -0
- package/skills/experience-aura-lwc-migrate/references/aura-style-expert.md +62 -0
- package/skills/experience-aura-lwc-migrate/references/aura-to-lwc-completeness-checklist.md +188 -0
- package/skills/experience-aura-lwc-migrate/references/aura-values-expert.md +67 -0
- package/skills/experience-content-media-search/SKILL.md +17 -12
- package/skills/experience-content-media-stock-image-search/SKILL.md +192 -0
- package/skills/experience-content-media-stock-image-search/scripts/download-stock-image.py +102 -0
- package/skills/experience-lds-best-practices-apply/SKILL.md +245 -0
- package/skills/experience-lds-best-practices-apply/references/adapter-apis.md +1640 -0
- package/skills/experience-lds-best-practices-apply/references/lds-data-consistency.md +126 -0
- package/skills/experience-lds-best-practices-apply/references/lds-expert.md +429 -0
- package/skills/experience-lds-best-practices-apply/references/lds-referential-integrity.md +322 -0
- package/skills/experience-lds-best-practices-apply/references/wire-adapter-types.md +1511 -0
- package/skills/experience-lds-graphql-generate/SKILL.md +222 -0
- package/skills/experience-lds-graphql-generate/references/generation-guide.md +236 -0
- package/skills/experience-lds-graphql-generate/references/generation-mutation.md +277 -0
- package/skills/experience-lds-graphql-generate/references/generation-query.md +237 -0
- package/skills/experience-lds-graphql-generate/scripts/fetch-lds-graphql-schema.sh +230 -0
- package/skills/experience-lds-graphql-generate/scripts/test-lds-graphql-query.sh +128 -0
- package/skills/experience-lwc-accessibility-validate/SKILL.md +112 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-1-1-non-text-content.md +88 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-3-1-i-lists.md +52 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-3-1-ii-tables.md +106 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-3-1-iii-form-labels.md +78 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-3-1-iv-regions.md +26 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-3-1-v-groups.md +66 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-3-5-identify-input.md +70 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-4-3-contrast.md +115 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-1-1-keyboard.md +47 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-4-4-link-purpose.md +39 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-4-6-headings-labels.md +50 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-5-1-pointer-gestures.md +54 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-5-2-pointer-cancellation.md +49 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-5-3-label-in-name.md +77 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-5-7-dragging-movement.md +45 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-3-2-1-on-focus.md +55 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-3-2-2-on-input.md +51 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-3-3-1-error-identification.md +84 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-3-3-2-labels-instructions.md +50 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-3-3-3-error-suggestion.md +64 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-4-1-2-i-name.md +105 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-4-1-2-ii-role.md +99 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-4-1-2-iii-value.md +97 -0
- package/skills/experience-lwc-accessibility-validate/references/vision/sc-1-1-1-non-text-content.md +83 -0
- package/skills/experience-lwc-accessibility-validate/references/vision/sc-1-4-1-use-of-color.md +62 -0
- package/skills/experience-lwc-accessibility-validate/references/vision/sc-1-4-10-resize-reflow.md +18 -0
- package/skills/experience-lwc-accessibility-validate/references/vision/sc-1-4-11-non-text-contrast.md +43 -0
- package/skills/experience-lwc-accessibility-validate/references/vision/sc-1-4-3-contrast.md +25 -0
- package/skills/experience-lwc-accessibility-validate/scripts/contrast-ratio.py +153 -0
- package/skills/experience-lwc-design-generate/SKILL.md +261 -0
- package/skills/experience-lwc-design-generate/references/figma-to-prd-blueprint.md +66 -0
- package/skills/experience-lwc-design-generate/references/prd-analysis-template.md +17 -0
- package/skills/experience-lwc-design-generate/scripts/check-component-name.sh +75 -0
- package/skills/experience-lwc-design-generate/scripts/detect-project-tools.sh +97 -0
- package/skills/experience-lwc-runtime-observe/SKILL.md +244 -0
- package/skills/experience-lwc-runtime-observe/examples/component-preview-and-dom.md +41 -0
- package/skills/experience-lwc-runtime-observe/scripts/extract-dom.sh +79 -0
- package/skills/experience-lwc-runtime-observe/scripts/open-frontdoor.sh +46 -0
- package/skills/experience-lwc-runtime-observe/scripts/verify-toolchain.sh +48 -0
- package/skills/experience-lwc-security-validate/SKILL.md +151 -0
- package/skills/experience-lwc-security-validate/examples/review-report.md +6 -0
- package/skills/experience-lwc-security-validate/examples/score-report.sarif.json +32 -0
- package/skills/experience-lwc-security-validate/references/lws-security-expert.md +986 -0
- package/skills/experience-lwc-security-validate/references/security-analysis.md +611 -0
- package/skills/experience-lwc-security-validate/scripts/check-lwc-import.sh +166 -0
- package/skills/experience-lwc-security-validate/scripts/validate-sarif.sh +131 -0
- package/skills/experience-ui-bundle-2gp-deploy/SKILL.md +454 -0
- package/skills/experience-ui-bundle-2gp-deploy/assets/CustomApplication.app-meta.xml +12 -0
- package/skills/experience-ui-bundle-2gp-deploy/assets/PermissionSet.permissionset-meta.xml +9 -0
- package/skills/experience-ui-bundle-2gp-deploy/scripts/find-bundle-package-dir.sh +53 -0
- package/skills/experience-ui-bundle-agentforce-client-generate/SKILL.md +104 -26
- package/skills/experience-ui-bundle-agentforce-client-generate/references/constraints.md +35 -24
- package/skills/experience-ui-bundle-agentforce-client-generate/references/examples.md +92 -1
- package/skills/experience-ui-bundle-agentforce-client-generate/references/style-tokens.md +2 -0
- package/skills/experience-ui-bundle-agentforce-client-generate/references/troubleshooting.md +14 -1
- package/skills/experience-ui-bundle-agentforce-client-generate/scripts/detect-framework.sh +67 -0
- package/skills/experience-ui-bundle-deploy/SKILL.md +83 -14
- package/skills/experience-ui-bundle-deploy/assets/Communities.settings-meta.xml +19 -0
- package/skills/experience-ui-bundle-deploy/assets/org-setup.config.template.json +5 -0
- package/skills/experience-ui-bundle-deploy/assets/social-login-auth-providers.apex +158 -0
- package/skills/experience-ui-bundle-deploy/references/config-scaffold.md +13 -1
- package/skills/experience-ui-bundle-deploy/references/social-login.md +179 -0
- package/skills/experience-ui-bundle-frontend-generate/SKILL.md +14 -0
- package/skills/experience-ui-bundle-mfa-configure/SKILL.md +6 -5
- package/skills/experience-ui-bundle-mfa-configure/references/social-login.md +15 -7
- package/skills/experience-ui-bundle-salesforce-data-access/SKILL.md +41 -5
- package/skills/experience-ui-bundle-salesforce-data-access/references/caching.md +10 -22
- package/skills/experience-ui-bundle-salesforce-data-access/references/graphql-hand-authoring.md +4 -19
- package/skills/experience-ui-bundle-salesforce-data-access/references/migration.md +5 -0
- package/skills/experience-ui-bundle-salesforce-data-access/references/sdk-api.md +33 -150
- package/skills/mobile-platform-native-capabilities-integrate/references/nfc.md +35 -0
- package/skills/platform-apex-generate/SKILL.md +8 -7
- package/skills/platform-apex-test-generate/SKILL.md +3 -1
- package/skills/platform-apex-test-run/SKILL.md +9 -8
- package/skills/platform-lightning-type-widget-coordinate/SKILL.md +1 -1
- package/skills/platform-lightning-type-widget-coordinate/examples/existing-lightning-type-with-widget-prompt.md +1 -1
- package/skills/platform-lightning-type-widget-coordinate/examples/new-lightning-type-with-widget-prompt.md +1 -1
- package/skills/platform-lightning-type-widget-coordinate/references/validation-gates.md +3 -3
- package/skills/platform-mcp-tool-widget-coordinate/SKILL.md +43 -67
- package/skills/platform-mcp-tool-widget-coordinate/examples/action-name-source-prompt.md +1 -2
- package/skills/platform-mcp-tool-widget-coordinate/examples/apex-invocable-source-prompt.md +2 -3
- package/skills/platform-mcp-tool-widget-coordinate/examples/nested-object-list-source-prompt.md +163 -0
- package/skills/platform-mcp-tool-widget-coordinate/examples/nested-object-single-source-prompt.md +198 -0
- package/skills/platform-mcp-tool-widget-coordinate/examples/pasted-tool-output-prompt.md +0 -1
- package/skills/platform-mcp-tool-widget-coordinate/references/build-plan-format.md +17 -11
- package/skills/platform-mcp-tool-widget-coordinate/references/mcp-tool-output-discovery.md +48 -15
- package/skills/platform-mcp-tool-widget-coordinate/references/two-clt-modeling.md +73 -10
- package/skills/platform-mcp-tool-widget-coordinate/references/validation-gates.md +48 -8
- package/skills/platform-policy-rule-generate/SKILL.md +22 -12
- package/skills/platform-policy-rule-generate/references/deploy-errors.md +1 -1
- package/skills/platform-policy-rule-generate/references/policy-schema-full.md +8 -29
- package/skills/platform-policy-rule-generate/references/templates-advanced.md +1 -1
- package/skills/platform-sharing-owd-configure/SKILL.md +20 -8
- package/skills/platform-sharing-owd-configure/references/access_levels.md +14 -1
- package/skills/platform-sharing-rules-generate/SKILL.md +67 -35
- package/skills/platform-sharing-rules-generate/examples/create-cases.md +16 -17
- package/skills/platform-sharing-rules-generate/examples/delete-cases.md +34 -79
- package/skills/platform-sharing-rules-generate/examples/edit-cases.md +13 -26
- package/skills/platform-sharing-rules-generate/scripts/count-remaining-rules.sh +33 -0
- package/skills/platform-widget-generate/SKILL.md +3 -5
- package/skills/platform-widget-generate/examples/conditional.json +18 -13
- package/skills/platform-widget-generate/examples/list-with-foreach.json +2 -2
- package/skills/platform-widget-generate/examples/single-object.json +2 -2
- package/skills/platform-widget-generate/references/schema-from-lightning-type.md +27 -6
- package/skills/platform-widget-generate/references/widget-bundle-layout.md +4 -3
- package/skills/service-itsm-agentic-setup-cmdb-access-assign/SKILL.md +287 -0
- package/skills/service-itsm-agentic-setup-cmdb-access-assign/references/mcp-invocation.md +260 -0
- package/skills/service-itsm-agentic-setup-cmdb-bundle-deploy/SKILL.md +252 -0
- package/skills/service-itsm-agentic-setup-cmdb-bundle-deploy/references/mcp-invocation.md +204 -0
- package/skills/service-itsm-agentic-setup-cmdb-configure/SKILL.md +259 -0
- package/skills/service-itsm-agentic-setup-cmdb-configure/references/mcp-invocation.md +188 -0
- package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +197 -0
- package/skills/service-itsm-agentic-setup-cmdb-coordinate/examples/output-templates.md +77 -0
- package/skills/service-itsm-agentic-setup-cmdb-discovery-configure/SKILL.md +316 -0
- package/skills/service-itsm-agentic-setup-cmdb-discovery-configure/references/mcp-invocation.md +221 -0
- package/skills/service-itsm-incident-priority-configure/SKILL.md +168 -0
- package/skills/service-itsm-incident-priority-configure/examples/matrix-operations.md +200 -0
- package/skills/service-itsm-incident-priority-configure/examples/render-matrix.md +54 -0
- package/skills/service-itsm-incident-priority-configure/examples/seed-full-matrix.md +52 -0
- package/skills/service-itsm-incident-priority-configure/references/sf-cli-invocation.md +264 -0
- package/skills/platform-mcp-tool-widget-coordinate/examples/nested-object-source-prompt.md +0 -191
- package/skills/platform-policy-rule-generate/references/fixtures-index.md +0 -29
|
@@ -0,0 +1,650 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# devhub.sh — Enable Dev Hub and view scratch org allocation for a Salesforce
|
|
4
|
+
# org, via the Salesforce CLI (sf).
|
|
5
|
+
#
|
|
6
|
+
# Dev Hub is the org feature that lets you create and manage scratch orgs and
|
|
7
|
+
# second-generation (2GP)/unlocked packages. This script reports whether Dev Hub
|
|
8
|
+
# is enabled, ENABLES it (or configures its sub-preferences) via a Metadata API
|
|
9
|
+
# deploy, shows the org's scratch org ALLOCATION (Active/Daily limits and how
|
|
10
|
+
# many remain), and lists the active scratch orgs created from the Dev Hub.
|
|
11
|
+
#
|
|
12
|
+
# How enablement works: the Dev Hub master switch is the deployable metadata
|
|
13
|
+
# field DevHubSettings.enableScratchOrgManagementPref (there is NO "enableDevHub"
|
|
14
|
+
# field, and no dedicated `sf` command). Deploying it true is exactly what the
|
|
15
|
+
# Setup toggle does. This script builds a DevHub.settings-meta.xml and deploys
|
|
16
|
+
# it. Enabling requires a user with ModifyAllData or ModifyMetadata (System
|
|
17
|
+
# Administrator has these); the org must NOT have a registered namespace and must
|
|
18
|
+
# NOT be a sandbox; and once on, Dev Hub CANNOT be turned off.
|
|
19
|
+
#
|
|
20
|
+
# How enablement is detected: the standard object ScratchOrgInfo is provisioned
|
|
21
|
+
# and becomes queryable only when Dev Hub is enabled. A successful "SELECT
|
|
22
|
+
# COUNT() FROM ScratchOrgInfo" means Dev Hub is ON; an INVALID_TYPE error means
|
|
23
|
+
# it is OFF. (Note: `sf org list limits` reports ActiveScratchOrgs/
|
|
24
|
+
# DailyScratchOrgs rows even on non-Dev-Hub orgs, so limits alone are NOT a
|
|
25
|
+
# reliable enablement test.)
|
|
26
|
+
#
|
|
27
|
+
# Usage:
|
|
28
|
+
# devhub.sh [org] # status: is Dev Hub on? + allocation
|
|
29
|
+
# devhub.sh [org] --allocation # scratch org allocation only
|
|
30
|
+
# devhub.sh [org] --list-scratch # list this Dev Hub's active scratch orgs
|
|
31
|
+
# devhub.sh [org] --enable # validate enabling Dev Hub (dry run)
|
|
32
|
+
# devhub.sh [org] --enable --apply # actually enable Dev Hub (irreversible)
|
|
33
|
+
# devhub.sh [org] --enable --packaging --apply # enable + turn on 2GP
|
|
34
|
+
# devhub.sh [org] --configure --snapshots --apply # set a sub-pref (Dev Hub already on)
|
|
35
|
+
# devhub.sh [org] --json # machine-readable status
|
|
36
|
+
# devhub.sh --fail-if-disabled # exit 3 if Dev Hub is not enabled (CI gate)
|
|
37
|
+
# devhub.sh [alias] --instance-url https://my-domain.my.salesforce.com --enable --apply
|
|
38
|
+
# # log in to that instance, then enable Dev Hub
|
|
39
|
+
# devhub.sh https://my-domain.my.salesforce.com # bare URL: log in to that instance
|
|
40
|
+
# devhub.sh myalias --login # just authenticate an org via the browser
|
|
41
|
+
#
|
|
42
|
+
# "org" is an alias or username. If omitted, the default target-org is used,
|
|
43
|
+
# and if that is unset, the default target-dev-hub. With --login/--instance-url,
|
|
44
|
+
# a supplied positional is used as the CLI alias for the org being logged in to.
|
|
45
|
+
# A bare positional that looks like a URL (contains "://") is treated as an
|
|
46
|
+
# --instance-url to log in to, not as an org alias.
|
|
47
|
+
#
|
|
48
|
+
# Options:
|
|
49
|
+
# --allocation, -A Show only the scratch org allocation (Active/Daily).
|
|
50
|
+
# --list-scratch, -l List active scratch orgs created from this Dev Hub.
|
|
51
|
+
# --enable, -e Enable Dev Hub (deploys enableScratchOrgManagementPref
|
|
52
|
+
# =true). Defaults to a validate-only dry run; add
|
|
53
|
+
# --apply to actually enable. May be combined with the
|
|
54
|
+
# sub-pref flags below to enable and configure at once.
|
|
55
|
+
# --configure, -c Configure Dev Hub sub-preferences without (re)enabling
|
|
56
|
+
# the master switch. Pair with one or more pref flags.
|
|
57
|
+
# Defaults to a dry run; add --apply to deploy.
|
|
58
|
+
# --packaging enablePackaging2=true (Unlocked + 2GP packages)
|
|
59
|
+
# --snapshots enableScratchOrgSnapshotPref=true
|
|
60
|
+
# --shape enableShapeExportPref=true
|
|
61
|
+
# --scratch-management enableScratchOrgManagementPref=true (the Dev Hub switch)
|
|
62
|
+
# --pref KEY=VALUE Any DevHubSettings sub-pref (KEY must start with
|
|
63
|
+
# "enable"; VALUE is true|false). Repeatable.
|
|
64
|
+
# --apply Actually deploy (default for --enable/--configure is a
|
|
65
|
+
# validate-only dry run).
|
|
66
|
+
# --login Authenticate an org first via `sf org login web`
|
|
67
|
+
# (opens a browser). Runs before the requested action.
|
|
68
|
+
# --instance-url URL Log in to a Salesforce instance (My Domain, sandbox,
|
|
69
|
+
# or pre-release/scratch instance) with
|
|
70
|
+
# `sf org login web --instance-url URL`. Implies --login.
|
|
71
|
+
# --json Emit machine-readable JSON.
|
|
72
|
+
# --fail-if-disabled Exit 3 if Dev Hub is not enabled on the target org.
|
|
73
|
+
# --help, -h Show this help.
|
|
74
|
+
#
|
|
75
|
+
# Exit codes:
|
|
76
|
+
# 0 success
|
|
77
|
+
# 1 the org could not be queried, or a deploy failed (auth/connection/deploy)
|
|
78
|
+
# 2 bad usage / missing dependency (sf or jq)
|
|
79
|
+
# 3 Dev Hub is not enabled (only when --fail-if-disabled is set)
|
|
80
|
+
|
|
81
|
+
set -uo pipefail
|
|
82
|
+
|
|
83
|
+
die() { echo "Error: $*" >&2; exit 2; }
|
|
84
|
+
|
|
85
|
+
# The skill must be invoked by ABSOLUTE path (see SKILL.md): a relative path like
|
|
86
|
+
# ./scripts/devhub.sh resolves against the caller's CWD and can run the wrong
|
|
87
|
+
# file. Enforce it here so the guarantee is deterministic and not left to the
|
|
88
|
+
# model. (A leading "/" is the portable test for an absolute path.)
|
|
89
|
+
case "$0" in
|
|
90
|
+
/*) : ;;
|
|
91
|
+
*) die "Run this script by its absolute path (got: '$0'). Example: bash \"/abs/path/to/skills/dx-org-devhub-configure/scripts/devhub.sh\"" ;;
|
|
92
|
+
esac
|
|
93
|
+
|
|
94
|
+
command -v sf >/dev/null 2>&1 || die "Salesforce CLI ('sf') not found on PATH."
|
|
95
|
+
command -v jq >/dev/null 2>&1 || die "'jq' not found on PATH."
|
|
96
|
+
|
|
97
|
+
# Keep CLI update chatter out of captured JSON/stdout.
|
|
98
|
+
export SF_AUTOUPDATE_DISABLE=true
|
|
99
|
+
|
|
100
|
+
# --- constants -----------------------------------------------------------
|
|
101
|
+
SETTINGS_API_VERSION="47.0" # DevHubSettings requires API >= 47.0
|
|
102
|
+
DEVHUB_SWITCH="enableScratchOrgManagementPref"
|
|
103
|
+
|
|
104
|
+
# --- option state --------------------------------------------------------
|
|
105
|
+
TARGET="" # org alias/username (positional or resolved default)
|
|
106
|
+
TARGET_EXPLICIT=0 # 1 when the caller supplied an org alias/username
|
|
107
|
+
MODE="status" # status | allocation | list | deploy
|
|
108
|
+
MODE_EXPLICIT=0 # 1 when the caller selected an operation
|
|
109
|
+
ENABLING=0 # 1 when --enable was passed (seeds the master switch)
|
|
110
|
+
OUTPUT="human" # human | json
|
|
111
|
+
APPLY=0 # deploy: 0 = dry run (validate only), 1 = real deploy
|
|
112
|
+
FAIL_IF_DISABLED=0
|
|
113
|
+
PREFS=() # requested DevHubSettings prefs (KEY=VALUE)
|
|
114
|
+
DO_LOGIN=0 # 1 when --login or --instance-url requests a browser login
|
|
115
|
+
LOGIN_INSTANCE_URL="" # instance URL for `sf org login web --instance-url`
|
|
116
|
+
|
|
117
|
+
# --- run state -----------------------------------------------------------
|
|
118
|
+
DEVHUB_STATE="" # enabled | disabled | auth_error
|
|
119
|
+
DEVHUB_ERRNAME="" # error .name when auth_error
|
|
120
|
+
DEVHUB_ERRMSG=""
|
|
121
|
+
SCRATCH_COUNT="" # ScratchOrgInfo count when enabled
|
|
122
|
+
INSTANCE_URL="" # resolved org instance URL (for the Setup deep link)
|
|
123
|
+
|
|
124
|
+
usage() {
|
|
125
|
+
sed -n '2,/^set -uo/p' "$0" | sed '/^set -uo/d; s/^# \{0,1\}//; s/^#//'
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# Set MODE, rejecting a second conflicting mode selection.
|
|
129
|
+
set_mode() {
|
|
130
|
+
if [ "$MODE" != "status" ] && [ "$MODE" != "$1" ]; then
|
|
131
|
+
die "Choose only one of --allocation, --list-scratch, --enable/--configure."
|
|
132
|
+
fi
|
|
133
|
+
MODE="$1"
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# True if PREFS already contains a KEY (any value).
|
|
137
|
+
has_pref_key() {
|
|
138
|
+
local p
|
|
139
|
+
for p in "${PREFS[@]:-}"; do
|
|
140
|
+
[ -n "$p" ] || continue
|
|
141
|
+
[ "${p%%=*}" = "$1" ] && return 0
|
|
142
|
+
done
|
|
143
|
+
return 1
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# Register a pref for deploy, validating shape and giving actionable guidance
|
|
147
|
+
# for the common wrong field name. De-dupes on key (later value wins).
|
|
148
|
+
add_pref() {
|
|
149
|
+
local kv="$1" key val existing kept
|
|
150
|
+
key="${kv%%=*}"; val="${kv#*=}"
|
|
151
|
+
case "$key" in
|
|
152
|
+
enableDevHub)
|
|
153
|
+
die "There is no 'enableDevHub' field. Use --enable (which sets $DEVHUB_SWITCH=true)." ;;
|
|
154
|
+
"$DEVHUB_SWITCH")
|
|
155
|
+
[ "$val" = "true" ] || die "$DEVHUB_SWITCH cannot be set to false because Dev Hub enablement is irreversible."
|
|
156
|
+
ENABLING=1 ;;
|
|
157
|
+
enable*) : ;;
|
|
158
|
+
*) die "--pref key must be a DevHubSettings field starting with 'enable' (got: '$key')." ;;
|
|
159
|
+
esac
|
|
160
|
+
case "$val" in
|
|
161
|
+
true|false) : ;;
|
|
162
|
+
*) die "--pref value must be true or false (got: '$key=$val')." ;;
|
|
163
|
+
esac
|
|
164
|
+
kept=()
|
|
165
|
+
for existing in "${PREFS[@]:-}"; do
|
|
166
|
+
[ -n "$existing" ] || continue
|
|
167
|
+
[ "${existing%%=*}" = "$key" ] && continue
|
|
168
|
+
kept+=("$existing")
|
|
169
|
+
done
|
|
170
|
+
kept+=("$key=$val")
|
|
171
|
+
PREFS=("${kept[@]}")
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
# --- argument parsing ----------------------------------------------------
|
|
175
|
+
while [ $# -gt 0 ]; do
|
|
176
|
+
case "$1" in
|
|
177
|
+
--allocation|-A) MODE_EXPLICIT=1; set_mode allocation; shift ;;
|
|
178
|
+
--list-scratch|-l) MODE_EXPLICIT=1; set_mode list; shift ;;
|
|
179
|
+
--enable|-e) MODE_EXPLICIT=1; ENABLING=1; set_mode deploy; shift ;;
|
|
180
|
+
--configure|-c) MODE_EXPLICIT=1; set_mode deploy; shift ;;
|
|
181
|
+
--packaging) MODE_EXPLICIT=1; add_pref "enablePackaging2=true"; set_mode deploy; shift ;;
|
|
182
|
+
--snapshots) MODE_EXPLICIT=1; add_pref "enableScratchOrgSnapshotPref=true"; set_mode deploy; shift ;;
|
|
183
|
+
--shape) MODE_EXPLICIT=1; add_pref "enableShapeExportPref=true"; set_mode deploy; shift ;;
|
|
184
|
+
--scratch-management) MODE_EXPLICIT=1; add_pref "$DEVHUB_SWITCH=true"; set_mode deploy; shift ;;
|
|
185
|
+
--pref)
|
|
186
|
+
shift
|
|
187
|
+
[ $# -gt 0 ] || die "--pref requires a KEY=VALUE argument (e.g. --pref enablePackaging2=true)."
|
|
188
|
+
case "$1" in *=*) : ;; *) die "--pref expects KEY=VALUE (got: '$1')." ;; esac
|
|
189
|
+
MODE_EXPLICIT=1; add_pref "$1"; set_mode deploy; shift ;;
|
|
190
|
+
--pref=*)
|
|
191
|
+
kv="${1#*=}"
|
|
192
|
+
case "$kv" in *=*) : ;; *) die "--pref expects KEY=VALUE (got: '$kv')." ;; esac
|
|
193
|
+
MODE_EXPLICIT=1; add_pref "$kv"; set_mode deploy; shift ;;
|
|
194
|
+
--apply) APPLY=1; shift ;;
|
|
195
|
+
--login) DO_LOGIN=1; shift ;;
|
|
196
|
+
--instance-url)
|
|
197
|
+
shift
|
|
198
|
+
[ $# -gt 0 ] || die "--instance-url requires a URL (e.g. --instance-url https://my-domain.my.salesforce.com)."
|
|
199
|
+
[ -n "$LOGIN_INSTANCE_URL" ] && die "Specify only one instance URL. Got extra: $1"
|
|
200
|
+
LOGIN_INSTANCE_URL="$1"; DO_LOGIN=1; shift ;;
|
|
201
|
+
--instance-url=*)
|
|
202
|
+
[ -n "$LOGIN_INSTANCE_URL" ] && die "Specify only one instance URL. Got extra: ${1#*=}"
|
|
203
|
+
LOGIN_INSTANCE_URL="${1#*=}"; DO_LOGIN=1; shift ;;
|
|
204
|
+
--json) OUTPUT="json"; shift ;;
|
|
205
|
+
--fail-if-disabled) FAIL_IF_DISABLED=1; shift ;;
|
|
206
|
+
--help|-h) usage; exit 0 ;;
|
|
207
|
+
--) shift; break ;;
|
|
208
|
+
-*) die "Unknown option: $1 (try --help)" ;;
|
|
209
|
+
*://*)
|
|
210
|
+
# A bare URL positional is an instance URL to log in to (My Domain,
|
|
211
|
+
# sandbox, or pre-release/scratch instance), not an org alias — an alias or
|
|
212
|
+
# username never contains "://". Route it to the login path.
|
|
213
|
+
[ -n "$LOGIN_INSTANCE_URL" ] && die "Specify only one instance URL. Got extra: $1"
|
|
214
|
+
LOGIN_INSTANCE_URL="$1"; DO_LOGIN=1; shift ;;
|
|
215
|
+
*)
|
|
216
|
+
[ -n "$TARGET" ] && die "Specify only one org. Got extra: $1"
|
|
217
|
+
TARGET="$1"; TARGET_EXPLICIT=1; shift ;;
|
|
218
|
+
esac
|
|
219
|
+
done
|
|
220
|
+
|
|
221
|
+
# --enable always includes the master switch.
|
|
222
|
+
if [ "$ENABLING" -eq 1 ] && ! has_pref_key "$DEVHUB_SWITCH"; then
|
|
223
|
+
add_pref "$DEVHUB_SWITCH=true"
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
if [ "$MODE" = "deploy" ] && [ "${#PREFS[@]}" -eq 0 ]; then
|
|
227
|
+
die "--configure needs at least one preference (e.g. --packaging, --snapshots, or --pref KEY=VALUE). To enable Dev Hub, use --enable."
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
if [ "$APPLY" -eq 1 ] && [ "$MODE" != "deploy" ]; then
|
|
231
|
+
die "--apply is valid only with --enable, --configure, or a preference flag."
|
|
232
|
+
fi
|
|
233
|
+
|
|
234
|
+
if [ "$APPLY" -eq 1 ] && [ "$TARGET_EXPLICIT" -ne 1 ]; then
|
|
235
|
+
die "--apply requires an explicit org alias or username; refusing to mutate an implicit default org."
|
|
236
|
+
fi
|
|
237
|
+
|
|
238
|
+
# A supplied instance URL must use an HTTPS Salesforce-owned hostname.
|
|
239
|
+
if [ -n "$LOGIN_INSTANCE_URL" ]; then
|
|
240
|
+
case "$LOGIN_INSTANCE_URL" in
|
|
241
|
+
https://*.salesforce.com|https://*.force.com|https://*.salesforce.mil) : ;;
|
|
242
|
+
*) die "--instance-url must use an https:// Salesforce hostname (got: '$LOGIN_INSTANCE_URL')." ;;
|
|
243
|
+
esac
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
# --- org resolution ------------------------------------------------------
|
|
247
|
+
resolve_target() {
|
|
248
|
+
[ -n "$TARGET" ] && return 0
|
|
249
|
+
TARGET="$(sf config get target-org --json 2>/dev/null | jq -r '.result[0].value // empty')"
|
|
250
|
+
[ -n "$TARGET" ] && return 0
|
|
251
|
+
TARGET="$(sf config get target-dev-hub --json 2>/dev/null | jq -r '.result[0].value // empty')"
|
|
252
|
+
[ -n "$TARGET" ] && return 0
|
|
253
|
+
echo "No org specified and no default target-org / target-dev-hub is set." >&2
|
|
254
|
+
echo >&2
|
|
255
|
+
echo "Pass an org alias/username, or set a default:" >&2
|
|
256
|
+
echo " sf org login web --alias <my-alias> # authenticate an org" >&2
|
|
257
|
+
echo " sf config set target-org <my-alias> # make it the default" >&2
|
|
258
|
+
exit 2
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
# --- interactive login ---------------------------------------------------
|
|
262
|
+
# Authenticate an org with `sf org login web`, honoring an optional
|
|
263
|
+
# --instance-url (My Domain, sandbox, or pre-release/scratch instance) and, when
|
|
264
|
+
# an org identifier was supplied, using it as the CLI alias. Opens a browser for
|
|
265
|
+
# the OAuth flow; returns non-zero if the login fails or times out.
|
|
266
|
+
do_login() {
|
|
267
|
+
local args=(org login web)
|
|
268
|
+
[ -n "$LOGIN_INSTANCE_URL" ] && args+=(--instance-url "$LOGIN_INSTANCE_URL")
|
|
269
|
+
[ -n "$TARGET" ] && args+=(--alias "$TARGET")
|
|
270
|
+
|
|
271
|
+
if [ "$OUTPUT" != "json" ]; then
|
|
272
|
+
echo "Authenticating with the Salesforce CLI (a browser window will open)..."
|
|
273
|
+
[ -n "$LOGIN_INSTANCE_URL" ] && echo " instance URL: $LOGIN_INSTANCE_URL"
|
|
274
|
+
[ -n "$TARGET" ] && echo " alias: $TARGET"
|
|
275
|
+
echo " Complete the login in the browser promptly (the session times out)."
|
|
276
|
+
echo
|
|
277
|
+
fi
|
|
278
|
+
|
|
279
|
+
local out ok
|
|
280
|
+
out="$(sf "${args[@]}" --json 2>/dev/null)"
|
|
281
|
+
ok="$(printf '%s' "$out" | jq -r 'if .status==0 then "true" else "false" end' 2>/dev/null)"
|
|
282
|
+
|
|
283
|
+
if [ "$ok" != "true" ]; then
|
|
284
|
+
local msg
|
|
285
|
+
msg="$(printf '%s' "$out" | jq -r '.message // empty' 2>/dev/null)"
|
|
286
|
+
if [ "$OUTPUT" = "json" ]; then
|
|
287
|
+
jq -n --arg msg "${msg:-login failed}" '{status:"login_failed", error:$msg}'
|
|
288
|
+
else
|
|
289
|
+
echo "Login failed: ${msg:-unknown error}." >&2
|
|
290
|
+
echo " Retry in your own terminal, or use the device flow if the browser flow keeps timing out:" >&2
|
|
291
|
+
echo " sf org login device${LOGIN_INSTANCE_URL:+ --instance-url $(shell_quote "$LOGIN_INSTANCE_URL")}${TARGET:+ --alias $(shell_quote "$TARGET")}" >&2
|
|
292
|
+
fi
|
|
293
|
+
return 1
|
|
294
|
+
fi
|
|
295
|
+
|
|
296
|
+
# Adopt the authenticated username as the target when none was supplied, so the
|
|
297
|
+
# rest of the run operates on the org the user just logged in to.
|
|
298
|
+
if [ -z "$TARGET" ]; then
|
|
299
|
+
TARGET="$(printf '%s' "$out" | jq -r '.result.username // empty' 2>/dev/null)"
|
|
300
|
+
fi
|
|
301
|
+
[ "$OUTPUT" != "json" ] && echo "Authenticated: ${TARGET:-(org)}" && echo
|
|
302
|
+
return 0
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
# Render one dynamic value as a safe, copy-pasteable shell argument.
|
|
306
|
+
shell_quote() {
|
|
307
|
+
printf "'%s'" "$(printf '%s' "$1" | sed "s/'/'\\\\''/g")"
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
# --- Dev Hub detection ---------------------------------------------------
|
|
311
|
+
# Sets DEVHUB_STATE (+ SCRATCH_COUNT when enabled, or error fields on failure).
|
|
312
|
+
# ScratchOrgInfo is queryable ONLY on a Dev Hub, so a clean COUNT == enabled and
|
|
313
|
+
# INVALID_TYPE == not enabled; any other failure is treated as an auth/conn error.
|
|
314
|
+
detect_devhub() {
|
|
315
|
+
local out rc
|
|
316
|
+
out="$(sf data query --query "SELECT COUNT() FROM ScratchOrgInfo" \
|
|
317
|
+
--target-org "$TARGET" --json 2>/dev/null)"
|
|
318
|
+
rc=$?
|
|
319
|
+
if [ "$rc" -eq 0 ]; then
|
|
320
|
+
DEVHUB_STATE="enabled"
|
|
321
|
+
SCRATCH_COUNT="$(printf '%s' "$out" | jq -r '.result.totalSize // empty')"
|
|
322
|
+
return 0
|
|
323
|
+
fi
|
|
324
|
+
local ename emsg
|
|
325
|
+
ename="$(printf '%s' "$out" | jq -r '.name // empty' 2>/dev/null)"
|
|
326
|
+
emsg="$(printf '%s' "$out" | jq -r '.message // empty' 2>/dev/null | tr '\t\n' ' ')"
|
|
327
|
+
case "$ename" in
|
|
328
|
+
INVALID_TYPE)
|
|
329
|
+
DEVHUB_STATE="disabled"; return 0 ;;
|
|
330
|
+
*)
|
|
331
|
+
DEVHUB_STATE="auth_error"; DEVHUB_ERRNAME="$ename"; DEVHUB_ERRMSG="$emsg"; return 1 ;;
|
|
332
|
+
esac
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
# Echoes TSV rows "name<TAB>remaining<TAB>max" for the two scratch org limits,
|
|
336
|
+
# or nothing if the org could not be queried.
|
|
337
|
+
allocation_rows() {
|
|
338
|
+
local out
|
|
339
|
+
out="$(sf org list limits --target-org "$TARGET" --json 2>/dev/null)" || return 1
|
|
340
|
+
printf '%s' "$out" | jq -r '
|
|
341
|
+
.result[]?
|
|
342
|
+
| select(.name=="ActiveScratchOrgs" or .name=="DailyScratchOrgs")
|
|
343
|
+
| [.name, (.remaining|tostring), (.max|tostring)] | @tsv'
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
# Resolve the org instance URL for the Setup deep link (best effort).
|
|
347
|
+
resolve_instance_url() {
|
|
348
|
+
[ -n "$INSTANCE_URL" ] && return 0
|
|
349
|
+
INSTANCE_URL="$(sf org display --target-org "$TARGET" --json 2>/dev/null \
|
|
350
|
+
| jq -r '.result.instanceUrl // empty')"
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
# --- auth error reporting ------------------------------------------------
|
|
354
|
+
print_auth_error() {
|
|
355
|
+
if [ "$OUTPUT" = "json" ]; then
|
|
356
|
+
jq -n --arg org "$TARGET" --arg name "$DEVHUB_ERRNAME" --arg msg "$DEVHUB_ERRMSG" \
|
|
357
|
+
'{org:$org, devHubEnabled:null, status:"auth_error", error:{name:$name, message:$msg}}'
|
|
358
|
+
return
|
|
359
|
+
fi
|
|
360
|
+
printf " %-30s could not query org (%s)\n" "$TARGET" "${DEVHUB_ERRNAME:-error}"
|
|
361
|
+
[ -n "$DEVHUB_ERRMSG" ] && printf " %-30s (%s)\n" "" "$DEVHUB_ERRMSG"
|
|
362
|
+
echo
|
|
363
|
+
if [ -n "$LOGIN_INSTANCE_URL" ]; then
|
|
364
|
+
# An instance URL was provided — show the exact command for it, and offer to
|
|
365
|
+
# let the script run it directly via --login.
|
|
366
|
+
echo " To authenticate against $LOGIN_INSTANCE_URL, run:"
|
|
367
|
+
echo " sf org login web --instance-url $(shell_quote "$LOGIN_INSTANCE_URL")${TARGET:+ --alias $(shell_quote "$TARGET")}"
|
|
368
|
+
echo " Or let this script log you in and continue in one step:"
|
|
369
|
+
echo " devhub.sh ${TARGET:+$(shell_quote "$TARGET") }--instance-url $(shell_quote "$LOGIN_INSTANCE_URL") --login"
|
|
370
|
+
else
|
|
371
|
+
echo " To authenticate, run one of:"
|
|
372
|
+
echo " sf org login web --alias $(shell_quote "$TARGET") # interactive browser login"
|
|
373
|
+
echo " sf org login web --alias <my-alias> --instance-url https://MYDOMAIN.my.salesforce.com # sandbox/My Domain"
|
|
374
|
+
echo " Or let this script log you in and continue in one step:"
|
|
375
|
+
echo " devhub.sh $(shell_quote "$TARGET") --login # prod/DE/trial"
|
|
376
|
+
echo " devhub.sh <my-alias> --instance-url https://MYDOMAIN.my.salesforce.com --login # sandbox/My Domain"
|
|
377
|
+
fi
|
|
378
|
+
echo " Then re-run. List existing logins with: sf org list"
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
# --- Setup UI fallback text ----------------------------------------------
|
|
382
|
+
print_ui_fallback() {
|
|
383
|
+
resolve_instance_url
|
|
384
|
+
echo " Manual alternative (Setup UI):"
|
|
385
|
+
echo " 1. Log in as a System Administrator."
|
|
386
|
+
echo " 2. Setup > Quick Find > \"Dev Hub\" > Dev Hub > turn Enable Dev Hub On."
|
|
387
|
+
if [ -n "$INSTANCE_URL" ]; then
|
|
388
|
+
echo " Open it directly: sf org open --path \"lightning/setup/DevHub/home\" --target-org \"$TARGET\""
|
|
389
|
+
fi
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
# --- allocation rendering ------------------------------------------------
|
|
393
|
+
render_allocation() {
|
|
394
|
+
local rows a_max a_rem d_max d_rem
|
|
395
|
+
rows="$(allocation_rows)" || { echo "Could not read org limits for '$TARGET'." >&2; return 1; }
|
|
396
|
+
a_rem="$(printf '%s\n' "$rows" | awk -F'\t' '$1=="ActiveScratchOrgs"{print $2}')"
|
|
397
|
+
a_max="$(printf '%s\n' "$rows" | awk -F'\t' '$1=="ActiveScratchOrgs"{print $3}')"
|
|
398
|
+
d_rem="$(printf '%s\n' "$rows" | awk -F'\t' '$1=="DailyScratchOrgs"{print $2}')"
|
|
399
|
+
d_max="$(printf '%s\n' "$rows" | awk -F'\t' '$1=="DailyScratchOrgs"{print $3}')"
|
|
400
|
+
|
|
401
|
+
if [ "$OUTPUT" = "json" ]; then
|
|
402
|
+
jq -n --arg org "$TARGET" \
|
|
403
|
+
--argjson am "${a_max:-null}" --argjson ar "${a_rem:-null}" \
|
|
404
|
+
--argjson dm "${d_max:-null}" --argjson dr "${d_rem:-null}" '
|
|
405
|
+
{org:$org,
|
|
406
|
+
allocation:{
|
|
407
|
+
activeScratchOrgs:{max:$am, remaining:$ar, used:(if $am!=null and $ar!=null then ($am-$ar) else null end)},
|
|
408
|
+
dailyScratchOrgs:{max:$dm, remaining:$dr, used:(if $dm!=null and $dr!=null then ($dm-$dr) else null end)}
|
|
409
|
+
}}'
|
|
410
|
+
return 0
|
|
411
|
+
fi
|
|
412
|
+
|
|
413
|
+
echo "Scratch org allocation for '$TARGET':"
|
|
414
|
+
if [ -z "$a_max" ] && [ -z "$d_max" ]; then
|
|
415
|
+
echo " No scratch org limits reported (org may not be a Dev Hub, or could not be queried)."
|
|
416
|
+
return 0
|
|
417
|
+
fi
|
|
418
|
+
printf " %-22s %10s %10s %10s\n" "Limit" "Used" "Remaining" "Max"
|
|
419
|
+
[ -n "$a_max" ] && printf " %-22s %10s %10s %10s\n" "Active scratch orgs" "$(( a_max - a_rem ))" "$a_rem" "$a_max"
|
|
420
|
+
[ -n "$d_max" ] && printf " %-22s %10s %10s %10s\n" "Daily scratch orgs" "$(( d_max - d_rem ))" "$d_rem" "$d_max"
|
|
421
|
+
echo
|
|
422
|
+
echo " Active = orgs alive right now; Daily = successful creations in a rolling 24h window."
|
|
423
|
+
echo " Allocation is set by the Dev Hub's edition (e.g. Developer/trial 3 & 6;"
|
|
424
|
+
echo " Enterprise 40 & 80; Unlimited/Performance 100 & 200) plus any purchased add-on."
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
# --- active scratch org listing ------------------------------------------
|
|
428
|
+
render_list() {
|
|
429
|
+
local out rc
|
|
430
|
+
out="$(sf data query --target-org "$TARGET" \
|
|
431
|
+
--query "SELECT SignupUsername, OrgName, Edition, ExpirationDate, ScratchOrg FROM ActiveScratchOrg ORDER BY ExpirationDate NULLS LAST" \
|
|
432
|
+
--json 2>/dev/null)"
|
|
433
|
+
rc=$?
|
|
434
|
+
if [ "$rc" -ne 0 ]; then
|
|
435
|
+
if [ "$OUTPUT" = "json" ]; then echo "[]"; else
|
|
436
|
+
echo "Could not list scratch orgs for '$TARGET' — is Dev Hub enabled and the org authenticated?" >&2
|
|
437
|
+
fi
|
|
438
|
+
return 1
|
|
439
|
+
fi
|
|
440
|
+
if [ "$OUTPUT" = "json" ]; then
|
|
441
|
+
printf '%s' "$out" | jq '[.result.records[]? | {signupUsername:.SignupUsername, orgName:.OrgName, edition:.Edition, expirationDate:.ExpirationDate, scratchOrgId:.ScratchOrg}]'
|
|
442
|
+
return 0
|
|
443
|
+
fi
|
|
444
|
+
local total
|
|
445
|
+
total="$(printf '%s' "$out" | jq -r '.result.totalSize // 0')"
|
|
446
|
+
echo "Active scratch orgs on Dev Hub '$TARGET': $total"
|
|
447
|
+
if [ "$total" = "0" ]; then
|
|
448
|
+
echo " (none active)"
|
|
449
|
+
return 0
|
|
450
|
+
fi
|
|
451
|
+
printf '%s' "$out" | jq -r '.result.records[]?
|
|
452
|
+
| " \(.SignupUsername // "?") edition=\(.Edition // "?") expires=\(.ExpirationDate // "?") id=\(.ScratchOrg // "?")"'
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
# --- deploy (enable / configure sub-prefs) -------------------------------
|
|
456
|
+
DEPLOY_TEMP_DIR=""
|
|
457
|
+
cleanup_deploy_temp() {
|
|
458
|
+
[ -n "$DEPLOY_TEMP_DIR" ] && rm -rf -- "$DEPLOY_TEMP_DIR"
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
render_deploy() {
|
|
462
|
+
# Sub-prefs (packaging, snapshots, shape) require Dev Hub to be on. If the
|
|
463
|
+
# user is configuring one without also enabling, and Dev Hub is off, warn.
|
|
464
|
+
if [ "$ENABLING" -eq 0 ] && [ "$DEVHUB_STATE" = "disabled" ] && [ "$OUTPUT" != "json" ]; then
|
|
465
|
+
echo "Note: Dev Hub is not enabled on '$TARGET'. Sub-preferences require Dev Hub — add --enable, or run --enable first." >&2
|
|
466
|
+
echo >&2
|
|
467
|
+
fi
|
|
468
|
+
|
|
469
|
+
local tmp
|
|
470
|
+
tmp="$(mktemp -d 2>/dev/null)" || die "Could not create a temporary directory for the deploy."
|
|
471
|
+
DEPLOY_TEMP_DIR="$tmp"
|
|
472
|
+
trap cleanup_deploy_temp EXIT
|
|
473
|
+
|
|
474
|
+
mkdir -p "$tmp/force-app/main/default/settings"
|
|
475
|
+
cat > "$tmp/sfdx-project.json" <<JSON
|
|
476
|
+
{ "packageDirectories": [{ "path": "force-app", "default": true }], "sourceApiVersion": "$SETTINGS_API_VERSION" }
|
|
477
|
+
JSON
|
|
478
|
+
{
|
|
479
|
+
echo '<?xml version="1.0" encoding="UTF-8"?>'
|
|
480
|
+
echo '<DevHubSettings xmlns="http://soap.sforce.com/2006/04/metadata">'
|
|
481
|
+
local kv key val
|
|
482
|
+
for kv in "${PREFS[@]}"; do
|
|
483
|
+
key="${kv%%=*}"; val="${kv#*=}"
|
|
484
|
+
echo " <$key>$val</$key>"
|
|
485
|
+
done
|
|
486
|
+
echo '</DevHubSettings>'
|
|
487
|
+
} > "$tmp/force-app/main/default/settings/DevHub.settings-meta.xml"
|
|
488
|
+
|
|
489
|
+
local dry="--dry-run" action="Validating (dry run)"
|
|
490
|
+
if [ "$APPLY" -eq 1 ]; then dry=""; action="Deploying"; fi
|
|
491
|
+
|
|
492
|
+
if [ "$OUTPUT" != "json" ]; then
|
|
493
|
+
if [ "$ENABLING" -eq 1 ]; then
|
|
494
|
+
echo "$action Dev Hub enablement on '$TARGET':"
|
|
495
|
+
else
|
|
496
|
+
echo "$action DevHubSettings on '$TARGET':"
|
|
497
|
+
fi
|
|
498
|
+
local kv2; for kv2 in "${PREFS[@]}"; do echo " $kv2"; done
|
|
499
|
+
if [ "$ENABLING" -eq 1 ] && [ "$APPLY" -eq 1 ]; then
|
|
500
|
+
echo
|
|
501
|
+
echo " WARNING: enabling Dev Hub is IRREVERSIBLE — it cannot be turned off."
|
|
502
|
+
echo " Requires ModifyAllData or ModifyMetadata (System Administrator)."
|
|
503
|
+
echo " Not allowed in a sandbox, or in an org with a registered namespace."
|
|
504
|
+
fi
|
|
505
|
+
echo
|
|
506
|
+
fi
|
|
507
|
+
|
|
508
|
+
local out ok verified="unknown"
|
|
509
|
+
out="$( cd "$tmp" && sf project deploy start $dry --source-dir force-app \
|
|
510
|
+
--target-org "$TARGET" --json 2>/dev/null )"
|
|
511
|
+
ok="$(printf '%s' "$out" | jq -r '.result.success // false')"
|
|
512
|
+
|
|
513
|
+
# On a real, successful enablement, re-detect so we report verified state.
|
|
514
|
+
if [ "$APPLY" -eq 1 ] && [ "$ENABLING" -eq 1 ] && [ "$ok" = "true" ]; then
|
|
515
|
+
detect_devhub >/dev/null 2>&1
|
|
516
|
+
verified="$DEVHUB_STATE"
|
|
517
|
+
fi
|
|
518
|
+
|
|
519
|
+
if [ "$OUTPUT" = "json" ]; then
|
|
520
|
+
printf '%s' "$out" | jq \
|
|
521
|
+
--arg applied "$([ "$APPLY" -eq 1 ] && echo true || echo false)" \
|
|
522
|
+
--arg enabling "$([ "$ENABLING" -eq 1 ] && echo true || echo false)" \
|
|
523
|
+
--arg verified "$verified" '
|
|
524
|
+
{applied:($applied=="true"),
|
|
525
|
+
enabling:($enabling=="true"),
|
|
526
|
+
success:(.result.success // false),
|
|
527
|
+
checkOnly:(.result.checkOnly // null),
|
|
528
|
+
devHubVerifiedState:(if $verified=="unknown" then null else $verified end),
|
|
529
|
+
failures:[.result.details.componentFailures[]? | {fullName, problem}],
|
|
530
|
+
message:(.message // null)}'
|
|
531
|
+
[ "$ok" = "true" ] && return 0 || return 1
|
|
532
|
+
fi
|
|
533
|
+
|
|
534
|
+
if [ "$ok" = "true" ]; then
|
|
535
|
+
if [ "$APPLY" -eq 1 ]; then
|
|
536
|
+
if [ "$ENABLING" -eq 1 ]; then
|
|
537
|
+
echo " Success — Dev Hub enabled (deploy succeeded)."
|
|
538
|
+
if [ "$verified" = "enabled" ]; then
|
|
539
|
+
echo " Verified: ScratchOrgInfo is now queryable."
|
|
540
|
+
else
|
|
541
|
+
echo " Note: provisioning may take a moment; re-run 'devhub.sh \"$TARGET\"' to confirm."
|
|
542
|
+
fi
|
|
543
|
+
echo " Set it as your default Dev Hub: sf config set target-dev-hub \"$TARGET\""
|
|
544
|
+
else
|
|
545
|
+
echo " Success — Dev Hub preferences deployed."
|
|
546
|
+
fi
|
|
547
|
+
else
|
|
548
|
+
echo " Dry run passed — valid. Re-run with --apply to deploy."
|
|
549
|
+
[ "$ENABLING" -eq 1 ] && echo " (Enabling Dev Hub is irreversible; --apply commits it.)"
|
|
550
|
+
fi
|
|
551
|
+
return 0
|
|
552
|
+
fi
|
|
553
|
+
|
|
554
|
+
echo " Deployment did not succeed:"
|
|
555
|
+
printf '%s' "$out" | jq -r '.result.details.componentFailures[]? | " - \(.fullName): \(.problem)"' 2>/dev/null
|
|
556
|
+
printf '%s' "$out" | jq -r '.message // empty' 2>/dev/null | sed 's/^/ /'
|
|
557
|
+
# Common cause: missing perms. Offer the UI route.
|
|
558
|
+
if printf '%s' "$out" | grep -qi "INSUFFICIENT_ACCESS\|ModifyAllData\|ModifyMetadata"; then
|
|
559
|
+
echo
|
|
560
|
+
echo " This looks like a permissions issue — the deploy needs ModifyAllData or ModifyMetadata."
|
|
561
|
+
[ "$ENABLING" -eq 1 ] && print_ui_fallback
|
|
562
|
+
fi
|
|
563
|
+
return 1
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
# --- status (default) ----------------------------------------------------
|
|
567
|
+
render_status() {
|
|
568
|
+
if [ "$OUTPUT" = "json" ]; then
|
|
569
|
+
local rows a_max a_rem d_max d_rem
|
|
570
|
+
rows="$(allocation_rows 2>/dev/null || true)"
|
|
571
|
+
a_rem="$(printf '%s\n' "$rows" | awk -F'\t' '$1=="ActiveScratchOrgs"{print $2}')"
|
|
572
|
+
a_max="$(printf '%s\n' "$rows" | awk -F'\t' '$1=="ActiveScratchOrgs"{print $3}')"
|
|
573
|
+
d_rem="$(printf '%s\n' "$rows" | awk -F'\t' '$1=="DailyScratchOrgs"{print $2}')"
|
|
574
|
+
d_max="$(printf '%s\n' "$rows" | awk -F'\t' '$1=="DailyScratchOrgs"{print $3}')"
|
|
575
|
+
jq -n --arg org "$TARGET" --arg state "$DEVHUB_STATE" \
|
|
576
|
+
--argjson count "${SCRATCH_COUNT:-null}" \
|
|
577
|
+
--argjson am "${a_max:-null}" --argjson ar "${a_rem:-null}" \
|
|
578
|
+
--argjson dm "${d_max:-null}" --argjson dr "${d_rem:-null}" '
|
|
579
|
+
{org:$org,
|
|
580
|
+
devHubEnabled:($state=="enabled"),
|
|
581
|
+
status:$state,
|
|
582
|
+
activeScratchOrgSignups:$count,
|
|
583
|
+
allocation:{
|
|
584
|
+
activeScratchOrgs:{max:$am, remaining:$ar},
|
|
585
|
+
dailyScratchOrgs:{max:$dm, remaining:$dr}
|
|
586
|
+
}}'
|
|
587
|
+
return 0
|
|
588
|
+
fi
|
|
589
|
+
|
|
590
|
+
echo "Dev Hub status for '$TARGET':"
|
|
591
|
+
if [ "$DEVHUB_STATE" = "enabled" ]; then
|
|
592
|
+
echo " Dev Hub: ENABLED (ScratchOrgInfo is queryable)"
|
|
593
|
+
[ -n "$SCRATCH_COUNT" ] && echo " Scratch org signup records: $SCRATCH_COUNT"
|
|
594
|
+
echo
|
|
595
|
+
render_allocation
|
|
596
|
+
else
|
|
597
|
+
echo " Dev Hub: NOT ENABLED"
|
|
598
|
+
echo
|
|
599
|
+
echo " Enable it (deploys $DEVHUB_SWITCH=true; irreversible):"
|
|
600
|
+
echo " devhub.sh \"$TARGET\" --enable # validate first (dry run)"
|
|
601
|
+
echo " devhub.sh \"$TARGET\" --enable --apply # actually enable"
|
|
602
|
+
echo " Requires ModifyAllData or ModifyMetadata (System Administrator);"
|
|
603
|
+
echo " not allowed in a sandbox or an org with a registered namespace."
|
|
604
|
+
echo
|
|
605
|
+
print_ui_fallback
|
|
606
|
+
fi
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
# --- dispatch ------------------------------------------------------------
|
|
610
|
+
# Authenticate first when requested. Login can supply the org, so it runs before
|
|
611
|
+
# resolve_target's "no org" guard; a bare positional (no other mode) with
|
|
612
|
+
# --login/--instance-url is treated as the alias to log in under.
|
|
613
|
+
if [ "$DO_LOGIN" -eq 1 ]; then
|
|
614
|
+
do_login || exit 1
|
|
615
|
+
if [ "$MODE_EXPLICIT" -eq 0 ] && [ "$FAIL_IF_DISABLED" -eq 0 ]; then
|
|
616
|
+
exit 0
|
|
617
|
+
fi
|
|
618
|
+
fi
|
|
619
|
+
|
|
620
|
+
resolve_target
|
|
621
|
+
|
|
622
|
+
# status/deploy need the enablement state; allocation and list query the org
|
|
623
|
+
# directly and surface their own errors.
|
|
624
|
+
case "$MODE" in
|
|
625
|
+
status|deploy)
|
|
626
|
+
if ! detect_devhub && [ "$DEVHUB_STATE" = "auth_error" ]; then
|
|
627
|
+
print_auth_error
|
|
628
|
+
exit 1
|
|
629
|
+
fi
|
|
630
|
+
;;
|
|
631
|
+
esac
|
|
632
|
+
|
|
633
|
+
rc=0
|
|
634
|
+
case "$MODE" in
|
|
635
|
+
status) render_status || rc=1 ;;
|
|
636
|
+
allocation) render_allocation || rc=1 ;;
|
|
637
|
+
list) render_list || rc=1 ;;
|
|
638
|
+
deploy) render_deploy || rc=1 ;;
|
|
639
|
+
esac
|
|
640
|
+
|
|
641
|
+
# CI gate: exit 3 if Dev Hub is not enabled (takes precedence for alerting).
|
|
642
|
+
if [ "$FAIL_IF_DISABLED" -eq 1 ]; then
|
|
643
|
+
[ -z "$DEVHUB_STATE" ] && detect_devhub >/dev/null 2>&1
|
|
644
|
+
if [ "$DEVHUB_STATE" != "enabled" ]; then
|
|
645
|
+
echo "ALERT: Dev Hub is not enabled on '$TARGET'." >&2
|
|
646
|
+
exit 3
|
|
647
|
+
fi
|
|
648
|
+
fi
|
|
649
|
+
|
|
650
|
+
exit "$rc"
|