-
Notifications
You must be signed in to change notification settings - Fork 96
feat(vscode): add "Deploy to Azure" webview and deploy flow (create Logic App without wizard) #8691
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
🤖 AI PR Validation ReportPR Review ResultsThank you for your submission! Here's detailed feedback on your PR title and body compliance:✅ PR Title
✅ Commit Type
❌ Risk Level
✅ What & Why
❌ Impact of Change
❌ Test Plan
|
| Section | Status | Recommendation |
|---|---|---|
| Title | ✅ | Shorten slightly and keep key action & scope |
| Commit Type | ✅ | Good (feature) |
| Risk Level | ❌ | Change to risk:high in both label & PR body |
| What & Why | ✅ | Add a one-line capabilities summary (optional) |
| Impact of Change | ❌ | Fill Developer and System impacts (see suggested text) |
| Test Plan | ❌ | Add unit/E2E tests or a detailed manual test plan |
| Contributors | Add credits/participants (recommended) | |
| Screenshots/Videos | Add screenshots/GIFs of the webview and flows |
Final Notes & Action Items
- Change the risk label and the Risk Level section in the PR body to High (risk:high) — this PR introduces cloud resource creation, new SDK deps, and extension/server interactions that elevate risk.
- Update the Impact of Change section with the bullet points suggested above (Users / Developers / System). Be explicit about new permissions, new dependencies, and potential CI/node version changes.
- Expand the Test Plan: add unit tests and/or E2E tests. If you must rely on manual testing, add a detailed manual test matrix and explain why automated tests are missing and when they will be added.
- Add screenshots or a short video of the Deploy webview showing flows and validations.
- Address the existing
needs-pr-updatelabel by making the above updates and removing the label once ready.
Please update the PR title/body to address the items above and re-submit for review. If you want, paste the updated PR body here and I will re-check it against the template.
Note: I set the advised risk level to High because the diff creates/changes code paths that create Azure resources, adds new Azure SDK packages, modifies resource creation behavior (creates RG/Plan/Storage/AppInsights), and adds a large webview surface — these changes have cross-cutting impact and require careful testing and permission review.
Last updated: Thu, 08 Jan 2026 20:47:59 GMT
| state.isCreatingNewStorageAccount = action.payload === '__CREATE_NEW__'; | ||
| }, | ||
| setNewStorageAccountName(state, action: PayloadAction<string>) { | ||
| state.newStorageAccountName = action.payload; |
Check failure
Code scanning / CodeQL
Insecure randomness High
Math.random()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request implements a significant UX improvement by migrating the Logic App deployment command from VS Code's native wizard interface to a custom webview. This change provides better control over the deployment process, enhanced validation, and persistent display of user inputs.
Key Changes
- New deployment webview: Custom React-based UI for deployment with comprehensive validation
- Enhanced state management: Added Redux slice for managing deployment state across subscription, resource group, Logic App, and dependent resource selections
- Wizard-free Logic App creation: New code path to create Logic Apps programmatically without user prompts
- Azure resource fetching: New API service methods to fetch subscriptions, Logic Apps, resource groups, locations, app service plans, and storage accounts
Reviewed changes
Copilot reviewed 20 out of 22 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Added Azure ARM dependencies (@azure/arm-resources, @azure/arm-subscriptions) for resource management |
| libs/vscode-extension/src/lib/models/project.ts | Added 'deploy' project name constant |
| libs/vscode-extension/src/lib/models/extensioncommand.ts | Added deploy-related extension commands (deploy, cancel_deploy, getFilteredLocations) |
| apps/vs-code-react/src/stateWrapper.tsx | Added navigation routing for deploy project |
| apps/vs-code-react/src/state/store.ts | Registered deploySlice reducer in Redux store |
| apps/vs-code-react/src/state/deploySlice.ts | Complete Redux slice for deployment state management with 21 state properties |
| apps/vs-code-react/src/run-service/types.ts | Added logicApps resource type and deploy route |
| apps/vs-code-react/src/run-service/export/index.ts | Added methods for fetching Logic Apps, locations, app service plans, storage accounts, and name availability checking |
| apps/vs-code-react/src/router/index.tsx | Added DeployApp route |
| apps/vs-code-react/src/intl/messages.ts | Added 271 new localization strings for deployment UI |
| apps/vs-code-react/src/intl/index.ts | Exported deployMessages |
| apps/vs-code-react/src/app/deploy/deployStyles.ts | Styling definitions for deployment UI |
| apps/vs-code-react/src/app/deploy/deploy.tsx | Main deployment React component (853 lines) with form validation and Azure resource management |
| apps/vs-code-designer/src/extensionVariables.ts | Added deploy webview key |
| apps/vs-code-designer/src/app/tree/subscriptionTree/subscriptionTreeItem.ts | Added createChildWithoutPrompts method for programmatic Logic App creation (254 lines) |
| apps/vs-code-designer/src/app/commands/registerCommands.ts | Changed deploy command from wizard to webview handler |
| apps/vs-code-designer/src/app/commands/deploy/deployWebview.ts | New webview handler for deployment with message processing |
| apps/vs-code-designer/src/app/commands/deploy/deploy.ts | Exported deploy function for reuse |
| apps/vs-code-designer/src/app/commands/createLogicApp/createLogicAppSteps/logicAppCreateStep.ts | Added httpsOnly and vnetRouteAllEnabled properties to site config |
| apps/vs-code-designer/src/app/commands/createLogicApp/createLogicApp.ts | Added createLogicAppWithoutWizard function for programmatic creation |
| apps/vs-code-designer/package.json | Added Azure ARM dependencies |
| Localize/lang/strings.json | Added localization keys and descriptions for deployment UI |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
| reserved: context.newSiteOS === WebsiteOS.linux, | ||
| identity: context.customLocation ? undefined : { type: 'SystemAssigned' }, | ||
| httpsOnly: true, | ||
| vnetRouteAllEnabled: false, // Enable VNet route all for enhanced security |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent handling of vnetRouteAllEnabled property. The comment says "Enable VNet route all for enhanced security" but the value is set to false, which disables the feature. Either the comment is incorrect or the value should be true.
| vnetRouteAllEnabled: false, // Enable VNet route all for enhanced security | |
| vnetRouteAllEnabled: true, // Enable VNet route all for enhanced security |
| createHandler: async (actionContext: IActionContext, data: any) => { | ||
| if (data.createNew) { | ||
| // User wants to create a new Logic App without wizard prompts | ||
| const createContext: any = { | ||
| ...actionContext, | ||
| newSiteName: data.newLogicAppName, | ||
| location: data.location, | ||
| newResourceGroupName: data.isCreatingNewResourceGroup ? data.resourceGroup : undefined, | ||
| resourceGroup: data.isCreatingNewResourceGroup ? undefined : { name: data.resourceGroup }, | ||
| newPlanName: data.isCreatingNewAppServicePlan ? data.appServicePlan : undefined, | ||
| plan: data.isCreatingNewAppServicePlan ? undefined : { id: data.appServicePlan }, | ||
| appServicePlanSku: data.appServicePlanSku || 'WS1', | ||
| newStorageAccountName: data.isCreatingNewStorageAccount ? data.storageAccount : undefined, | ||
| storageAccount: data.isCreatingNewStorageAccount ? undefined : { id: data.storageAccount }, | ||
| createAppInsights: data.createAppInsights, | ||
| newAppInsightsName: data.appInsightsName, | ||
| }; | ||
|
|
||
| // Create the Logic App using the wizard-free method | ||
| const node: SlotTreeItem = await createLogicAppWithoutWizard( | ||
| createContext, | ||
| data.subscriptionId, | ||
| true // Skip notification since we're deploying next | ||
| ); | ||
|
|
||
| // Now deploy to the newly created Logic App | ||
| await deploy(actionContext, node.fullId, node.fullId); | ||
| } else { | ||
| // Deploy to existing Logic App | ||
| await deploy(actionContext, data.logicAppId, data.logicAppId); | ||
| } | ||
| }, |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing input validation in deployViaWebview handler. The data object should be validated before being used to create resources. Required fields like subscriptionId, newLogicAppName, location, resourceGroup should be checked for existence and validity to prevent runtime errors.
| // Check storage account name availability (debounced) | ||
| useEffect(() => { | ||
| if (!newStorageAccountName || !isCreatingNew || !isCreatingNewStorageAccount || !selectedSubscription || storageAccountNameError) { | ||
| setStorageNameUnavailable(false); | ||
| setStorageNameMessage(''); | ||
| return; | ||
| } | ||
|
|
||
| setIsCheckingStorageName(true); | ||
| const timeoutId = setTimeout(async () => { | ||
| try { | ||
| const result = await apiService.checkStorageAccountNameAvailability(selectedSubscription, newStorageAccountName); | ||
| setStorageNameUnavailable(!result.available); | ||
| setStorageNameMessage(result.message || ''); | ||
| } catch (error) { | ||
| console.error('Error checking storage account name availability:', error); | ||
| } finally { | ||
| setIsCheckingStorageName(false); | ||
| } | ||
| }, 500); // 500ms debounce | ||
|
|
||
| return () => clearTimeout(timeoutId); | ||
| }, [newStorageAccountName, isCreatingNew, isCreatingNewStorageAccount, selectedSubscription, storageAccountNameError, apiService]); | ||
|
|
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate useEffect for storage account name availability check. Lines 294-316 and 318-340 contain identical logic. This will cause the availability check to run twice for every state change, doubling the API calls and potentially causing race conditions.
| // Check storage account name availability (debounced) | |
| useEffect(() => { | |
| if (!newStorageAccountName || !isCreatingNew || !isCreatingNewStorageAccount || !selectedSubscription || storageAccountNameError) { | |
| setStorageNameUnavailable(false); | |
| setStorageNameMessage(''); | |
| return; | |
| } | |
| setIsCheckingStorageName(true); | |
| const timeoutId = setTimeout(async () => { | |
| try { | |
| const result = await apiService.checkStorageAccountNameAvailability(selectedSubscription, newStorageAccountName); | |
| setStorageNameUnavailable(!result.available); | |
| setStorageNameMessage(result.message || ''); | |
| } catch (error) { | |
| console.error('Error checking storage account name availability:', error); | |
| } finally { | |
| setIsCheckingStorageName(false); | |
| } | |
| }, 500); // 500ms debounce | |
| return () => clearTimeout(timeoutId); | |
| }, [newStorageAccountName, isCreatingNew, isCreatingNewStorageAccount, selectedSubscription, storageAccountNameError, apiService]); |
| // Generate a simple GUID-like suffix | ||
| const generateGuid = () => { | ||
| return Math.random().toString(36).substring(2, 10); | ||
| }; | ||
|
|
||
| const guid = generateGuid(); |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The random GUID generation using Math.random() is not cryptographically secure and may produce collisions. Consider using a proper UUID library or crypto.randomUUID() for generating unique identifiers for Azure resources.
| // Generate a simple GUID-like suffix | |
| const generateGuid = () => { | |
| return Math.random().toString(36).substring(2, 10); | |
| }; | |
| const guid = generateGuid(); | |
| // Generate a simple GUID-like suffix using cryptographically secure random values | |
| const generateSecureSuffix = () => { | |
| const bytes = new Uint8Array(8); | |
| crypto.getRandomValues(bytes); | |
| return Array.from(bytes, (b) => b.toString(36).padStart(2, '0')).join('').substring(0, 8); | |
| }; | |
| const guid = generateSecureSuffix(); |
| * @param skipNotification - If true, skips the completion notification | ||
| * @returns The created Logic App tree item | ||
| */ | ||
| export async function createLogicAppWithoutWizard( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't SubscriptionTreeItem.createChild already skip prompts if the values are provided in context? And if not, would it make sense to modify that method to skip prompts when not needed instead of adding this one?
| }; | ||
|
|
||
| // Create the Logic App using the wizard-free method | ||
| const node: SlotTreeItem = await createLogicAppWithoutWizard( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't createLogicApp called from deploy if the logic app doesn't exist? Can this be refactored so that the logic app is either always created prior to deploy or always created within deploy function?
Commit Type
Risk Level
What & Why
This moves the deploy command from using vscode wizards to a custom webview which allows more control and validation from the extension. We also display all relevant information so that users don't have to remember what they had input previously.
Impact of Change
Users now see all content before deploying, and allow naming of resources when a new logic app is created.
Test Plan
Contributors
Screenshots/Videos