Skip to content

Commit 9730450

Browse files
authored
feat: Update CLI reference for azd app run command and add new flags (#117)
- Changed example command for `azd app run` to include `--force` and added a new example for `--runtime aspire`. - Updated the flags section to include descriptions for the new `--force` flag. - Added additional example commands to demonstrate usage. --- chore: Enhance "What's New" section with v0.11.0 updates - Added new article for version v0.11.0 with features, fixes, and enhancements. - Removed outdated v0.9.0 article to streamline the changelog. --- feat: Introduce Environment Name Display feature in dashboard - Created a new specification for displaying the current Azure environment name in the dashboard header. - Recommended placement and visual design for the environment name badge. - Updated backend API to include environment name and modified frontend components to display it. --- feat: Implement EnvironmentBadge component for displaying environment name - Added `EnvironmentBadge` component to show the Azure environment name in the header. - Ensured the badge is responsive and hidden on mobile devices. - Integrated the badge into the header with appropriate styling and accessibility features.
1 parent c5d2051 commit 9730450

File tree

16 files changed

+830
-93
lines changed

16 files changed

+830
-93
lines changed

cli/dashboard/design/features/environment-name-display.md

Lines changed: 646 additions & 0 deletions
Large diffs are not rendered by default.

cli/dashboard/src/App.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useState, useEffect, useMemo } from 'react'
22
import { useServicesContext } from '@/contexts/ServicesContext'
33
import { useHealthStream } from '@/hooks/useHealthStream'
4+
import { useCodespaceEnv } from '@/hooks/useCodespaceEnv'
45
import { App as DashboardApp } from '@/components/App'
56
import { BackendConnectionContext } from '@/hooks/useBackendConnection'
67
import type { HealthCheckResult } from '@/types'
@@ -9,6 +10,9 @@ function App() {
910
const [projectName, setProjectName] = useState<string>('')
1011
const { services } = useServicesContext()
1112

13+
// Environment info (includes Azure environment name)
14+
const { environmentName } = useCodespaceEnv()
15+
1216
// Real-time health monitoring
1317
const {
1418
healthReport,
@@ -74,6 +78,7 @@ function App() {
7478
healthMap={healthMap}
7579
healthError={healthError}
7680
healthReconnect={healthReconnect}
81+
environmentName={environmentName}
7782
/>
7883
</BackendConnectionContext.Provider>
7984
)

cli/dashboard/src/components/App.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ export interface AppProps {
3737
healthError?: string | null
3838
/** Function to manually reconnect */
3939
healthReconnect?: () => void
40+
/** Azure environment name to display in header */
41+
environmentName?: string
4042
/** Additional class names */
4143
className?: string
4244
}
@@ -133,6 +135,7 @@ export function App({
133135
healthReport,
134136
healthMap,
135137
healthError,
138+
environmentName,
136139
className,
137140
}: AppProps) {
138141
const [activeView, setActiveView] = React.useState<View>(getInitialView)
@@ -358,6 +361,7 @@ export function App({
358361
services={services}
359362
hasActiveErrors={false}
360363
loading={!connected && services.length === 0}
364+
environmentName={environmentName}
361365
/>
362366

363367
{/* Settings Dialog */}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* EnvironmentBadge - Displays Azure environment name in the header
3+
* Shows a subtle badge with the environment name (e.g., "· dev")
4+
* Hidden on mobile devices (<640px)
5+
*/
6+
import { cn } from '@/lib/utils'
7+
8+
// =============================================================================
9+
// Types
10+
// =============================================================================
11+
12+
export interface EnvironmentBadgeProps {
13+
/** Azure environment name to display */
14+
environmentName?: string
15+
/** Additional class names */
16+
className?: string
17+
}
18+
19+
// =============================================================================
20+
// EnvironmentBadge Component
21+
// =============================================================================
22+
23+
export function EnvironmentBadge({
24+
environmentName,
25+
className
26+
}: EnvironmentBadgeProps) {
27+
// Don't render if no environment name
28+
if (!environmentName) {
29+
return null
30+
}
31+
32+
return (
33+
<span
34+
className={cn(
35+
'hidden sm:inline-flex items-center gap-1.5',
36+
'px-2 py-[3px] rounded',
37+
'text-xs font-medium leading-none',
38+
'bg-slate-100 dark:bg-slate-800',
39+
'text-slate-500 dark:text-slate-400',
40+
className
41+
)}
42+
aria-label={`Environment: ${environmentName}`}
43+
role="status"
44+
>
45+
<span className="text-cyan-500 dark:text-cyan-400 leading-none" aria-hidden="true">·</span>
46+
<span className="leading-none">{environmentName}</span>
47+
</span>
48+
)
49+
}

cli/dashboard/src/components/Header.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { cn } from '@/lib/utils'
1616
import { ThemeToggle } from './ThemeToggle'
1717
import { HealthPill, ConnectionStatus } from './StatusIndicator'
1818
import { ServiceStatusCard } from './ServiceStatusCard'
19+
import { EnvironmentBadge } from './EnvironmentBadge'
1920
import type { HealthSummary, Service } from '@/types'
2021

2122
// =============================================================================
@@ -52,6 +53,8 @@ export interface HeaderProps {
5253
hasActiveErrors?: boolean
5354
/** Whether dashboard is loading */
5455
loading?: boolean
56+
/** Azure environment name to display */
57+
environmentName?: string
5558
/** Additional class names */
5659
className?: string
5760
}
@@ -124,6 +127,7 @@ export function Header({
124127
services,
125128
hasActiveErrors = false,
126129
loading = false,
130+
environmentName,
127131
className,
128132
}: HeaderProps) {
129133
const navRef = React.useRef<HTMLDivElement>(null)
@@ -201,6 +205,7 @@ export function Header({
201205
<h1 className="text-lg font-semibold text-slate-900 dark:text-slate-100 truncate tracking-tight">
202206
{projectName || 'Dashboard'}
203207
</h1>
208+
<EnvironmentBadge environmentName={environmentName} />
204209
{connected && (
205210
<span className="relative flex h-2 w-2" aria-hidden="true">
206211
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>

cli/dashboard/src/components/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ export {
3737
} from './StatusIndicator'
3838
export type { EffectiveStatus } from './StatusIndicator'
3939

40+
// Environment Badge
41+
export { EnvironmentBadge } from './EnvironmentBadge'
42+
export type { EnvironmentBadgeProps } from './EnvironmentBadge'
43+
4044
// Console View
4145
export { ConsoleView } from './ConsoleView'
4246
export type { ConsoleViewProps } from './ConsoleView'

cli/dashboard/src/hooks/useCodespaceEnv.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export interface UseCodespaceEnvReturn {
1616
isCodespace: boolean
1717
/** Codespace configuration (null if not in Codespace or loading) */
1818
config: CodespaceConfig | null
19+
/** Azure environment name (if available) */
20+
environmentName?: string
1921
/** Whether the environment info is still loading */
2022
loading: boolean
2123
/** Error message if fetch failed */
@@ -98,6 +100,11 @@ export function useCodespaceEnv(): UseCodespaceEnvReturn {
98100
const cached = getCachedEnv()
99101
return cached?.codespace ?? null
100102
})
103+
const [environmentName, setEnvironmentName] = useState<string | undefined>(() => {
104+
// Initialize from cache if available
105+
const cached = getCachedEnv()
106+
return cached?.environmentName
107+
})
101108
const [loading, setLoading] = useState<boolean>(() => {
102109
// Skip loading if we have cached data
103110
return getCachedEnv() === null
@@ -121,6 +128,7 @@ export function useCodespaceEnv(): UseCodespaceEnvReturn {
121128
setCachedEnv(data)
122129

123130
setConfig(data.codespace)
131+
setEnvironmentName(data.environmentName)
124132
} catch (err) {
125133
const message = err instanceof Error ? err.message : 'Unknown error'
126134
setError(message)
@@ -151,6 +159,7 @@ export function useCodespaceEnv(): UseCodespaceEnvReturn {
151159
return {
152160
isCodespace: config?.enabled ?? false,
153161
config,
162+
environmentName,
154163
loading,
155164
error,
156165
refresh,

cli/dashboard/src/lib/codespace-utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export interface CodespaceConfig {
2121

2222
export interface EnvironmentInfo {
2323
codespace: CodespaceConfig
24+
environmentName?: string
2425
}
2526

2627
// =============================================================================

cli/docs/cli-reference.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ These flags are available for all commands:
3939
| `--debug` | | bool | `false` | Enable debug logging |
4040
| `--structured-logs` | | bool | `false` | Enable structured JSON logging to stderr |
4141
| `--cwd` | `-C` | string | `""` | Sets the current working directory |
42+
| `--environment` | `-e` | string | `""` | The name of the environment to use |
4243

4344
**Examples:**
4445
```bash
@@ -53,6 +54,9 @@ azd app deps --structured-logs
5354

5455
# Run from a specific project directory
5556
azd app run --cwd ./my-project
57+
58+
# Use a specific environment
59+
azd app run --environment production
5660
```
5761

5862
## Commands Overview
@@ -73,7 +77,6 @@ azd app run --cwd ./my-project
7377
| `mcp` | Model Context Protocol server for AI assistant integration | [→ Full Spec](commands/mcp.md) |
7478
| `notifications` | Manage process notifications for service state changes | [→ Full Spec](commands/notifications.md) |
7579
| `version` | Show version information | [→ Full Spec](commands/version.md) |
76-
| `completion` | Generate shell autocompletion scripts | [→ Full Spec](commands/completion.md) |
7780
| `listen` | Extension framework integration (hidden, used by azd internally) | [→ Full Spec](commands/listen.md) |
7881

7982
---
@@ -293,6 +296,9 @@ azd app run --env-file .env.local
293296
294297
# Combine multiple flags
295298
azd app run -s web -v --runtime aspire
299+
300+
# Force clean dependency reinstall before running
301+
azd app run --force
296302
```
297303

298304
### Flags
@@ -305,6 +311,7 @@ azd app run -s web -v --runtime aspire
305311
| `--verbose` | `-v` | bool | `false` | Enable verbose logging |
306312
| `--dry-run` | | bool | `false` | Show what would be run without starting services |
307313
| `--restart-containers` | | bool | `false` | Restart containers even if they are already running |
314+
| `--force` | `-f` | bool | `false` | Force clean dependency reinstall (passes --force to deps) |
308315
| `--web` | `-w` | bool | `false` | Open dashboard in browser |
309316

310317
### Runtime Modes

cli/src/internal/dashboard/server_handlers.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,17 @@ func (s *Server) handleGetEnvironment(w http.ResponseWriter, r *http.Request) {
4747
// Only in browser-based Codespace do we need to transform localhost URLs
4848
isVsCodeDesktop := runningOnVsCodeDesktop()
4949

50+
// Get Azure environment name if available
51+
azureEnvName := os.Getenv("AZURE_ENV_NAME")
52+
5053
response := map[string]interface{}{
5154
"codespace": map[string]interface{}{
5255
"enabled": codespaceName != "",
5356
"name": codespaceName,
5457
"domain": codespacePortDomain,
5558
"isVsCodeDesktop": isVsCodeDesktop,
5659
},
60+
"environmentName": azureEnvName,
5761
}
5862

5963
WriteJSONSuccess(w, response)

0 commit comments

Comments
 (0)