sentry-cli 3.3.2__tar.gz → 3.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/Cargo.lock +1 -1
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/Cargo.toml +1 -1
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/PKG-INFO +1 -1
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/sentry_cli.egg-info/PKG-INFO +1 -1
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/sentry_cli.egg-info/SOURCES.txt +4 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/data_types/chunking/build.rs +7 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/data_types/chunking/mod.rs +1 -1
- sentry_cli-3.3.4/src/api/data_types/code_mappings.rs +37 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/data_types/mod.rs +2 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/data_types/snapshots.rs +2 -14
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/mod.rs +31 -1
- sentry_cli-3.3.4/src/commands/build/download.rs +106 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/build/mod.rs +2 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/build/snapshots.rs +43 -16
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/build/upload.rs +15 -0
- sentry_cli-3.3.4/src/commands/code_mappings/mod.rs +45 -0
- sentry_cli-3.3.4/src/commands/code_mappings/upload.rs +452 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/mod.rs +2 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/vcs.rs +19 -7
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/LICENSE +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/MANIFEST.in +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/README.md +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/AGENTS.md +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/CLAUDE.md +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/Cargo.toml +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/build.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/native/swift/AssetCatalogParser/Package.swift +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/AssetCatalogParser/AssetCatalogReader.swift +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/ObjcSupport/include/safeValueForKey.h +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/ObjcSupport/safeValueForKey.m +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/AssetCatalogParserTests.swift +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/Resources/test.xcarchive/Info.plist +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/Resources/test.xcarchive/Products/Applications/DemoApp.app/Assets.car +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/src/asset_catalog.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/apple-catalog-parsing/src/lib.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/build.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/pyproject.toml +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/sentry_cli.egg-info/dependency_links.txt +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/sentry_cli.egg-info/top_level.txt +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/setup.cfg +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/setup.py +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/AGENTS.md +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/CLAUDE.md +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/connection_manager.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/data_types/chunking/artifact.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/data_types/chunking/compression.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/data_types/chunking/dif.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/data_types/chunking/file_state.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/data_types/chunking/hash_algorithm.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/data_types/chunking/upload/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/data_types/chunking/upload/options.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/data_types/deploy.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/encoding.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/envelopes_api.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/errors/api_error.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/errors/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/errors/sentry_error.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/pagination.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/api/serialization.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/bashsupport.sh +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/bash_hook.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/dart_symbol_map/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/dart_symbol_map/upload.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/debug_files/bundle_jvm.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/debug_files/bundle_sources.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/debug_files/check.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/debug_files/find.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/debug_files/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/debug_files/print_sources.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/debug_files/upload.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/deploys/list.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/deploys/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/deploys/new.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/derive_parser.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/events/list.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/events/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/info.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/issues/list.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/issues/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/issues/mute.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/issues/resolve.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/issues/unresolve.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/login.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/logs/list.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/logs/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/monitors/list.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/monitors/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/monitors/run.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/organizations/list.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/organizations/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/proguard/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/proguard/upload.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/proguard/uuid.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/projects/list.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/projects/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/react_native/gradle.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/react_native/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/react_native/xcode.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/releases/archive.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/releases/delete.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/releases/finalize.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/releases/info.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/releases/list.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/releases/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/releases/new.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/releases/propose_version.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/releases/restore.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/releases/set_commits.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/repos/list.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/repos/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/send_envelope.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/send_event.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/send_metric/common_args.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/send_metric/increment.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/send_metric/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/send_metric/set.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/sourcemaps/inject.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/sourcemaps/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/sourcemaps/resolve.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/sourcemaps/upload.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/uninstall.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/update.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/upload_dif.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/upload_dsym.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/commands/upload_proguard.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/config.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/constants.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/main.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/android.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/args.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/auth_token/auth_token_impl.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/auth_token/error.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/auth_token/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/auth_token/org_auth_token.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/auth_token/redacting.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/auth_token/test.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/auth_token/user_auth_token.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/build/apple.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/build/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/build/normalize.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/build/validation.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/build_vcs.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/chunks/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/chunks/options.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/chunks/types.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/chunks/upload.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/ci.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/cordova.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/dif.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/dif_upload/error.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/dif_upload/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/event.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/file_search.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/file_upload.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/formatting.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/fs.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/http.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/logging.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/non_empty.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/progress.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/proguard/mapping.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/proguard/mod.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/proguard/upload.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/releases.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/retry.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_default_twenty.snap +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_ignore_missing.snap +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_base.snap +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_previous_commit.snap +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/snapshots/sentry_cli__utils__vcs__tests__get_commits_from_git.snap +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/source_bundle.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/sourcemaps/inject.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/sourcemaps.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/system.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/ui.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/update.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/value_parsers.rs +0 -0
- {sentry_cli-3.3.2 → sentry_cli-3.3.4}/src/utils/xcode.rs +0 -0
|
@@ -36,6 +36,7 @@ src/api/envelopes_api.rs
|
|
|
36
36
|
src/api/mod.rs
|
|
37
37
|
src/api/pagination.rs
|
|
38
38
|
src/api/serialization.rs
|
|
39
|
+
src/api/data_types/code_mappings.rs
|
|
39
40
|
src/api/data_types/deploy.rs
|
|
40
41
|
src/api/data_types/mod.rs
|
|
41
42
|
src/api/data_types/snapshots.rs
|
|
@@ -63,9 +64,12 @@ src/commands/update.rs
|
|
|
63
64
|
src/commands/upload_dif.rs
|
|
64
65
|
src/commands/upload_dsym.rs
|
|
65
66
|
src/commands/upload_proguard.rs
|
|
67
|
+
src/commands/build/download.rs
|
|
66
68
|
src/commands/build/mod.rs
|
|
67
69
|
src/commands/build/snapshots.rs
|
|
68
70
|
src/commands/build/upload.rs
|
|
71
|
+
src/commands/code_mappings/mod.rs
|
|
72
|
+
src/commands/code_mappings/upload.rs
|
|
69
73
|
src/commands/dart_symbol_map/mod.rs
|
|
70
74
|
src/commands/dart_symbol_map/upload.rs
|
|
71
75
|
src/commands/debug_files/bundle_jvm.rs
|
|
@@ -28,6 +28,13 @@ pub struct AssembleBuildResponse {
|
|
|
28
28
|
pub artifact_url: Option<String>,
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
#[derive(Debug, Deserialize)]
|
|
32
|
+
#[serde(rename_all = "camelCase")]
|
|
33
|
+
pub struct BuildInstallDetails {
|
|
34
|
+
pub is_installable: bool,
|
|
35
|
+
pub install_url: Option<String>,
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
/// VCS information for build app uploads
|
|
32
39
|
#[derive(Debug, Serialize)]
|
|
33
40
|
pub struct VcsInfo<'a> {
|
|
@@ -10,7 +10,7 @@ mod hash_algorithm;
|
|
|
10
10
|
mod upload;
|
|
11
11
|
|
|
12
12
|
pub use self::artifact::{AssembleArtifactsResponse, ChunkedArtifactRequest};
|
|
13
|
-
pub use self::build::{AssembleBuildResponse, ChunkedBuildRequest, VcsInfo};
|
|
13
|
+
pub use self::build::{AssembleBuildResponse, BuildInstallDetails, ChunkedBuildRequest, VcsInfo};
|
|
14
14
|
pub use self::compression::ChunkCompression;
|
|
15
15
|
pub use self::dif::{AssembleDifsRequest, AssembleDifsResponse, ChunkedDifRequest};
|
|
16
16
|
pub use self::file_state::ChunkedFileState;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//! Data types for the bulk code mappings API.
|
|
2
|
+
|
|
3
|
+
use serde::{Deserialize, Serialize};
|
|
4
|
+
|
|
5
|
+
#[derive(Debug, Serialize)]
|
|
6
|
+
#[serde(rename_all = "camelCase")]
|
|
7
|
+
pub struct BulkCodeMappingsRequest<'a> {
|
|
8
|
+
pub project: &'a str,
|
|
9
|
+
pub repository: &'a str,
|
|
10
|
+
pub default_branch: &'a str,
|
|
11
|
+
pub mappings: &'a [BulkCodeMapping],
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
#[derive(Debug, Deserialize, Serialize)]
|
|
15
|
+
#[serde(rename_all = "camelCase")]
|
|
16
|
+
pub struct BulkCodeMapping {
|
|
17
|
+
pub stack_root: String,
|
|
18
|
+
pub source_root: String,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#[derive(Debug, Deserialize)]
|
|
22
|
+
pub struct BulkCodeMappingsResponse {
|
|
23
|
+
pub created: u64,
|
|
24
|
+
pub updated: u64,
|
|
25
|
+
pub errors: u64,
|
|
26
|
+
pub mappings: Vec<BulkCodeMappingResult>,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#[derive(Debug, Deserialize)]
|
|
30
|
+
#[serde(rename_all = "camelCase")]
|
|
31
|
+
pub struct BulkCodeMappingResult {
|
|
32
|
+
pub stack_root: String,
|
|
33
|
+
pub source_root: String,
|
|
34
|
+
pub status: String,
|
|
35
|
+
#[serde(default)]
|
|
36
|
+
pub detail: Option<String>,
|
|
37
|
+
}
|
|
@@ -7,7 +7,6 @@ use serde_json::Value;
|
|
|
7
7
|
|
|
8
8
|
use super::VcsInfo;
|
|
9
9
|
|
|
10
|
-
const IMAGE_FILE_NAME_FIELD: &str = "image_file_name";
|
|
11
10
|
const WIDTH_FIELD: &str = "width";
|
|
12
11
|
const HEIGHT_FIELD: &str = "height";
|
|
13
12
|
|
|
@@ -42,16 +41,7 @@ pub struct ImageMetadata {
|
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
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 {
|
|
55
45
|
extra.insert(WIDTH_FIELD.to_owned(), Value::from(width));
|
|
56
46
|
extra.insert(HEIGHT_FIELD.to_owned(), Value::from(height));
|
|
57
47
|
|
|
@@ -68,18 +58,16 @@ mod tests {
|
|
|
68
58
|
#[test]
|
|
69
59
|
fn cli_managed_fields_override_sidecar_fields() {
|
|
70
60
|
let extra = serde_json::from_value(json!({
|
|
71
|
-
(IMAGE_FILE_NAME_FIELD): "from-sidecar.png",
|
|
72
61
|
(WIDTH_FIELD): 1,
|
|
73
62
|
(HEIGHT_FIELD): 2,
|
|
74
63
|
"custom": "keep-me"
|
|
75
64
|
}))
|
|
76
65
|
.unwrap();
|
|
77
66
|
|
|
78
|
-
let metadata = ImageMetadata::new(
|
|
67
|
+
let metadata = ImageMetadata::new(100, 200, extra);
|
|
79
68
|
let serialized = serde_json::to_value(metadata).unwrap();
|
|
80
69
|
|
|
81
70
|
let expected = json!({
|
|
82
|
-
(IMAGE_FILE_NAME_FIELD): "from-cli.png",
|
|
83
71
|
(WIDTH_FIELD): 100,
|
|
84
72
|
(HEIGHT_FIELD): 200,
|
|
85
73
|
"custom": "keep-me"
|
|
@@ -16,7 +16,6 @@ use std::borrow::Cow;
|
|
|
16
16
|
use std::cell::RefCell;
|
|
17
17
|
use std::collections::HashMap;
|
|
18
18
|
use std::error::Error as _;
|
|
19
|
-
#[cfg(any(target_os = "macos", not(feature = "managed")))]
|
|
20
19
|
use std::fs::File;
|
|
21
20
|
use std::io::{self, Read as _, Write};
|
|
22
21
|
use std::rc::Rc;
|
|
@@ -724,6 +723,26 @@ impl AuthenticatedApi<'_> {
|
|
|
724
723
|
.convert_rnf(ApiErrorKind::ProjectNotFound)
|
|
725
724
|
}
|
|
726
725
|
|
|
726
|
+
pub fn get_build_install_details(
|
|
727
|
+
&self,
|
|
728
|
+
org: &str,
|
|
729
|
+
build_id: &str,
|
|
730
|
+
) -> ApiResult<BuildInstallDetails> {
|
|
731
|
+
let url = format!(
|
|
732
|
+
"/organizations/{}/preprodartifacts/{}/install-details/",
|
|
733
|
+
PathArg(org),
|
|
734
|
+
PathArg(build_id)
|
|
735
|
+
);
|
|
736
|
+
|
|
737
|
+
self.get(&url)?.convert()
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
pub fn download_installable_build(&self, url: &str, dst: &mut File) -> ApiResult<ApiResponse> {
|
|
741
|
+
self.request(Method::Get, url)?
|
|
742
|
+
.progress_bar_mode(ProgressBarMode::Response)
|
|
743
|
+
.send_into(dst)
|
|
744
|
+
}
|
|
745
|
+
|
|
727
746
|
/// List all organizations associated with the authenticated token
|
|
728
747
|
/// in the given `Region`. If no `Region` is provided, we assume
|
|
729
748
|
/// we're issuing a request to a monolith deployment.
|
|
@@ -978,6 +997,17 @@ impl AuthenticatedApi<'_> {
|
|
|
978
997
|
Ok(rv)
|
|
979
998
|
}
|
|
980
999
|
|
|
1000
|
+
/// Bulk uploads code mappings for an organization.
|
|
1001
|
+
pub fn bulk_upload_code_mappings(
|
|
1002
|
+
&self,
|
|
1003
|
+
org: &str,
|
|
1004
|
+
body: &BulkCodeMappingsRequest,
|
|
1005
|
+
) -> ApiResult<BulkCodeMappingsResponse> {
|
|
1006
|
+
let path = format!("/organizations/{}/code-mappings/bulk/", PathArg(org));
|
|
1007
|
+
self.post(&path, body)?
|
|
1008
|
+
.convert_rnf(ApiErrorKind::OrganizationNotFound)
|
|
1009
|
+
}
|
|
1010
|
+
|
|
981
1011
|
/// Creates a preprod snapshot artifact for the given project.
|
|
982
1012
|
pub fn create_preprod_snapshot<S: Serialize>(
|
|
983
1013
|
&self,
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
use std::fs;
|
|
2
|
+
use std::path::PathBuf;
|
|
3
|
+
|
|
4
|
+
use anyhow::{bail, Result};
|
|
5
|
+
use clap::{Arg, ArgMatches, Command};
|
|
6
|
+
use log::info;
|
|
7
|
+
|
|
8
|
+
use crate::api::Api;
|
|
9
|
+
use crate::config::Config;
|
|
10
|
+
use crate::utils::args::ArgExt as _;
|
|
11
|
+
use crate::utils::fs::TempFile;
|
|
12
|
+
|
|
13
|
+
const EXPERIMENTAL_WARNING: &str =
|
|
14
|
+
"[EXPERIMENTAL] The \"build download\" command is experimental. \
|
|
15
|
+
The command is subject to breaking changes, including removal, in any Sentry CLI release.";
|
|
16
|
+
|
|
17
|
+
pub fn make_command(command: Command) -> Command {
|
|
18
|
+
command
|
|
19
|
+
.about("[EXPERIMENTAL] Download a build artifact.")
|
|
20
|
+
.long_about(format!(
|
|
21
|
+
"Download a build artifact.\n\n{EXPERIMENTAL_WARNING}"
|
|
22
|
+
))
|
|
23
|
+
.org_arg()
|
|
24
|
+
.arg(
|
|
25
|
+
Arg::new("build_id")
|
|
26
|
+
.long("build-id")
|
|
27
|
+
.short('b')
|
|
28
|
+
.required(true)
|
|
29
|
+
.help("The ID of the build to download."),
|
|
30
|
+
)
|
|
31
|
+
.arg(Arg::new("output").long("output").help(
|
|
32
|
+
"The output file path. Defaults to \
|
|
33
|
+
'preprod_artifact_<build_id>.<ext>' in the current directory, \
|
|
34
|
+
where ext is ipa or apk depending on the platform.",
|
|
35
|
+
))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// For iOS builds, the install URL points to a plist manifest.
|
|
39
|
+
/// Replace the response_format to download the actual IPA binary instead.
|
|
40
|
+
fn ensure_binary_format(url: &str) -> String {
|
|
41
|
+
url.replace("response_format=plist", "response_format=ipa")
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// Extract the file extension from the response_format query parameter.
|
|
45
|
+
fn extension_from_url(url: &str) -> Result<&str> {
|
|
46
|
+
if url.contains("response_format=ipa") {
|
|
47
|
+
Ok("ipa")
|
|
48
|
+
} else if url.contains("response_format=apk") {
|
|
49
|
+
Ok("apk")
|
|
50
|
+
} else {
|
|
51
|
+
bail!("Unsupported build format in download URL.")
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
56
|
+
eprintln!("{EXPERIMENTAL_WARNING}");
|
|
57
|
+
let config = Config::current();
|
|
58
|
+
let org = config.get_org(matches)?;
|
|
59
|
+
let build_id = matches
|
|
60
|
+
.get_one::<String>("build_id")
|
|
61
|
+
.expect("build_id is required");
|
|
62
|
+
|
|
63
|
+
let api = Api::current();
|
|
64
|
+
let authenticated_api = api.authenticated()?;
|
|
65
|
+
|
|
66
|
+
info!("Fetching install details for build {build_id}");
|
|
67
|
+
let details = authenticated_api.get_build_install_details(&org, build_id)?;
|
|
68
|
+
|
|
69
|
+
if !details.is_installable {
|
|
70
|
+
bail!("Build {build_id} is not installable.");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let install_url = details
|
|
74
|
+
.install_url
|
|
75
|
+
.ok_or_else(|| anyhow::anyhow!("Build {build_id} has no install URL."))?;
|
|
76
|
+
|
|
77
|
+
let download_url = ensure_binary_format(&install_url);
|
|
78
|
+
|
|
79
|
+
let output_path = match matches.get_one::<String>("output") {
|
|
80
|
+
Some(path) => PathBuf::from(path),
|
|
81
|
+
None => {
|
|
82
|
+
let ext = extension_from_url(&download_url)?;
|
|
83
|
+
PathBuf::from(format!("preprod_artifact_{build_id}.{ext}"))
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
info!("Downloading build {build_id} to {}", output_path.display());
|
|
88
|
+
|
|
89
|
+
let tmp = TempFile::create()?;
|
|
90
|
+
let mut file = tmp.open()?;
|
|
91
|
+
let response = authenticated_api.download_installable_build(&download_url, &mut file)?;
|
|
92
|
+
|
|
93
|
+
if response.failed() {
|
|
94
|
+
bail!(
|
|
95
|
+
"Failed to download build (server returned status {}).",
|
|
96
|
+
response.status()
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
drop(file);
|
|
101
|
+
fs::copy(tmp.path(), &output_path)?;
|
|
102
|
+
|
|
103
|
+
println!("Successfully downloaded build to {}", output_path.display());
|
|
104
|
+
|
|
105
|
+
Ok(())
|
|
106
|
+
}
|
|
@@ -3,11 +3,13 @@ use clap::{ArgMatches, Command};
|
|
|
3
3
|
|
|
4
4
|
use crate::utils::args::ArgExt as _;
|
|
5
5
|
|
|
6
|
+
pub mod download;
|
|
6
7
|
pub mod snapshots;
|
|
7
8
|
pub mod upload;
|
|
8
9
|
|
|
9
10
|
macro_rules! each_subcommand {
|
|
10
11
|
($mac:ident) => {
|
|
12
|
+
$mac!(download);
|
|
11
13
|
$mac!(snapshots);
|
|
12
14
|
$mac!(upload);
|
|
13
15
|
};
|
|
@@ -3,6 +3,7 @@ use std::fs::File;
|
|
|
3
3
|
use std::io::BufReader;
|
|
4
4
|
use std::path::{Path, PathBuf};
|
|
5
5
|
use std::str::FromStr as _;
|
|
6
|
+
use std::time::Duration;
|
|
6
7
|
|
|
7
8
|
use anyhow::{Context as _, Result};
|
|
8
9
|
use clap::{Arg, ArgMatches, Command};
|
|
@@ -301,6 +302,7 @@ fn upload_images(
|
|
|
301
302
|
};
|
|
302
303
|
auth
|
|
303
304
|
})
|
|
305
|
+
.configure_reqwest(|r| r.connect_timeout(Duration::from_secs(10)))
|
|
304
306
|
.build()?;
|
|
305
307
|
|
|
306
308
|
let mut scope = Usecase::new("preprod").scope();
|
|
@@ -329,11 +331,28 @@ fn upload_images(
|
|
|
329
331
|
|
|
330
332
|
let mut many_builder = session.many();
|
|
331
333
|
let mut manifest_entries = HashMap::new();
|
|
332
|
-
let
|
|
333
|
-
|
|
334
|
+
let mut collisions: HashMap<String, Vec<String>> = HashMap::new();
|
|
335
|
+
let mut kept_paths: HashMap<String, String> = HashMap::new();
|
|
334
336
|
for image in images {
|
|
335
337
|
debug!("Processing image: {}", image.path.display());
|
|
336
338
|
|
|
339
|
+
let image_file_name = image
|
|
340
|
+
.relative_path
|
|
341
|
+
.file_name()
|
|
342
|
+
.unwrap_or_default()
|
|
343
|
+
.to_string_lossy()
|
|
344
|
+
.into_owned();
|
|
345
|
+
|
|
346
|
+
let relative_path = crate::utils::fs::path_as_url(&image.relative_path);
|
|
347
|
+
|
|
348
|
+
if manifest_entries.contains_key(&image_file_name) {
|
|
349
|
+
collisions
|
|
350
|
+
.entry(image_file_name)
|
|
351
|
+
.or_default()
|
|
352
|
+
.push(relative_path);
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
|
|
337
356
|
let hash = compute_sha256_hash(&image.path)?;
|
|
338
357
|
let file = runtime
|
|
339
358
|
.block_on(tokio::fs::File::open(&image.path))
|
|
@@ -351,33 +370,40 @@ fn upload_images(
|
|
|
351
370
|
.expiration_policy(expiration),
|
|
352
371
|
);
|
|
353
372
|
|
|
354
|
-
let
|
|
355
|
-
.relative_path
|
|
356
|
-
.file_name()
|
|
357
|
-
.unwrap_or_default()
|
|
358
|
-
.to_string_lossy()
|
|
359
|
-
.into_owned();
|
|
360
|
-
|
|
361
|
-
let extra = read_sidecar_metadata(&image.path).unwrap_or_else(|err| {
|
|
373
|
+
let mut extra = read_sidecar_metadata(&image.path).unwrap_or_else(|err| {
|
|
362
374
|
warn!("Error reading sidecar metadata, ignoring it instead: {err:#}");
|
|
363
375
|
HashMap::new()
|
|
364
376
|
});
|
|
377
|
+
extra.insert("content_hash".to_owned(), serde_json::Value::String(hash));
|
|
365
378
|
|
|
379
|
+
kept_paths.insert(image_file_name.clone(), relative_path);
|
|
366
380
|
manifest_entries.insert(
|
|
367
|
-
|
|
368
|
-
ImageMetadata::new(
|
|
381
|
+
image_file_name,
|
|
382
|
+
ImageMetadata::new(image.width, image.height, extra),
|
|
369
383
|
);
|
|
370
384
|
}
|
|
371
385
|
|
|
386
|
+
if !collisions.is_empty() {
|
|
387
|
+
let mut details = String::new();
|
|
388
|
+
for (name, excluded_paths) in &collisions {
|
|
389
|
+
let mut all_paths = vec![kept_paths[name].as_str()];
|
|
390
|
+
all_paths.extend(excluded_paths.iter().map(|s| s.as_str()));
|
|
391
|
+
details.push_str(&format!("\n {name}: {}", all_paths.join(", ")));
|
|
392
|
+
}
|
|
393
|
+
warn!("Some images share identical file names. Only the first occurrence of each is included:{details}");
|
|
394
|
+
}
|
|
395
|
+
|
|
372
396
|
let result = runtime.block_on(async { many_builder.send().error_for_failures().await });
|
|
373
397
|
|
|
398
|
+
let uploaded_count = manifest_entries.len();
|
|
399
|
+
|
|
374
400
|
match result {
|
|
375
401
|
Ok(()) => {
|
|
376
402
|
println!(
|
|
377
403
|
"{} Uploaded {} image {}",
|
|
378
404
|
style(">").dim(),
|
|
379
|
-
style(
|
|
380
|
-
if
|
|
405
|
+
style(uploaded_count).yellow(),
|
|
406
|
+
if uploaded_count == 1 { "file" } else { "files" }
|
|
381
407
|
);
|
|
382
408
|
Ok(manifest_entries)
|
|
383
409
|
}
|
|
@@ -385,10 +411,11 @@ fn upload_images(
|
|
|
385
411
|
eprintln!("There were errors uploading images:");
|
|
386
412
|
let mut error_count = 0;
|
|
387
413
|
for error in errors {
|
|
388
|
-
|
|
414
|
+
let error = anyhow::Error::new(error);
|
|
415
|
+
eprintln!(" {}", style(format!("{error:#}")).red());
|
|
389
416
|
error_count += 1;
|
|
390
417
|
}
|
|
391
|
-
anyhow::bail!("Failed to upload {error_count} out of {
|
|
418
|
+
anyhow::bail!("Failed to upload {error_count} out of {uploaded_count} images")
|
|
392
419
|
}
|
|
393
420
|
}
|
|
394
421
|
}
|
|
@@ -143,6 +143,20 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
|
143
143
|
return Err(anyhow!("Path does not exist: {}", path.display()));
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
// On non-Apple Silicon, reject xcarchive/IPA early before trying to
|
|
147
|
+
// open the path as a file (xcarchive is a directory, so ByteView::open
|
|
148
|
+
// would fail with a confusing I/O error).
|
|
149
|
+
#[cfg(not(all(target_os = "macos", target_arch = "aarch64")))]
|
|
150
|
+
{
|
|
151
|
+
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("");
|
|
152
|
+
if ext.eq_ignore_ascii_case("xcarchive") || ext.eq_ignore_ascii_case("ipa") {
|
|
153
|
+
return Err(anyhow!(
|
|
154
|
+
"Uploading XCArchive and IPA files requires an Apple Silicon Mac: {}",
|
|
155
|
+
path.display()
|
|
156
|
+
));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
146
160
|
let byteview = ByteView::open(path)?;
|
|
147
161
|
debug!("Loaded file with {} bytes", byteview.len());
|
|
148
162
|
|
|
@@ -301,6 +315,7 @@ fn validate_is_supported_build(path: &Path, bytes: &[u8]) -> Result<()> {
|
|
|
301
315
|
}
|
|
302
316
|
|
|
303
317
|
debug!("File format validation failed");
|
|
318
|
+
|
|
304
319
|
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
|
|
305
320
|
let format_list = "APK, AAB, XCArchive, or IPA";
|
|
306
321
|
#[cfg(not(all(target_os = "macos", target_arch = "aarch64")))]
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
use anyhow::Result;
|
|
2
|
+
use clap::{ArgMatches, Command};
|
|
3
|
+
|
|
4
|
+
use crate::utils::args::ArgExt as _;
|
|
5
|
+
|
|
6
|
+
pub mod upload;
|
|
7
|
+
|
|
8
|
+
macro_rules! each_subcommand {
|
|
9
|
+
($mac:ident) => {
|
|
10
|
+
$mac!(upload);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
pub fn make_command(mut command: Command) -> Command {
|
|
15
|
+
macro_rules! add_subcommand {
|
|
16
|
+
($name:ident) => {{
|
|
17
|
+
command = command.subcommand(crate::commands::code_mappings::$name::make_command(
|
|
18
|
+
Command::new(stringify!($name).replace('_', "-")),
|
|
19
|
+
));
|
|
20
|
+
}};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
command = command
|
|
24
|
+
.about("Manage code mappings for Sentry. Code mappings link stack trace paths to source code paths in your repository, enabling source context and code linking in Sentry.")
|
|
25
|
+
.subcommand_required(true)
|
|
26
|
+
.arg_required_else_help(true)
|
|
27
|
+
.org_arg()
|
|
28
|
+
.project_arg(false);
|
|
29
|
+
each_subcommand!(add_subcommand);
|
|
30
|
+
command
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
34
|
+
macro_rules! execute_subcommand {
|
|
35
|
+
($name:ident) => {{
|
|
36
|
+
if let Some(sub_matches) =
|
|
37
|
+
matches.subcommand_matches(&stringify!($name).replace('_', "-"))
|
|
38
|
+
{
|
|
39
|
+
return crate::commands::code_mappings::$name::execute(&sub_matches);
|
|
40
|
+
}
|
|
41
|
+
}};
|
|
42
|
+
}
|
|
43
|
+
each_subcommand!(execute_subcommand);
|
|
44
|
+
unreachable!();
|
|
45
|
+
}
|