App Extension for Azure Developer CLI

An Azure Developer CLI (azd) extension that automates development environment setup by detecting project types and running appropriate commands across multiple languages and frameworks.
Overview
App automatically detects and manages dependencies for:
- Node.js: npm, pnpm, yarn (Express, Next.js, React, Vue, Angular, Svelte, Astro, NestJS)
- Python: uv, poetry, pip (with automatic virtual environment setup) - FastAPI, Flask, Django, Streamlit, Gradio
- .NET: dotnet restore for projects and solutions (ASP.NET Core)
- Aspire: .NET Aspire application orchestration
- Java: Maven, Gradle (Spring Boot, Quarkus)
- Go: go mod for Go projects
- Rust: cargo for Rust projects
- PHP: composer (Laravel)
- Docker Compose: Container orchestration
Features
- π Smart Detection: Automatically identifies project types and package managers
- π¦ Multi-Language Support: Works with Node.js, Python, and .NET projects
- π One-Command Setup: Install all dependencies with a single command
- π― Environment-Aware: Creates and manages virtual environments for Python
- πͺ Lifecycle Hooks: Automate tasks before and after services start (prerun/postrun)
- π³ Docker Compose Compatible: Environment variable syntax matches Docker Compose exactly
- β‘ Fast Iteration: Minimal test dependencies for quick validation
- βοΈ Azure Logs Integration: Stream logs from Azure services with guided setup wizard
Azure Logs Setup Guide
The built-in Azure Logs Setup Guide makes it easy to configure log streaming from Azure:
- π§ 4-Step Wizard: Guides you through workspace, authentication, diagnostic settings, and verification
- π Auto-Detection: Continuously monitors your setup status in real-time
- π Copy-Paste Examples: Bicep templates and CLI commands for each step
- π― Deep Linking: Jump to specific steps from error messages
- β
Validation: Tests each step before allowing you to proceed
Access the guide by clicking the Azure button in the dashboard when logs aren't configured yet.
π Learn more: Azure Logs Documentation
Installation
For End Users
First, add the extension registry:
azd config set extension.registry https://raw.githubusercontent.com/jongio/azd-app/main/registry.json
Then install the extension:
azd extension install jongio.azd.app
Or install from a specific version:
azd extension install jongio.azd.app --version 0.1.0
To uninstall:
azd extension uninstall app
For Development & Testing
Quick Start - Recommended Method:
# Clone and navigate to the project
git clone https://github.com/jongio/azd-app.git
cd azd-app/cli
# Install mage (if not already installed)
go install github.com/magefile/mage@latest
# Build and install locally
mage install
# Test it!
azd app reqs
Development Workflow:
After making changes to your code:
# Use mage for all development tasks
mage install # Build and install locally
mage watch # Watch for changes and auto-rebuild
mage test # Run unit tests
mage lint # Run linter
mage clean # Clean build artifacts
# Or use azd x commands directly
azd x build # Build and install
azd x watch # Watch for changes
# See all available commands
mage -l
Uninstalling Development Build:
mage uninstall
Using Devcontainer
For a consistent, pre-configured development environment:
- Install Docker and VS Code Dev Containers extension
- Open the project in VS Code
- Click "Reopen in Container" when prompted
The devcontainer includes:
- Go, Node.js, Python, .NET pre-installed
- All package managers (npm, pnpm, yarn, pip, poetry, uv)
- Azure Developer CLI and Azure CLI
- Mage, golangci-lint, and all development tools
- Your Azure credentials automatically mounted
See .devcontainer/README.md for details.
Prerequisites
- Azure Developer CLI (azd) installed
- Go 1.25 or later (for building from source)
- Node.js 20.0.0 or later (for building dashboard)
- npm 10.0.0 or later (for building dashboard)
- PowerShell 7.4 or later (recommended: 7.5.4 for full compatibility with build scripts)
- TypeScript 5.9.3 (installed via npm, required for dashboard)
Quick Start
Once installed, you can use these commands:
azd app reqs
Verifies that all required tools are installed and optionally checks if they are running. Can also auto-generate requirements based on your project.
# Check requirements defined in azure.yaml
azd app reqs
# Auto-generate requirements from your project
azd app reqs --generate
# Preview what would be generated without making changes
azd app reqs --generate --dry-run
Features:
- β
Checks if required tools are installed
- β
Validates minimum version requirements
- β
Verifies if services are running (e.g., Docker daemon)
- β
Auto-generates requirements from detected project dependencies
- β
Smart version normalization (e.g., Node: major only, Python: major.minor)
- β
Merges with existing requirements without duplicates
- β
Supports custom tool configurations
- β
Built-in support for Node.js, Python, .NET, Aspire, Docker, Git, Azure CLI, and more
Auto-Generation Example:
When you run azd app reqs --generate in a Node.js project:
azd app notifications
Manage process notifications for service state changes and events.
# List notification history
azd app notifications list
# Show only unread notifications
azd app notifications list --unread
# Filter by service name
azd app notifications list --service web
# Mark notification as read
azd app notifications mark-read 123
# Mark all as read
azd app notifications mark-read --all
# View notification statistics
azd app notifications stats
# Clear old notifications
azd app notifications clear --older-than 7d
# Clear all notifications
azd app notifications clear
Features:
- β
Track service state changes (starting, running, stopped, failed)
- β
Desktop notifications for critical events (OS-native)
- β
Persistent notification history with SQLite database
- β
Mark notifications as read/unread
- β
Filter by service, severity, or read status
- β
Automatic cleanup of old notifications
- β
Statistics and reporting
π Scanning project for dependencies...
Found:
β Node.js project (pnpm)
π Detected requirements:
β’ node (22.19.0 installed) β minVersion: "22.0.0"
β’ pnpm (10.20.0 installed) β minVersion: "10.0.0"
β
Created azure.yaml with 2 requirements
The generated azure.yaml:
name: my-project
reqs:
- id: node
minVersion: 22.0.0
- id: pnpm
minVersion: 10.0.0
Supported Detection:
- Node.js: Automatically detects npm, pnpm, or yarn based on lock files
- Python: Detects pip, poetry, uv, or pipenv based on project files
- .NET: Detects dotnet SDK and Aspire workloads
- Docker: Detects from Dockerfile or docker-compose files
- Git: Detects from .git directory
Manual Configuration Example:
name: my-project
reqs:
- id: docker
minVersion: "20.0.0"
checkRunning: true
- id: nodejs
minVersion: "20.0.0"
- id: python
minVersion: "3.12.0"
Output:
π Checking requirements...
β
docker: 24.0.5 (required: 20.0.0) - β
RUNNING
β
nodejs: 22.19.0 (required: 20.0.0)
β
python: 3.13.9 (required: 3.12.0)
β
All requirements are satisfied!
See docs/reqs-command.md for detailed documentation.
azd app deps
Automatically detects your project type and installs all dependencies.
azd app deps
Features:
- π Detects Node.js, Python, and .NET projects
- π¦ Identifies package manager (npm/pnpm/yarn, uv/poetry/pip, dotnet)
- π Installs dependencies with the correct tool
- π Creates Python virtual environments automatically
azd app run
Starts your development environment based on project type.
# Run with default azd dashboard
azd app run
# Run specific services only
azd app run --service web,api
# Use native Aspire dashboard (for .NET Aspire projects)
azd app run --runtime aspire
# Preview what would run without starting
azd app run --dry-run
# Enable verbose logging
azd app run --verbose
# Load environment variables from custom file
azd app run --env-file .env.local
Flags:
--service, -s: Run specific service(s) only (comma-separated)
--runtime: Runtime mode - azd (default, uses azd dashboard) or aspire (native Aspire with dotnet run)
--env-file: Load environment variables from .env file
--verbose, -v: Enable verbose logging
--dry-run: Show what would be run without starting services
Environment Variables:
Services can define environment variables in azure.yaml using Docker Compose-compatible syntax:
services:
api:
# Map format (recommended)
environment:
NODE_ENV: production
PORT: "3000"
web:
# Array of strings (Docker Compose style)
environment:
- API_URL=http://localhost:5000
- DEBUG=true
See Environment Variables Documentation for all supported formats and advanced usage.
Lifecycle Hooks:
Execute custom scripts before and after starting services using hooks:
hooks:
prerun:
run: ./scripts/setup-db.sh
shell: bash
postrun:
run: echo "All services ready!"
shell: sh
See Hooks Documentation for complete hook configuration and examples.
Runtime Modes:
- azd (default): Runs services through azd's built-in dashboard, works with all project types
- aspire: Uses native .NET Aspire dashboard via
dotnet run (only for Aspire projects)
Supports:
- Services defined in azure.yaml (multi-service orchestration)
- .NET Aspire projects (AppHost.cs)
- pnpm dev servers
- Docker Compose orchestration
Commands
For complete command reference with all flags and options, see the CLI Reference Documentation.
AZD Context Access
All commands automatically have access to azd environment variables when invoked via azd:
import "os"
// Access Azure subscription ID
subscriptionId := os.Getenv("AZURE_SUBSCRIPTION_ID")
// Access resource group name
resourceGroup := os.Getenv("AZURE_RESOURCE_GROUP_NAME")
// Access any azd environment variable
envName := os.Getenv("AZURE_ENV_NAME")
See docs/azd-context.md for comprehensive documentation on accessing azd context and environment variables.
Development
Project Structure
azd-app-extension/
βββ src/
β βββ cmd/
β β βββ app/
β β βββ commands/ # Command implementations
β β β βββ core.go # Orchestrator setup
β β β βββ deps.go # Dependency installation
β β β βββ reqs.go # Prerequisites check
β β β βββ run.go # Dev environment runner
β β βββ main.go # Main entry point
β βββ internal/
β βββ detector/ # Project detection logic
β β βββ detector.go
β βββ installer/ # Dependency installation
β β βββ installer.go
β βββ runner/ # Project execution
β β βββ runner.go
β βββ executor/ # Safe command execution
β β βββ executor.go
β βββ orchestrator/ # Command dependency chain
β β βββ orchestrator.go
β βββ security/ # Input validation
β β βββ validation.go
β βββ types/ # Shared types
β βββ types.go
βββ tests/
β βββ projects/ # Test project fixtures
β βββ node/
β βββ python/
β βββ aspire-test/
β βββ azure/
βββ docs/ # Documentation
β βββ quickstart.md
β βββ add-command-guide.md
β βββ command-dependency-chain.md
β βββ azd-context.md
β βββ reqs-command.md
βββ .github/
β βββ workflows/
β βββ ci.yml # CI pipeline
β βββ release.yml # Release automation
βββ extension.yaml # Extension manifest
βββ registry.json # Extension registry entry
βββ go.mod # Go module definition
βββ magefile.go # Mage build targets (PRIMARY BUILD TOOL)
βββ .golangci.yml # Linter configuration
βββ AGENTS.md # AI agent guidelines
βββ CONTRIBUTING.md # Contribution guidelines
βββ LICENSE # MIT License
βββ README.md # This file
Development Commands
This project uses Mage as the primary build tool. Mage is a make/rake-like build tool using Go.
Installation:
go install github.com/magefile/mage@latest
Common Commands:
# See all available commands
mage -l
# Building
mage build # Build for current platform
mage buildall # Build for all platforms
# Testing
mage test # Run unit tests
mage testintegration # Run integration tests
mage testall # Run all tests
mage testcoverage # Run tests with coverage report
# Development
mage install # Build and install locally
mage uninstall # Uninstall the extension
mage clean # Clean build artifacts
mage fmt # Format code
mage lint # Run linter
# Releasing
mage release # Interactive release (prompts for version bump)
mage releasepatch # Create patch release (0.1.0 β 0.1.1)
mage releaseminor # Create minor release (0.1.0 β 0.2.0)
mage releasemajor # Create major release (0.1.0 β 1.0.0)
# Dashboard
mage dashboardbuild # Build dashboard assets
mage dashboarddev # Start dashboard dev server
# Dependency Management
mage checkdeps # Check for outdated dependencies
mage updatedeps # Update all dependencies to latest versions
# Environment variables for updatedeps:
# DRY_RUN=true # Preview updates without applying them
# MINOR_ONLY=true # Only update to latest minor versions (safer)
# Pre-flight checks
mage preflight # Run all checks before shipping
Running Tests
# Run unit tests only (fast)
go test ./src/internal/service/...
# Run unit tests with verbose output
go test -v ./src/internal/service/...
# Run integration tests (requires Python, creates real venvs, slower)
go test -tags=integration -v ./src/internal/service/...
# Run all tests via mage
mage test # Unit tests only
mage testIntegration # Integration tests only
mage testAll # Unit + integration tests
mage testCoverage # Tests with coverage report
# Run preflight checks (includes all tests)
mage preflight
Integration Tests:
Integration tests create real Python virtual environments and install actual packages. They:
- Verify venv detection works with real filesystems
- Test that Python packages are correctly installed in venvs
- Validate cross-platform path handling (Windows vs Linux/macOS)
- Ensure subprocess spawning inherits the correct environment
Requirements:
- Python 3.8+ installed and available in PATH
- Internet connection (for pip install)
- ~2 minutes execution time
Running specific integration tests:
# Run only FastAPI integration test
go test -tags=integration -v ./src/internal/service/... -run TestPythonVenvIntegration/FastAPI
# Run venv fallback test
go test -tags=integration -v ./src/internal/service/... -run TestPythonVenvFallback
Dashboard Development:
The dashboard is a React + TypeScript application that provides a web UI for monitoring services.
# Build the dashboard (TypeScript compilation + Vite build)
mage dashboardBuild
# Start dashboard development server with hot reload
mage dashboardDev
# Build dashboard manually
cd dashboard
npm install
npm run build
The dashboard build is automatically included in:
mage all - Ensures dashboard is built before Go compilation
mage preflight - Validates TypeScript compilation and catches type errors
- CI/CD workflows - Dashboard is built and validated in all pipelines
Learn more about Mage:
Adding New Commands
To add a new command, describe what you want to GitHub Copilot and it will generate the implementation for you.
Important: Always request both unit tests and integration tests for your command.
Example prompt:
Add a new 'azd app validate' command that checks project configuration.
Include unit tests and integration tests.
Copilot will:
- Create the command file in
src/cmd/app/commands/
- Register it in
src/cmd/app/main.go
- Update
extension.yaml
- Generate unit tests in the same directory
- Generate integration tests in
src/internal/*/ directories as needed
Testing
Unit Tests
# Run unit tests only (fast)
mage test
# Run with coverage
mage testCoverage
# View coverage report
open coverage/coverage.html # macOS
start coverage/coverage.html # Windows
xdg-open coverage/coverage.html # Linux
Integration Tests
# Run all integration tests
mage testIntegration
# Run specific package integration tests
TEST_PACKAGE=runner mage testIntegration
TEST_PACKAGE=commands mage testIntegration
# Run specific test
TEST_NAME=TestHealthCommandE2E_FullWorkflow mage testIntegration
E2E Tests
End-to-end tests verify complete workflows across all platforms:
# Run E2E tests for health command
mage testE2E
# Run all tests (unit + integration + E2E)
mage testAll
E2E Test Coverage:
- Health command full workflow (install deps β start services β health checks)
- JSON/Table output validation
- Service filtering and verbose modes
- Streaming health updates
- Error handling scenarios
- Cross-platform process/port checking (Windows/macOS/Linux)
Test Projects:
Test projects are located in tests/projects/ with minimal dependencies:
# Health monitoring test project (comprehensive E2E testing)
cd tests/projects/health-test
./quick-start.sh # Linux/macOS
./quick-start.ps1 # Windows
# Node.js detection and dependency installation
cd tests/projects/node/test-npm-project
azd app deps
# Python detection and dependency installation
cd tests/projects/python/test-uv-project
azd app deps
CI/CD Testing
- Unit tests: Run on every PR (Ubuntu, Windows, macOS)
- Integration tests: Run in main CI workflow
- E2E tests: Run automatically on health command changes
- Manual E2E: Trigger via workflow dispatch in
.github/workflows/health-e2e.yml
View test results:
Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Developer Documentation
- azd-core Integration Guide: How to work with azd-core locally and in CI/CD
- Local development setup with
go.work
- Running tests with azd-core
- CI/CD module pinning
- Debugging integration issues
- Key Vault Integration: User and developer guide for Key Vault reference resolution
Code Quality Requirements
- All tests must pass:
go test ./...
- Code coverage minimum: 80%
- Linter must pass:
golangci-lint run
- Code must be formatted:
gofmt
- Follow Go best practices and idioms
License
MIT License - Copyright (c) 2024 Jon Gallant (jongio)
See LICENSE for details.
Resources
Documentation
External Resources
Support
Acknowledgments
This extension is built with: