Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .cursor/rules/rust-development.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ cargo fmt
## Swift/Apple Integration

- Swift code in `apple-catalog-parsing/` is used for parsing xarchive files
- Used by the `mobile-app upload` command for iOS app processing
- Used by the `build upload` command for iOS app processing
- Built as a separate crate with FFI bindings to Rust
- Only compiled on macOS targets
- Tests run via `swift-test.yml` workflow in CI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use sha1_smol::Digest;
use super::ChunkedFileState;

#[derive(Debug, Serialize)]
pub struct ChunkedMobileAppRequest<'a> {
pub struct ChunkedBuildRequest<'a> {
pub checksum: Digest,
pub chunks: &'a [Digest],
#[serde(skip_serializing_if = "Option::is_none")]
Expand All @@ -30,7 +30,7 @@ pub struct ChunkedMobileAppRequest<'a> {

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AssembleMobileAppResponse {
pub struct AssembleBuildResponse {
pub state: ChunkedFileState,
pub missing_chunks: Vec<Digest>,
pub detail: Option<String>,
Expand Down
4 changes: 2 additions & 2 deletions src/api/data_types/chunking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
//! from the server.

mod artifact;
mod build;
mod compression;
mod dif;
mod file_state;
mod hash_algorithm;
mod mobile_app;
mod upload;

pub use self::artifact::{AssembleArtifactsResponse, ChunkedArtifactRequest};
pub use self::build::{AssembleBuildResponse, ChunkedBuildRequest};
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::mobile_app::{AssembleMobileAppResponse, ChunkedMobileAppRequest};
pub use self::upload::{ChunkServerOptions, ChunkUploadCapability};
6 changes: 3 additions & 3 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1030,23 +1030,23 @@ impl<'a> AuthenticatedApi<'a> {
.convert_rnf(ApiErrorKind::ReleaseNotFound)
}

pub fn assemble_mobile_app(
pub fn assemble_build(
&self,
org: &str,
project: &str,
checksum: Digest,
chunks: &[Digest],
build_configuration: Option<&str>,
vcs_info: &VcsInfo<'_>,
) -> ApiResult<AssembleMobileAppResponse> {
) -> ApiResult<AssembleBuildResponse> {
let url = format!(
"/projects/{}/{}/files/preprodartifacts/assemble/",
PathArg(org),
PathArg(project)
);

self.request(Method::Post, &url)?
.with_json_body(&ChunkedMobileAppRequest {
.with_json_body(&ChunkedBuildRequest {
checksum,
chunks,
build_configuration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ macro_rules! each_subcommand {
pub fn make_command(mut command: Command) -> Command {
macro_rules! add_subcommand {
($name:ident) => {{
command = command.subcommand(crate::commands::mobile_app::$name::make_command(
command = command.subcommand(crate::commands::build::$name::make_command(
Command::new(stringify!($name).replace('_', "-")),
));
}};
}

command = command
.about("[EXPERIMENTAL] Manage mobile apps.")
.about("[EXPERIMENTAL] Manage builds.")
.subcommand_required(true)
.arg_required_else_help(true)
.org_arg()
Expand All @@ -34,7 +34,7 @@ pub fn make_command(mut command: Command) -> Command {

pub fn execute(matches: &ArgMatches) -> Result<()> {
log::warn!(
"EXPERIMENTAL: The mobile-app subcommand is experimental. \
"EXPERIMENTAL: The build subcommand is experimental. \
The command is subject to breaking changes and may be removed \
without notice in any release."
);
Expand All @@ -44,7 +44,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
if let Some(sub_matches) =
matches.subcommand_matches(&stringify!($name).replace('_', "-"))
{
return crate::commands::mobile_app::$name::execute(&sub_matches);
return crate::commands::build::$name::execute(&sub_matches);
}
}};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,27 @@ use zip::{DateTime, ZipWriter};
use crate::api::{Api, AuthenticatedApi, ChunkUploadCapability, ChunkedFileState, VcsInfo};
use crate::config::Config;
use crate::utils::args::ArgExt as _;
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
use crate::utils::build::{handle_asset_catalogs, ipa_to_xcarchive, is_apple_app, is_ipa_file};
use crate::utils::build::{is_aab_file, is_apk_file, is_zip_file, normalize_directory};
use crate::utils::chunks::{upload_chunks, Chunk};
use crate::utils::fs::get_sha1_checksums;
use crate::utils::fs::TempDir;
use crate::utils::fs::TempFile;
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
use crate::utils::mobile_app::{
handle_asset_catalogs, ipa_to_xcarchive, is_apple_app, is_ipa_file,
};
use crate::utils::mobile_app::{is_aab_file, is_apk_file, is_zip_file, normalize_directory};
use crate::utils::progress::ProgressBar;
use crate::utils::vcs::{
self, get_provider_from_remote, get_repo_from_remote, git_repo_remote_url,
};

pub fn make_command(command: Command) -> Command {
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
const HELP_TEXT: &str = "The path to the mobile app files to upload. Supported files include Apk, Aab, XCArchive, and IPA.";
const HELP_TEXT: &str =
"The path to the build to upload. Supported files include Apk, Aab, XCArchive, and IPA.";
#[cfg(not(all(target_os = "macos", target_arch = "aarch64")))]
const HELP_TEXT: &str =
"The path to the mobile app files to upload. Supported files include Apk, and Aab.";
"The path to the build to upload. Supported files include Apk, and Aab.";
command
.about("[EXPERIMENTAL] Upload mobile app files to a project.")
.about("[EXPERIMENTAL] Upload builds to a project.")
.org_arg()
.project_arg(false)
.arg(
Expand Down Expand Up @@ -149,10 +148,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
let api = Api::current();
let authenticated_api = api.authenticated()?;

debug!(
"Starting mobile app upload for {} paths",
path_strings.len()
);
debug!("Starting upload for {} paths", path_strings.len());

let mut normalized_zips = vec![];
for path_string in path_strings {
Expand All @@ -166,7 +162,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
let byteview = ByteView::open(path)?;
debug!("Loaded file with {} bytes", byteview.len());

validate_is_mobile_app(path, &byteview)?;
validate_is_supported_build(path, &byteview)?;

let normalized_zip = if path.is_file() {
debug!("Normalizing file: {}", path.display());
Expand Down Expand Up @@ -285,8 +281,8 @@ fn handle_file(path: &Path, byteview: &ByteView) -> Result<TempFile> {
})
}

fn validate_is_mobile_app(path: &Path, bytes: &[u8]) -> Result<()> {
debug!("Validating mobile app format for: {}", path.display());
fn validate_is_supported_build(path: &Path, bytes: &[u8]) -> Result<()> {
debug!("Validating build format for: {}", path.display());

#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
if is_apple_app(path) {
Expand Down Expand Up @@ -325,7 +321,7 @@ fn validate_is_mobile_app(path: &Path, bytes: &[u8]) -> Result<()> {
let format_list = "APK, or AAB";

Err(anyhow!(
"File is not a recognized mobile app format ({format_list}): {}",
"File is not a recognized supported build format ({format_list}): {}",
path.display()
))
}
Expand Down Expand Up @@ -379,7 +375,7 @@ fn upload_file(
vcs_info: &VcsInfo<'_>,
) -> Result<String> {
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 mobile-app upload command.";
update to the latest version of Sentry to use the build upload command.";

debug!(
"Uploading file to organization: {}, project: {}, build_configuration: {}, vcs_info: {:?}",
Expand All @@ -392,7 +388,7 @@ fn upload_file(
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 mobile app uploads. {SELF_HOSTED_ERROR_HINT}"
is required for build uploads. {SELF_HOSTED_ERROR_HINT}"
)
})?;

Expand Down Expand Up @@ -433,7 +429,7 @@ fn upload_file(
// n. state=error, artifact_url unset

let result = loop {
let response = api.assemble_mobile_app(
let response = api.assemble_build(
org,
project,
checksum,
Expand Down Expand Up @@ -497,7 +493,7 @@ mod tests {
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
fn test_xcarchive_upload_includes_parsed_assets() -> Result<()> {
// Test that XCArchive uploads include parsed asset catalogs
let xcarchive_path = Path::new("tests/integration/_fixtures/mobile_app/archive.xcarchive");
let xcarchive_path = Path::new("tests/integration/_fixtures/build/archive.xcarchive");

// Process the XCArchive directory
let result = handle_directory(xcarchive_path)?;
Expand Down Expand Up @@ -529,7 +525,7 @@ mod tests {
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
fn test_ipa_upload_includes_parsed_assets() -> Result<()> {
// Test that IPA uploads handle missing asset catalogs gracefully
let ipa_path = Path::new("tests/integration/_fixtures/mobile_app/ipa_with_asset.ipa");
let ipa_path = Path::new("tests/integration/_fixtures/build/ipa_with_asset.ipa");
let byteview = ByteView::open(ipa_path)?;

// Process the IPA file - this should work even without asset catalogs
Expand Down
4 changes: 2 additions & 2 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::utils::update::run_sentrycli_update_nagger;
use crate::utils::value_parsers::auth_token_parser;

mod bash_hook;
mod build;
mod dart_symbol_map;
mod debug_files;
mod deploys;
Expand All @@ -30,7 +31,6 @@ mod info;
mod issues;
mod login;
mod logs;
mod mobile_app;
mod monitors;
mod organizations;
mod projects;
Expand All @@ -52,6 +52,7 @@ mod upload_proguard;
macro_rules! each_subcommand {
($mac:ident) => {
$mac!(bash_hook);
$mac!(build);
$mac!(debug_files);
$mac!(deploys);
$mac!(events);
Expand All @@ -60,7 +61,6 @@ macro_rules! each_subcommand {
$mac!(issues);
$mac!(login);
$mac!(logs);
$mac!(mobile_app);
$mac!(monitors);
$mac!(organizations);
$mac!(projects);
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod android;
pub mod appcenter;
pub mod args;
pub mod auth_token;
pub mod build;
pub mod chunks;
pub mod cordova;
pub mod dif;
Expand All @@ -15,7 +16,6 @@ pub mod fs;
pub mod http;
pub mod logging;
pub mod metrics;
pub mod mobile_app;
pub mod progress;
pub mod proguard;
pub mod releases;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
```
$ sentry-cli mobile-app --help
$ sentry-cli build --help
? success
[EXPERIMENTAL] Manage mobile apps.
[EXPERIMENTAL] Manage builds.

Usage: sentry-cli[EXE] mobile-app [OPTIONS] <COMMAND>
Usage: sentry-cli[EXE] build [OPTIONS] <COMMAND>

Commands:
upload [EXPERIMENTAL] Upload mobile app files to a project.
upload [EXPERIMENTAL] Upload builds to a project.
help Print this message or the help of the given subcommand(s)

Options:
Expand All @@ -22,4 +22,4 @@ Options:
[aliases: silent]
-h, --help Print help

```
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
```
$ sentry-cli build upload tests/integration/_fixtures/build/apk.apk
? success
[..]WARN[..]EXPERIMENTAL: The build subcommand is experimental. The command is subject to breaking changes and may be removed without notice in any release.
Successfully uploaded 1 file to Sentry
- tests/integration/_fixtures/build/apk.apk (http[..]/wat-org/preprod/wat-project/42)

```
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
```
$ sentry-cli mobile-app upload tests/integration/_fixtures/mobile_app/apk.apk
$ sentry-cli build upload tests/integration/_fixtures/build/apk.apk
? failed
[..]WARN[..]EXPERIMENTAL: The mobile-app subcommand is experimental. The command is subject to breaking changes and may be removed without notice in any release.
[..]WARN[..]EXPERIMENTAL: The build subcommand is experimental. The command is subject to breaking changes and may be removed without notice in any release.
error: Auth token is required for this request. Please run `sentry-cli login` and try again!

Add --log-level=[info|debug] or export SENTRY_LOG_LEVEL=[info|debug] to see more output.
Expand Down
8 changes: 8 additions & 0 deletions tests/integration/_cases/build/build-upload-apk.trycmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
```
$ sentry-cli build upload tests/integration/_fixtures/build/apk.apk --head-sha test_head_sha
? success
[..]WARN[..]EXPERIMENTAL: The build subcommand is experimental. The command is subject to breaking changes and may be removed without notice in any release.
Successfully uploaded 1 file to Sentry
- tests/integration/_fixtures/build/apk.apk (http[..]/wat-org/preprod/wat-project/42)

```
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
```
$ sentry-cli mobile-app upload --help
[EXPERIMENTAL] Upload mobile app files to a project.
$ sentry-cli build upload --help
? success
[EXPERIMENTAL] Upload builds to a project.

Usage: sentry-cli[EXE] mobile-app upload [OPTIONS] <PATH>...
Usage: sentry-cli[EXE] build upload [OPTIONS] <PATH>...

Arguments:
<PATH>... The path to the mobile app files to upload. Supported files include Apk, and Aab.
<PATH>... The path to the build to upload. Supported files include Apk, Aab, XCArchive, and IPA.

Options:
-o, --org <ORG>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
```
$ sentry-cli mobile-app upload --help
? success
[EXPERIMENTAL] Upload mobile app files to a project.
$ sentry-cli build upload --help
[EXPERIMENTAL] Upload builds to a project.

Usage: sentry-cli[EXE] mobile-app upload [OPTIONS] <PATH>...
Usage: sentry-cli[EXE] build upload [OPTIONS] <PATH>...

Arguments:
<PATH>... The path to the mobile app files to upload. Supported files include Apk, Aab,
XCArchive, and IPA.
<PATH>... The path to the build to upload. Supported files include Apk, and Aab.

Options:
-o, --org <ORG>
Expand Down
8 changes: 8 additions & 0 deletions tests/integration/_cases/build/build-upload-ipa.trycmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
```
$ sentry-cli build upload tests/integration/_fixtures/build/ipa.ipa --head-sha test_head_sha
? success
[..]WARN[..]EXPERIMENTAL: The build subcommand is experimental. The command is subject to breaking changes and may be removed without notice in any release.
Successfully uploaded 1 file to Sentry
- tests/integration/_fixtures/build/ipa.ipa (http[..]/wat-org/preprod/wat-project/some-text-id)

```
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
```
$ sentry-cli mobile-app upload
$ sentry-cli build upload
? failed
error: the following required arguments were not provided:
<PATH>...

Usage: sentry-cli[EXE] mobile-app upload <PATH>...
Usage: sentry-cli[EXE] build upload <PATH>...

For more information, try '--help'.

Expand Down

This file was deleted.

Loading