azure/webapps-deploy@v3 / OneDeploy 409 left Linux Python App Service in compressed-only wwwroot state; startup.sh missing
- Dominant language
- TypeScript
- Stars
- 338
- Forks
- 234
- Avg merge
- 53m
- Merged PRs (30d)
- 3
Description
## Summary
`azure/webapps-deploy@v3` failed during OneDeploy with `409 Conflict` and left a Linux Python App Service in a broken partial deployment state.
After the failed deploy, `/home/site/wwwroot` contained only:
```text
.ostype
hostingstart.html
output.tar.zst
```
The expected app files were inside `output.tar.zst`, but were not extracted/activated into `wwwroot`. Because the App Service startup command was `startup.sh`, the app failed to boot with:
```text
/opt/startup/startup.sh: 23: startup.sh: not found
```
## Environment
- Azure App Service on Linux
- Python 3.12
- Deployment via GitHub Actions
- Action: `azure/webapps-deploy@v3`
- Deployment backend: OneDeploy
- Startup command: `startup.sh`
## Deploy failure
```text
Package deployment using OneDeploy initiated.
Error: Failed to deploy web package to App Service.
Error: Deployment Failed, Error: Failed to deploy web package using OneDeploy to App Service.
Conflict (CODE: 409)
```
## Runtime failure
```text
Site's appCommandLine: startup.sh
Launching oryx with: create-script -appPath /home/site/wwwroot -output /opt/startup/startup.sh -virtualEnvName antenv -defaultApp /opt/defaultsite -userStartupCommand 'startup.sh'
WARNING: Could not find virtual environment directory /home/site/wwwroot/antenv.
/opt/startup/startup.sh: 23: startup.sh: not found
```
## Kudu findings
Deployment state appeared stuck/incomplete:
```text
/home/site/deployments/pending
/home/site/deployments/temp-*
/home/site/locks/status.lock
```
The compressed artifact did contain the expected files:
```text
./startup.sh
./pyproject.toml
./antenv/
./app/app.py
```
## Manual recovery
The app was recovered by clearing the stale deployment state and manually extracting the artifact:
```bash
rm -f /home/site/locks/status.lock
rm -f /home/site/locks/info.lock
rm -f /home/site/deployments/pending
rm -rf /home/site/deployments/temp-*
cd /home/site/wwwroot
tar --zstd -xf output.tar.zst
chmod +x startup.sh
```
After restarting, App Service successfully found the startup file and virtual environment.
## Expected behavior
If OneDeploy fails, the App Service should either:
1. Complete extraction/activation of the artifact, or
2. Fail atomically and preserve the previous working deployment.
It should not leave `wwwroot` containing only `output.tar.zst` while the configured startup command points to a file that exists only inside the archive.
## Questions
- Is this a known issue with `azure/webapps-deploy@v3`, OneDeploy, Linux App Service, Python/Oryx, or `output.tar.zst` activation?
- Under what conditions can OneDeploy leave `wwwroot` in this compressed-only state?
- What is the recommended production-safe deployment configuration to prevent this?
- Should the action detect or recover from stale `pending`, `temp-*`, or `status.lock` deployment state?
## Impact
This caused a production outage and required manual Kudu intervention to restore service.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reproducing the azure/webapps-deploy@v3 OneDeploy path for a Linux Python App Service and inspect the Kudu deployment state, including pending, temp-* and lock files. Compare the wwwroot contents with output.tar.zst after a 409; done means a failed deployment either activates the artifact completely or preserves the previous working deployment without manual intervention.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, github-actions, python, typescript
- Domain
- cloud, devops
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100