Skip to content

fix(launchpad): Ensure mobile artifact's zip structures are preserved#2585

Merged
NicoHinderling merged 7 commits intomasterfrom
preserve-xcarchive-zip-structure
Jul 14, 2025
Merged

fix(launchpad): Ensure mobile artifact's zip structures are preserved#2585
NicoHinderling merged 7 commits intomasterfrom
preserve-xcarchive-zip-structure

Conversation

@NicoHinderling
Copy link
Copy Markdown
Contributor

WIthout this, the code would remove the xcarchive wrapper directory, which causes issues when trying to parse the artifact in launchpad

Copy link
Copy Markdown
Member

@szokeasaurusrex szokeasaurusrex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see inline comments.

Also, small nitpick: prior to merge, please rename the commit message to fix(mobile-app): ... in keeping with Sentry's commit message naming conventions (we use fix instead of bug, and mobile-app is the user-facing name of this feature).

@NicoHinderling NicoHinderling changed the title bug(launchpad): Ensure mobile artifact's zip structures are preserved fix(launchpad): Ensure mobile artifact's zip structures are preserved Jul 9, 2025
@NicoHinderling NicoHinderling force-pushed the preserve-xcarchive-zip-structure branch from c782961 to 6991773 Compare July 9, 2025 14:11
Copy link
Copy Markdown
Member

@szokeasaurusrex szokeasaurusrex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see inline comments.

Also, I am struggling to see how the behavior has changed following these changes. As far as I can tell, this code should behave exactly the same as what we had before because it looks to me like the zip_path is equivalent to the previous relative_path.

Can you please explain what the desired difference in behavior is? If possible, please add a test case, which fails against the original code, but passes against the new code, to verify the desired behavior. This will also help me understand the purpose of this change, which I am currently struggling to grasp.

Comment on lines 252 to 261
.map(|entry| Ok(entry.into_path()))
.collect::<Result<Vec<_>>>()?
.into_iter()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrapping this in an Ok is unnecessary, because it is an infallible operation. Also, no need to collect into a vector just to make an iterator again.

Suggested change
.map(|entry| Ok(entry.into_path()))
.collect::<Result<Vec<_>>>()?
.into_iter()
.map(|entry| entry.into_path())

debug!("Adding file to zip: {}", zip_path.display());

zip.start_file(relative_path.to_string_lossy(), options)?;
zip.start_file(zip_path.to_string_lossy(), options)?;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this zip_path different from the relative_path we had before?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The top level path is no longer being stripped.

Example: entry_path = /full/path/to/MyApp.xcarchive/Products/app.txt

relative_path stripped the entire path (/full/path/to/MyApp.xcarchive), losing the directory name
zip_path strips only the parent path (/full/path/to), keeping the directory name

Before: relative_path = Products/app.txt
After: zip_path = MyApp.xcarchive/Products/app.txt

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay! I think I see the difference now. Whereas previously, you called strip_prefix(path), you now call strip_prefix(path.parent), correct?

Assuming the above is correct, I have two questions:

  1. Couldn't you have simply added the path.parent call where we were previously computing the relative_path? It seems like you are also refactoring the code by moving this changed strip_prefix into the for loop. Is this refactor causing some other functionality change which I am missing?
  2. Is it reasonable to assume that the path should always have a parent? E.g., what if we are running this from the root directory? Not that I think it would be super common, but perhaps there are some scenarios where this could occur (e.g. if running from within a Docker container)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. No I think you're right that the for loop refactor was not necessary. I've changed it to be this way, apologies for the thrash.
  2. Yes it is but I've added a ok_or_else just in case

@NicoHinderling
Copy link
Copy Markdown
Contributor Author

NicoHinderling commented Jul 11, 2025

Please see inline comments.

Also, I am struggling to see how the behavior has changed following these changes. As far as I can tell, this code should behave exactly the same as what we had before because it looks to me like the zip_path is equivalent to the previous relative_path.

Can you please explain what the desired difference in behavior is? If possible, please add a test case, which fails against the original code, but passes against the new code, to verify the desired behavior. This will also help me understand the purpose of this change, which I am currently struggling to grasp.

It's about preserving the top directory in the path. I've added a unit test 👍

@NicoHinderling NicoHinderling force-pushed the preserve-xcarchive-zip-structure branch from 7a4cc1a to b9d924c Compare July 11, 2025 20:30
Copy link
Copy Markdown
Member

@szokeasaurusrex szokeasaurusrex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the test and explaining the functionality change, this makes some more sense now. Although, I still have a couple small questions

Ok(())
}

#[cfg(not(windows))]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not run on Windows?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unit test just fails because instead of MyApp.xcarchive/Products/app.txt it's something like C:\\MyApp.xcarchive\\Products\\app.txt. Lets just skip

let mut archive = ZipArchive::new(zip_file)?;
let file = archive.by_index(0)?;
let file_path = file.name();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure why the formatter did not catch this

Suggested change

for entry_path in entries {
let zip_path = entry_path.strip_prefix(
path.parent().ok_or_else(|| anyhow!("Failed to get parent directory"))?
)?.to_owned();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to call to_owned here; it just causes an unnecessary memory allocation and the code compiles without it.

Suggested change
)?.to_owned();
)?;

debug!("Adding file to zip: {}", zip_path.display());

zip.start_file(relative_path.to_string_lossy(), options)?;
zip.start_file(zip_path.to_string_lossy(), options)?;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay! I think I see the difference now. Whereas previously, you called strip_prefix(path), you now call strip_prefix(path.parent), correct?

Assuming the above is correct, I have two questions:

  1. Couldn't you have simply added the path.parent call where we were previously computing the relative_path? It seems like you are also refactoring the code by moving this changed strip_prefix into the for loop. Is this refactor causing some other functionality change which I am missing?
  2. Is it reasonable to assume that the path should always have a parent? E.g., what if we are running this from the root directory? Not that I think it would be super common, but perhaps there are some scenarios where this could occur (e.g. if running from within a Docker container)?

Copy link
Copy Markdown
Member

@szokeasaurusrex szokeasaurusrex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@NicoHinderling NicoHinderling merged commit 8ce9577 into master Jul 14, 2025
25 checks passed
@NicoHinderling NicoHinderling deleted the preserve-xcarchive-zip-structure branch July 14, 2025 14:12
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.

2 participants