Skip to content

[App Service] Add deployment guidance, warnings for Linux web apps#33088

Open
vageorge00 wants to merge 9 commits intoAzure:devfrom
vageorge00:appservice-deploy-ux-improvements
Open

[App Service] Add deployment guidance, warnings for Linux web apps#33088
vageorge00 wants to merge 9 commits intoAzure:devfrom
vageorge00:appservice-deploy-ux-improvements

Conversation

@vageorge00
Copy link
Copy Markdown

@vageorge00 vageorge00 commented Mar 27, 2026

Related command
az webapp create, az webapp deploy, az webapp up, az webapp delete, az webapp deployment source config-local-git, az appservice plan update

Description
Fixes https://github.com/serverless-paas-balam/tuxedo/issues/119
Improves the Azure CLI experience for deploying Linux web apps by adding help text, runtime warnings.

Help text: Added deployment guidance to az webapp create, SCM_DO_BUILD_DURING_DEPLOYMENT guidance to az webapp deploy, OS/runtime/plan defaults to az webapp up, branch convention to config-local-git, and scale up vs scale out to az appservice plan update.

Code: Added warning for container image path doubling when --container-image-name includes the registry host. Added runtime warnings for Linux zip deploy, OS type defaulting, runtime auto-detection, plan auto-generation, delete plan warning, and local-git branch convention.

Testing Guide

azdev style appservice  # PASSED
azdev linter appservice  # PASSED

 # Verify help text changes:
 az webapp create --help
 az webapp deploy --help
 az webapp up --help
 az appservice plan update --help
 
 # Verify deploy warning (Linux zip deploy):
 az webapp deploy -g MyRG -n MyLinuxApp --src-path app.zip --type zip
 # Should see: "Note: 'az webapp deploy' does not run build automation..."
 
 # Verify container image warning (registry host in image name):
 az webapp create -g MyRG -n MyApp --plan MyPlan --container-image-name docker.io/nginx:latest --container-registry-url docker.io
 # Should see: "Note: --container-image-name 'docker.io/nginx:latest' appears to include the registry host..."

End-to-end agent tests across Python, .NET, Java, and containers confirmed all warnings fire correctly.

Manual end-end tests for logging changes:

  1. See log that 'az webapp deploy' does not install dependencies:
image
  1. See log if Image name already includes the registry host (docker.io/) for az webapp create
    az webapp create -g test-startup4-rg -n test-pr-container --plan test-startup4-plan --container-image-name docker.io/nginx:latest --container-registry-url docker.io
image
  1. See log about branch info for
    az webapp deployment source config-local-git -g test-container-rg -n test-container-app2
image
  1. See log about plan being deleted
    az webapp delete -g test-container-rg -n test-container-app3
image
  1. Spot checking for help and param changes:
    We get added help/param info
    az webapp create --help
image image

History Notes

[App Service] az webapp create: Add post-creation deployment guidance and startup command examples
[App Service] az webapp deploy: Add build automation guidance for Linux zip deployments
[App Service] az webapp up: Add logging for OS type, runtime auto-detection, and plan auto-generation
[App Service] Add warning for container image path when --container-image-name includes registry host
[App Service] az webapp delete: Add warning about App Service Plan deletion


@microsoft-github-policy-service agree company="Microsoft"

vageorge00 and others added 3 commits March 27, 2026 10:50
…Linux

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-client-tools-bot-prd
Copy link
Copy Markdown

azure-client-tools-bot-prd bot commented Mar 27, 2026

️✔️AzureCLI-FullTest
️✔️acr
️✔️latest
️✔️3.12
️✔️3.13
️✔️acs
️✔️latest
️✔️3.12
️✔️3.13
️✔️advisor
️✔️latest
️✔️3.12
️✔️3.13
️✔️ams
️✔️latest
️✔️3.12
️✔️3.13
️✔️apim
️✔️latest
️✔️3.12
️✔️3.13
️✔️appconfig
️✔️latest
️✔️3.12
️✔️3.13
️✔️appservice
️✔️latest
️✔️3.12
️✔️3.13
️✔️aro
️✔️latest
️✔️3.12
️✔️3.13
️✔️backup
️✔️latest
️✔️3.12
️✔️3.13
️✔️batch
️✔️latest
️✔️3.12
️✔️3.13
️✔️batchai
️✔️latest
️✔️3.12
️✔️3.13
️✔️billing
️✔️latest
️✔️3.12
️✔️3.13
️✔️botservice
️✔️latest
️✔️3.12
️✔️3.13
️✔️cdn
️✔️latest
️✔️3.12
️✔️3.13
️✔️cloud
️✔️latest
️✔️3.12
️✔️3.13
️✔️cognitiveservices
️✔️latest
️✔️3.12
️✔️3.13
️✔️compute_recommender
️✔️latest
️✔️3.12
️✔️3.13
️✔️computefleet
️✔️latest
️✔️3.12
️✔️3.13
️✔️config
️✔️latest
️✔️3.12
️✔️3.13
️✔️configure
️✔️latest
️✔️3.12
️✔️3.13
️✔️consumption
️✔️latest
️✔️3.12
️✔️3.13
️✔️container
️✔️latest
️✔️3.12
️✔️3.13
️✔️containerapp
️✔️latest
️✔️3.12
️✔️3.13
️✔️core
️✔️latest
️✔️3.12
️✔️3.13
️✔️cosmosdb
️✔️latest
️✔️3.12
️✔️3.13
️✔️databoxedge
️✔️latest
️✔️3.12
️✔️3.13
️✔️dls
️✔️latest
️✔️3.12
️✔️3.13
️✔️dms
️✔️latest
️✔️3.12
️✔️3.13
️✔️eventgrid
️✔️latest
️✔️3.12
️✔️3.13
️✔️eventhubs
️✔️latest
️✔️3.12
️✔️3.13
️✔️feedback
️✔️latest
️✔️3.12
️✔️3.13
️✔️find
️✔️latest
️✔️3.12
️✔️3.13
️✔️hdinsight
️✔️latest
️✔️3.12
️✔️3.13
️✔️identity
️✔️latest
️✔️3.12
️✔️3.13
️✔️iot
️✔️latest
️✔️3.12
️✔️3.13
️✔️keyvault
️✔️latest
️✔️3.12
️✔️3.13
️✔️lab
️✔️latest
️✔️3.12
️✔️3.13
️✔️managedservices
️✔️latest
️✔️3.12
️✔️3.13
️✔️maps
️✔️latest
️✔️3.12
️✔️3.13
️✔️marketplaceordering
️✔️latest
️✔️3.12
️✔️3.13
️✔️monitor
️✔️latest
️✔️3.12
️✔️3.13
️✔️mysql
️✔️latest
️✔️3.12
️✔️3.13
️✔️netappfiles
️✔️latest
️✔️3.12
️✔️3.13
️✔️network
️✔️latest
️✔️3.12
️✔️3.13
️✔️policyinsights
️✔️latest
️✔️3.12
️✔️3.13
️✔️postgresql
️✔️latest
️✔️3.12
️✔️3.13
️✔️privatedns
️✔️latest
️✔️3.12
️✔️3.13
️✔️profile
️✔️latest
️✔️3.12
️✔️3.13
️✔️rdbms
️✔️latest
️✔️3.12
️✔️3.13
️✔️redis
️✔️latest
️✔️3.12
️✔️3.13
️✔️relay
️✔️latest
️✔️3.12
️✔️3.13
️✔️resource
️✔️latest
️✔️3.12
️✔️3.13
️✔️role
️✔️latest
️✔️3.12
️✔️3.13
️✔️search
️✔️latest
️✔️3.12
️✔️3.13
️✔️security
️✔️latest
️✔️3.12
️✔️3.13
️✔️servicebus
️✔️latest
️✔️3.12
️✔️3.13
️✔️serviceconnector
️✔️latest
️✔️3.12
️✔️3.13
️✔️servicefabric
️✔️latest
️✔️3.12
️✔️3.13
️✔️signalr
️✔️latest
️✔️3.12
️✔️3.13
️✔️sql
️✔️latest
️✔️3.12
️✔️3.13
️✔️sqlvm
️✔️latest
️✔️3.12
️✔️3.13
️✔️storage
️✔️latest
️✔️3.12
️✔️3.13
️✔️synapse
️✔️latest
️✔️3.12
️✔️3.13
️✔️telemetry
️✔️latest
️✔️3.12
️✔️3.13
️✔️util
️✔️latest
️✔️3.12
️✔️3.13
️✔️vm
️✔️latest
️✔️3.12
️✔️3.13

@azure-client-tools-bot-prd
Copy link
Copy Markdown

Hi @vageorge00,
Since the current milestone time is less than 7 days, this pr will be reviewed in the next milestone.

@azure-client-tools-bot-prd
Copy link
Copy Markdown

azure-client-tools-bot-prd bot commented Mar 27, 2026

❌AzureCLI-BreakingChangeTest
❌apim
rule cmd_name rule_message suggest_message
1012 - SubgroupRemove apim backend sub group apim backend removed please confirm sub group apim backend removed

Please submit your Breaking Change Pre-announcement ASAP if you haven't already. Please note:

  • Breaking changes can only be merged during the designated breaking change window
  • A pre-announcement must be released at least one month in advance

For more details on how to introduce breaking changes, refer to the documentation: azure-cli/doc/how_to_introduce_breaking_changes.md

@yonzhan
Copy link
Copy Markdown
Collaborator

yonzhan commented Mar 27, 2026

Thank you for your contribution! We will review the pull request and get back to you soon.

@github-actions
Copy link
Copy Markdown

The git hooks are available for azure-cli and azure-cli-extensions repos. They could help you run required checks before creating the PR.

Please sync the latest code with latest dev branch (for azure-cli) or main branch (for azure-cli-extensions).
After that please run the following commands to enable git hooks:

pip install azdev --upgrade
azdev setup -c <your azure-cli repo path> -r <your azure-cli-extensions repo path>

type: command
short-summary: Get a URL for a git repository endpoint to clone and push to for web app deployment.
long-summary: |
Note: The default deployment branch is 'master'. If your local branch is 'main',
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

site_config = get_site_configs(cmd, resource_group_name, name, slot)
site_config.scm_type = 'LocalGit'
_generic_site_operation(cmd.cli_ctx, resource_group_name, name, 'create_or_update_configuration', slot, site_config)
logger.warning("Note: The default deployment branch is 'master'. If your local branch is 'main', "
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linux_fx = getattr(site_config, 'linux_fx_version', '') or ''
stack_prefix = linux_fx.split('|')[0].upper() if '|' in linux_fx else ''
if stack_prefix in ('PYTHON', 'NODE', 'PHP'):
logger.warning(
Copy link
Copy Markdown
Author

@vageorge00 vageorge00 Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we add this warning log:
Pros:
Helps with deployment confusion when --help is not read

Cons:

  • Logs even if SCM_DO_BUILD_DURING_DEPLOYMENT is already set. Could check app settings (extra API call) to suppress, but could add some latency.
  • If WEBSITE_RUN_FROM_PACKAGE=1 is also set, it overrides SCM_DO_BUILD_DURING_DEPLOYMENT and Oryx won't run. The warning's guidance would be misleading in that case.
  • Also logs when --type is not specified (artifact_type=None), which could include non-zip deploys. The stack check (PYTHON/NODE/PHP) mitigates most false positives since Java/.NET stacks won't match.

Open to removing the runtime warning and keeping only the help text guidance if the noise is a concern.

@vageorge00 vageorge00 marked this pull request as ready for review March 27, 2026 23:09
Copilot AI review requested due to automatic review settings March 27, 2026 23:09
Good point - no ruby

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@yonzhan yonzhan assigned yanzhudd and unassigned jiasli and zhoxing-ms Mar 27, 2026
… static site fix, container warning, startup command clarification

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@yanzhudd
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@sarsharma
Copy link
Copy Markdown
Member

nit: From the screenshot in the description, I see that we still suggest deployment commands even if cx is using docker images
image
Should we skip that for docker image scenarios to avoid confusion

az webapp create -g MyResourceGroup -p MyPlan -n MyUniqueAppName --end-to-end-encryption-enabled true --min-tls-version 1.2
- name: Create a Linux Python web app with a custom startup command.
text: >
az webapp create -g MyResourceGroup -p MyLinuxPlan -n MyUniqueAppName --runtime "PYTHON:3.14" --startup-file "gunicorn --bind=0.0.0.0 app:app"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we double check here on --startup-file
I think it might be reference to the startup script file itself instead of the actual command

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Checked -> we are able to use startup file like "startup.sh" and also a command. Fixed, added example

short-summary: Get the details for available web app publishing credentials
short-summary: Get the details for available web app publishing credentials.
long-summary: |
Note: SCM basic authentication must be enabled to use these credentials for deployment.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe also suggest the command to enable basic auth?

Copy link
Copy Markdown
Author

@vageorge00 vageorge00 Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added! To enable: az webapp update -g -n --basic-auth Enabled

long-summary: |
Usage notes:
- If the app already exists, the existing SKU is kept — the --sku flag is ignored for existing apps.
- Progress messages appear as WARNING level — these are informational, not errors.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe we can skip this about warning? this behaviour is common throughout CLI and not specific to this command

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Run this command with the --debug parameter to see the API calls and parameters values being used.
long-summary: |
Usage notes:
- If the app already exists, the existing SKU is kept — the --sku flag is ignored for existing apps.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vnit: extra hyphen after kept?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Each time the command is successfully run, default argument values for resource group, sku, location, plan, and name are saved for the current directory.
These defaults are then used for any arguments not provided on subsequent runs of the command in the same directory. Use 'az configure' to manage defaults.
Run this command with the --debug parameter to see the API calls and parameters values being used.
long-summary: |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe also add this as suggestion, since this command is likely to be used by someone deploying for the first time
Use az webapp list-runtimes to get the list of supported runtimes

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added


az webapp config appsettings set -g ResourceGroup -n AppName --settings SCM_DO_BUILD_DURING_DEPLOYMENT=true

Alternatively, use 'az webapp up' which handles resource creation, zipping, and build automatically.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we avoid suggesting webapp up here, these two commands are different use cases

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed webapp up suggestion

Note: Progress messages may appear as WARNING level — these are informational and do not
indicate errors.
examples:
- name: Deploy a Python/Node.js app from a zip file (must enable build first).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(must enable build first)
looks a little confusing, maybe we can re-phrase something like
Enable remote build(platform side build) and deploy an app from a zip file

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

with self.argument_context('appservice plan update') as c:
c.argument('sku', arg_type=sku_arg_type)
c.argument('sku', arg_type=sku_arg_type,
help='SKU of the app service plan. Use this to scale up (change machine size), e.g. --sku P1v3.')
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: scale up/down

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

c.argument('elastic_scale', arg_type=get_three_state_flag(), help='Enable or disable automatic scaling. Set to "true" to enable elastic scale for this plan, or "false" to disable elastic scale for this plan. The SKU must be a Premium V2 SKU (P1V2, P2V2, P3V2) or a Premium V3 SKU (P1V3, P2V3, P3V3)')
c.argument('max_elastic_worker_count', options_list=['--max-elastic-worker-count', '-m'], type=int, help='Maximum number of instances that the plan can scale out to. The plan must be an elastic scale plan.')
c.argument('number_of_workers', type=int, help='Number of workers to be allocated.')
c.argument('number_of_workers', type=int, help='Number of workers to be allocated. Use this to scale out (add instances), e.g. --number-of-workers 3.')
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: scale out/in (add or remove instances)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

local_context_attribute=LocalContextAttribute(name='web_name', actions=[LocalContextAction.SET],
scopes=['webapp', 'cupertino']))
c.argument('startup_file', help="Linux only. The web's startup file")
c.argument('startup_file', help="Linux only. The web's startup command. "
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as mentioned previously, let's double check on this
is this property taking the script file as input or the actual command itself?
also, if you want to accept startup command, lets add a new param for it as this can be a breaking change if you modify existing param

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double checked, it can be file or command, thanks! fixed

help="Set the OS type for the app to be created. Defaults to Linux for Python "
"and Node.js runtimes, and to Windows for .NET and ASP.NET runtimes. "
"Use 'linux' explicitly for .NET Linux deployments.")
c.argument('runtime', options_list=['--runtime', '-r'], help="canonicalized web runtime in the format of Framework:Version, e.g. \"PHP:7.2\". "
Copy link
Copy Markdown
Member

@sarsharma sarsharma Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, also suggest command to view available runtimes
az webapp list-runtimes

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

plan=plan,
is_linux=_is_linux,
client=client)
if not _plan_was_provided:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we can just check here if plan is None

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

app = client.web_apps.get(resource_group_name, name)
params.is_linux_webapp = is_linux_webapp(app)

# Warn interpreted-language Linux apps that zip deploy won't auto-build
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curios what is the case of dotnet, does it auto build?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested: .NET does auto-build with SCM_DO_BUILD_DURING_DEPLOYMENT=true. Without it, raw source gets copied but never compiled (app falls back to default placeholder). I have updated the warning to log for all Linux zip deploys, not just Python/Node/PHP. Good catch!

vageorge00 and others added 3 commits March 30, 2026 15:04
…ix, startup command clarification, scale up/down/in/out, runtime version updates

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… for basic auth

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
c.argument('acr_identity', help='Accept system or user assigned identity which will be set for acr image pull. '
'Use \'[system]\' to refer system assigned identity, or a resource id to refer user assigned identity.')
c.argument('basic_auth', help='Enable or disable basic auth for both SCM and FTP Basic Auth Publishing Credentials. Defaults to Enabled if not specified. See https://aka.ms/app-service-basic-auth to learn more.', arg_type=get_enum_type(BASIC_AUTH_TYPES))
c.argument('basic_auth', help='Enable or disable basic auth for both SCM and FTP Basic Auth Publishing Credentials. Disabled by default for new apps. See https://aka.ms/app-service-basic-auth to learn more.', arg_type=get_enum_type(BASIC_AUTH_TYPES))
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vageorge00 vageorge00 changed the title [App Service] Add deployment guidance, warnings, and container image fix for Linux web apps [App Service] Add deployment guidance, warnings for Linux web apps Mar 31, 2026
…add startup script example

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@vageorge00
Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree company="Microsoft"

@yanzhudd
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

act-observability-squad act-platform-engineering-squad Auto-Assign Auto assign by bot customer-reported Issues that are reported by GitHub users external to the Azure organization. Installation Web Apps az webapp

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants