From 36a6c11f63872c45813e5f0f5b869922d8f5c345 Mon Sep 17 00:00:00 2001 From: Noah Martin Date: Tue, 20 Jan 2026 14:33:36 -0800 Subject: [PATCH] feat(build): Add --distribution-group parameter to build upload Add support for distribution groups in build uploads. This parameter allows specifying one or more groups that control update visibility. Builds with at least one matching distribution group will be shown updates for each other. Co-Authored-By: Claude Opus 4.5 --- CHANGELOG.md | 6 +++ src/api/data_types/chunking/build.rs | 6 +++ src/commands/build/upload.rs | 51 +++++++++++++------ .../build/build-upload-help-macos.trycmd | 4 ++ .../build/build-upload-help-not-macos.trycmd | 4 ++ 5 files changed, 56 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ed6d65a09..ee6f90b371 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Features + +- Add `--install-group` parameter to `sentry-cli build upload` for controlling update visibility between builds ([#3094](https://github.com/getsentry/sentry-cli/pull/3094)) + ## 3.1.0 ### New Features diff --git a/src/api/data_types/chunking/build.rs b/src/api/data_types/chunking/build.rs index cc94ab2fa1..21bc80dc77 100644 --- a/src/api/data_types/chunking/build.rs +++ b/src/api/data_types/chunking/build.rs @@ -5,6 +5,10 @@ use sha1_smol::Digest; use super::ChunkedFileState; +fn is_empty_slice(slice: &[T]) -> bool { + slice.is_empty() +} + #[derive(Debug, Serialize)] pub struct ChunkedBuildRequest<'a> { pub checksum: Digest, @@ -13,6 +17,8 @@ pub struct ChunkedBuildRequest<'a> { pub build_configuration: Option<&'a str>, #[serde(skip_serializing_if = "Option::is_none")] pub release_notes: Option<&'a str>, + #[serde(skip_serializing_if = "is_empty_slice")] + pub install_groups: &'a [String], #[serde(flatten)] pub vcs_info: &'a VcsInfo<'a>, } diff --git a/src/commands/build/upload.rs b/src/commands/build/upload.rs index 611a8ebd56..d55b2388ad 100644 --- a/src/commands/build/upload.rs +++ b/src/commands/build/upload.rs @@ -106,6 +106,16 @@ pub fn make_command(command: Command) -> Command { .long("release-notes") .help("The release notes to use for the upload.") ) + .arg( + Arg::new("install_group") + .long("install-group") + .action(ArgAction::Append) + .help( + "The install group(s) for this build. Can be specified multiple times. \ + Builds with at least one matching install group will be shown updates \ + for each other.", + ) + ) .arg( Arg::new("force_git_metadata") .long("force-git-metadata") @@ -175,6 +185,10 @@ pub fn execute(matches: &ArgMatches) -> Result<()> { let build_configuration = matches.get_one("build_configuration").map(String::as_str); let release_notes = matches.get_one("release_notes").map(String::as_str); + let install_groups: Vec = matches + .get_many::("install_group") + .map(|vals| vals.cloned().collect()) + .unwrap_or_default(); let (plugin_name, plugin_version) = parse_plugin_from_pipeline(config.get_pipeline_env()); @@ -237,15 +251,13 @@ pub fn execute(matches: &ArgMatches) -> Result<()> { for (path, zip) in normalized_zips { info!("Uploading file: {}", path.display()); let bytes = ByteView::open(zip.path())?; - match upload_file( - &authenticated_api, - &bytes, - &org, - &project, + let metadata = BuildMetadata { build_configuration, release_notes, - &vcs_info, - ) { + install_groups: &install_groups, + vcs_info: &vcs_info, + }; + match upload_file(&authenticated_api, &bytes, &org, &project, &metadata) { Ok(artifact_url) => { info!("Successfully uploaded file: {}", path.display()); uploaded_paths_and_urls.push((path.to_path_buf(), artifact_url)); @@ -588,19 +600,27 @@ fn handle_directory( normalize_directory(path, temp_dir.path(), plugin_name, plugin_version) } +/// Metadata for a build upload. +struct BuildMetadata<'a> { + build_configuration: Option<&'a str>, + release_notes: Option<&'a str>, + install_groups: &'a [String], + vcs_info: &'a VcsInfo<'a>, +} + /// Returns artifact url if upload was successful. fn upload_file( api: &AuthenticatedApi, bytes: &[u8], org: &str, project: &str, - build_configuration: Option<&str>, - release_notes: Option<&str>, - vcs_info: &VcsInfo<'_>, + metadata: &BuildMetadata<'_>, ) -> Result { debug!( - "Uploading file to organization: {org}, project: {project}, build_configuration: {}, vcs_info: {vcs_info:?}", - build_configuration.unwrap_or("unknown"), + "Uploading file to organization: {org}, project: {project}, build_configuration: {}, install_groups: {:?}, vcs_info: {:?}", + metadata.build_configuration.unwrap_or("unknown"), + metadata.install_groups, + metadata.vcs_info, ); let chunk_upload_options = api.get_chunk_upload_options(org)?; @@ -641,9 +661,10 @@ fn upload_file( &ChunkedBuildRequest { checksum, chunks: &checksums, - build_configuration, - release_notes, - vcs_info, + build_configuration: metadata.build_configuration, + release_notes: metadata.release_notes, + install_groups: metadata.install_groups, + vcs_info: metadata.vcs_info, }, )?; chunks.retain(|Chunk((digest, _))| response.missing_chunks.contains(digest)); diff --git a/tests/integration/_cases/build/build-upload-help-macos.trycmd b/tests/integration/_cases/build/build-upload-help-macos.trycmd index d1a0a51c4e..a0e49748dc 100644 --- a/tests/integration/_cases/build/build-upload-help-macos.trycmd +++ b/tests/integration/_cases/build/build-upload-help-macos.trycmd @@ -74,6 +74,10 @@ Options: --release-notes The release notes to use for the upload. + --install-group + The install group(s) for this build. Can be specified multiple times. Builds with at + least one matching install group will be shown updates for each other. + --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 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 ab4df7233e..c1e0a67926 100644 --- a/tests/integration/_cases/build/build-upload-help-not-macos.trycmd +++ b/tests/integration/_cases/build/build-upload-help-not-macos.trycmd @@ -73,6 +73,10 @@ Options: --release-notes The release notes to use for the upload. + --install-group + The install group(s) for this build. Can be specified multiple times. Builds with at + least one matching install group will be shown updates for each other. + --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