From 4b0c2c07d4151dafe65b5519dca03292051a6813 Mon Sep 17 00:00:00 2001 From: Daniel Szoke Date: Wed, 7 Jan 2026 16:41:12 +0100 Subject: [PATCH] ref: Assume chunk uploading support (#3064) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description Assume that the Sentry server supports all file types we would like to upload. This change fixes compatibility with uploading ProGuard files self-hosted version 24.11.1, which [can receive chunk-uploaded ProGuard files](https://github.com/getsentry/sentry/commit/7c7e79fa2c4a41537687545a381aca1a091897dc), but [does not declare support in the `accept` field, yet](https://github.com/getsentry/sentry/commit/e0b7ff2fb72e49bfe862c6b90e42257990ea38e1). This will allow us to expand Sentry CLI 3.x's official support to all self-hosted versions above 24.11.1. We also no longer check the `accept` field during `dart-symbol-map` and `build` uploads. As not all versions ≥24.11.1 support these features, this means that users on a self-hosted version that supports these features tries to use the command, they will no longer get an error message that states that their server lacks uploading support for those file types if they attempt to upload it. But, I think this is okay, as long as we are clear what versions are supported for these features. ### Issues - Resolves #3050 - Resolves [CLI-254](https://linear.app/getsentry/issue/CLI-254/assume-chunk-upload-support) --- src/api/data_types/chunking/mod.rs | 2 +- .../data_types/chunking/upload/capability.rs | 30 ------------------ src/api/data_types/chunking/upload/mod.rs | 2 -- src/api/data_types/chunking/upload/options.rs | 11 +------ src/commands/build/upload.rs | 15 ++------- src/commands/dart_symbol_map/mod.rs | 3 +- src/commands/dart_symbol_map/upload.rs | 7 +---- src/commands/upload_proguard.rs | 8 +---- .../build/build-upload-help-macos.trycmd | 31 ++++++++++++++++--- .../build/build-upload-help-not-macos.trycmd | 29 +++++++++++++++-- 10 files changed, 61 insertions(+), 77 deletions(-) delete mode 100644 src/api/data_types/chunking/upload/capability.rs diff --git a/src/api/data_types/chunking/mod.rs b/src/api/data_types/chunking/mod.rs index 54b1fae405..8b5657ee1c 100644 --- a/src/api/data_types/chunking/mod.rs +++ b/src/api/data_types/chunking/mod.rs @@ -15,4 +15,4 @@ pub use self::compression::ChunkCompression; pub use self::dif::{AssembleDifsRequest, AssembleDifsResponse, ChunkedDifRequest}; pub use self::file_state::ChunkedFileState; pub use self::hash_algorithm::ChunkHashAlgorithm; -pub use self::upload::{ChunkServerOptions, ChunkUploadCapability}; +pub use self::upload::ChunkServerOptions; diff --git a/src/api/data_types/chunking/upload/capability.rs b/src/api/data_types/chunking/upload/capability.rs deleted file mode 100644 index b79f62c761..0000000000 --- a/src/api/data_types/chunking/upload/capability.rs +++ /dev/null @@ -1,30 +0,0 @@ -use serde::{Deserialize, Deserializer}; - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum ChunkUploadCapability { - /// Upload of Dart symbol maps - DartSymbolMap, - - /// Upload of preprod artifacts - PreprodArtifacts, - - /// Upload of ProGuard mappings - Proguard, - - /// Any other unsupported capability (ignored) - Unknown, -} - -impl<'de> Deserialize<'de> for ChunkUploadCapability { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Ok(match String::deserialize(deserializer)?.as_str() { - "dartsymbolmap" => ChunkUploadCapability::DartSymbolMap, - "preprod_artifacts" => ChunkUploadCapability::PreprodArtifacts, - "proguard" => ChunkUploadCapability::Proguard, - _ => ChunkUploadCapability::Unknown, - }) - } -} diff --git a/src/api/data_types/chunking/upload/mod.rs b/src/api/data_types/chunking/upload/mod.rs index 3f70dbdfbf..88fd7d2d6e 100644 --- a/src/api/data_types/chunking/upload/mod.rs +++ b/src/api/data_types/chunking/upload/mod.rs @@ -1,7 +1,5 @@ use super::*; -mod capability; mod options; -pub use self::capability::ChunkUploadCapability; pub use self::options::ChunkServerOptions; diff --git a/src/api/data_types/chunking/upload/options.rs b/src/api/data_types/chunking/upload/options.rs index 1afec7e9a2..cc4236903b 100644 --- a/src/api/data_types/chunking/upload/options.rs +++ b/src/api/data_types/chunking/upload/options.rs @@ -2,7 +2,7 @@ use std::num::NonZeroUsize; use serde::Deserialize; -use super::{ChunkCompression, ChunkHashAlgorithm, ChunkUploadCapability}; +use super::{ChunkCompression, ChunkHashAlgorithm}; /// Chunk upload options which are set by the Sentry server. #[derive(Debug, Deserialize)] @@ -23,13 +23,4 @@ pub struct ChunkServerOptions { pub concurrency: u8, #[serde(default)] pub compression: Vec, - #[serde(default)] - pub accept: Vec, -} - -impl ChunkServerOptions { - /// Returns whether the given capability is accepted by the chunk upload endpoint. - pub fn supports(&self, capability: ChunkUploadCapability) -> bool { - self.accept.contains(&capability) - } } diff --git a/src/commands/build/upload.rs b/src/commands/build/upload.rs index 11fe9b438a..611a8ebd56 100644 --- a/src/commands/build/upload.rs +++ b/src/commands/build/upload.rs @@ -11,9 +11,7 @@ use symbolic::common::ByteView; use zip::write::SimpleFileOptions; use zip::{DateTime, ZipWriter}; -use crate::api::{ - Api, AuthenticatedApi, ChunkUploadCapability, ChunkedBuildRequest, ChunkedFileState, VcsInfo, -}; +use crate::api::{Api, AuthenticatedApi, ChunkedBuildRequest, ChunkedFileState, VcsInfo}; use crate::config::Config; use crate::utils::args::ArgExt as _; #[cfg(all(target_os = "macos", target_arch = "aarch64"))] @@ -42,6 +40,7 @@ pub fn make_command(command: Command) -> Command { "The path to the build to upload. Supported files include Apk, and Aab."; command .about("Upload builds to a project.") + .long_about("Upload builds to a project.\n\nThis feature only works with Sentry SaaS.") .org_arg() .project_arg(false) .arg( @@ -599,9 +598,6 @@ fn upload_file( release_notes: Option<&str>, vcs_info: &VcsInfo<'_>, ) -> Result { - const SELF_HOSTED_ERROR_HINT: &str = "If you are using a self-hosted Sentry server, \ - update to the latest version of Sentry to use the build upload command."; - debug!( "Uploading file to organization: {org}, project: {project}, build_configuration: {}, vcs_info: {vcs_info:?}", build_configuration.unwrap_or("unknown"), @@ -609,13 +605,6 @@ fn upload_file( let chunk_upload_options = api.get_chunk_upload_options(org)?; - if !chunk_upload_options.supports(ChunkUploadCapability::PreprodArtifacts) { - bail!( - "The Sentry server lacks support for receiving files uploaded \ - with this command. {SELF_HOSTED_ERROR_HINT}" - ); - } - let progress_style = ProgressStyle::default_spinner().template("{spinner} Preparing for upload..."); let pb = ProgressBar::new_spinner(); diff --git a/src/commands/dart_symbol_map/mod.rs b/src/commands/dart_symbol_map/mod.rs index 24dd414c98..315f2122b8 100644 --- a/src/commands/dart_symbol_map/mod.rs +++ b/src/commands/dart_symbol_map/mod.rs @@ -7,7 +7,8 @@ const GROUP_ABOUT: &str = "Manage Dart/Flutter symbol maps for Sentry."; const UPLOAD_ABOUT: &str = "Upload a Dart/Flutter symbol map (dartsymbolmap) for deobfuscating Dart exception types."; const UPLOAD_LONG_ABOUT: &str = - "Upload a Dart/Flutter symbol map (dartsymbolmap) for deobfuscating Dart exception types.{n}{n}Examples:{n} sentry-cli dart-symbol-map upload --org my-org --project my-proj path/to/dartsymbolmap.json path/to/debug/file{n}{n}The mapping must be a JSON array of strings with an even number of entries (pairs).{n}The debug file must contain exactly one Debug ID."; + "Upload a Dart/Flutter symbol map (dartsymbolmap) for deobfuscating Dart exception types.{n}{n}Examples:{n} sentry-cli dart-symbol-map upload --org my-org --project my-proj path/to/dartsymbolmap.json path/to/debug/file{n}{n}The mapping must be a JSON array of strings with an even number of entries (pairs).{n}The debug file must contain exactly one Debug ID. {n}{n}\ + This command is supported on Sentry SaaS and self-hosted versions ≥25.8.0."; #[derive(Args)] pub(super) struct DartSymbolMapArgs { diff --git a/src/commands/dart_symbol_map/upload.rs b/src/commands/dart_symbol_map/upload.rs index 2784060806..7f4d600ed5 100644 --- a/src/commands/dart_symbol_map/upload.rs +++ b/src/commands/dart_symbol_map/upload.rs @@ -6,7 +6,7 @@ use std::path::Path; use anyhow::{bail, Context as _, Result}; use clap::Args; -use crate::api::{Api, ChunkUploadCapability}; +use crate::api::Api; use crate::config::Config; use crate::constants::{DEFAULT_MAX_DIF_SIZE, DEFAULT_MAX_WAIT}; use crate::utils::chunks::{upload_chunked_objects, Assemblable, ChunkOptions, Chunked}; @@ -134,11 +134,6 @@ pub(super) fn execute(args: DartSymbolMapUploadArgs) -> Result<()> { .authenticated()? .get_chunk_upload_options(org)?; - if !chunk_upload_options.supports(ChunkUploadCapability::DartSymbolMap) { - bail!( - "Server does not support uploading Dart symbol maps via chunked upload. Please update your Sentry server." - ); - } // Early file size check against server or default limits (same as debug files) let effective_max_file_size = if chunk_upload_options.max_file_size > 0 { diff --git a/src/commands/upload_proguard.rs b/src/commands/upload_proguard.rs index 35658701ce..4e623c7dc2 100644 --- a/src/commands/upload_proguard.rs +++ b/src/commands/upload_proguard.rs @@ -8,7 +8,6 @@ use symbolic::common::ByteView; use uuid::Uuid; use crate::api::Api; -use crate::api::ChunkUploadCapability; use crate::config::Config; use crate::utils::android::dump_proguard_uuids_as_properties; use crate::utils::args::ArgExt as _; @@ -148,10 +147,5 @@ pub fn execute(matches: &ArgMatches) -> Result<()> { let (org, project) = config.get_org_and_project(matches)?; let chunk_upload_options = authenticated_api.get_chunk_upload_options(&org)?; - - if chunk_upload_options.supports(ChunkUploadCapability::Proguard) { - proguard::chunk_upload(&mappings, chunk_upload_options, &org, &project) - } else { - Err(anyhow::anyhow!("Server does not support uploading ProGuard mappings via chunked upload. Please update your Sentry server.")) - } + proguard::chunk_upload(&mappings, chunk_upload_options, &org, &project) } diff --git a/tests/integration/_cases/build/build-upload-help-macos.trycmd b/tests/integration/_cases/build/build-upload-help-macos.trycmd index 72b1d88a0c..d1a0a51c4e 100644 --- a/tests/integration/_cases/build/build-upload-help-macos.trycmd +++ b/tests/integration/_cases/build/build-upload-help-macos.trycmd @@ -3,63 +3,86 @@ $ sentry-cli build upload --help ? success Upload builds to a project. -Usage: sentry-cli[EXE] build upload [OPTIONS] ... +This feature only works with Sentry SaaS. + +Usage: sentry-cli build upload [OPTIONS] ... Arguments: - ... The path to the build to upload. Supported files include Apk, Aab, XCArchive, and IPA. + ... + The path to the build to upload. Supported files include Apk, Aab, XCArchive, and IPA. Options: -o, --org The organization ID or slug. + --header Custom headers that should be attached to all requests in key:value format. + -p, --project The project ID or slug. + --auth-token Use the given Sentry auth token. + --head-sha The VCS commit sha to use for the upload. If not provided, the current commit sha will be used. + --base-sha The VCS commit's base sha to use for the upload. If not provided, the merge-base of the current and remote branch will be used. + --log-level Set the log output verbosity. [possible values: trace, debug, info, warn, error] + --quiet Do not print any output while preserving correct exit code. This flag is currently - implemented only for selected subcommands. [aliases: --silent] + implemented only for selected subcommands. + + [aliases: --silent] + --vcs-provider The VCS provider to use for the upload. If not provided, the current provider will be used. + --head-repo-name The name of the git repository to use for the upload (e.g. organization/repository). If not provided, the current repository will be used. + --base-repo-name The name of the git repository to use for the upload (e.g. organization/repository). If not provided, the current repository will be used. + --head-ref The reference (branch) to use for the upload. If not provided, the current reference will be used. + --base-ref The base reference (branch) to use for the upload. If not provided, the merge-base with the remote tracking branch will be used. + --pr-number The pull request number to use for the upload. If not provided and running in a pull_request-triggered GitHub Actions workflow, the PR number will be automatically detected from GitHub Actions environment variables. + --build-configuration The build configuration to use for the upload. If not provided, the current version will be used. + --release-notes The release notes to use for the upload. + --force-git-metadata Force collection and sending of git metadata (branch, commit, etc.). If neither this nor --no-git-metadata is specified, git metadata is automatically collected when running in most CI environments. + --no-git-metadata Disable collection and sending of git metadata. + -h, --help - Print help + Print help (see a summary with '-h') ``` diff --git a/tests/integration/_cases/build/build-upload-help-not-macos.trycmd b/tests/integration/_cases/build/build-upload-help-not-macos.trycmd index b144a302c6..ab4df7233e 100644 --- a/tests/integration/_cases/build/build-upload-help-not-macos.trycmd +++ b/tests/integration/_cases/build/build-upload-help-not-macos.trycmd @@ -2,63 +2,86 @@ $ sentry-cli build upload --help Upload builds to a project. +This feature only works with Sentry SaaS. + Usage: sentry-cli[EXE] build upload [OPTIONS] ... Arguments: - ... The path to the build to upload. Supported files include Apk, and Aab. + ... + The path to the build to upload. Supported files include Apk, and Aab. Options: -o, --org The organization ID or slug. + --header Custom headers that should be attached to all requests in key:value format. + -p, --project The project ID or slug. + --auth-token Use the given Sentry auth token. + --head-sha The VCS commit sha to use for the upload. If not provided, the current commit sha will be used. + --base-sha The VCS commit's base sha to use for the upload. If not provided, the merge-base of the current and remote branch will be used. + --log-level Set the log output verbosity. [possible values: trace, debug, info, warn, error] + --quiet Do not print any output while preserving correct exit code. This flag is currently - implemented only for selected subcommands. [aliases: --silent] + implemented only for selected subcommands. + + [aliases: --silent] + --vcs-provider The VCS provider to use for the upload. If not provided, the current provider will be used. + --head-repo-name The name of the git repository to use for the upload (e.g. organization/repository). If not provided, the current repository will be used. + --base-repo-name The name of the git repository to use for the upload (e.g. organization/repository). If not provided, the current repository will be used. + --head-ref The reference (branch) to use for the upload. If not provided, the current reference will be used. + --base-ref The base reference (branch) to use for the upload. If not provided, the merge-base with the remote tracking branch will be used. + --pr-number The pull request number to use for the upload. If not provided and running in a pull_request-triggered GitHub Actions workflow, the PR number will be automatically detected from GitHub Actions environment variables. + --build-configuration The build configuration to use for the upload. If not provided, the current version will be used. + --release-notes The release notes to use for the upload. + --force-git-metadata Force collection and sending of git metadata (branch, commit, etc.). If neither this nor --no-git-metadata is specified, git metadata is automatically collected when running in most CI environments. + --no-git-metadata Disable collection and sending of git metadata. + -h, --help - Print help + Print help (see a summary with '-h') ```