-
Notifications
You must be signed in to change notification settings - Fork 6.3k
fix: Hydrator wipes out entire branch when multiple Applications hydrate to the same branch with different path (fixes #24179) #24185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
🔴 Preview Environment stopped on BunnyshellSee: Environment Details | Pipeline Logs Available commands (reply to this comment):
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #24185 +/- ##
==========================================
+ Coverage 60.11% 60.14% +0.02%
==========================================
Files 347 348 +1
Lines 59856 59894 +38
==========================================
+ Hits 35985 36025 +40
+ Misses 20984 20980 -4
- Partials 2887 2889 +2 ☔ View full report in Codecov by Sentry. |
725bd4d
to
02dd790
Compare
commitserver/commit/commit.go
Outdated
return "", "", fmt.Errorf("failed to clear path %s: %w", targetPath, err) | ||
} | ||
logCtx.Debugf("Recreating directory %s", targetPath) | ||
if err := os.MkdirAll(targetPath, 0o755); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't WriteForPaths
creates a directory already?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, WriteForPaths does attempt to create the target directory for each manifest path before writing the files. However, there are two reasons I explicitly ensure the directory exists in handleCommitRequest:
Path Deletion Race: Immediately after deleting a directory with os.RemoveAll, there can be a brief moment (especially under heavy parallelization or on some filesystems) where the directory is still being cleaned up. Explicitly recreating it guarantees a safe write regardless of timing.
Top-Level Metadata: The top-level hydrator.metadata is written to the root (dirPath), and in edge cases (such as root path hydration), it’s important to be sure dirPath wasn't accidentally removed or left missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Path Deletion Race: Immediately after deleting a directory with os.RemoveAll, there can be a brief moment (especially under heavy parallelization or on some filesystems) where the directory is still being cleaned up. Explicitly recreating it guarantees a safe write regardless of timing.
Did you try these changes locally? Woudln't you get an error if you're trying to create the same directory again provided it has already been created once?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @nitishfy, i have run it locally and it's working good. The main reason i recreates the directory is because os.RemoveAll(targetPath) will remove everything at targetPath, including all files and the directory itself. So whenever i am calling os.RemoveAll(), i am recreating the directory after that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something feels a bit off about changes....Please consider putting a demonstration video if possible OR prefer adding more tests to validate this behaviour. Thanks!
Not related to PR changes..... I see someone already asked about working on the issue. Although the person wasn't assigned but please get an issue assigned beforehand and raise a fix then. There are chances that the other person might have started working on the issue that would lead to wastage of efforts at the end. |
40c0a5a
to
f95155e
Compare
commitserver/commit/commit.go
Outdated
logCtx.Debug("Using root directory for manifests, no directory removal needed") | ||
} else { | ||
logCtx.Debugf("Clearing path %s", targetPath) | ||
if err := os.RemoveAll(targetPath); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if err := os.RemoveAll(targetPath); err != nil { | |
if err := os.RemoveAll(targetPath); err != nil { |
Why aren't we using gitClient.RemoveContents()
anymore? I think we should modify the git client call than calling the os.RemoveAll
function here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is a little bit related to fixing #23944. I'd suggest going through the PR that fixes that issue and take some inspiration from that. For now, this PR needs a lot of modification and I'd prefer having a demonstration video at the end to make sure everything is working before finally approving.
Also, if you want, you can bring this PR in Argo CD community call happening at Thursday (8:45 PM IST)
50dacc3
to
332e638
Compare
Thanks, @nitishfy, for the reply and sharing the related issue #23944. I see that both issues are quite similar. I believe stopping users from providing the root directory as a path might be restrictive since some users may want to store manifests directly in the root. Instead, focusing on cleaning only subdirectories during commits should solve the problem—since commits in the root directory will only modify files like README.md, manifests.yaml, and hydrator.metadata, leaving CI/CD config files unaffected.I will prepare and share a demonstration video to showcase this approach. Thanks also for the insight on preferring gitClient.RemoveContents() over os.RemoveAll(). Thanks again for the valuable feedback! |
Demonstartion video: https://github.com/user-attachments/assets/c9c1a854-b7a2-4467-87f2-eeb6850dba52 Clip 1: The hydrator targets the subdirectory test, which contains .txt files. These files are properly removed and replaced during hydration. Clip 2: The hydrator targets the root path, where a critical file config.yaml exists. This file remains unaffected by the hydration process, ensuring important root-level config files are preserved. |
332e638
to
f017621
Compare
0a185eb
to
aa4892c
Compare
…ple Applications hydrate to the same branch with different path Signed-off-by: Aditya Raj <[email protected]>
Signed-off-by: Aditya Raj <[email protected]>
Signed-off-by: Aditya Raj <[email protected]>
aa4892c
to
53fb859
Compare
Hydrator wipes out entire branch when multiple Applications hydrate to the same branch with different path.
Description:
Closes:
Why this PR is necessary:
Without this fix, hydrating multiple Applications to the same branch is destructive. This makes source hydrator unsafe in multi-application setups. With this fix, Applications can hydrate independently to different directories inside the same branch.
Demonstartion video: https://github.com/user-attachments/assets/c9c1a854-b7a2-4467-87f2-eeb6850dba52
Checklist: