[App Service] Tests: Bump Node runtime from 20 to 22 LTS#33302
[App Service] Tests: Bump Node runtime from 20 to 22 LTS#33302
Conversation
Node.js 20 (Iron) reached end-of-life on April 30, 2026. The App Service runtime resolver filters out EOL runtimes locally, causing 13 tests in test_webapp_commands.py to fail with 'ValidationError: Linux Runtime NODE|20-LTS is not supported'. Updates: - test_webapp_commands.py: NODE|20-* / NODE:20* and ~20 references -> Node 22 LTS (preserving original case at each call site). - test_webapp_up_commands.py: legacy node|14-* / node|16-* / NODE|20-* references in @live_only tests -> Node 22 LTS so they no longer rely on EOL runtimes when run live. - Regenerated 13 affected recordings against a live subscription so cassette PATCH/PUT bodies match the new runtime values. Note: Windows App Service does not yet expose Node 24, so Node 22 LTS (supported on both Linux and Windows) was selected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
️✔️AzureCLI-FullTest
|
️✔️AzureCLI-BreakingChangeTest
|
|
Thank you for your contribution! We will review the pull request and get back to you soon. |
|
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). pip install azdev --upgrade
azdev setup -c <your azure-cli repo path> -r <your azure-cli-extensions repo path>
|
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Updates App Service test suite runtime expectations to Node.js 22 LTS (replacing EOL Node 20) and refreshes VCR recordings so playback matches the new request bodies.
Changes:
- Replace Node 20 runtime strings / app setting expectations with Node 22 equivalents across App Service scenario tests.
- Update
@live_only“webapp up” tests to avoid legacy/EOL Node runtimes. - Regenerate VCR recordings to reflect updated runtimes in PUT/PATCH request bodies.
Reviewed changes
Copilot reviewed 2 out of 15 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_webapp_up_commands.py | Updates webapp up tests to use Node 22 LTS and adjusts runtime/app-setting assertions. |
| src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_webapp_commands.py | Bumps Node runtime references and Windows WEBSITE_NODE_DEFAULT_VERSION expectations to ~22. |
| src/azure-cli/azure/cli/command_modules/appservice/tests/latest/recordings/test_linux_webapp_remote_ssh.yaml | Re-records HTTP interactions reflecting Node 22 runtime and updated request/response payloads. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| # test the full E2E operation works | ||
| self.cmd('webapp up -n {} -g {} --plan {} --os "windows" --runtime "node|14-LTS"'.format(webapp_name, resource_group, plan)) | ||
| self.cmd('webapp up -n {} -g {} --plan {} --os "windows" --runtime "node|22-LTS"'.format(webapp_name, resource_group, plan)) |
There was a problem hiding this comment.
The test test_webapp_up_change_runtime_version_windows no longer validates a runtime change (both runs target Node 22, differing only by case). This reduces the test’s ability to catch regressions in “change runtime” behavior. Consider either (mandatory) updating the test intent/name to reflect idempotency/case-insensitivity, or (preferred) changing the scenario to switch between two supported Windows Node runtimes if available (e.g., oldest supported → Node 22) so the test still exercises an actual version transition.
| self.assertIn("22", app_settings["WEBSITE_NODE_DEFAULT_VERSION"].lower()) | ||
|
|
||
| # test changing runtime to newer version | ||
| self.cmd('webapp up -n {} -g {} --plan {} --os "windows" --runtime "node|16-lts"'.format(webapp_name, resource_group, plan)) | ||
| self.cmd('webapp up -n {} -g {} --plan {} --os "windows" --runtime "node|22-lts"'.format(webapp_name, resource_group, plan)) |
There was a problem hiding this comment.
The test test_webapp_up_change_runtime_version_windows no longer validates a runtime change (both runs target Node 22, differing only by case). This reduces the test’s ability to catch regressions in “change runtime” behavior. Consider either (mandatory) updating the test intent/name to reflect idempotency/case-insensitivity, or (preferred) changing the scenario to switch between two supported Windows Node runtimes if available (e.g., oldest supported → Node 22) so the test still exercises an actual version transition.
| app_settings = {s["name"] : s["value"] for s in app_settings} | ||
| self.assertIn("WEBSITE_NODE_DEFAULT_VERSION", app_settings) | ||
| self.assertIn("16", app_settings["WEBSITE_NODE_DEFAULT_VERSION"].lower()) | ||
| self.assertIn("22", app_settings["WEBSITE_NODE_DEFAULT_VERSION"].lower()) |
There was a problem hiding this comment.
The test test_webapp_up_change_runtime_version_windows no longer validates a runtime change (both runs target Node 22, differing only by case). This reduces the test’s ability to catch regressions in “change runtime” behavior. Consider either (mandatory) updating the test intent/name to reflect idempotency/case-insensitivity, or (preferred) changing the scenario to switch between two supported Windows Node runtimes if available (e.g., oldest supported → Node 22) so the test still exercises an actual version transition.
| app_settings = {s["name"] : s["value"] for s in app_settings} | ||
| self.assertIn("WEBSITE_NODE_DEFAULT_VERSION", app_settings) | ||
| self.assertIn("14", app_settings["WEBSITE_NODE_DEFAULT_VERSION"].lower()) | ||
| self.assertIn("22", app_settings["WEBSITE_NODE_DEFAULT_VERSION"].lower()) |
There was a problem hiding this comment.
These assertions are now very weak: any value containing “22” will pass (including unexpected formats), so a regression could slip through. Since other tests in this PR check exact values like ~22, consider asserting equality (or at least startswith("~22")) for WEBSITE_NODE_DEFAULT_VERSION to keep the test precise and consistent with the Windows runtime contract.
| app_settings = {s["name"] : s["value"] for s in app_settings} | ||
| self.assertIn("WEBSITE_NODE_DEFAULT_VERSION", app_settings) | ||
| self.assertIn("16", app_settings["WEBSITE_NODE_DEFAULT_VERSION"].lower()) | ||
| self.assertIn("22", app_settings["WEBSITE_NODE_DEFAULT_VERSION"].lower()) |
There was a problem hiding this comment.
These assertions are now very weak: any value containing “22” will pass (including unexpected formats), so a regression could slip through. Since other tests in this PR check exact values like ~22, consider asserting equality (or at least startswith("~22")) for WEBSITE_NODE_DEFAULT_VERSION to keep the test precise and consistent with the Windows runtime contract.
| @@ -5,20 +5,20 @@ interactions: | |||
| Accept: | |||
| - application/json | |||
| Accept-Encoding: | |||
| - gzip, deflate | |||
| - gzip, deflate, zstd | |||
There was a problem hiding this comment.
The regenerated cassette includes highly environment-specific request headers (Accept-Encoding and User-Agent with exact CLI/Python/OS versions). If the VCR matching configuration ever considers headers (now or in future changes), these recordings can become non-portable across dev machines/CI agents (Windows vs macOS, different CLI builds). Consider scrubbing/normalizing these headers during recording (or explicitly configuring the matcher to ignore them) to keep playback stable across environments.
| CommandName: | ||
| - appservice plan create | ||
| Connection: | ||
| - keep-alive | ||
| ParameterSetName: | ||
| - -g -n --sku --is-linux | ||
| User-Agent: | ||
| - AZURECLI/2.79.0 azsdk-python-core/1.35.0 Python/3.13.9 (Windows-11-10.0.26200-SP0) | ||
| - AZURECLI/2.86.0 azsdk-python-core/1.39.0 Python/3.14.2 (macOS-26.4.1-arm64-arm-64bit-Mach-O) |
There was a problem hiding this comment.
The regenerated cassette includes highly environment-specific request headers (Accept-Encoding and User-Agent with exact CLI/Python/OS versions). If the VCR matching configuration ever considers headers (now or in future changes), these recordings can become non-portable across dev machines/CI agents (Windows vs macOS, different CLI builds). Consider scrubbing/normalizing these headers during recording (or explicitly configuring the matcher to ignore them) to keep playback stable across environments.
* Regenerate test_win_webapp_quick_create.yaml: my prior change of
the WEBSITE_NODE_DEFAULT_VERSION assertion from '~20' to '~22'
invalidated the existing recording (which still returned '~20'),
so the test was failing in CI playback. The cassette now reflects
the App Service default of Node 22.
* Regenerate test_acr_integration.yaml against the
azure-mgmt-containerregistry==15.1.0b1 SDK pinned in
src/azure-cli/requirements.py3.*.txt so the recorded API version
(2026-01-01-preview) matches what the CI environment sends.
* test_webapp_up_runtime_case_insensitivity_windows: rename and
rework former 'change_runtime_version_windows' test. Windows
App Service currently exposes only Node 22 LTS, so the test
cannot exercise a real runtime version transition; renaming to
reflect that it now validates 'webapp up --runtime' is
case-insensitive / idempotent for the same runtime token.
* Tighten WEBSITE_NODE_DEFAULT_VERSION assertions from
assertIn('22', ...) to assertEqual(..., '~22') for precision,
matching the contract enforced by other tests in this file.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Thanks for the review! Pushed Review comments addressed
CI failures fixed
All 14 affected tests pass in playback locally (14.16s). |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Addressed remaining CI failures:
|
Description
Node.js 20 (Iron) reached end-of-life on April 30, 2026. The App Service runtime resolver filters out EOL runtimes locally (
src/azure-cli/azure/cli/command_modules/appservice/custom.py), causing 13 tests intest_webapp_commands.pyto fail with:This PR bumps the Node.js runtime references in the App Service tests from Node 20 to Node 22 LTS and regenerates the affected VCR recordings.
Changes
test_webapp_commands.py— 25 edits replacingNODE|20-LTS/NODE:20LTS/NODE:20-lts(and the~20WEBSITE_NODE_DEFAULT_VERSIONassertions) with their Node 22 equivalents. Original case is preserved at each call site.test_webapp_up_commands.py— 23 edits cleaning up legacynode|14-*/node|16-*/NODE|20-*references in@live_onlytests so they no longer rely on EOL runtimes when run live.tests/latest/recordings/. Cassettes had to be re-recorded because Azure CLI's VCR matcher includes the request body, and the runtime field appears in PATCH/PUT bodies sent to the App Service control plane.Verification
Tests covered
WebappQuickCreateTest::test_linux_webapp_quick_create_cdWebappQuickCreateTest::test_win_webapp_quick_create_cdWebappQuickCreateTest::test_win_webapp_quick_create_runtimeAppServiceLogTest::test_download_win_web_logWebappConfigureTest::test_webapp_configLinuxWebappScenarioTest::test_linux_webappLinuxWebappRemoteSSHScenarioTest::test_linux_webapp_remote_sshWebappACRScenarioTest::test_acr_integrationWebappAcrUseManagedIdentityCredsTests::test_webapp_linux_acr_use_identityTrackRuntimeStatusTest::test_webapp_deployment_source_track_runtimestatus_buildfailedTrackRuntimeStatusTest::test_webapp_deployment_source_track_runtimestatus_runtimefailedTrackRuntimeStatusTest::test_webapp_track_runtimestatus_buildfailedTrackRuntimeStatusTest::test_webapp_track_runtimestatus_runtimefailed