sentry-cli 3.3.5__tar.gz → 3.4.1__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.5 → sentry_cli-3.4.1}/Cargo.lock +7 -28
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/Cargo.toml +3 -3
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/PKG-INFO +1 -1
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/sentry_cli.egg-info/PKG-INFO +1 -1
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/snapshots.rs +49 -2
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/mod.rs +2 -1
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/build/snapshots.rs +110 -84
- sentry_cli-3.4.1/src/commands/debug_files/bundle_jvm.rs +535 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/file_search.rs +26 -5
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/logging.rs +4 -8
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/progress.rs +1 -1
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/source_bundle.rs +58 -32
- sentry_cli-3.3.5/src/commands/debug_files/bundle_jvm.rs +0 -102
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/LICENSE +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/MANIFEST.in +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/README.md +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/AGENTS.md +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/CLAUDE.md +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/Cargo.toml +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/build.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/native/swift/AssetCatalogParser/Package.swift +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/AssetCatalogParser/AssetCatalogReader.swift +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/ObjcSupport/include/safeValueForKey.h +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/ObjcSupport/safeValueForKey.m +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/AssetCatalogParserTests.swift +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/Resources/test.xcarchive/Info.plist +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/Resources/test.xcarchive/Products/Applications/DemoApp.app/Assets.car +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/src/asset_catalog.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/apple-catalog-parsing/src/lib.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/build.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/pyproject.toml +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/sentry_cli.egg-info/SOURCES.txt +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/sentry_cli.egg-info/dependency_links.txt +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/sentry_cli.egg-info/top_level.txt +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/setup.cfg +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/setup.py +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/AGENTS.md +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/CLAUDE.md +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/connection_manager.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/chunking/artifact.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/chunking/build.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/chunking/compression.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/chunking/dif.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/chunking/file_state.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/chunking/hash_algorithm.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/chunking/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/chunking/upload/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/chunking/upload/options.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/code_mappings.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/deploy.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/data_types/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/encoding.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/envelopes_api.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/errors/api_error.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/errors/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/errors/sentry_error.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/pagination.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/api/serialization.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/bashsupport.sh +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/bash_hook.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/build/download.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/build/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/build/upload.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/code_mappings/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/code_mappings/upload.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/dart_symbol_map/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/dart_symbol_map/upload.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/debug_files/bundle_sources.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/debug_files/check.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/debug_files/find.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/debug_files/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/debug_files/print_sources.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/debug_files/upload.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/deploys/list.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/deploys/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/deploys/new.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/derive_parser.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/events/list.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/events/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/info.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/issues/list.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/issues/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/issues/mute.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/issues/resolve.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/issues/unresolve.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/login.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/logs/list.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/logs/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/monitors/list.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/monitors/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/monitors/run.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/organizations/list.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/organizations/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/proguard/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/proguard/upload.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/proguard/uuid.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/projects/list.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/projects/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/react_native/gradle.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/react_native/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/react_native/xcode.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/releases/archive.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/releases/delete.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/releases/finalize.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/releases/info.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/releases/list.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/releases/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/releases/new.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/releases/propose_version.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/releases/restore.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/releases/set_commits.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/repos/list.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/repos/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/send_envelope.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/send_event.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/send_metric/common_args.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/send_metric/increment.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/send_metric/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/send_metric/set.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/sourcemaps/inject.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/sourcemaps/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/sourcemaps/resolve.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/sourcemaps/upload.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/uninstall.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/update.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/upload_dif.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/upload_dsym.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/commands/upload_proguard.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/config.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/constants.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/main.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/android.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/args.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/auth_token/auth_token_impl.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/auth_token/error.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/auth_token/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/auth_token/org_auth_token.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/auth_token/redacting.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/auth_token/test.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/auth_token/user_auth_token.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/build/apple.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/build/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/build/normalize.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/build/validation.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/build_vcs.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/chunks/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/chunks/options.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/chunks/types.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/chunks/upload.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/ci.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/cordova.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/dif.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/dif_upload/error.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/dif_upload/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/event.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/file_upload.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/formatting.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/fs.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/http.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/non_empty.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/proguard/mapping.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/proguard/mod.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/proguard/upload.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/releases.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/retry.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_default_twenty.snap +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_ignore_missing.snap +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_base.snap +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_previous_commit.snap +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/snapshots/sentry_cli__utils__vcs__tests__get_commits_from_git.snap +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/sourcemaps/inject.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/sourcemaps.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/system.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/ui.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/update.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/value_parsers.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/vcs.rs +0 -0
- {sentry_cli-3.3.5 → sentry_cli-3.4.1}/src/utils/xcode.rs +0 -0
|
@@ -206,28 +206,6 @@ dependencies = [
|
|
|
206
206
|
"tokio",
|
|
207
207
|
]
|
|
208
208
|
|
|
209
|
-
[[package]]
|
|
210
|
-
name = "async-stream"
|
|
211
|
-
version = "0.3.6"
|
|
212
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
213
|
-
checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
|
|
214
|
-
dependencies = [
|
|
215
|
-
"async-stream-impl",
|
|
216
|
-
"futures-core",
|
|
217
|
-
"pin-project-lite",
|
|
218
|
-
]
|
|
219
|
-
|
|
220
|
-
[[package]]
|
|
221
|
-
name = "async-stream-impl"
|
|
222
|
-
version = "0.3.6"
|
|
223
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
224
|
-
checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
|
|
225
|
-
dependencies = [
|
|
226
|
-
"proc-macro2",
|
|
227
|
-
"quote",
|
|
228
|
-
"syn",
|
|
229
|
-
]
|
|
230
|
-
|
|
231
209
|
[[package]]
|
|
232
210
|
name = "atomic-waker"
|
|
233
211
|
version = "1.1.2"
|
|
@@ -2322,12 +2300,11 @@ dependencies = [
|
|
|
2322
2300
|
|
|
2323
2301
|
[[package]]
|
|
2324
2302
|
name = "objectstore-client"
|
|
2325
|
-
version = "0.1.
|
|
2303
|
+
version = "0.1.6"
|
|
2326
2304
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2327
|
-
checksum = "
|
|
2305
|
+
checksum = "f99caa869461b61decd1985c029d7e1462d1bde8e2448040db27d567165fcc1e"
|
|
2328
2306
|
dependencies = [
|
|
2329
2307
|
"async-compression",
|
|
2330
|
-
"async-stream",
|
|
2331
2308
|
"bytes",
|
|
2332
2309
|
"futures-util",
|
|
2333
2310
|
"infer",
|
|
@@ -2346,9 +2323,9 @@ dependencies = [
|
|
|
2346
2323
|
|
|
2347
2324
|
[[package]]
|
|
2348
2325
|
name = "objectstore-types"
|
|
2349
|
-
version = "0.1.
|
|
2326
|
+
version = "0.1.6"
|
|
2350
2327
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2351
|
-
checksum = "
|
|
2328
|
+
checksum = "c375bccef8773d1739eabb7e2b1bbd7e9a9071c8f9557e3b50dce7220e8c8736"
|
|
2352
2329
|
dependencies = [
|
|
2353
2330
|
"http",
|
|
2354
2331
|
"humantime",
|
|
@@ -3345,6 +3322,7 @@ version = "0.8.0"
|
|
|
3345
3322
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3346
3323
|
checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
|
|
3347
3324
|
dependencies = [
|
|
3325
|
+
"serde",
|
|
3348
3326
|
"zeroize",
|
|
3349
3327
|
]
|
|
3350
3328
|
|
|
@@ -3414,7 +3392,7 @@ dependencies = [
|
|
|
3414
3392
|
|
|
3415
3393
|
[[package]]
|
|
3416
3394
|
name = "sentry-cli"
|
|
3417
|
-
version = "3.
|
|
3395
|
+
version = "3.4.1"
|
|
3418
3396
|
dependencies = [
|
|
3419
3397
|
"anyhow",
|
|
3420
3398
|
"anylog",
|
|
@@ -4142,6 +4120,7 @@ dependencies = [
|
|
|
4142
4120
|
"bytes",
|
|
4143
4121
|
"futures-core",
|
|
4144
4122
|
"futures-sink",
|
|
4123
|
+
"futures-util",
|
|
4145
4124
|
"pin-project-lite",
|
|
4146
4125
|
"tokio",
|
|
4147
4126
|
]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
build = "build.rs"
|
|
3
3
|
name = "sentry-cli"
|
|
4
|
-
version = "3.
|
|
4
|
+
version = "3.4.1"
|
|
5
5
|
edition = "2021"
|
|
6
6
|
rust-version = "1.91"
|
|
7
7
|
|
|
@@ -44,7 +44,7 @@ java-properties = "2.0.0"
|
|
|
44
44
|
lazy_static = "1.4.0"
|
|
45
45
|
libc = "0.2.139"
|
|
46
46
|
log = { version = "0.4.17", features = ["std"] }
|
|
47
|
-
objectstore-client = { version = "0.1.
|
|
47
|
+
objectstore-client = { version = "0.1.6" , default-features = false, features = ["native-tls"] }
|
|
48
48
|
open = "3.2.0"
|
|
49
49
|
parking_lot = "0.12.1"
|
|
50
50
|
percent-encoding = "2.2.0"
|
|
@@ -79,7 +79,7 @@ zip = "2.4.2"
|
|
|
79
79
|
data-encoding = "2.3.3"
|
|
80
80
|
magic_string = "0.3.4"
|
|
81
81
|
chrono-tz = "0.8.4"
|
|
82
|
-
secrecy = "0.8.0"
|
|
82
|
+
secrecy = { version = "0.8.0", features = ["serde"] }
|
|
83
83
|
lru = "0.16.3"
|
|
84
84
|
backon = { version = "1.5.2", features = ["std", "std-blocking-sleep"] }
|
|
85
85
|
|
|
@@ -25,6 +25,14 @@ pub struct CreateSnapshotResponse {
|
|
|
25
25
|
pub struct SnapshotsManifest<'a> {
|
|
26
26
|
pub app_id: String,
|
|
27
27
|
pub images: HashMap<String, ImageMetadata>,
|
|
28
|
+
/// If set, Sentry will only report images as changed if their difference %
|
|
29
|
+
/// is greater than this value (e.g. 0.01 = only report changes >= 1%).
|
|
30
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
31
|
+
pub diff_threshold: Option<f64>,
|
|
32
|
+
/// When true, this upload contains only a subset of images.
|
|
33
|
+
/// Removals and renames will not be detected on PRs.
|
|
34
|
+
#[serde(skip_serializing_if = "std::ops::Not::not")]
|
|
35
|
+
pub selective: bool,
|
|
28
36
|
#[serde(flatten)]
|
|
29
37
|
pub vcs_info: VcsInfo<'a>,
|
|
30
38
|
}
|
|
@@ -32,8 +40,8 @@ pub struct SnapshotsManifest<'a> {
|
|
|
32
40
|
// Keep in sync with https://github.com/getsentry/sentry/blob/master/src/sentry/preprod/snapshots/manifest.py
|
|
33
41
|
/// Metadata for a single image in a snapshot manifest.
|
|
34
42
|
///
|
|
35
|
-
/// CLI-managed fields (`
|
|
36
|
-
///
|
|
43
|
+
/// CLI-managed fields (`width`, `height`) override any identically named
|
|
44
|
+
/// fields provided by user sidecar metadata.
|
|
37
45
|
#[derive(Debug, Serialize)]
|
|
38
46
|
pub struct ImageMetadata {
|
|
39
47
|
#[serde(flatten)]
|
|
@@ -55,6 +63,45 @@ mod tests {
|
|
|
55
63
|
|
|
56
64
|
use serde_json::json;
|
|
57
65
|
|
|
66
|
+
fn empty_vcs_info() -> VcsInfo<'static> {
|
|
67
|
+
VcsInfo {
|
|
68
|
+
head_sha: None,
|
|
69
|
+
base_sha: None,
|
|
70
|
+
vcs_provider: "".into(),
|
|
71
|
+
head_repo_name: "".into(),
|
|
72
|
+
base_repo_name: "".into(),
|
|
73
|
+
head_ref: "".into(),
|
|
74
|
+
base_ref: "".into(),
|
|
75
|
+
pr_number: None,
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#[test]
|
|
80
|
+
fn manifest_omits_selective_when_false() {
|
|
81
|
+
let manifest = SnapshotsManifest {
|
|
82
|
+
app_id: "app".into(),
|
|
83
|
+
images: HashMap::new(),
|
|
84
|
+
diff_threshold: None,
|
|
85
|
+
selective: false,
|
|
86
|
+
vcs_info: empty_vcs_info(),
|
|
87
|
+
};
|
|
88
|
+
let json = serde_json::to_value(&manifest).unwrap();
|
|
89
|
+
assert!(!json.as_object().unwrap().contains_key("selective"));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
#[test]
|
|
93
|
+
fn manifest_includes_selective_when_true() {
|
|
94
|
+
let manifest = SnapshotsManifest {
|
|
95
|
+
app_id: "app".into(),
|
|
96
|
+
images: HashMap::new(),
|
|
97
|
+
diff_threshold: None,
|
|
98
|
+
selective: true,
|
|
99
|
+
vcs_info: empty_vcs_info(),
|
|
100
|
+
};
|
|
101
|
+
let json = serde_json::to_value(&manifest).unwrap();
|
|
102
|
+
assert_eq!(json["selective"], json!(true));
|
|
103
|
+
}
|
|
104
|
+
|
|
58
105
|
#[test]
|
|
59
106
|
fn cli_managed_fields_override_sidecar_fields() {
|
|
60
107
|
let extra = serde_json::from_value(json!({
|
|
@@ -33,7 +33,7 @@ use lazy_static::lazy_static;
|
|
|
33
33
|
use log::{debug, info, warn};
|
|
34
34
|
use parking_lot::Mutex;
|
|
35
35
|
use regex::{Captures, Regex};
|
|
36
|
-
use secrecy::ExposeSecret as _;
|
|
36
|
+
use secrecy::{ExposeSecret as _, SecretString};
|
|
37
37
|
use serde::de::DeserializeOwned;
|
|
38
38
|
use serde::{Deserialize, Serialize};
|
|
39
39
|
use sha1_smol::Digest;
|
|
@@ -2065,5 +2065,6 @@ pub struct SnapshotsUploadOptions {
|
|
|
2065
2065
|
pub struct ObjectstoreUploadOptions {
|
|
2066
2066
|
pub url: String,
|
|
2067
2067
|
pub scopes: Vec<(String, String)>,
|
|
2068
|
+
pub auth_token: Option<SecretString>,
|
|
2068
2069
|
pub expiration_policy: String,
|
|
2069
2070
|
}
|
|
@@ -9,7 +9,7 @@ use anyhow::{Context as _, Result};
|
|
|
9
9
|
use clap::{Arg, ArgMatches, Command};
|
|
10
10
|
use console::style;
|
|
11
11
|
use itertools::Itertools as _;
|
|
12
|
-
use log::{debug,
|
|
12
|
+
use log::{debug, warn};
|
|
13
13
|
use objectstore_client::{ClientBuilder, ExpirationPolicy, Usecase};
|
|
14
14
|
use rayon::prelude::*;
|
|
15
15
|
use secrecy::ExposeSecret as _;
|
|
@@ -51,6 +51,32 @@ pub fn make_command(command: Command) -> Command {
|
|
|
51
51
|
.help("The application identifier.")
|
|
52
52
|
.required(true),
|
|
53
53
|
)
|
|
54
|
+
.arg(
|
|
55
|
+
Arg::new("diff_threshold")
|
|
56
|
+
.long("diff-threshold")
|
|
57
|
+
.value_name("THRESHOLD")
|
|
58
|
+
.value_parser(|s: &str| {
|
|
59
|
+
let v: f64 = s.parse().map_err(|e| format!("invalid float: {e}"))?;
|
|
60
|
+
if !(0.0..=1.0).contains(&v) {
|
|
61
|
+
return Err("value must be between 0.0 and 1.0".to_owned());
|
|
62
|
+
}
|
|
63
|
+
Ok(v)
|
|
64
|
+
})
|
|
65
|
+
.help(
|
|
66
|
+
"If set, Sentry will only report images as changed if their \
|
|
67
|
+
difference % is greater than this value. \
|
|
68
|
+
Example: 0.01 = only report image changes >= 1%.",
|
|
69
|
+
),
|
|
70
|
+
)
|
|
71
|
+
.arg(
|
|
72
|
+
Arg::new("selective")
|
|
73
|
+
.long("selective")
|
|
74
|
+
.action(clap::ArgAction::SetTrue)
|
|
75
|
+
.help(
|
|
76
|
+
"Indicates this upload contains only a subset of images. \
|
|
77
|
+
Removals and renames cannot be detected on PRs.",
|
|
78
|
+
),
|
|
79
|
+
)
|
|
54
80
|
.git_metadata_args()
|
|
55
81
|
}
|
|
56
82
|
|
|
@@ -123,9 +149,15 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
|
123
149
|
let manifest_entries = upload_images(images, &org, &project)?;
|
|
124
150
|
|
|
125
151
|
// Build manifest from discovered images
|
|
152
|
+
let diff_threshold = matches.get_one::<f64>("diff_threshold").copied();
|
|
153
|
+
|
|
154
|
+
let selective = matches.get_flag("selective");
|
|
155
|
+
|
|
126
156
|
let manifest = SnapshotsManifest {
|
|
127
157
|
app_id: app_id.clone(),
|
|
128
158
|
images: manifest_entries,
|
|
159
|
+
diff_threshold,
|
|
160
|
+
selective,
|
|
129
161
|
vcs_info,
|
|
130
162
|
};
|
|
131
163
|
|
|
@@ -283,6 +315,11 @@ fn read_sidecar_metadata(image_path: &Path) -> Result<HashMap<String, Value>> {
|
|
|
283
315
|
})
|
|
284
316
|
}
|
|
285
317
|
|
|
318
|
+
struct PreparedImage {
|
|
319
|
+
path: PathBuf,
|
|
320
|
+
key: String,
|
|
321
|
+
}
|
|
322
|
+
|
|
286
323
|
fn upload_images(
|
|
287
324
|
images: Vec<ImageInfo>,
|
|
288
325
|
org: &str,
|
|
@@ -295,33 +332,43 @@ fn upload_images(
|
|
|
295
332
|
let expiration = ExpirationPolicy::from_str(&options.objectstore.expiration_policy)
|
|
296
333
|
.context("Failed to parse expiration policy from upload options")?;
|
|
297
334
|
|
|
298
|
-
let
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
335
|
+
let mut builder = ClientBuilder::new(options.objectstore.url);
|
|
336
|
+
if let Some(token) = options.objectstore.auth_token {
|
|
337
|
+
builder = builder.token(token.expose_secret().to_owned());
|
|
338
|
+
}
|
|
339
|
+
let builder = builder;
|
|
340
|
+
|
|
341
|
+
let sentry_token = match authenticated_api.auth() {
|
|
342
|
+
Auth::Token(token) => token.raw().expose_secret().to_owned(),
|
|
343
|
+
};
|
|
344
|
+
let sentry_token = format!("Bearer {sentry_token}")
|
|
345
|
+
.parse()
|
|
346
|
+
// Ignore original error to avoid leaking the token (even though it's invalid)
|
|
347
|
+
.map_err(|_| anyhow::anyhow!("Invalid auth token"))?;
|
|
348
|
+
let client = builder
|
|
349
|
+
.configure_reqwest(|r| {
|
|
350
|
+
let mut headers = http::HeaderMap::new();
|
|
351
|
+
headers.insert(http::header::AUTHORIZATION, sentry_token);
|
|
352
|
+
r.connect_timeout(Duration::from_secs(10))
|
|
353
|
+
.default_headers(headers)
|
|
305
354
|
})
|
|
306
|
-
.configure_reqwest(|r| r.connect_timeout(Duration::from_secs(10)))
|
|
307
355
|
.build()?;
|
|
308
356
|
|
|
357
|
+
let scopes = options.objectstore.scopes;
|
|
358
|
+
|
|
359
|
+
let find_scope = |name: &str| {
|
|
360
|
+
scopes
|
|
361
|
+
.iter()
|
|
362
|
+
.find(|(k, _)| k == name)
|
|
363
|
+
.map(|(_, v)| v.clone())
|
|
364
|
+
};
|
|
365
|
+
let org_id = find_scope("org").context("Missing org in UploadOptions scope")?;
|
|
366
|
+
let project_id = find_scope("project").context("Missing project in UploadOptions scope")?;
|
|
367
|
+
|
|
309
368
|
let mut scope = Usecase::new("preprod").scope();
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
scope = scope.push(&key, value.clone());
|
|
313
|
-
if key == "org" {
|
|
314
|
-
org_id = Some(value);
|
|
315
|
-
} else if key == "project" {
|
|
316
|
-
project_id = Some(value);
|
|
317
|
-
}
|
|
369
|
+
for (key, value) in scopes {
|
|
370
|
+
scope = scope.push(&key, value);
|
|
318
371
|
}
|
|
319
|
-
let Some(org_id) = org_id else {
|
|
320
|
-
anyhow::bail!("Missing org in UploadOptions scope");
|
|
321
|
-
};
|
|
322
|
-
let Some(project_id) = project_id else {
|
|
323
|
-
anyhow::bail!("Missing project in UploadOptions scope");
|
|
324
|
-
};
|
|
325
372
|
|
|
326
373
|
let session = scope.session(&client)?;
|
|
327
374
|
|
|
@@ -330,10 +377,9 @@ fn upload_images(
|
|
|
330
377
|
.build()
|
|
331
378
|
.context("Failed to create tokio runtime")?;
|
|
332
379
|
|
|
333
|
-
let mut many_builder = session.many();
|
|
334
380
|
let mut manifest_entries = HashMap::new();
|
|
335
|
-
let mut
|
|
336
|
-
let mut
|
|
381
|
+
let mut duplicates: Vec<String> = Vec::new();
|
|
382
|
+
let mut uploads = Vec::with_capacity(images.len());
|
|
337
383
|
|
|
338
384
|
let hashed_images: Vec<_> = images
|
|
339
385
|
.into_par_iter()
|
|
@@ -344,38 +390,14 @@ fn upload_images(
|
|
|
344
390
|
.collect::<Result<Vec<_>>>()?;
|
|
345
391
|
|
|
346
392
|
for (image, hash) in hashed_images {
|
|
347
|
-
let
|
|
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);
|
|
393
|
+
let image_key = crate::utils::fs::path_as_url(&image.relative_path);
|
|
355
394
|
|
|
356
|
-
if manifest_entries.contains_key(&
|
|
357
|
-
|
|
358
|
-
.entry(image_file_name)
|
|
359
|
-
.or_default()
|
|
360
|
-
.push(relative_path);
|
|
395
|
+
if manifest_entries.contains_key(&image_key) {
|
|
396
|
+
duplicates.push(image_key);
|
|
361
397
|
continue;
|
|
362
398
|
}
|
|
363
399
|
|
|
364
|
-
let file = runtime
|
|
365
|
-
.block_on(tokio::fs::File::open(&image.path))
|
|
366
|
-
.with_context(|| {
|
|
367
|
-
format!("Failed to open image for upload: {}", image.path.display())
|
|
368
|
-
})?;
|
|
369
|
-
|
|
370
400
|
let key = format!("{org_id}/{project_id}/{hash}");
|
|
371
|
-
info!("Queueing {} as {key}", image.relative_path.display());
|
|
372
|
-
|
|
373
|
-
many_builder = many_builder.push(
|
|
374
|
-
session
|
|
375
|
-
.put_file(file)
|
|
376
|
-
.key(&key)
|
|
377
|
-
.expiration_policy(expiration),
|
|
378
|
-
);
|
|
379
401
|
|
|
380
402
|
let mut extra = read_sidecar_metadata(&image.path).unwrap_or_else(|err| {
|
|
381
403
|
warn!("Error reading sidecar metadata, ignoring it instead: {err:#}");
|
|
@@ -383,48 +405,52 @@ fn upload_images(
|
|
|
383
405
|
});
|
|
384
406
|
extra.insert("content_hash".to_owned(), serde_json::Value::String(hash));
|
|
385
407
|
|
|
386
|
-
|
|
408
|
+
uploads.push(PreparedImage {
|
|
409
|
+
path: image.path,
|
|
410
|
+
key,
|
|
411
|
+
});
|
|
387
412
|
manifest_entries.insert(
|
|
388
|
-
|
|
413
|
+
image_key,
|
|
389
414
|
ImageMetadata::new(image.width, image.height, extra),
|
|
390
415
|
);
|
|
391
416
|
}
|
|
392
417
|
|
|
393
|
-
if !
|
|
394
|
-
let
|
|
395
|
-
|
|
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}");
|
|
418
|
+
if !duplicates.is_empty() {
|
|
419
|
+
let paths = duplicates.join(", ");
|
|
420
|
+
warn!("Duplicate paths encountered, skipping: {paths}");
|
|
401
421
|
}
|
|
402
422
|
|
|
403
|
-
let
|
|
423
|
+
let total_count = uploads.len();
|
|
404
424
|
|
|
405
|
-
let
|
|
425
|
+
let mut many_builder = session.many();
|
|
426
|
+
for prepared in uploads {
|
|
427
|
+
many_builder = many_builder.push(
|
|
428
|
+
session
|
|
429
|
+
.put_path(prepared.path.clone())
|
|
430
|
+
.key(&prepared.key)
|
|
431
|
+
.expiration_policy(expiration),
|
|
432
|
+
);
|
|
433
|
+
}
|
|
406
434
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
);
|
|
415
|
-
Ok(manifest_entries)
|
|
416
|
-
}
|
|
417
|
-
Err(errors) => {
|
|
418
|
-
eprintln!("There were errors uploading images:");
|
|
419
|
-
let mut error_count = 0;
|
|
420
|
-
for error in errors {
|
|
421
|
-
let error = anyhow::Error::new(error);
|
|
422
|
-
eprintln!(" {}", style(format!("{error:#}")).red());
|
|
423
|
-
error_count += 1;
|
|
424
|
-
}
|
|
425
|
-
anyhow::bail!("Failed to upload {error_count} out of {uploaded_count} images")
|
|
435
|
+
let result = runtime.block_on(async { many_builder.send().await.error_for_failures().await });
|
|
436
|
+
if let Err(errors) = result {
|
|
437
|
+
let errors: Vec<_> = errors.collect();
|
|
438
|
+
let error_count = errors.len();
|
|
439
|
+
eprintln!("There were errors uploading images:");
|
|
440
|
+
for error in errors {
|
|
441
|
+
let error = anyhow::Error::new(error);
|
|
442
|
+
eprintln!(" {}", style(format!("{error:#}")).red());
|
|
426
443
|
}
|
|
444
|
+
anyhow::bail!("Failed to upload {error_count} images");
|
|
427
445
|
}
|
|
446
|
+
|
|
447
|
+
println!(
|
|
448
|
+
"{} Uploaded {} image {}",
|
|
449
|
+
style(">").dim(),
|
|
450
|
+
style(total_count).yellow(),
|
|
451
|
+
if total_count == 1 { "file" } else { "files" }
|
|
452
|
+
);
|
|
453
|
+
Ok(manifest_entries)
|
|
428
454
|
}
|
|
429
455
|
|
|
430
456
|
#[cfg(test)]
|