Skip to content

Commit e2ceb14

Browse files
authored
Merge branch 'master' into feat/pe-dwarf-companion-upload-support
2 parents 500a177 + 572bb4c commit e2ceb14

14 files changed

Lines changed: 292 additions & 90 deletions

File tree

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
# Files co-owned by Emerge Tools team
1515
/apple-catalog-parsing @getsentry/emerge-tools @getsentry/owners-sentry-cli
16+
/src/api/data_types/snapshots.rs @getsentry/emerge-tools @getsentry/owners-sentry-cli
1617
/src/commands/build @getsentry/emerge-tools @getsentry/owners-sentry-cli
1718
/src/utils/build @getsentry/emerge-tools @getsentry/owners-sentry-cli
1819
/tests/integration/build @getsentry/emerge-tools @getsentry/owners-sentry-cli

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,21 @@
22

33
## Unreleased
44

5+
### Performance
6+
7+
- (snapshots) Parallelize image hashing with rayon ([#3250](https://github.com/getsentry/sentry-cli/pull/3250))
8+
9+
### Fixes
10+
11+
- (sourcemaps) Skip non-base64 embedded sourcemaps during injection ([#3243](https://github.com/getsentry/sentry-cli/pull/3243))
12+
513
### New Features ✨
614

715
- Add `sentry-cli build download` command to download installable builds (IPA/APK) by build ID ([#3221](https://github.com/getsentry/sentry-cli/pull/3221)).
16+
- Add `sentry-cli code-mappings upload` command to bulk upload code mappings from a JSON file ([#3207](https://github.com/getsentry/sentry-cli/pull/3207), [#3208](https://github.com/getsentry/sentry-cli/pull/3208), [#3209](https://github.com/getsentry/sentry-cli/pull/3209), [#3210](https://github.com/getsentry/sentry-cli/pull/3210)).
17+
- Code mappings link stack trace paths (e.g. `com/example/module`) to source paths in your repository (e.g. `src/main/java/com/example/module`), enabling Sentry to display source context and link directly to your code from error stack traces.
18+
- Repository name and default branch are automatically inferred from your local git remotes, or can be specified explicitly with `--repo` and `--default-branch`.
19+
- Large mapping files are automatically split into batches for upload.
820

921
## 3.3.3
1022

package-lock.json

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/api/data_types/snapshots.rs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use serde_json::Value;
77

88
use super::VcsInfo;
99

10-
const IMAGE_FILE_NAME_FIELD: &str = "image_file_name";
1110
const WIDTH_FIELD: &str = "width";
1211
const HEIGHT_FIELD: &str = "height";
1312

@@ -42,16 +41,7 @@ pub struct ImageMetadata {
4241
}
4342

4443
impl ImageMetadata {
45-
pub fn new(
46-
image_file_name: String,
47-
width: u32,
48-
height: u32,
49-
mut extra: HashMap<String, Value>,
50-
) -> Self {
51-
extra.insert(
52-
IMAGE_FILE_NAME_FIELD.to_owned(),
53-
Value::String(image_file_name),
54-
);
44+
pub fn new(width: u32, height: u32, mut extra: HashMap<String, Value>) -> Self {
5545
extra.insert(WIDTH_FIELD.to_owned(), Value::from(width));
5646
extra.insert(HEIGHT_FIELD.to_owned(), Value::from(height));
5747

@@ -68,18 +58,16 @@ mod tests {
6858
#[test]
6959
fn cli_managed_fields_override_sidecar_fields() {
7060
let extra = serde_json::from_value(json!({
71-
(IMAGE_FILE_NAME_FIELD): "from-sidecar.png",
7261
(WIDTH_FIELD): 1,
7362
(HEIGHT_FIELD): 2,
7463
"custom": "keep-me"
7564
}))
7665
.unwrap();
7766

78-
let metadata = ImageMetadata::new("from-cli.png".to_owned(), 100, 200, extra);
67+
let metadata = ImageMetadata::new(100, 200, extra);
7968
let serialized = serde_json::to_value(metadata).unwrap();
8069

8170
let expected = json!({
82-
(IMAGE_FILE_NAME_FIELD): "from-cli.png",
8371
(WIDTH_FIELD): 100,
8472
(HEIGHT_FIELD): 200,
8573
"custom": "keep-me"

src/commands/build/snapshots.rs

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use console::style;
1111
use itertools::Itertools as _;
1212
use log::{debug, info, warn};
1313
use objectstore_client::{ClientBuilder, ExpirationPolicy, Usecase};
14+
use rayon::prelude::*;
1415
use secrecy::ExposeSecret as _;
1516
use serde_json::Value;
1617
use sha2::{Digest as _, Sha256};
@@ -230,7 +231,7 @@ fn compute_sha256_hash(path: &Path) -> Result<String> {
230231
let mut file = std::fs::File::open(path)
231232
.with_context(|| format!("Failed to open image for hashing: {}", path.display()))?;
232233
let mut hasher = Sha256::new();
233-
let mut buffer = [0u8; 8192];
234+
let mut buffer = [0u8; 65536];
234235
loop {
235236
let bytes_read = file
236237
.read(&mut buffer)
@@ -331,12 +332,35 @@ fn upload_images(
331332

332333
let mut many_builder = session.many();
333334
let mut manifest_entries = HashMap::new();
334-
let image_count = images.len();
335+
let mut collisions: HashMap<String, Vec<String>> = HashMap::new();
336+
let mut kept_paths = HashMap::new();
337+
338+
let hashed_images: Vec<_> = images
339+
.into_par_iter()
340+
.map(|image| {
341+
let hash = compute_sha256_hash(&image.path)?;
342+
Ok((image, hash))
343+
})
344+
.collect::<Result<Vec<_>>>()?;
335345

336-
for image in images {
337-
debug!("Processing image: {}", image.path.display());
346+
for (image, hash) in hashed_images {
347+
let image_file_name = image
348+
.relative_path
349+
.file_name()
350+
.unwrap_or_default()
351+
.to_string_lossy()
352+
.into_owned();
353+
354+
let relative_path = crate::utils::fs::path_as_url(&image.relative_path);
355+
356+
if manifest_entries.contains_key(&image_file_name) {
357+
collisions
358+
.entry(image_file_name)
359+
.or_default()
360+
.push(relative_path);
361+
continue;
362+
}
338363

339-
let hash = compute_sha256_hash(&image.path)?;
340364
let file = runtime
341365
.block_on(tokio::fs::File::open(&image.path))
342366
.with_context(|| {
@@ -353,33 +377,40 @@ fn upload_images(
353377
.expiration_policy(expiration),
354378
);
355379

356-
let image_file_name = image
357-
.relative_path
358-
.file_name()
359-
.unwrap_or_default()
360-
.to_string_lossy()
361-
.into_owned();
362-
363-
let extra = read_sidecar_metadata(&image.path).unwrap_or_else(|err| {
380+
let mut extra = read_sidecar_metadata(&image.path).unwrap_or_else(|err| {
364381
warn!("Error reading sidecar metadata, ignoring it instead: {err:#}");
365382
HashMap::new()
366383
});
384+
extra.insert("content_hash".to_owned(), serde_json::Value::String(hash));
367385

386+
kept_paths.insert(image_file_name.clone(), relative_path);
368387
manifest_entries.insert(
369-
hash,
370-
ImageMetadata::new(image_file_name, image.width, image.height, extra),
388+
image_file_name,
389+
ImageMetadata::new(image.width, image.height, extra),
371390
);
372391
}
373392

393+
if !collisions.is_empty() {
394+
let mut details = String::new();
395+
for (name, excluded_paths) in &collisions {
396+
let mut all_paths = vec![kept_paths[name].as_str()];
397+
all_paths.extend(excluded_paths.iter().map(|s| s.as_str()));
398+
details.push_str(&format!("\n {name}: {}", all_paths.join(", ")));
399+
}
400+
warn!("Some images share identical file names. Only the first occurrence of each is included:{details}");
401+
}
402+
374403
let result = runtime.block_on(async { many_builder.send().error_for_failures().await });
375404

405+
let uploaded_count = manifest_entries.len();
406+
376407
match result {
377408
Ok(()) => {
378409
println!(
379410
"{} Uploaded {} image {}",
380411
style(">").dim(),
381-
style(image_count).yellow(),
382-
if image_count == 1 { "file" } else { "files" }
412+
style(uploaded_count).yellow(),
413+
if uploaded_count == 1 { "file" } else { "files" }
383414
);
384415
Ok(manifest_entries)
385416
}
@@ -391,7 +422,7 @@ fn upload_images(
391422
eprintln!(" {}", style(format!("{error:#}")).red());
392423
error_count += 1;
393424
}
394-
anyhow::bail!("Failed to upload {error_count} out of {image_count} images")
425+
anyhow::bail!("Failed to upload {error_count} out of {uploaded_count} images")
395426
}
396427
}
397428
}

0 commit comments

Comments
 (0)