@khester/create-dynamics-app 1.1.0 → 2.1.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/README.md +74 -0
- package/dist/artifacts/registry.d.ts +18 -0
- package/dist/artifacts/registry.d.ts.map +1 -0
- package/dist/artifacts/registry.js +340 -0
- package/dist/artifacts/registry.js.map +1 -0
- package/dist/artifacts/types.d.ts +122 -0
- package/dist/artifacts/types.d.ts.map +1 -0
- package/dist/artifacts/types.js +7 -0
- package/dist/artifacts/types.js.map +1 -0
- package/dist/artifacts/validators.d.ts +16 -0
- package/dist/artifacts/validators.d.ts.map +1 -0
- package/dist/artifacts/validators.js +45 -0
- package/dist/artifacts/validators.js.map +1 -0
- package/dist/fromDesign.d.ts +5 -0
- package/dist/fromDesign.d.ts.map +1 -0
- package/dist/fromDesign.js +98 -0
- package/dist/fromDesign.js.map +1 -0
- package/dist/index.js +129 -177
- package/dist/index.js.map +1 -1
- package/dist/injectDevTools.d.ts +28 -0
- package/dist/injectDevTools.d.ts.map +1 -0
- package/dist/injectDevTools.js +148 -0
- package/dist/injectDevTools.js.map +1 -0
- package/dist/scaffold.d.ts +48 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +180 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/templatePlan.d.ts +3 -0
- package/dist/templatePlan.d.ts.map +1 -0
- package/dist/templatePlan.js +43 -0
- package/dist/templatePlan.js.map +1 -0
- package/dist/utils/copyTemplate.d.ts +13 -1
- package/dist/utils/copyTemplate.d.ts.map +1 -1
- package/dist/utils/copyTemplate.js +98 -4
- package/dist/utils/copyTemplate.js.map +1 -1
- package/dist/utils/updatePackageJson.d.ts +11 -1
- package/dist/utils/updatePackageJson.d.ts.map +1 -1
- package/dist/utils/updatePackageJson.js +12 -10
- package/dist/utils/updatePackageJson.js.map +1 -1
- package/package.json +10 -7
- package/templates/_shared/dev-tools/auth/get-token.js +72 -0
- package/templates/_shared/dev-tools/dev/mock-xrm.js +42 -0
- package/templates/_shared/dev-tools/metadata-sync/index.js +152 -0
- package/templates/_shared/dev-tools/smoke/test-retrieve.js +44 -0
- package/templates/dialog-form/README.md +27 -0
- package/templates/dialog-form/_variants/App.v8.tsx +39 -0
- package/templates/dialog-form/_variants/App.v9.tsx +41 -0
- package/templates/dialog-form/gitignore +5 -0
- package/templates/dialog-form/package.json +27 -0
- package/templates/dialog-form/public/index.html +11 -0
- package/templates/dialog-form/src/index.tsx +10 -0
- package/templates/dialog-form/src/services/dataverse.ts +30 -0
- package/templates/dialog-form/tsconfig.json +15 -0
- package/templates/dialog-form/webpack.config.js +17 -0
- package/templates/grid-customizer/README.md +28 -0
- package/templates/grid-customizer/gitignore +4 -0
- package/templates/grid-customizer/package.json +25 -0
- package/templates/grid-customizer/src/GridCustomizer.ts +28 -0
- package/templates/grid-customizer/src/cell-renderers.tsx +35 -0
- package/templates/grid-customizer/src/index.ts +4 -0
- package/templates/grid-customizer/src/types/grid-types.ts +30 -0
- package/templates/grid-customizer/src/utils/color-utils.ts +24 -0
- package/templates/grid-customizer/tsconfig.json +15 -0
- package/templates/grid-customizer/webpack.config.js +17 -0
- package/templates/pcf-dataset/ControlManifest.Input.xml +16 -0
- package/templates/pcf-dataset/README.md +21 -0
- package/templates/pcf-dataset/gitignore +5 -0
- package/templates/pcf-dataset/index.ts +39 -0
- package/templates/pcf-dataset/package.json +30 -0
- package/templates/pcf-dataset/strings/{{componentName}}.1033.resx +47 -0
- package/templates/pcf-dataset/tsconfig.json +8 -0
- package/templates/pcf-dataset/{{componentName}}Component.tsx +39 -0
- package/templates/pcf-field/ControlManifest.Input.xml +17 -0
- package/templates/pcf-field/README.md +95 -0
- package/templates/pcf-field/_variants/ValueInput.boolean.tsx +24 -0
- package/templates/pcf-field/_variants/ValueInput.date.tsx +27 -0
- package/templates/pcf-field/_variants/ValueInput.number.tsx +35 -0
- package/templates/pcf-field/_variants/ValueInput.text.tsx +27 -0
- package/templates/pcf-field/gitignore +5 -0
- package/templates/pcf-field/index.ts +61 -0
- package/templates/pcf-field/package.json +30 -0
- package/templates/pcf-field/strings/{{componentName}}.1033.resx +47 -0
- package/templates/pcf-field/tsconfig.json +8 -0
- package/templates/pcf-field/{{componentName}}Component.tsx +35 -0
- package/templates/power-pages-starter/gitignore +5 -0
- package/templates/react-custom-page/gitignore +5 -0
- package/templates/{dynamics-365-starter → react-custom-page}/package.json +3 -3
- package/templates/react-custom-page/tools/metadata-sync/index.js +152 -0
- package/templates/static-web-app/README.md +36 -0
- package/templates/static-web-app/_variants/App.v8.tsx +32 -0
- package/templates/static-web-app/_variants/App.v9.tsx +31 -0
- package/templates/static-web-app/api/host.json +12 -0
- package/templates/static-web-app/api/package.json +19 -0
- package/templates/static-web-app/api/src/functions/hello.ts +16 -0
- package/templates/static-web-app/api/tsconfig.json +14 -0
- package/templates/static-web-app/frontend/index.html +12 -0
- package/templates/static-web-app/frontend/package.json +23 -0
- package/templates/static-web-app/frontend/src/index.tsx +8 -0
- package/templates/static-web-app/frontend/tsconfig.json +16 -0
- package/templates/static-web-app/frontend/vite.config.ts +13 -0
- package/templates/static-web-app/gitignore +8 -0
- package/templates/static-web-app/package.json +15 -0
- package/templates/static-web-app/staticwebapp.config.json +7 -0
- package/templates/teams-app/README.md +27 -0
- package/templates/teams-app/_variants/graph.off.ts +7 -0
- package/templates/teams-app/_variants/graph.on.ts +22 -0
- package/templates/teams-app/appPackage/manifest.json +26 -0
- package/templates/teams-app/gitignore +5 -0
- package/templates/teams-app/index.html +12 -0
- package/templates/teams-app/package.json +26 -0
- package/templates/teams-app/src/App.tsx +25 -0
- package/templates/teams-app/src/index.tsx +8 -0
- package/templates/teams-app/tsconfig.json +16 -0
- package/templates/teams-app/vite.config.ts +9 -0
- package/templates/web-resource/README.md +39 -0
- package/templates/web-resource/_variants/App.v8.tsx +29 -0
- package/templates/web-resource/_variants/App.v9.tsx +28 -0
- package/templates/web-resource/gitignore +5 -0
- package/templates/web-resource/package.json +27 -0
- package/templates/web-resource/public/index.html +11 -0
- package/templates/web-resource/src/index.tsx +10 -0
- package/templates/web-resource/src/services/dataverse.ts +30 -0
- package/templates/web-resource/tsconfig.json +15 -0
- package/templates/web-resource/webpack.config.js +17 -0
- package/dist/utils/consultingHelpers.d.ts +0 -13
- package/dist/utils/consultingHelpers.d.ts.map +0 -1
- package/dist/utils/consultingHelpers.js +0 -569
- package/dist/utils/consultingHelpers.js.map +0 -1
- package/templates/dynamics-365-starter/INTEGRATION_TEST_RESULTS.md +0 -302
- package/templates/dynamics-365-starter/PHASE_4_COMPLETION_SUMMARY.md +0 -305
- package/templates/dynamics-365-starter/deployment/QUICKSTART-MAC.md +0 -507
- package/templates/dynamics-365-starter/deployment/QUICKSTART-WINDOWS.md +0 -372
- package/templates/dynamics-365-starter/deployment/pipelines/README.md +0 -375
- package/templates/dynamics-365-starter/deployment/pipelines/azure-pipelines.yml +0 -330
- package/templates/dynamics-365-starter/deployment/pipelines/github-actions.yml +0 -422
- package/templates/dynamics-365-starter/deployment/pipelines/jenkins.groovy +0 -636
- package/templates/dynamics-365-starter/deployment/scripts/deploy.ps1 +0 -417
- package/templates/dynamics-365-starter/deployment/scripts/deploy.sh +0 -582
- package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.ps1 +0 -486
- package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.sh +0 -567
- package/templates/dynamics-365-starter/deployment/scripts/validate-setup.ps1 +0 -703
- package/templates/dynamics-365-starter/deployment/scripts/validate-setup.sh +0 -671
- package/templates/dynamics-365-starter/docs/team-standards/README.md +0 -273
- package/templates/dynamics-365-starter/docs/team-standards/client-onboarding.md +0 -577
- package/templates/dynamics-365-starter/docs/team-standards/code-review-checklist.md +0 -359
- package/templates/dynamics-365-starter/docs/team-standards/coding-standards.md +0 -700
- package/templates/dynamics-365-starter/docs/team-standards/cross-platform-team-guide.md +0 -736
- package/templates/dynamics-365-starter/docs/team-standards/development-workflows.md +0 -727
- package/templates/dynamics-365-starter/docs/troubleshooting/common-errors.md +0 -758
- package/templates/dynamics-365-starter/docs/troubleshooting/platform-specific-issues.md +0 -878
- package/templates/dynamics-365-starter/src/client-project-template/README.md +0 -234
- package/templates/dynamics-365-starter/src/client-project-template/config/client.template.json +0 -114
- package/templates/dynamics-365-starter/src/client-project-template/config/environments/template.json +0 -186
- package/templates/dynamics-365-starter/src/client-project-template/scripts/client-setup.js +0 -667
- package/templates/dynamics-365-starter/src/examples/README.md +0 -52
- package/templates/dynamics-365-starter/src/examples/component-examples/opportunity-management.tsx +0 -625
- package/templates/dynamics-365-starter/src/examples/entity-examples/opportunity-model.ts +0 -545
- package/templates/dynamics-365-starter/src/examples/integration-examples/custom-pcf-wrapper.tsx +0 -722
- package/templates/dynamics-365-starter/src/examples/workflow-examples/sales-workflow.ts +0 -662
- package/templates/dynamics-365-starter/src/page-templates/EntityDashboard.tsx +0 -519
- package/templates/dynamics-365-starter/src/page-templates/EntityDetailPage.tsx +0 -456
- package/templates/dynamics-365-starter/src/page-templates/EntityListPage.tsx +0 -406
- package/templates/dynamics-365-starter/src/page-templates/RelatedEntitiesPage.tsx +0 -578
- package/templates/dynamics-365-starter/src/page-templates/SearchPage.tsx +0 -629
- package/templates/dynamics-365-starter/tools/entity-generator/index.js +0 -168
- package/templates/dynamics-365-starter/tools/entity-generator/templates/constants.template.ts +0 -124
- package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.css +0 -283
- package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.tsx +0 -275
- package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.css +0 -204
- package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.tsx +0 -413
- package/templates/dynamics-365-starter/tools/entity-generator/templates/model.template.ts +0 -250
- package/templates/dynamics-365-starter/tools/metadata-sync/d365-client.js +0 -410
- package/templates/dynamics-365-starter/tools/metadata-sync/index.js +0 -512
- package/templates/dynamics-365-starter/tools/metadata-sync/type-generator.js +0 -675
- /package/templates/{dynamics-365-starter → react-custom-page}/README.md +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/deployment/README.md +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/docs/ARCHITECTURE_OVERVIEW.md +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/docs/BEST_PRACTICES.md +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/docs/MIGRATION_GUIDE.md +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/public/index.html +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/scripts/custom-build.js +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountForm.css +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountForm.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountManagement.css +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountManagement.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactForm.css +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactForm.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactManagement.css +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactManagement.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LogDialog.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingContext.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingDebugPanel.css +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingDebugPanel.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingProvider.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/logger.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/constants/account.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/constants/contact.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/index.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/models/Account.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/models/BaseEntity.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/models/Contact.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/pcf/ContactControlWrapper.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/pcf/MultiEntityControlWrapper.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/providers/DynamicsProvider.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/services/MockApiService.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/services/ServiceFactory.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/services/XrmApiService.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/styles/index.css +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/tsconfig.json +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/webpack.config.js +0 -0
|
@@ -1,417 +0,0 @@
|
|
|
1
|
-
# Dynamics 365 Deployment Automation Script
|
|
2
|
-
# PowerShell script for automated deployment to Dynamics 365 environments
|
|
3
|
-
|
|
4
|
-
param(
|
|
5
|
-
[Parameter(Mandatory=$true)]
|
|
6
|
-
[ValidateSet("dev", "test", "staging", "prod")]
|
|
7
|
-
[string]$Environment,
|
|
8
|
-
|
|
9
|
-
[Parameter(Mandatory=$false)]
|
|
10
|
-
[string]$ConfigPath = "config/environments",
|
|
11
|
-
|
|
12
|
-
[Parameter(Mandatory=$false)]
|
|
13
|
-
[switch]$DryRun,
|
|
14
|
-
|
|
15
|
-
[Parameter(Mandatory=$false)]
|
|
16
|
-
[switch]$Force,
|
|
17
|
-
|
|
18
|
-
[Parameter(Mandatory=$false)]
|
|
19
|
-
[string]$SolutionPath = "solutions",
|
|
20
|
-
|
|
21
|
-
[Parameter(Mandatory=$false)]
|
|
22
|
-
[switch]$SkipBackup,
|
|
23
|
-
|
|
24
|
-
[Parameter(Mandatory=$false)]
|
|
25
|
-
[switch]$Verbose
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
# Set error action preference
|
|
29
|
-
$ErrorActionPreference = "Stop"
|
|
30
|
-
|
|
31
|
-
# Import required modules
|
|
32
|
-
Import-Module Microsoft.PowerApps.Administration.PowerShell -Force
|
|
33
|
-
Import-Module Microsoft.PowerApps.PowerShell -AllowClobber -Force
|
|
34
|
-
|
|
35
|
-
# Script configuration
|
|
36
|
-
$ScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
37
|
-
$ProjectRoot = Split-Path -Parent (Split-Path -Parent $ScriptRoot)
|
|
38
|
-
$LogPath = Join-Path $ProjectRoot "deployment/logs"
|
|
39
|
-
$BackupPath = Join-Path $ProjectRoot "deployment/backups"
|
|
40
|
-
|
|
41
|
-
# Ensure directories exist
|
|
42
|
-
New-Item -ItemType Directory -Force -Path $LogPath | Out-Null
|
|
43
|
-
New-Item -ItemType Directory -Force -Path $BackupPath | Out-Null
|
|
44
|
-
|
|
45
|
-
# Initialize logging
|
|
46
|
-
$LogFile = Join-Path $LogPath "deploy-$Environment-$(Get-Date -Format 'yyyyMMdd-HHmmss').log"
|
|
47
|
-
|
|
48
|
-
function Write-Log {
|
|
49
|
-
param([string]$Message, [string]$Level = "INFO")
|
|
50
|
-
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
51
|
-
$LogEntry = "[$Timestamp] [$Level] $Message"
|
|
52
|
-
Write-Host $LogEntry
|
|
53
|
-
Add-Content -Path $LogFile -Value $LogEntry
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function Show-Banner {
|
|
57
|
-
Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
|
|
58
|
-
Write-Host "║ Dynamics 365 Deployment Automation ║" -ForegroundColor Cyan
|
|
59
|
-
Write-Host "║ Enterprise Consulting Edition ║" -ForegroundColor Cyan
|
|
60
|
-
Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
|
|
61
|
-
Write-Host ""
|
|
62
|
-
Write-Host "Environment: $Environment" -ForegroundColor Yellow
|
|
63
|
-
Write-Host "Timestamp: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Yellow
|
|
64
|
-
if ($DryRun) {
|
|
65
|
-
Write-Host "Mode: DRY RUN (no changes will be made)" -ForegroundColor Magenta
|
|
66
|
-
}
|
|
67
|
-
Write-Host ""
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function Load-Configuration {
|
|
71
|
-
param([string]$Environment)
|
|
72
|
-
|
|
73
|
-
Write-Log "Loading configuration for environment: $Environment"
|
|
74
|
-
|
|
75
|
-
$ConfigFile = Join-Path $ProjectRoot "$ConfigPath/$Environment.json"
|
|
76
|
-
|
|
77
|
-
if (-not (Test-Path $ConfigFile)) {
|
|
78
|
-
throw "Configuration file not found: $ConfigFile"
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
$Config = Get-Content $ConfigFile | ConvertFrom-Json
|
|
83
|
-
Write-Log "Configuration loaded successfully"
|
|
84
|
-
return $Config
|
|
85
|
-
}
|
|
86
|
-
catch {
|
|
87
|
-
throw "Failed to parse configuration file: $_"
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function Test-Prerequisites {
|
|
92
|
-
Write-Log "Checking deployment prerequisites..."
|
|
93
|
-
|
|
94
|
-
# Check if PowerShell modules are available
|
|
95
|
-
$RequiredModules = @(
|
|
96
|
-
"Microsoft.PowerApps.Administration.PowerShell",
|
|
97
|
-
"Microsoft.PowerApps.PowerShell"
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
foreach ($Module in $RequiredModules) {
|
|
101
|
-
if (-not (Get-Module -Name $Module -ListAvailable)) {
|
|
102
|
-
throw "Required PowerShell module not found: $Module"
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
# Check if build artifacts exist
|
|
107
|
-
$DistPath = Join-Path $ProjectRoot "dist"
|
|
108
|
-
if (-not (Test-Path $DistPath)) {
|
|
109
|
-
throw "Build artifacts not found. Please run 'npm run build:prod' first."
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
# Check if solution files exist
|
|
113
|
-
$SolutionDir = Join-Path $ProjectRoot $SolutionPath
|
|
114
|
-
if (-not (Test-Path $SolutionDir)) {
|
|
115
|
-
Write-Log "Solution directory not found, will create web resources only" -Level "WARN"
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
Write-Log "Prerequisites check completed successfully"
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function Connect-Environment {
|
|
122
|
-
param([object]$Config)
|
|
123
|
-
|
|
124
|
-
Write-Log "Connecting to Dynamics 365 environment..."
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
# Connect using service principal
|
|
128
|
-
if ($Config.authentication.type -eq "oauth2") {
|
|
129
|
-
$TenantId = $Config.authentication.tenantId
|
|
130
|
-
$ClientId = $Config.authentication.clientId
|
|
131
|
-
$ClientSecret = $Config.authentication.clientSecret
|
|
132
|
-
|
|
133
|
-
if ($DryRun) {
|
|
134
|
-
Write-Log "DRY RUN: Would connect to environment with client ID: $ClientId"
|
|
135
|
-
return $true
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
# Note: In real implementation, you would use proper authentication
|
|
139
|
-
Write-Log "Authenticating with Azure AD..."
|
|
140
|
-
# Add-PowerAppsAccount -TenantID $TenantId -ApplicationId $ClientId -ClientSecret $ClientSecret
|
|
141
|
-
|
|
142
|
-
Write-Log "Connected to environment successfully"
|
|
143
|
-
return $true
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
throw "Unsupported authentication type: $($Config.authentication.type)"
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
throw "Failed to connect to environment: $_"
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function Backup-Environment {
|
|
155
|
-
param([object]$Config)
|
|
156
|
-
|
|
157
|
-
if ($SkipBackup) {
|
|
158
|
-
Write-Log "Skipping environment backup as requested"
|
|
159
|
-
return
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
Write-Log "Creating environment backup..."
|
|
163
|
-
|
|
164
|
-
$BackupName = "backup-$Environment-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
|
|
165
|
-
$BackupFile = Join-Path $BackupPath "$BackupName.zip"
|
|
166
|
-
|
|
167
|
-
if ($DryRun) {
|
|
168
|
-
Write-Log "DRY RUN: Would create backup: $BackupFile"
|
|
169
|
-
return
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
try {
|
|
173
|
-
# In real implementation, you would create an actual backup
|
|
174
|
-
Write-Log "Creating backup: $BackupName"
|
|
175
|
-
# Backup-CdsEnvironment -EnvironmentName $Config.dynamics365.environmentId -BackupLabel $BackupName
|
|
176
|
-
|
|
177
|
-
Write-Log "Backup created successfully: $BackupFile"
|
|
178
|
-
}
|
|
179
|
-
catch {
|
|
180
|
-
if (-not $Force) {
|
|
181
|
-
throw "Failed to create backup: $_"
|
|
182
|
-
}
|
|
183
|
-
Write-Log "Backup failed but continuing due to -Force flag: $_" -Level "WARN"
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function Deploy-WebResources {
|
|
188
|
-
param([object]$Config)
|
|
189
|
-
|
|
190
|
-
Write-Log "Deploying web resources..."
|
|
191
|
-
|
|
192
|
-
$DistPath = Join-Path $ProjectRoot "dist"
|
|
193
|
-
$WebResources = @()
|
|
194
|
-
|
|
195
|
-
# Get all files from dist directory
|
|
196
|
-
Get-ChildItem -Path $DistPath -Recurse -File | ForEach-Object {
|
|
197
|
-
$RelativePath = $_.FullName.Substring($DistPath.Length + 1)
|
|
198
|
-
$WebResourceName = "dynamics_ui_kit_" + ($RelativePath -replace "[\\\/]", "_" -replace "\.", "_")
|
|
199
|
-
|
|
200
|
-
$WebResources += @{
|
|
201
|
-
Name = $WebResourceName
|
|
202
|
-
DisplayName = "Dynamics UI Kit - $RelativePath"
|
|
203
|
-
FilePath = $_.FullName
|
|
204
|
-
RelativePath = $RelativePath
|
|
205
|
-
Type = Get-WebResourceType $_.Extension
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
Write-Log "Found $($WebResources.Count) web resources to deploy"
|
|
210
|
-
|
|
211
|
-
foreach ($WebResource in $WebResources) {
|
|
212
|
-
if ($DryRun) {
|
|
213
|
-
Write-Log "DRY RUN: Would deploy web resource: $($WebResource.Name)"
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
try {
|
|
217
|
-
Write-Log "Deploying web resource: $($WebResource.Name)"
|
|
218
|
-
|
|
219
|
-
# In real implementation, you would use D365 Web API or PowerShell cmdlets
|
|
220
|
-
# New-CdsWebResource -Name $WebResource.Name -DisplayName $WebResource.DisplayName -FilePath $WebResource.FilePath -Type $WebResource.Type
|
|
221
|
-
|
|
222
|
-
Write-Log "Web resource deployed successfully: $($WebResource.Name)"
|
|
223
|
-
}
|
|
224
|
-
catch {
|
|
225
|
-
Write-Log "Failed to deploy web resource $($WebResource.Name): $_" -Level "ERROR"
|
|
226
|
-
if (-not $Force) {
|
|
227
|
-
throw
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
# Publish all customizations
|
|
234
|
-
if (-not $DryRun) {
|
|
235
|
-
Write-Log "Publishing customizations..."
|
|
236
|
-
# Publish-CdsCustomizations
|
|
237
|
-
Write-Log "Customizations published successfully"
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function Deploy-Solutions {
|
|
242
|
-
param([object]$Config)
|
|
243
|
-
|
|
244
|
-
$SolutionDir = Join-Path $ProjectRoot $SolutionPath
|
|
245
|
-
|
|
246
|
-
if (-not (Test-Path $SolutionDir)) {
|
|
247
|
-
Write-Log "No solutions directory found, skipping solution deployment"
|
|
248
|
-
return
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
Write-Log "Deploying solutions..."
|
|
252
|
-
|
|
253
|
-
# Get all solution files
|
|
254
|
-
$SolutionFiles = Get-ChildItem -Path $SolutionDir -Filter "*.zip" | Sort-Object Name
|
|
255
|
-
|
|
256
|
-
if ($SolutionFiles.Count -eq 0) {
|
|
257
|
-
Write-Log "No solution files found in $SolutionDir"
|
|
258
|
-
return
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
foreach ($SolutionFile in $SolutionFiles) {
|
|
262
|
-
if ($DryRun) {
|
|
263
|
-
Write-Log "DRY RUN: Would deploy solution: $($SolutionFile.Name)"
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
try {
|
|
267
|
-
Write-Log "Deploying solution: $($SolutionFile.Name)"
|
|
268
|
-
|
|
269
|
-
# In real implementation, you would use proper solution import
|
|
270
|
-
# Import-CdsSolution -SolutionFilePath $SolutionFile.FullName -PublishWorkflows -OverwriteUnmanagedCustomizations
|
|
271
|
-
|
|
272
|
-
Write-Log "Solution deployed successfully: $($SolutionFile.Name)"
|
|
273
|
-
}
|
|
274
|
-
catch {
|
|
275
|
-
Write-Log "Failed to deploy solution $($SolutionFile.Name): $_" -Level "ERROR"
|
|
276
|
-
if (-not $Force) {
|
|
277
|
-
throw
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function Get-WebResourceType {
|
|
285
|
-
param([string]$Extension)
|
|
286
|
-
|
|
287
|
-
switch ($Extension.ToLower()) {
|
|
288
|
-
".js" { return "JavaScript" }
|
|
289
|
-
".css" { return "CSS" }
|
|
290
|
-
".html" { return "HTML" }
|
|
291
|
-
".htm" { return "HTML" }
|
|
292
|
-
".xml" { return "XML" }
|
|
293
|
-
".png" { return "PNG" }
|
|
294
|
-
".jpg" { return "JPG" }
|
|
295
|
-
".jpeg" { return "JPG" }
|
|
296
|
-
".gif" { return "GIF" }
|
|
297
|
-
".ico" { return "ICO" }
|
|
298
|
-
".svg" { return "SVG" }
|
|
299
|
-
default { return "Other" }
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
function Test-Deployment {
|
|
304
|
-
param([object]$Config)
|
|
305
|
-
|
|
306
|
-
Write-Log "Running post-deployment tests..."
|
|
307
|
-
|
|
308
|
-
if ($DryRun) {
|
|
309
|
-
Write-Log "DRY RUN: Would run post-deployment tests"
|
|
310
|
-
return $true
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
try {
|
|
314
|
-
# Test basic connectivity
|
|
315
|
-
Write-Log "Testing environment connectivity..."
|
|
316
|
-
|
|
317
|
-
# Test web resources accessibility
|
|
318
|
-
Write-Log "Testing web resources accessibility..."
|
|
319
|
-
|
|
320
|
-
# Test solution health
|
|
321
|
-
Write-Log "Testing solution health..."
|
|
322
|
-
|
|
323
|
-
Write-Log "All post-deployment tests passed"
|
|
324
|
-
return $true
|
|
325
|
-
}
|
|
326
|
-
catch {
|
|
327
|
-
Write-Log "Post-deployment tests failed: $_" -Level "ERROR"
|
|
328
|
-
return $false
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
function Send-Notification {
|
|
333
|
-
param([string]$Status, [object]$Config, [string]$Error = "")
|
|
334
|
-
|
|
335
|
-
Write-Log "Sending deployment notification..."
|
|
336
|
-
|
|
337
|
-
$Subject = "Dynamics 365 Deployment - $Environment - $Status"
|
|
338
|
-
$Body = @"
|
|
339
|
-
Deployment Details:
|
|
340
|
-
- Environment: $Environment
|
|
341
|
-
- Status: $Status
|
|
342
|
-
- Timestamp: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
|
|
343
|
-
- Log File: $LogFile
|
|
344
|
-
|
|
345
|
-
$(if ($Error) { "Error Details:`n$Error" })
|
|
346
|
-
"@
|
|
347
|
-
|
|
348
|
-
if ($Config.notifications.deploymentSuccess.enabled -and $Status -eq "SUCCESS") {
|
|
349
|
-
Write-Log "Sending success notification"
|
|
350
|
-
# Send-MailMessage or use other notification methods
|
|
351
|
-
}
|
|
352
|
-
elseif ($Config.notifications.deploymentFailure.enabled -and $Status -eq "FAILED") {
|
|
353
|
-
Write-Log "Sending failure notification"
|
|
354
|
-
# Send-MailMessage or use other notification methods
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
# Main deployment workflow
|
|
359
|
-
try {
|
|
360
|
-
Show-Banner
|
|
361
|
-
|
|
362
|
-
Write-Log "Starting deployment to $Environment environment"
|
|
363
|
-
Write-Log "Log file: $LogFile"
|
|
364
|
-
|
|
365
|
-
# Load configuration
|
|
366
|
-
$Config = Load-Configuration -Environment $Environment
|
|
367
|
-
|
|
368
|
-
# Check prerequisites
|
|
369
|
-
Test-Prerequisites
|
|
370
|
-
|
|
371
|
-
# Connect to environment
|
|
372
|
-
Connect-Environment -Config $Config
|
|
373
|
-
|
|
374
|
-
# Create backup
|
|
375
|
-
Backup-Environment -Config $Config
|
|
376
|
-
|
|
377
|
-
# Deploy web resources
|
|
378
|
-
Deploy-WebResources -Config $Config
|
|
379
|
-
|
|
380
|
-
# Deploy solutions
|
|
381
|
-
Deploy-Solutions -Config $Config
|
|
382
|
-
|
|
383
|
-
# Run tests
|
|
384
|
-
$TestResults = Test-Deployment -Config $Config
|
|
385
|
-
|
|
386
|
-
if ($TestResults) {
|
|
387
|
-
Write-Log "Deployment completed successfully!" -Level "SUCCESS"
|
|
388
|
-
Send-Notification -Status "SUCCESS" -Config $Config
|
|
389
|
-
|
|
390
|
-
Write-Host ""
|
|
391
|
-
Write-Host "✅ Deployment completed successfully!" -ForegroundColor Green
|
|
392
|
-
Write-Host "📋 Log file: $LogFile" -ForegroundColor Cyan
|
|
393
|
-
|
|
394
|
-
if (-not $DryRun) {
|
|
395
|
-
Write-Host "🌐 Environment URL: $($Config.dynamics365.orgUrl)" -ForegroundColor Cyan
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
else {
|
|
399
|
-
throw "Post-deployment tests failed"
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
catch {
|
|
403
|
-
$ErrorMessage = $_.Exception.Message
|
|
404
|
-
Write-Log "Deployment failed: $ErrorMessage" -Level "ERROR"
|
|
405
|
-
Send-Notification -Status "FAILED" -Config $Config -Error $ErrorMessage
|
|
406
|
-
|
|
407
|
-
Write-Host ""
|
|
408
|
-
Write-Host "❌ Deployment failed!" -ForegroundColor Red
|
|
409
|
-
Write-Host "Error: $ErrorMessage" -ForegroundColor Red
|
|
410
|
-
Write-Host "📋 Log file: $LogFile" -ForegroundColor Cyan
|
|
411
|
-
|
|
412
|
-
exit 1
|
|
413
|
-
}
|
|
414
|
-
finally {
|
|
415
|
-
Write-Host ""
|
|
416
|
-
Write-Host "Deployment process completed." -ForegroundColor Blue
|
|
417
|
-
}
|