New issue checklist
Task name
AzureRmWebAppDeployment
Task version
4 and 5
Issue Description
Issue Description
Issue Summary
We observed a deployment inconsistency when deploying a WAR package to Azure App Service on Linux using the AzureRmWebAppDeployment task.
After investigation:
AzureRmWebAppDeployment@3 works as expected.
AzureRmWebAppDeployment@4 and AzureRmWebAppDeployment@5 do not reliably update all files.
- The issue appears related to the deployment mechanism used by
@4/@5, specifically the Kudu WarDeploy API.
This occurs when WAR packages are built with reproducible or normalized timestamps (e.g., 1980-02-01T08:00:00+00:00).
Environment
- Azure App Service:
- Azure DevOps task:
- Affected:
AzureRmWebAppDeployment@4, AzureRmWebAppDeployment@5
- Working:
AzureRmWebAppDeployment@3
- Package type:
Symptom
After deploying a WAR package using AzureRmWebAppDeployment@4 or @5:
index.html is not updated
- Hashed assets (e.g.,
main-<hash>.js) are updated correctly
The same deployment works correctly with AzureRmWebAppDeployment@3.
Observed Behavior
AzureRmWebAppDeployment@5 deploys WAR packages via Kudu:
POST /api/wardeploy?isAsync=true&name=ROOT → 202
During deployment:
- The WAR is extracted to a temporary directory
- Files are synchronized to:
/home/site/wwwroot/webapps/ROOT
- Synchronization appears to use
rsync
Observed result:
Number of regular files transferred: 0
Total transferred file size: 0 bytes
This indicates no files were updated, even though the WAR contains new content.
Root Cause Analysis
The issue is caused by how rsync determines file changes.
By default, rsync compares:
- File size
- Modification timestamp (mtime)
It does not compare file content.
In this case:
- WAR files are built with normalized timestamps (e.g.,
1980-02-01T08:00:00)
- Existing deployed files also have the same mtime
For a file like index.html:
| Attribute |
Result |
| mtime |
same |
| size |
same |
| content |
different |
Because both mtime and size match, rsync skips the file.
Why Hashed Files Still Update
Files like:
are updated because:
- Filename changes between builds
- File does not exist in the destination
Therefore, rsync writes the new file regardless of timestamp.
Why AzureRmWebAppDeployment@3 Works
AzureRmWebAppDeployment@3 uses a different deployment API:
PUT /api/zip/site/wwwroot/webapps/ROOT/ → 200
This method:
- Extracts files directly into the target directory
- Overwrites existing files unconditionally
- Does not rely on mtime/size comparison
As a result, all files (including index.html) are correctly updated.
Expected Behavior
WAR deployment should update files when content changes, even if:
- File name is unchanged
- File size is unchanged
- Timestamp (mtime) is unchanged due to reproducible builds
Actual Behavior
Files may be skipped during deployment when:
- mtime is unchanged
- file size is unchanged
Resulting in stale content being served after deployment.
Impact
This can lead to partially updated deployments for Java applications, especially when using:
- Gradle or Maven reproducible builds
- Normalized archive timestamps
The deployment reports success, but application content is inconsistent.
Workarounds
- Ensure file timestamps (mtime) change between builds
- Use
AzureRmWebAppDeployment@3 instead of @4/@5
Suggested Improvements
Please consider improving WAR deployment behavior in @4/@5:
- Use checksum-based comparison (
rsync --checksum)
- Provide an option to force overwrite
- Allow disabling rsync optimization
- Align behavior with
@3 (ZIP extract overwrite)
- Document this limitation for reproducible WAR builds
Conclusion
The issue occurs because AzureRmWebAppDeployment@4/@5 relies on WarDeploy (rsync), which compares file size and mtime but not content.
When WAR files are built with normalized timestamps, changed files (e.g., index.html) may be skipped during deployment, resulting in stale application content.
Environment type (Please select at least one enviroment where you face this issue)
Azure DevOps Server type
dev.azure.com (formerly visualstudio.com)
Azure DevOps Server Version (if applicable)
No response
Operation system
Ubuntu
Relevant log output
No error but we can see the following in the log even we did have change in the index.html:
Number of regular files transferred: 0
Total transferred file size: 0 bytes
Full task logs with system.debug enabled
No response
Repro steps
We can reproduce the issue using the following task by modifying the content of index.html while keeping the file size unchanged. After building the WAR package with Gradle (with reproducible builds enabled) and deploying it, we can observe that index.html remains unchanged and is not updated.
steps:
- task: AzureRmWebAppDeployment@4
displayName: 'Azure App Service Deploy: xxx'
inputs:
azureSubscription: 'xxx'
appType: webAppLinux
WebAppName: 'xxx'
packageForLinux: '$(System.DefaultWorkingDirectory)/_xxx/xxx-artifact/build/libs/ROOT.war'
New issue checklist
Task name
AzureRmWebAppDeployment
Task version
4 and 5
Issue Description
Issue Description
Issue Summary
We observed a deployment inconsistency when deploying a WAR package to Azure App Service on Linux using the
AzureRmWebAppDeploymenttask.After investigation:
AzureRmWebAppDeployment@3works as expected.AzureRmWebAppDeployment@4andAzureRmWebAppDeployment@5do not reliably update all files.@4/@5, specifically the Kudu WarDeploy API.This occurs when WAR packages are built with reproducible or normalized timestamps (e.g.,
1980-02-01T08:00:00+00:00).Environment
AzureRmWebAppDeployment@4,AzureRmWebAppDeployment@5AzureRmWebAppDeployment@3Symptom
After deploying a WAR package using
AzureRmWebAppDeployment@4or@5:index.htmlis not updatedmain-<hash>.js) are updated correctlyThe same deployment works correctly with
AzureRmWebAppDeployment@3.Observed Behavior
AzureRmWebAppDeployment@5deploys WAR packages via Kudu:During deployment:
rsyncObserved result:
This indicates no files were updated, even though the WAR contains new content.
Root Cause Analysis
The issue is caused by how
rsyncdetermines file changes.By default,
rsynccompares:It does not compare file content.
In this case:
1980-02-01T08:00:00)For a file like
index.html:Because both mtime and size match,
rsyncskips the file.Why Hashed Files Still Update
Files like:
are updated because:
Therefore,
rsyncwrites the new file regardless of timestamp.Why
AzureRmWebAppDeployment@3WorksAzureRmWebAppDeployment@3uses a different deployment API:This method:
As a result, all files (including
index.html) are correctly updated.Expected Behavior
WAR deployment should update files when content changes, even if:
Actual Behavior
Files may be skipped during deployment when:
Resulting in stale content being served after deployment.
Impact
This can lead to partially updated deployments for Java applications, especially when using:
The deployment reports success, but application content is inconsistent.
Workarounds
AzureRmWebAppDeployment@3instead of@4/@5Suggested Improvements
Please consider improving WAR deployment behavior in
@4/@5:rsync --checksum)@3(ZIP extract overwrite)Conclusion
The issue occurs because
AzureRmWebAppDeployment@4/@5relies on WarDeploy (rsync), which compares file size and mtime but not content.When WAR files are built with normalized timestamps, changed files (e.g.,
index.html) may be skipped during deployment, resulting in stale application content.Environment type (Please select at least one enviroment where you face this issue)
Azure DevOps Server type
dev.azure.com (formerly visualstudio.com)
Azure DevOps Server Version (if applicable)
No response
Operation system
Ubuntu
Relevant log output
Full task logs with system.debug enabled
No response
Repro steps