Azure Developer CLI: From Dev to Prod with One Click

This post walks through how to implement a “build once, deploy everywhere” pattern using Azure Developer CLI (azd) that provisions environment-specific infrastructure and promotes applications from dev to prod with the same build artifacts. You’ll learn how to use conditional Bicep deployment, environment variable injection, package preservation across environments, and automated CI/CD promotion from development to production.

Environment-Specific Infrastructure

When deploying applications across environments, different requirements emerge:

Component
Development
Production

Networking
Public access
VNet integration + Private endpoints

Storage
Public with restrictions
Private endpoints only

App Service Plan
B2 Basic
S1 Standard

Security
Managed identity
Enhanced network isolation

Rather than maintaining separate infrastructure templates or complex configuration files for each environment, we can use a single set of Bicep files that adapt based on an environment variable. This approach eliminates infrastructure drift while keeping deployments simple and consistent.

Set up resources based on an environment variable

To conditionally provision resources based on environment type, azd leverages an environment variable AZURE_ENV_TYPE to make decisions at deployment time.

Behind the scenes, azd passes AZURE_ENV_TYPE to Bicep as the envType parameter:

@description(‘Environment type – determines networking configuration (dev/test/prod)’)
@allowed([‘dev’, ‘test’, ‘prod’])
param envType string = ‘dev’

This parameter then drives conditional resource deployment in Bicep:

For Network Deployment:

// Deploy network infrastructure only for production environments
module network ‘./network.bicep’ = if (envType == ‘prod’) {
name: ‘networkDeployment’
params: {
location: location
tags: tags
abbrs: abbrs
resourceToken: resourceToken
}
}

Similarly for Storage Configuration:

module storageAccount ‘br/public:avm/res/storage/storage-account:0.17.2’ = {
name: ‘storageAccount’
params: {
name: storageAccountName
allowSharedKeyAccess: false
publicNetworkAccess: envType == ‘prod’ ? ‘Disabled’ : ‘Enabled’
networkAcls: envType == ‘prod’ ? {
defaultAction: ‘Deny’
virtualNetworkRules: []
bypass: ‘AzureServices’
} : {
defaultAction: ‘Allow’
virtualNetworkRules: []
bypass: ‘AzureServices’
}
// … other configuration
}
}

Finally for App Service Plan Sizing:

sku: {
name: envType == ‘prod’ ? ‘S1’ : ‘B2’
tier: envType == ‘prod’ ? ‘Standard’ : ‘Basic’
}

Enhance default CI/CD workflow

azd includes a powerful command to bootstrap CI/CD pipeline:

azd pipeline config

This generates a basic workflow. However, for dev-to-prod promotion, enhance it with these steps:

1. Package Once:

– name: Package Application
run: |
mkdir -p ./dist
azd package app –output-path ./dist/app-package.zip
# Create a backup copy for production deployment
cp ./dist/app-package.zip ./app-package-backup.zip
echo “✅ Application packaged and backup created”

2. Deploy to Dev:

– name: Deploy to Development
run: azd deploy app –from-package ./dist/app-package.zip –no-prompt

3. Validation Gate:

– name: Validate Application
run: |
echo “🔍 Validating application in development environment…”
# Add your validation logic here:
# – Health checks and integration tests
# – Security and compliance scanning
# – Performance validation
sleep 3 # Simulate validation time
echo “✅ Application validation passed”

4. Set environment variables:

– name: Promote to Production
run: |
# Create production environment name by replacing -dev with -prod, or adding -prod if no -dev suffix
PROD_ENV_NAME=”${AZURE_ENV_NAME%-dev}-prod”
echo “Production environment name: $PROD_ENV_NAME”

# Set environment variables for this step
export AZURE_ENV_NAME=”$PROD_ENV_NAME”
export AZURE_ENV_TYPE=”prod”

5. Deploy to Prod:

# Use the same package created earlier – true “build once, deploy everywhere”
PACKAGE_PATH=”./app-package-backup.zip”

if [ -f “$PACKAGE_PATH” ]; then
echo “🚀 Deploying to production using existing package: $PACKAGE_PATH”
azd deploy app –from-package “$PACKAGE_PATH” –no-prompt
echo “✅ Production deployment completed successfully”

6. Clean Up:

# Clean up the backup package after successful deployment
rm -f “$PACKAGE_PATH”
echo “🧹 Cleaned up package backup”
else
echo “❌ Package backup not found – falling back to regular deployment”
azd deploy –no-prompt
fi

Try It Out

You can try this approach using the complete implementation here.

Watch the walkthrough: See this entire process in action in the video below that shows the complete setup and deployment flow.

Step-by-Step Setup

Follow these steps to set up both development and production environments, then configure the CI/CD pipeline:

1. Initialize project from the template

azd init -t https://github.com/puicchan/azd-dev-prod-appservice-storage

This downloads the complete implementation with all Bicep files and enhanced GitHub Actions workflow.

2. Set Up Development Environment

azd up

When prompted for the environment name, use myproj-dev (or your preferred naming pattern with -dev suffix).

Note: The default envType is dev, so you don’t need to set the AZURE_ENV_TYPE environment variable for development. The infrastructure will automatically provision with public access and cost-optimized resources.

3. Set Up Production Environment

Create and configure the production environment:

# Create new production environment
azd env new myproj-prod

# Set environment type to production
azd env set AZURE_ENV_TYPE prod

# Deploy production environment
azd up

This provisions production infrastructure with VNet integration, private endpoints, and enhanced security. Note that running azd up deploys the app to the production infrastructure as well. This is for demonstration purpose plus we are still in development stage. In a real-world scenario, you’d probably never deploy your app directly if it is already in production.

4. Switch Back to Development Environment

azd env select myproj-dev

You’re now ready to develop and test in the development environment.

5. Make Code Changes

Edit your application code (e.g., modify app/templates/index.html or app.py) to test the promotion workflow.

6. Configure CI/CD Pipeline

azd pipeline config

The GitHub Actions workflow is enhanced with dev-to-prod promotion logic. Specifically, the pipeline will:

Deploy and validate in development (`myproj-dev`)
Automatically promote to production (`myproj-prod`) using the same package
Handle environment naming conversion automatically

Once configured, every push to the main branch will trigger the automated dev-to-prod promotion pipeline!

Conclusion

In summary, this pattern combines conditional Bicep deployment, package preservation, and smart environment naming to create reliable dev-to-prod promotions with the same build artifacts.

Questions about implementation or want to share your own approach? Join the discussion here.

The post Azure Developer CLI: From Dev to Prod with One Click appeared first on Azure DevOps Blog.

Scroll to Top