Skip to content

Deploy an Azure App Service: support Flex Consumption plans via OneDeploy - #2077

Open
HuyPhanNguyen wants to merge 3 commits into
mainfrom
huy/2026/hpy-20-azure-flex-consumption-plan
Open

Deploy an Azure App Service: support Flex Consumption plans via OneDeploy#2077
HuyPhanNguyen wants to merge 3 commits into
mainfrom
huy/2026/hpy-20-azure-flex-consumption-plan

Conversation

@HuyPhanNguyen

@HuyPhanNguyen HuyPhanNguyen commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Background

The built-in "Deploy an Azure App Service" step fails with HTTP 404 when the target Function App runs on an Azure Flex Consumption plan. Calamari uploads the package by POSTing to the Kudu /api/zipdeploy endpoint, which Flex Consumption plans don't expose. Microsoft now recommends Flex Consumption over the classic Consumption plan and is deprecating the classic plan on 2028-09-30, so more customers will hit this over time.

Results

Detects the App Service Plan SKU tier at deploy time and, when it's Flex Consumption, uploads zip/nupkg packages through the OneDeploy (/api/publish?type=zip) endpoint with an application/zip content type instead of ZipDeploy.

Fixes HPY-20.

Before

Deploying a zip/nupkg package to a Flex Consumption Function App POSTs to https://<scm>/api/zipdeploy and returns 404 (Not Found), so the step fails.
image

After (this PR)

The step resolves the plan tier (App Service Plan '...' is on the 'FlexConsumption' tier (SKU 'FC1')), POSTs to /api/publish?type=zip, polls to completion, and the deployment succeeds. Non-Flex plans are unaffected and still use /api/zipdeploy.
image

Both captured live against the same real Flex Consumption Function App, same package — only the Calamari build differs.

Testing

  • Unit: extended PackageProviderFactoryFixture to assert the upload endpoint, sync/async mode, and content type for the Flex and non-Flex cases across .zip/.nupkg/.war/.jar.
  • Live end-to-end against a real Azure Flex Consumption Function App (dotnet-isolated 8.0), deploying via the built-in step with this build injected through Octopus.Calamari.Executable:
    • Before: POST .../api/zipdeploy?isAsync=true404 (Not Found), deployment fails.
    • After: App Service Plan ... is on the 'FlexConsumption' tier (SKU 'FC1')POST .../api/publish?type=zip → deployment succeeds.

Automated Tests

  • Run full chain build (PRs targeting main release/* branches only)

Pre-requisites

  • I have read How we use GitHub Issues for help deciding when and where it's appropriate to make an issue.
  • I have considered informing or consulting the right people, according to the ownership map.
  • I have considered the appropriate target version for this PR.
  • I have considered appropriate testing for my change.
  • I have considered manually testing my changes on a branch instance to check correctness, stability and performance on Octopus Cloud.
  • I have considered safety nets to reduce any time-to-recovery for my change.

…plans

Flex Consumption plans don't expose Kudu /api/zipdeploy (404). Detect the
plan SKU tier and, when it's FlexConsumption, upload zip/nupkg packages via
the OneDeploy /api/publish?type=zip endpoint with an application/zip content type.
- Wrap Flex detection in try/catch; fall back to ZipDeploy (with a warning
  naming serverfarms/read) so a plan-read 403 can't break non-Flex deploys.
- Extract testable IsFlexConsumptionTier; also match SKU name 'FC1' so a null
  Tier doesn't silently route to the wrong endpoint.
- CopyNupkgToZip: use Path.ChangeExtension and overwrite to survive retries.
- Unit tests for tier detection and the nupkg->zip conversion.
… as success

OneDeploy (/api/publish) returns 202 Accepted + a Location and processes the
deployment asynchronously; the previous code treated the 202 as success. Poll
the Location until complete and fail on a non-success Kudu status. Verified
live: a package missing the .azurefunctions directory now fails the step
(status 3) instead of reporting green.
@wlthomson
wlthomson marked this pull request as ready for review July 23, 2026 00:03
@HuyPhanNguyen
HuyPhanNguyen requested a review from a team July 23, 2026 00:06
@HuyPhanNguyen
HuyPhanNguyen enabled auto-merge (squash) July 23, 2026 05:01
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.

1 participant