Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@
as the changelog is updated for minor releases. Prior to merging the PR stack for 3.0,
we should rename this section to "Unreleased" -->

### New Sentry Support Policy

`sentry-cli` 3.0.0 and above only officially supports Sentry SaaS and Sentry self-hosted versions [25.10.0](https://github.com/getsentry/sentry/releases/tag/25.10.0) and higher. While many Sentry CLI features may, in practice, continue working with some older Sentry versions, continued support for Sentry versions older than 25.10.0 is not guaranteed. Changes which break support for Sentry versions below 25.10.0 may occur in minor or patch releases.

### Breaking Changes

- Removed the `upload-proguard` subcommand's `--app-id`, `--version`, and `--version-code` arguments ([#2876](https://github.com/getsentry/sentry-cli/pull/2876)). Users using these arguments should stop using them, as they are unnecessary. The information passed to these arguments is no longer visible in Sentry.

### Fixes

- Fixed misleading error message claiming the server doesn't support chunk uploading when the actual error was a non-existent organization ([#2930](https://github.com/getsentry/sentry-cli/pull/2930)).

## 2.58.2

### Improvements
Expand Down
5 changes: 3 additions & 2 deletions src/api/errors/api_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ pub(in crate::api) enum ApiErrorKind {
ProjectNotFound,
#[error("Release not found. Ensure that you configured the correct release, project, and organization.")]
ReleaseNotFound,
#[error("chunk upload endpoint not supported by sentry server")]
ChunkUploadNotSupported,
#[error("API request failed")]
RequestFailed,
#[error("could not compress data")]
Expand Down Expand Up @@ -63,6 +61,9 @@ impl ApiError {
}
}

// This method is currently only used in the macOS binary, there is no reason
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm confused by this comment, should it read "there is no reason to expose it on other platforms" ?

// why not to expose it on other platforms, if we ever need it.
#[cfg(target_os = "macos")]
pub(in crate::api) fn kind(&self) -> ApiErrorKind {
self.inner
}
Expand Down
17 changes: 3 additions & 14 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -956,21 +956,10 @@ impl<'a> AuthenticatedApi<'a> {
}

/// Get the server configuration for chunked file uploads.
pub fn get_chunk_upload_options(&self, org: &str) -> ApiResult<Option<ChunkServerOptions>> {
pub fn get_chunk_upload_options(&self, org: &str) -> ApiResult<ChunkServerOptions> {
let url = format!("/organizations/{}/chunk-upload/", PathArg(org));
match self
.get(&url)?
.convert_rnf::<ChunkServerOptions>(ApiErrorKind::ChunkUploadNotSupported)
{
Ok(options) => Ok(Some(options)),
Err(error) => {
if error.kind() == ApiErrorKind::ChunkUploadNotSupported {
Ok(None)
} else {
Err(error)
}
}
}
self.get(&url)?
.convert_rnf::<ChunkServerOptions>(ApiErrorKind::OrganizationNotFound)
}

/// Request DIF assembling and processing from chunks.
Expand Down
7 changes: 1 addition & 6 deletions src/commands/build/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,12 +523,7 @@ fn upload_file(
build_configuration.unwrap_or("unknown"),
);

let chunk_upload_options = api.get_chunk_upload_options(org)?.ok_or_else(|| {
anyhow!(
"The Sentry server lacks chunked uploading support, which \
is required for build uploads. {SELF_HOSTED_ERROR_HINT}"
)
})?;
let chunk_upload_options = api.get_chunk_upload_options(org)?;

if !chunk_upload_options.supports(ChunkUploadCapability::PreprodArtifacts) {
bail!(
Expand Down
5 changes: 1 addition & 4 deletions src/commands/dart_symbol_map/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,7 @@ pub(super) fn execute(args: DartSymbolMapUploadArgs) -> Result<()> {
))?;
let chunk_upload_options = api
.authenticated()?
.get_chunk_upload_options(org)?
.ok_or_else(|| anyhow::anyhow!(
"server does not support chunked uploading. Please update your Sentry server."
))?;
.get_chunk_upload_options(org)?;

if !chunk_upload_options.supports(ChunkUploadCapability::DartSymbolMap) {
bail!(
Expand Down
2 changes: 1 addition & 1 deletion src/commands/files/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
note: None,
wait,
max_wait,
chunk_upload_options: chunk_upload_options.as_ref(),
chunk_upload_options: &chunk_upload_options,
};

let path = Path::new(matches.get_one::<String>("path").unwrap());
Expand Down
4 changes: 2 additions & 2 deletions src/commands/react_native/appcenter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
note: None,
wait,
max_wait,
chunk_upload_options: chunk_upload_options.as_ref(),
chunk_upload_options: &chunk_upload_options,
})?;
}
Some(dists) => {
Expand All @@ -220,7 +220,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
note: None,
wait,
max_wait,
chunk_upload_options: chunk_upload_options.as_ref(),
chunk_upload_options: &chunk_upload_options,
})?;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/commands/react_native/gradle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
note: None,
wait,
max_wait,
chunk_upload_options: chunk_upload_options.as_ref(),
chunk_upload_options: &chunk_upload_options,
})?;
}
} else {
Expand All @@ -142,7 +142,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
note: None,
wait,
max_wait,
chunk_upload_options: chunk_upload_options.as_ref(),
chunk_upload_options: &chunk_upload_options,
})?;
}

Expand Down
6 changes: 3 additions & 3 deletions src/commands/react_native/xcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
note: None,
wait,
max_wait,
chunk_upload_options: chunk_upload_options.as_ref(),
chunk_upload_options: &chunk_upload_options,
})?;
} else {
let (dist, release_name) = match (&dist_from_env, &release_from_env) {
Expand Down Expand Up @@ -386,7 +386,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
note: None,
wait,
max_wait,
chunk_upload_options: chunk_upload_options.as_ref(),
chunk_upload_options: &chunk_upload_options,
})?;
}
Some(dists) => {
Expand All @@ -399,7 +399,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
note: None,
wait,
max_wait,
chunk_upload_options: chunk_upload_options.as_ref(),
chunk_upload_options: &chunk_upload_options,
})?;
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/commands/sourcemaps/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,10 +437,10 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
log::warn!("The --use-artifact-bundle option and the SENTRY_FORCE_ARTIFACT_BUNDLES environment variable \
are both deprecated, and both will be removed in the next major version.");

if let Some(ref mut options) = chunk_upload_options {
if !options.supports(ChunkUploadCapability::ArtifactBundles) {
options.accept.push(ChunkUploadCapability::ArtifactBundles);
}
if !chunk_upload_options.supports(ChunkUploadCapability::ArtifactBundles) {
chunk_upload_options
.accept
.push(ChunkUploadCapability::ArtifactBundles);
}
}

Expand All @@ -461,7 +461,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
note: matches.get_one::<String>("note").map(String::as_str),
wait,
max_wait,
chunk_upload_options: chunk_upload_options.as_ref(),
chunk_upload_options: &chunk_upload_options,
};

if matches.get_flag("strict") {
Expand Down
12 changes: 1 addition & 11 deletions src/commands/upload_proguard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,17 +184,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
authenticated_api = api.authenticated()?;
(org, project) = config.get_org_and_project(matches)?;

let chunk_upload_options = authenticated_api
.get_chunk_upload_options(&org)
.map_err(|e| anyhow::anyhow!(e))
.and_then(|options| {
options.ok_or_else(|| {
anyhow::anyhow!(
"server does not support chunked uploading. unset \
{CHUNK_UPLOAD_ENV_VAR} to continue."
)
})
})?;
let chunk_upload_options = authenticated_api.get_chunk_upload_options(&org)?;

proguard::chunk_upload(&mappings, chunk_upload_options, &org, &project)?;
} else {
Expand Down
35 changes: 17 additions & 18 deletions src/utils/dif_upload/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1625,26 +1625,25 @@ impl<'a> DifUpload<'a> {
}

let api = Api::current();
if let Some(chunk_options) = api.authenticated()?.get_chunk_upload_options(self.org)? {
if chunk_options.max_file_size > 0 {
self.max_file_size = chunk_options.max_file_size;
}
if chunk_options.max_wait > 0 {
self.max_wait = self
.max_wait
.min(Duration::from_secs(chunk_options.max_wait));
}
let chunk_options = api.authenticated()?.get_chunk_upload_options(self.org)?;
if chunk_options.max_file_size > 0 {
self.max_file_size = chunk_options.max_file_size;
}
if chunk_options.max_wait > 0 {
self.max_wait = self
.max_wait
.min(Duration::from_secs(chunk_options.max_wait));
}

self.pdbs_allowed = chunk_options.supports(ChunkUploadCapability::Pdbs);
self.portablepdbs_allowed = chunk_options.supports(ChunkUploadCapability::PortablePdbs);
self.sources_allowed = chunk_options.supports(ChunkUploadCapability::Sources);
self.bcsymbolmaps_allowed = chunk_options.supports(ChunkUploadCapability::BcSymbolmap);
self.il2cpp_mappings_allowed = chunk_options.supports(ChunkUploadCapability::Il2Cpp);
self.pdbs_allowed = chunk_options.supports(ChunkUploadCapability::Pdbs);
self.portablepdbs_allowed = chunk_options.supports(ChunkUploadCapability::PortablePdbs);
self.sources_allowed = chunk_options.supports(ChunkUploadCapability::Sources);
self.bcsymbolmaps_allowed = chunk_options.supports(ChunkUploadCapability::BcSymbolmap);
self.il2cpp_mappings_allowed = chunk_options.supports(ChunkUploadCapability::Il2Cpp);

if chunk_options.supports(ChunkUploadCapability::DebugFiles) {
self.validate_capabilities();
return upload_difs_chunked(self, chunk_options);
}
if chunk_options.supports(ChunkUploadCapability::DebugFiles) {
self.validate_capabilities();
return upload_difs_chunked(self, chunk_options);
}

self.validate_capabilities();
Expand Down
65 changes: 27 additions & 38 deletions src/utils/file_upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ use crate::utils::source_bundle;

use super::file_search::ReleaseFileMatch;

/// Fallback concurrency for release file uploads.
static DEFAULT_CONCURRENCY: usize = 4;

/// Old versions of Sentry cannot assemble artifact bundles straight away, they require
/// that those bundles are associated to a release.
///
Expand All @@ -42,11 +39,10 @@ pub fn initialize_legacy_release_upload(context: &UploadContext) -> Result<()> {
// need to do anything here. Artifact bundles will also only work
// if a project is provided which is technically unnecessary for the
// legacy upload though it will unlikely to be what users want.
let chunk_options = context.chunk_upload_options;
if context.projects.is_some()
&& context.chunk_upload_options.is_some_and(|x| {
x.supports(ChunkUploadCapability::ArtifactBundles)
|| x.supports(ChunkUploadCapability::ArtifactBundlesV2)
})
&& (chunk_options.supports(ChunkUploadCapability::ArtifactBundles)
|| chunk_options.supports(ChunkUploadCapability::ArtifactBundlesV2))
{
return Ok(());
}
Expand Down Expand Up @@ -75,19 +71,8 @@ pub fn initialize_legacy_release_upload(context: &UploadContext) -> Result<()> {
..Default::default()
},
)?;
} else if context.chunk_upload_options.is_some() {
bail!("This version of Sentry does not support artifact bundles. A release slug is required (provide with --release or by setting the SENTRY_RELEASE environment variable)");
} else {
// We got a 404 when trying to get the chunk options from the server. Most likely, the
// organization does not exist, though old self-hosted Sentry servers may also completely
// lack support for chunked uploads.
bail!(
"The provided organization \"{}\" does not exist. If you are using a self-hosted \
Sentry server, it is also possible that your Sentry server lacks support for \
uploading artifact bundles, in which case you need to provide a release slug with \
--release or by setting the SENTRY_RELEASE environment variable.",
context.org
);
bail!("This version of Sentry does not support artifact bundles. A release slug is required (provide with --release or by setting the SENTRY_RELEASE environment variable)");
}
Ok(())
}
Expand All @@ -101,7 +86,7 @@ pub struct UploadContext<'a> {
pub note: Option<&'a str>,
pub wait: bool,
pub max_wait: Duration,
pub chunk_upload_options: Option<&'a ChunkServerOptions>,
pub chunk_upload_options: &'a ChunkServerOptions,
}

impl UploadContext<'_> {
Expand Down Expand Up @@ -372,11 +357,17 @@ impl<'a> FileUpload<'a> {
// multiple projects OK
initialize_legacy_release_upload(self.context)?;

if let Some(chunk_options) = self.context.chunk_upload_options {
if chunk_options.supports(ChunkUploadCapability::ReleaseFiles) {
// multiple projects OK
return upload_files_chunked(self.context, &self.files, chunk_options);
}
if self
.context
.chunk_upload_options
.supports(ChunkUploadCapability::ReleaseFiles)
{
// multiple projects OK
return upload_files_chunked(
self.context,
&self.files,
self.context.chunk_upload_options,
);
}

log::warn!(
Expand All @@ -398,10 +389,7 @@ impl<'a> FileUpload<'a> {
);
}

let concurrency = self
.context
.chunk_upload_options
.map_or(DEFAULT_CONCURRENCY, |o| usize::from(o.concurrency));
let concurrency = self.context.chunk_upload_options.concurrency as usize;

let legacy_context = &self.context.try_into().map_err(|e| {
anyhow::anyhow!(
Expand Down Expand Up @@ -701,15 +689,16 @@ fn print_upload_context_details(context: &UploadContext) {
style("> Dist:").dim(),
style(context.dist.unwrap_or("None")).yellow()
);
let upload_type = match context.chunk_upload_options {
None => "single file",
Some(opts)
if opts.supports(ChunkUploadCapability::ArtifactBundles)
|| opts.supports(ChunkUploadCapability::ArtifactBundlesV2) =>
{
"artifact bundle"
}
_ => "release bundle",
let upload_type = if context
.chunk_upload_options
.supports(ChunkUploadCapability::ArtifactBundles)
|| context
.chunk_upload_options
.supports(ChunkUploadCapability::ArtifactBundlesV2)
{
"artifact bundle"
} else {
"release bundle"
};
println!(
"{} {}",
Expand Down
Loading