Skip to content

fix: handle read-only .git files in deploy cleanup on Windows - #4719

Closed
weiguangli-io wants to merge 4 commits into
google:mainfrom
weiguangli-io:codex/adk-4635-windows-rmtree-readonly
Closed

weiguangli-io wants to merge 4 commits into
google:mainfrom
weiguangli-io:codex/adk-4635-windows-rmtree-readonly

Conversation

@weiguangli-io

Copy link
Copy Markdown
Contributor

Summary

Fixes #4635

On Windows, files inside .git/objects/ are marked read-only by default. When adk deploy cleans up the temporary directory in its finally block, shutil.rmtree() raises PermissionError: [WinError 5] Access denied on these files, causing the CLI to crash even after a successful deployment.

This PR introduces a _robust_rmtree() helper that passes an error handler to shutil.rmtree. On Windows, the handler clears the read-only bit (os.chmod(path, stat.S_IWRITE)) and retries the deletion. On non-Windows platforms, shutil.rmtree is called without any handler. The fix uses onexc for Python >= 3.12 and onerror for Python < 3.12 to avoid deprecation warnings.

All six shutil.rmtree() call sites in cli_deploy.py (to_cloud_run, to_agent_engine, to_gke) are updated.

Test Plan

  • Added TestRobustRmtree with three unit tests:
    • test_removes_directory_tree -- verifies normal directory removal
    • test_removes_readonly_files -- verifies removal of trees containing read-only files
    • test_on_rm_error_clears_readonly_and_retries -- verifies the error handler chmod + retry logic
  • All 33 existing + new tests pass: pytest tests/unittests/cli/utils/test_cli_deploy.py

… cleanup

Replace all bare shutil.rmtree() calls in cli_deploy.py with a
_robust_rmtree() helper that clears the read-only bit before
retrying deletion on Windows. This prevents PermissionError
([WinError 5]) when cleaning up .git/objects after deployment.

The fix is compatible with Python 3.10+ (uses onerror for <3.12
and onexc for >=3.12).
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@adk-bot adk-bot added the tools [Component] This issue is related to tools label Mar 5, 2026
@rohityan rohityan self-assigned this Mar 9, 2026
@rohityan
rohityan requested a review from yeesian March 11, 2026 18:57
@rohityan

Copy link
Copy Markdown
Collaborator

Hi @weiguangli-io , Thank you for your contribution! We appreciate you taking the time to submit this pull request. Can you please fix the failing mypy-diff tests.

@rohityan rohityan added core [Component] This issue is related to the core interface and implementation request clarification [Status] The maintainer need clarification or more information from the author and removed tools [Component] This issue is related to tools labels Mar 11, 2026
@rohityan rohityan added needs review [Status] The PR/issue is awaiting review from the maintainer and removed request clarification [Status] The maintainer need clarification or more information from the author labels Mar 12, 2026
@rohityan

Copy link
Copy Markdown
Collaborator

Hi @wuliang229 , can you please review this.

@musaslmv

Copy link
Copy Markdown

Hi @rohityan @yeesian , would it be possible to speed up the review of this request, please? thanks a lot!

@weiguangli-io

Copy link
Copy Markdown
Contributor Author

Friendly ping — CI is green. Would appreciate a review when you get a chance. Thanks!

@haranrk haranrk assigned haranrk and unassigned rohityan Jun 17, 2026
copybara-service Bot pushed a commit that referenced this pull request Aug 14, 2026
On Windows, files inside `.git/objects/` are marked read-only by default. When `adk deploy` cleans up the temporary directory in its `finally` block, `shutil.rmtree()` raises `PermissionError: [WinError 5] Access denied` on these files, causing the CLI to crash even after a successful deployment.

This PR introduces a `_robust_rmtree()` helper that passes an error handler to `shutil.rmtree`. On Windows, the handler clears the read-only bit (`os.chmod(path, stat.S_IWRITE)`) and retries the deletion. On non-Windows platforms, `shutil.rmtree` is called without any handler. The fix uses `onexc` for Python >= 3.12 and `onerror` for Python < 3.12 to avoid deprecation warnings.

All six `shutil.rmtree()` call sites in `cli_deploy.py` (`to_cloud_run`, `to_agent_engine`, `to_gke`) are updated.

Fixes #4635

Merge #4719

PiperOrigin-RevId: 964392331
@adk-bot

adk-bot commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Thank you @weiguangli-io for your contribution! 🎉

Your changes have been successfully imported and merged via Copybara in commit c93fcc0.

Closing this PR as the changes are now in the main branch.

@adk-bot adk-bot added the merged [Status] This PR is merged label Aug 14, 2026
@adk-bot adk-bot closed this Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core [Component] This issue is related to the core interface and implementation merged [Status] This PR is merged needs review [Status] The PR/issue is awaiting review from the maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Windows] adk deploy fails with [WinError 5] during cleanup of .git repositories

5 participants