Skip to content

Commit 806c749

Browse files
authored
{Misc.} Enhance the development experience of AAZ (#32025)
1 parent 28133fd commit 806c749

File tree

9 files changed

+637
-0
lines changed

9 files changed

+637
-0
lines changed

.devcontainer/Dockerfile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FROM mcr.microsoft.com/devcontainers/python:3.12
2+
3+
# Copy binaries from the official
4+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
5+
6+
# Remove after production
7+
RUN pip install --no-cache-dir mcp

.devcontainer/devcontainer.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "Azure CLI Dev Container",
3+
"build": {
4+
"dockerfile": "Dockerfile"
5+
},
6+
"features": {
7+
"ghcr.io/devcontainers/features/github-cli:1": {}
8+
},
9+
"workspaceFolder": "/workspaces",
10+
"onCreateCommand": "uv venv .venv --seed",
11+
"postCreateCommand": "REPO_NAME=$(basename $GITHUB_REPOSITORY) && cat $REPO_NAME/.devcontainer/init.sh >> ~/.bashrc && mkdir .vscode && cp $REPO_NAME/.devcontainer/mcp.json .vscode/",
12+
"hostRequirements": {
13+
"cpus": 16,
14+
"memory": "64gb",
15+
"storage": "128gb"
16+
}
17+
}

.devcontainer/init.sh

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
2+
source .venv/bin/activate
3+
4+
# Logout default account
5+
export GITHUB_TOKEN=
6+
7+
# Check `repo` scope exists or not
8+
if gh auth status -a 2>/dev/null | grep "Token scopes: " | grep -q "repo"; then
9+
echo "You now have access to GitHub."
10+
else
11+
gh auth login -p https -w
12+
fi
13+
14+
# Check `aaz-dev` is available or not
15+
if ! command -v aaz-dev &> /dev/null; then
16+
GREEN="\033[0;32m"
17+
YELLOW="\033[0;33m"
18+
NC="\033[0m" # no color
19+
20+
set_or_add_remote() {
21+
local REPO=$1
22+
local REMOTE=$2
23+
local DIR="/workspaces/$REPO"
24+
local OWNER=$([ "$REMOTE" = "origin" ] && echo "$GITHUB_USER" || echo "Azure")
25+
local URL="https://github.com/$OWNER/$REPO.git"
26+
27+
git -C "$DIR" remote get-url "$REMOTE" &>/dev/null || git -C "$DIR" remote add "$REMOTE" "$URL"
28+
git -C "$DIR" remote set-url "$REMOTE" "$URL"
29+
}
30+
31+
setup_repo() {
32+
local REPO=$1
33+
local DIR="/workspaces/$REPO"
34+
35+
echo
36+
gh repo fork "Azure/$REPO" --clone=false --default-branch-only
37+
38+
if [ -d "$DIR" ]; then
39+
set_or_add_remote "$REPO" origin
40+
set_or_add_remote "$REPO" upstream
41+
else
42+
git clone "https://github.com/$GITHUB_USER/$REPO.git" --single-branch --no-tags
43+
set_or_add_remote "$REPO" upstream
44+
45+
# Synchronize with upstream
46+
BRANCH=$(git -C "$DIR" remote show upstream | grep "HEAD branch" | awk '{print $NF}')
47+
git -C "$DIR" pull -r upstream "$BRANCH"
48+
fi
49+
}
50+
51+
SECONDS=0
52+
53+
echo
54+
uv pip install aaz-dev --link-mode=copy
55+
56+
# `azdev` repositories
57+
setup_repo "azure-cli"
58+
setup_repo "azure-cli-extensions"
59+
60+
azdev setup -c -r ./azure-cli-extensions
61+
62+
# `aaz-dev` repositories
63+
setup_repo "aaz"
64+
setup_repo "azure-rest-api-specs"
65+
66+
ELAPSED_TIME=$SECONDS
67+
68+
echo -e "\n${YELLOW}Elapsed time: $((ELAPSED_TIME / 60))m $((ELAPSED_TIME % 60))s.${NC}"
69+
echo -e "\n${GREEN}Finished setup! Please launch the codegen tool via:${NC}"
70+
echo -e "${GREEN}\$ aaz-dev run -c azure-cli -e azure-cli-extensions -s azure-rest-api-specs -a aaz${NC}\n"
71+
else
72+
echo -e "\nPlease launch the codegen tool via:"
73+
echo -e "$ aaz-dev run -c azure-cli -e azure-cli-extensions -s azure-rest-api-specs -a aaz\n"
74+
fi

.devcontainer/mcp.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"inputs": [
3+
{
4+
"type": "promptString",
5+
"id": "extension_or_module_name",
6+
"description": "The name of the Azure CLI extension or module to generate commands for."
7+
},
8+
{
9+
"type": "promptString",
10+
"id": "swagger_module_path",
11+
"description": "The file path to the Swagger module."
12+
},
13+
{
14+
"type": "promptString",
15+
"id": "resource_provider",
16+
"description": "The Azure resource provider for which to generate commands."
17+
},
18+
{
19+
"type": "promptString",
20+
"id": "swagger_tag",
21+
"description": "The Swagger tag to use for command generation."
22+
}
23+
],
24+
"servers": {
25+
"AAZ Flow": {
26+
"command": "python",
27+
"args": [
28+
"azure-cli/tools/aaz-flow/main.py"
29+
],
30+
"env": {
31+
"AAZ_PATH": "/workspaces/aaz",
32+
"CLI_PATH": "/workspaces/azure-cli",
33+
"CLI_EXTENSION_PATH": "/workspaces/azure-cli-extensions",
34+
"SWAGGER_PATH": "/workspaces/azure-rest-api-specs"
35+
}
36+
}
37+
}
38+
}

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/doc/ @jiasli @kairu-ms @jsntcy
1010
/tools/ @kairu-ms @jiasli @wangzelin007 @calvinhzy @bebound
11+
/tools/aaz-flow @a0x1ab @necusjz @yanzhudd
1112
/scripts/ @kairu-ms @jiasli @wangzelin007 @calvinhzy @bebound
1213
/scripts/live_test @kairu-ms @wangzelin007
1314
/src/azure-cli-testsdk/ @jsntcy @jiasli @kairu-ms @wangzelin007 @bebound

tools/aaz-flow/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## AAZ MCP Server
2+
MCP Server for the AAZ API, enabling prune command-line interface, implement custom logic, generate meaningful example, and more.
3+
4+
Please note that AAZ Flow is currently in early development. The functionality and available tools are subject to change and expansion as we continue to develop and improve the server.
5+
6+
### Tools
7+
1. `generate_code`
8+
- xx
9+
- Inputs:
10+
- xx
11+
- xx
12+
- Returns:

tools/aaz-flow/main.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# --------------------------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License. See License.txt in the project root for license information.
4+
# --------------------------------------------------------------------------------------------
5+
import os
6+
from mcp.server.fastmcp import FastMCP
7+
8+
# Initialize MCP server
9+
mcp = FastMCP("AAZ Flow")
10+
11+
12+
@mcp.tool()
13+
def generate_code(
14+
extension_or_module_name: str,
15+
swagger_module_path: str,
16+
resource_provider: str,
17+
swagger_tag: str,
18+
):
19+
# Generate Azure CLI commands based on Swagger specifications
20+
aaz_path = os.getenv("AAZ_PATH", "/workspaces/aaz")
21+
cli_path = os.getenv("CLI_PATH", "/workspaces/azure-cli")
22+
cli_extension_path = os.getenv("CLI_EXTENSION_PATH", "/workspaces/azure-cli-extensions")
23+
swagger_path = os.getenv("SWAGGER_PATH", "/workspaces/azure-rest-api-specs")
24+
25+
swagger_module = os.path.split(swagger_module_path)[-1]
26+
27+
des = (
28+
f"Just run the following command in the terminal: 'aaz-dev command-model generate-from-swagger --swagger-path {swagger_path} --swagger-module-path {swagger_module_path} --aaz-path {aaz_path} --module {swagger_module} --resource-provider {resource_provider} --swagger-tag {swagger_tag}'",
29+
f"After the command is run successfully, then run the following command: 'aaz-dev cli generate-by-swagger-tag --aaz-path {aaz_path} --cli-path {cli_path} --cli-extension-path {cli_extension_path} --extension-or-module-name {extension_or_module_name} --swagger-module-path {swagger_module_path} --resource-provider {resource_provider} --swagger-tag {swagger_tag} --profile latest'",
30+
f"After the command is run successfully, this task will be marked as completed.",
31+
)
32+
return des
33+
34+
35+
if __name__ == "__main__":
36+
mcp.run(transport="stdio")

tools/aaz-flow/pyproject.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[project]
2+
name = "aaz-flow"
3+
version = "0.1.0"
4+
description = "The MCP server utilized for code generation in Azure CLI (AAZ)."
5+
readme = "README.md"
6+
requires-python = ">=3.12"
7+
dependencies = [
8+
"mcp>=1.12.0",
9+
]

0 commit comments

Comments
 (0)