feat: Implement comprehensive Azure Functions code generation and deployment workflow
- Added detailed planning, code generation, testing, and deployment steps for Azure Functions. - Introduced status tracking and error handling mechanisms. - Established best practices for code generation and deployment, including security and structure guidelines. - Created GitHub Actions workflow for production deployment with build, test, and deployment stages. - Developed PowerShell script for full production deployment with custom domain support. - Designed Bicep templates for infrastructure setup, including Azure Static Web Apps and Function Apps. - Configured parameters for production deployment, including Stripe public key and custom domain settings. - Added SWA CLI configuration for local development and deployment. - Documented production deployment success criteria and post-deployment tasks.
This commit is contained in:
146
.github/chatmodes/Azure_function_codegen_and_deployment.chatmode.md
vendored
Normal file
146
.github/chatmodes/Azure_function_codegen_and_deployment.chatmode.md
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
---
|
||||
description: Generate and deploy Azure Functions with comprehensive planning, code generation, and deployment automation.
|
||||
tools: ["changes","edit","extensions","fetch","findTestFiles","githubRepo","new","openSimpleBrowser","problems","runCommands","runNotebooks","runTasks","search","testFailure","todos","usages","vscodeAPI","Microsoft Docs","azureterraformbestpractices","bicepschema","deploy","quota","get_bestpractices","azure_query_azure_resource_graph","azure_generate_azure_cli_command","azure_get_auth_state","azure_get_current_tenant","azure_get_available_tenants","azure_set_current_tenant","azure_get_selected_subscriptions","azure_open_subscription_picker","azure_sign_out_azure_user","azure_diagnose_resource","azure_list_activity_logs"]
|
||||
model: Claude Sonnet 4
|
||||
---
|
||||
|
||||
# Azure Functions Code Generation and Deployment
|
||||
|
||||
Enterprise-grade Azure Functions development workflow with automated planning, code generation, testing, and deployment using Azure best practices and Infrastructure as Code (IaC).
|
||||
|
||||
## Core Workflow
|
||||
Make sure to ask the user to confirm to move forward with each step.
|
||||
|
||||
### 1. Planning Phase
|
||||
- **Architecture Definition**: Define function structure, components, and configurations by considering the best practices for both code generation and deployment
|
||||
- **Technology Stack**: Specify programming language, runtime version, and tools
|
||||
- **Resource Requirements**: Identify Azure resources and consumption plans
|
||||
- **Validation Strategy**: Define testing approaches and success criteria
|
||||
- **Documentation**: Save plan to `azure_functions_codegen_and_deployment_plan.md`
|
||||
|
||||
### 2. Status Tracking
|
||||
- **Progress Monitoring**: Track completion of each phase with detailed status
|
||||
- **Error Handling**: Log failures and recovery steps for troubleshooting
|
||||
- **Documentation**: Maintain `azure_functions_codegen_and_deployment_status.md`
|
||||
|
||||
### 3. Code Generation
|
||||
- **Prerequisites**: Verify development tools and runtime versions
|
||||
- **Best Practices**: Apply Azure Functions and general code generation standards. Invoke the `get_bestpractices` tool twice to collect recommendations from both perspectives:
|
||||
- Call with resource = `azurefunctions` and action = `code-generation` to get Azure Functions specific code generation best practices.
|
||||
- Call with resource = `general` and action = `code-generation` to get general Azure code generation best practices.
|
||||
Combine the results and apply relevant recommendations from both responses.
|
||||
- **Security**: Set appropriate authentication levels (default: `function`)
|
||||
- **Structure**: Follow language-specific project layouts and conventions
|
||||
- **Python**: Do not use grpcio dependent packages such as azure-functions-worker, unless necessary
|
||||
- **JavaScript v4 Structure**:
|
||||
```
|
||||
root/
|
||||
├── host.json # Function host configuration
|
||||
├── local.settings.json # Development settings
|
||||
├── package.json # Dependencies
|
||||
├── src/
|
||||
│ ├── app.js # Main application entry
|
||||
│ └── [modules].js # Business logic
|
||||
└── tests/ # Test suite
|
||||
```
|
||||
|
||||
### 4. Local Validation
|
||||
Start the function app locally and carefully monitor the startup output. Look for any errors, warnings, or unusual messages.
|
||||
Don't proceed to testing until you've confirmed a clean startup. If you see any issues, investigate and fix them before continuing.
|
||||
- **Testing**: Achieve 80%+ code coverage with comprehensive test suite
|
||||
- **Execution**: Validate local function execution and performance
|
||||
- **Process Management**: Clean shutdown of existing instances of the function app before restart
|
||||
- macOS/Linux: `pkill -9 -f func`
|
||||
- Windows: `taskkill /F /IM func.exe /T`
|
||||
#### Post-Testing Cleanup Protocol
|
||||
Upon finishing testing, ensure all processes are properly shut down to prevent resource conflicts and port binding issues:
|
||||
|
||||
### 5. Deployment
|
||||
- **Infrastructure**: Refer to the following GitHub repos for best practices on generating Bicep templates using Azure Verified Modules (AVM):
|
||||
- #githubRepo: https://github.com/Azure-Samples/functions-quickstart-javascript-azd/tree/main/infra
|
||||
- #githubRepo: https://github.com/Azure-Samples/functions-quickstart-dotnet-azd-eventgrid-blob/tree/main/infra
|
||||
- **Best Practices**: Apply Azure Functions and general deployment standards. Invoke the `get_bestpractices` tool twice to collect recommendations from both perspectives:
|
||||
- Call with resource = `azurefunctions` and action = `deployment` to get Azure Functions specific deployment best practices.
|
||||
- Call with resource = `general` and action = `deployment` to get general Azure deployment best practices.
|
||||
Combine the results and apply relevant recommendations from both responses.
|
||||
- **Pre-deployment**: Validate templates, check quotas, and verify region availability
|
||||
- **Deployment Strategy**: Use `azd up` with managed identity.
|
||||
- ALWAYS Use Flex Consumption plan (FC1) for deployment, never Y1 dynamic.
|
||||
- ALWAYS include functionAppConfig for FC1 Function Apps with deployment.storage configuration. Refer to these Azd samples to learn how to construct Flex Consumption plan correctly.
|
||||
- #githubRepo: https://github.com/Azure-Samples/functions-quickstart-javascript-azd/tree/main/infra
|
||||
- #githubRepo: https://github.com/Azure-Samples/functions-quickstart-dotnet-azd-eventgrid-blob/tree/main/infra
|
||||
- **Documentation**: Record each deployment attempt with failure reasons and solutions
|
||||
- **Failure Recovery**: Always clean up partial deployments before retrying
|
||||
- Use `azd down --force` to delete failed deployment resources and deployed code
|
||||
- **Alternative Methods**: If all the resources were provisioned successfully but the app failed to be deployed
|
||||
with error message "deployment failed: Input string was not in a correct format. Failure to parse near offset 40.
|
||||
Format item ends prematurely.", use Azure CLI deployment to upload the function app code.
|
||||
|
||||
|
||||
### 6. Post-Deployment
|
||||
- **Authentication**: Retrieve function names being deployed, then retrieve and configure function keys
|
||||
- **Endpoint Testing**: Validate all function endpoints with proper authentication
|
||||
- **Monitoring**: Verify Application Insights telemetry and establish performance baselines
|
||||
- **Documentation**: Create a README with deployment and usage instructions
|
||||
|
||||
## Enterprise Environment Considerations
|
||||
|
||||
### Corporate Policy Compliance
|
||||
- **Alternative Strategies**: Prepare Azure CLI fallback for blocked `azd` commands
|
||||
- **Compliance Standards**: Use Azure Verified Modules (AVM) for enterprise requirements
|
||||
- **Network Restrictions**: Consider VNet integration and private endpoints
|
||||
|
||||
### Security & Authentication
|
||||
- **Managed Identity**: Preferred authentication method for Azure-hosted resources
|
||||
- **Function Keys**: Use function-level keys following principle of least privilege
|
||||
- **Key Management**: Retrieve keys post-deployment for endpoint testing
|
||||
- **RBAC Configuration**: Implement proper role assignments for dependencies
|
||||
|
||||
## Quality Assurance
|
||||
|
||||
### Testing Requirements
|
||||
- **Unit Tests**: 100% passing rate
|
||||
- **Integration Tests**: 80%+ coverage of main scenarios
|
||||
- **Code Quality**: ESLint/linting checks passing
|
||||
- **Performance**: Baseline performance validation
|
||||
|
||||
### Deployment Validation
|
||||
- **Infrastructure**: Bicep templates pass validation
|
||||
- **Pre-deployment**: Use deploy tool and set parameter `command` to be `deploy_iac_rules_get` to get the best practices rules for iac generation.
|
||||
- **Authentication**: Proper managed identity and RBAC configuration
|
||||
- **Monitoring**: Application Insights receiving telemetry
|
||||
|
||||
## Failure Recovery & Troubleshooting
|
||||
|
||||
### Common Issues & Solutions
|
||||
1. **Policy Violations**: Switch to Azure CLI deployment methods
|
||||
2. **Missing Dependencies**: Systematic tool installation and validation
|
||||
3. **Authentication Issues**: Comprehensive RBAC and managed identity setup
|
||||
4. **Runtime Compatibility**: Use supported versions (Node.js 20+, Python 3.11+)
|
||||
5. **Partial Deployments**: Clean resource group deletion before retry
|
||||
|
||||
### Deployment Failure Recovery Protocol
|
||||
```bash
|
||||
# Delete failed deployment resources and deployed code
|
||||
azd down --force
|
||||
|
||||
# Or
|
||||
# Clean failed deployment
|
||||
az group delete --name rg-<AZURE_ENV_NAME> --yes --no-wait
|
||||
az group wait --name rg-<AZURE_ENV_NAME> --deleted --timeout 300
|
||||
|
||||
# Retry deployment
|
||||
azd up
|
||||
```
|
||||
|
||||
## Reference Resources
|
||||
|
||||
### Azure Functions Best Practices
|
||||
- **Programming Models**: Use latest versions (v4 JavaScript, v2 Python)
|
||||
- **Extension Bundles**: Prefer over SDKs for simplified dependency management
|
||||
- **Event Sources**: Use EventGrid for blob triggers
|
||||
- **Configuration**: Generate `local.settings.json` for local development
|
||||
|
||||
### Infrastructure Templates
|
||||
- [JavaScript Azure Functions AZD Sample](https://github.com/Azure-Samples/functions-quickstart-javascript-azd/tree/main/infra)
|
||||
- [.NET Azure Functions with EventGrid Sample](https://github.com/Azure-Samples/functions-quickstart-dotnet-azd-eventgrid-blob/tree/main/infra)
|
||||
249
.github/workflows/production-deployment.yml
vendored
Normal file
249
.github/workflows/production-deployment.yml
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
name: Production Deployment
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
custom_domain:
|
||||
description: 'Custom domain name'
|
||||
required: false
|
||||
default: 'miraclesinmotion.org'
|
||||
force_deploy:
|
||||
description: 'Force deployment even if tests fail'
|
||||
required: false
|
||||
default: 'false'
|
||||
|
||||
env:
|
||||
NODE_VERSION: '22'
|
||||
AZURE_STATIC_WEB_APPS_API_TOKEN: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
|
||||
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build and Test
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
lfs: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install main dependencies
|
||||
run: npm install --legacy-peer-deps
|
||||
|
||||
- name: Install API dependencies
|
||||
run: |
|
||||
cd api
|
||||
npm install
|
||||
cd ..
|
||||
|
||||
- name: Run linting
|
||||
run: npm run lint
|
||||
continue-on-error: true
|
||||
|
||||
- name: Run tests
|
||||
run: npx vitest run --reporter=verbose
|
||||
continue-on-error: ${{ github.event.inputs.force_deploy == 'true' }}
|
||||
|
||||
- name: Build application
|
||||
run: npm run build
|
||||
|
||||
- name: Build API
|
||||
run: |
|
||||
cd api
|
||||
npm run build || npm run tsc
|
||||
cd ..
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-files
|
||||
path: |
|
||||
dist/
|
||||
api/
|
||||
staticwebapp.config.json
|
||||
|
||||
deploy-infrastructure:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-and-test
|
||||
name: Deploy Infrastructure
|
||||
outputs:
|
||||
static-web-app-name: ${{ steps.deploy.outputs.staticWebAppName }}
|
||||
function-app-name: ${{ steps.deploy.outputs.functionAppName }}
|
||||
static-web-app-url: ${{ steps.deploy.outputs.staticWebAppUrl }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Azure Login
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
|
||||
- name: Create Resource Group
|
||||
run: |
|
||||
az group create \
|
||||
--name rg-miraclesinmotion-prod \
|
||||
--location "East US"
|
||||
|
||||
- name: Deploy Infrastructure
|
||||
id: deploy
|
||||
run: |
|
||||
DEPLOYMENT_NAME="mim-prod-$(date +%Y%m%d-%H%M%S)"
|
||||
|
||||
# Deploy infrastructure
|
||||
DEPLOYMENT_OUTPUT=$(az deployment group create \
|
||||
--resource-group rg-miraclesinmotion-prod \
|
||||
--template-file infrastructure/main-production.bicep \
|
||||
--parameters infrastructure/main-production.parameters.json \
|
||||
--parameters stripePublicKey="${{ secrets.STRIPE_PUBLIC_KEY }}" \
|
||||
--parameters customDomainName="${{ github.event.inputs.custom_domain || 'miraclesinmotion.org' }}" \
|
||||
--parameters enableCustomDomain=true \
|
||||
--name $DEPLOYMENT_NAME \
|
||||
--output json)
|
||||
|
||||
# Extract outputs
|
||||
STATIC_WEB_APP_NAME=$(echo $DEPLOYMENT_OUTPUT | jq -r '.properties.outputs.staticWebAppName.value')
|
||||
FUNCTION_APP_NAME=$(echo $DEPLOYMENT_OUTPUT | jq -r '.properties.outputs.functionAppName.value')
|
||||
STATIC_WEB_APP_URL=$(echo $DEPLOYMENT_OUTPUT | jq -r '.properties.outputs.staticWebAppUrl.value')
|
||||
|
||||
# Set outputs
|
||||
echo "staticWebAppName=$STATIC_WEB_APP_NAME" >> $GITHUB_OUTPUT
|
||||
echo "functionAppName=$FUNCTION_APP_NAME" >> $GITHUB_OUTPUT
|
||||
echo "staticWebAppUrl=$STATIC_WEB_APP_URL" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "✅ Infrastructure deployed successfully"
|
||||
echo "📱 Static Web App: $STATIC_WEB_APP_NAME"
|
||||
echo "⚡ Function App: $FUNCTION_APP_NAME"
|
||||
echo "🌐 URL: $STATIC_WEB_APP_URL"
|
||||
|
||||
deploy-application:
|
||||
runs-on: ubuntu-latest
|
||||
needs: deploy-infrastructure
|
||||
name: Deploy Application
|
||||
environment:
|
||||
name: production
|
||||
url: ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-files
|
||||
|
||||
- name: Azure Login
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
|
||||
- name: Get Static Web App Deployment Token
|
||||
id: swa-token
|
||||
run: |
|
||||
DEPLOYMENT_TOKEN=$(az staticwebapp secrets list \
|
||||
--name ${{ needs.deploy-infrastructure.outputs.static-web-app-name }} \
|
||||
--resource-group rg-miraclesinmotion-prod \
|
||||
--query "properties.apiKey" \
|
||||
--output tsv)
|
||||
echo "::add-mask::$DEPLOYMENT_TOKEN"
|
||||
echo "token=$DEPLOYMENT_TOKEN" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Setup Node.js for SWA CLI
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
|
||||
- name: Install SWA CLI
|
||||
run: npm install -g @azure/static-web-apps-cli
|
||||
|
||||
- name: Deploy to Static Web App
|
||||
run: |
|
||||
swa deploy ./dist \
|
||||
--api-location ./api \
|
||||
--env production \
|
||||
--deployment-token ${{ steps.swa-token.outputs.token }}
|
||||
|
||||
- name: Deploy Azure Functions
|
||||
run: |
|
||||
# Create deployment package
|
||||
cd api
|
||||
zip -r ../api-deployment.zip . -x "node_modules/*" "*.test.*" "*.md"
|
||||
cd ..
|
||||
|
||||
# Deploy functions
|
||||
az functionapp deployment source config-zip \
|
||||
--resource-group rg-miraclesinmotion-prod \
|
||||
--name ${{ needs.deploy-infrastructure.outputs.function-app-name }} \
|
||||
--src api-deployment.zip
|
||||
|
||||
- name: Warm up application
|
||||
run: |
|
||||
echo "🔥 Warming up the deployed application..."
|
||||
curl -s ${{ needs.deploy-infrastructure.outputs.static-web-app-url }} > /dev/null
|
||||
curl -s ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/portals > /dev/null
|
||||
echo "✅ Application warmed up successfully"
|
||||
|
||||
post-deployment:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [deploy-infrastructure, deploy-application]
|
||||
name: Post-Deployment Tasks
|
||||
steps:
|
||||
- name: Run smoke tests
|
||||
run: |
|
||||
echo "🧪 Running smoke tests..."
|
||||
|
||||
# Test main page
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" ${{ needs.deploy-infrastructure.outputs.static-web-app-url }})
|
||||
if [ $STATUS -eq 200 ]; then
|
||||
echo "✅ Main page is accessible"
|
||||
else
|
||||
echo "❌ Main page returned status: $STATUS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test portals page
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/portals)
|
||||
if [ $STATUS -eq 200 ]; then
|
||||
echo "✅ Portals page is accessible"
|
||||
else
|
||||
echo "❌ Portals page returned status: $STATUS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🎉 All smoke tests passed!"
|
||||
|
||||
- name: Create deployment summary
|
||||
run: |
|
||||
echo "## 🚀 Production Deployment Complete" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### 📊 Deployment Details" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Static Web App**: ${{ needs.deploy-infrastructure.outputs.static-web-app-name }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Primary URL**: ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Portal Access**: ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/portals" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Custom Domain**: https://${{ github.event.inputs.custom_domain || 'miraclesinmotion.org' }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### 🔗 Quick Links" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- [🏠 Main Site](${{ needs.deploy-infrastructure.outputs.static-web-app-url }})" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- [🚪 Portals](${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/portals)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- [💰 Donate](${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/donate)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- [🤝 Volunteer](${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/volunteers)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- [📊 Analytics](${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/analytics)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### 📋 Next Steps" >> $GITHUB_STEP_SUMMARY
|
||||
echo "1. Configure DNS records for custom domain" >> $GITHUB_STEP_SUMMARY
|
||||
echo "2. Update Stripe webhook endpoints" >> $GITHUB_STEP_SUMMARY
|
||||
echo "3. Test all portal functionality" >> $GITHUB_STEP_SUMMARY
|
||||
echo "4. Monitor application performance" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Notify team
|
||||
if: success()
|
||||
run: |
|
||||
echo "🎉 Production deployment completed successfully!"
|
||||
echo "🌐 Application is live at: ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}"
|
||||
echo "🚪 Portals are accessible at: ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/portals"
|
||||
Reference in New Issue
Block a user