Skip to content

[App Service] Tests: Bump Node runtime from 20 to 22 LTS#33302

Open
seligj95 wants to merge 3 commits intoAzure:devfrom
seligj95:appservice/tests-node22
Open

[App Service] Tests: Bump Node runtime from 20 to 22 LTS#33302
seligj95 wants to merge 3 commits intoAzure:devfrom
seligj95:appservice/tests-node22

Conversation

@seligj95
Copy link
Copy Markdown
Contributor

@seligj95 seligj95 commented Apr 30, 2026

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 in test_webapp_commands.py to fail with:

ValidationError: Linux Runtime 'NODE|20-LTS' is not supported.

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 replacing NODE|20-LTS / NODE:20LTS / NODE:20-lts (and the ~20 WEBSITE_NODE_DEFAULT_VERSION assertions) with their Node 22 equivalents. Original case is preserved at each call site.
  • test_webapp_up_commands.py — 23 edits cleaning up legacy node|14-* / node|16-* / NODE|20-* references in @live_only tests so they no longer rely on EOL runtimes when run live.
  • 13 regenerated VCR recordings under 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

  • All 13 originally-failing tests were re-recorded against a live subscription.
  • Final playback run of all 13 tests: 13 passed in 12.35s

Tests covered

  • WebappQuickCreateTest::test_linux_webapp_quick_create_cd
  • WebappQuickCreateTest::test_win_webapp_quick_create_cd
  • WebappQuickCreateTest::test_win_webapp_quick_create_runtime
  • AppServiceLogTest::test_download_win_web_log
  • WebappConfigureTest::test_webapp_config
  • LinuxWebappScenarioTest::test_linux_webapp
  • LinuxWebappRemoteSSHScenarioTest::test_linux_webapp_remote_ssh
  • WebappACRScenarioTest::test_acr_integration
  • WebappAcrUseManagedIdentityCredsTests::test_webapp_linux_acr_use_identity
  • TrackRuntimeStatusTest::test_webapp_deployment_source_track_runtimestatus_buildfailed
  • TrackRuntimeStatusTest::test_webapp_deployment_source_track_runtimestatus_runtimefailed
  • TrackRuntimeStatusTest::test_webapp_track_runtimestatus_buildfailed
  • TrackRuntimeStatusTest::test_webapp_track_runtimestatus_runtimefailed

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>
Copilot AI review requested due to automatic review settings April 30, 2026 15:57
@azure-client-tools-bot-prd
Copy link
Copy Markdown

azure-client-tools-bot-prd Bot commented Apr 30, 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

azure-client-tools-bot-prd Bot commented Apr 30, 2026

️✔️AzureCLI-BreakingChangeTest
️✔️Non Breaking Changes

@yonzhan
Copy link
Copy Markdown
Collaborator

yonzhan commented Apr 30, 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>

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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))
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines +1111 to +1114
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))
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
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())
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
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())
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
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())
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
@@ -5,20 +5,20 @@ interactions:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
- gzip, deflate, zstd
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
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)
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
* 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>
@seligj95
Copy link
Copy Markdown
Contributor Author

Thanks for the review! Pushed 5fae77d to address the feedback and the failing CI tests:

Review comments addressed

  • test_webapp_up_change_runtime_version_windows (test_webapp_up_commands.py): renamed to test_webapp_up_runtime_case_insensitivity_windows and updated the inline comment to reflect what the test now validates. Windows App Service currently exposes only Node 22 LTS for Node, so a real version transition isn't possible — taking the mandatory path from the review (rename / restate intent).
  • assertIn("22", value.lower())assertEqual(value, "~22") for both WEBSITE_NODE_DEFAULT_VERSION checks, so the assertion is precise and consistent with the ~22 checks elsewhere in this PR.
  • VCR cassette headers (Accept-Encoding / User-Agent): leaving as-is. The current VCR matcher in this repo doesn't match on headers (only method, scheme, host, port, path, custom query, body), and changing the recording-side scrubbing is out-of-scope for an EOL bump.

CI failures fixed

  • test_win_webapp_quick_create: my earlier source change '~20''~22' invalidated the existing cassette (which still returned ~20). Re-recorded live; the regenerated cassette now reflects App Service's current default of Node 22.
  • test_acr_integration: the original re-recording was made against azure-mgmt-containerregistry==14.1.0b1 (locally stale), so the cassette had api-version=2025-04-01 while CI's pinned 15.1.0b1 sends 2026-01-01-preview. Re-recorded against the pinned SDK version; the new cassette URLs match CI.

All 14 affected tests pass in playback locally (14.16s).

@seligj95 seligj95 changed the title [App Service] Tests: bump Node runtime from 20 to 22 LTS {App Service} Tests: bump Node runtime from 20 to 22 LTS Apr 30, 2026
@seligj95 seligj95 changed the title {App Service} Tests: bump Node runtime from 20 to 22 LTS [App Service] Bump Node runtime from 20 to 22 LTS in tests Apr 30, 2026
@seligj95 seligj95 changed the title [App Service] Bump Node runtime from 20 to 22 LTS in tests [App Service] Tests: Bump Node runtime from 20 to 22 LTS Apr 30, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@seligj95
Copy link
Copy Markdown
Contributor Author

Addressed remaining CI failures:

  • PR title format: Capitalized first word after : (bumpBump).
  • Secret Scan: ACR access tokens were captured in test_acr_integration.yaml during live recording. Masked the two unique CommonAnnotatedSecurityKey values with ***. Re-scanned with azdev scan — no secrets detected. Test still passes in playback (1.79s).

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants