sentry-cli 3.3.1__tar.gz → 3.3.3__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.1 → sentry_cli-3.3.3}/Cargo.lock +1 -1
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/Cargo.toml +1 -1
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/PKG-INFO +1 -1
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/sentry_cli.egg-info/PKG-INFO +1 -1
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/sentry_cli.egg-info/SOURCES.txt +1 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/data_types/snapshots.rs +5 -1
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/build/snapshots.rs +15 -1
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/build/upload.rs +2 -259
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/args.rs +67 -0
- sentry_cli-3.3.3/src/utils/build_vcs.rs +205 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/mod.rs +1 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/LICENSE +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/MANIFEST.in +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/README.md +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/AGENTS.md +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/CLAUDE.md +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/Cargo.toml +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/build.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/native/swift/AssetCatalogParser/Package.swift +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/AssetCatalogParser/AssetCatalogReader.swift +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/ObjcSupport/include/safeValueForKey.h +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/ObjcSupport/safeValueForKey.m +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/AssetCatalogParserTests.swift +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/Resources/test.xcarchive/Info.plist +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/Resources/test.xcarchive/Products/Applications/DemoApp.app/Assets.car +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/src/asset_catalog.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/apple-catalog-parsing/src/lib.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/build.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/pyproject.toml +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/sentry_cli.egg-info/dependency_links.txt +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/sentry_cli.egg-info/top_level.txt +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/setup.cfg +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/setup.py +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/AGENTS.md +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/CLAUDE.md +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/connection_manager.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/data_types/chunking/artifact.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/data_types/chunking/build.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/data_types/chunking/compression.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/data_types/chunking/dif.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/data_types/chunking/file_state.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/data_types/chunking/hash_algorithm.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/data_types/chunking/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/data_types/chunking/upload/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/data_types/chunking/upload/options.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/data_types/deploy.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/data_types/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/encoding.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/envelopes_api.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/errors/api_error.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/errors/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/errors/sentry_error.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/pagination.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/api/serialization.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/bashsupport.sh +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/bash_hook.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/build/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/dart_symbol_map/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/dart_symbol_map/upload.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/debug_files/bundle_jvm.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/debug_files/bundle_sources.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/debug_files/check.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/debug_files/find.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/debug_files/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/debug_files/print_sources.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/debug_files/upload.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/deploys/list.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/deploys/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/deploys/new.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/derive_parser.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/events/list.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/events/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/info.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/issues/list.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/issues/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/issues/mute.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/issues/resolve.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/issues/unresolve.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/login.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/logs/list.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/logs/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/monitors/list.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/monitors/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/monitors/run.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/organizations/list.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/organizations/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/proguard/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/proguard/upload.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/proguard/uuid.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/projects/list.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/projects/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/react_native/gradle.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/react_native/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/react_native/xcode.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/releases/archive.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/releases/delete.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/releases/finalize.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/releases/info.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/releases/list.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/releases/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/releases/new.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/releases/propose_version.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/releases/restore.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/releases/set_commits.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/repos/list.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/repos/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/send_envelope.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/send_event.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/send_metric/common_args.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/send_metric/increment.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/send_metric/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/send_metric/set.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/sourcemaps/inject.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/sourcemaps/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/sourcemaps/resolve.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/sourcemaps/upload.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/uninstall.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/update.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/upload_dif.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/upload_dsym.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/commands/upload_proguard.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/config.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/constants.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/main.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/android.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/auth_token/auth_token_impl.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/auth_token/error.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/auth_token/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/auth_token/org_auth_token.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/auth_token/redacting.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/auth_token/test.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/auth_token/user_auth_token.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/build/apple.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/build/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/build/normalize.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/build/validation.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/chunks/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/chunks/options.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/chunks/types.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/chunks/upload.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/ci.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/cordova.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/dif.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/dif_upload/error.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/dif_upload/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/event.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/file_search.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/file_upload.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/formatting.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/fs.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/http.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/logging.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/non_empty.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/progress.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/proguard/mapping.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/proguard/mod.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/proguard/upload.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/releases.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/retry.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_default_twenty.snap +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_ignore_missing.snap +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_base.snap +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_previous_commit.snap +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/snapshots/sentry_cli__utils__vcs__tests__get_commits_from_git.snap +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/source_bundle.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/sourcemaps/inject.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/sourcemaps.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/system.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/ui.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/update.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/value_parsers.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/vcs.rs +0 -0
- {sentry_cli-3.3.1 → sentry_cli-3.3.3}/src/utils/xcode.rs +0 -0
|
@@ -5,6 +5,8 @@ use std::collections::HashMap;
|
|
|
5
5
|
use serde::{Deserialize, Serialize};
|
|
6
6
|
use serde_json::Value;
|
|
7
7
|
|
|
8
|
+
use super::VcsInfo;
|
|
9
|
+
|
|
8
10
|
const IMAGE_FILE_NAME_FIELD: &str = "image_file_name";
|
|
9
11
|
const WIDTH_FIELD: &str = "width";
|
|
10
12
|
const HEIGHT_FIELD: &str = "height";
|
|
@@ -21,9 +23,11 @@ pub struct CreateSnapshotResponse {
|
|
|
21
23
|
// Keep in sync with https://github.com/getsentry/sentry/blob/master/src/sentry/preprod/snapshots/manifest.py
|
|
22
24
|
/// Manifest describing a set of snapshot images for an app.
|
|
23
25
|
#[derive(Debug, Serialize)]
|
|
24
|
-
pub struct SnapshotsManifest {
|
|
26
|
+
pub struct SnapshotsManifest<'a> {
|
|
25
27
|
pub app_id: String,
|
|
26
28
|
pub images: HashMap<String, ImageMetadata>,
|
|
29
|
+
#[serde(flatten)]
|
|
30
|
+
pub vcs_info: VcsInfo<'a>,
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
// Keep in sync with https://github.com/getsentry/sentry/blob/master/src/sentry/preprod/snapshots/manifest.py
|
|
@@ -3,6 +3,7 @@ use std::fs::File;
|
|
|
3
3
|
use std::io::BufReader;
|
|
4
4
|
use std::path::{Path, PathBuf};
|
|
5
5
|
use std::str::FromStr as _;
|
|
6
|
+
use std::time::Duration;
|
|
6
7
|
|
|
7
8
|
use anyhow::{Context as _, Result};
|
|
8
9
|
use clap::{Arg, ArgMatches, Command};
|
|
@@ -18,6 +19,8 @@ use walkdir::WalkDir;
|
|
|
18
19
|
use crate::api::{Api, CreateSnapshotResponse, ImageMetadata, SnapshotsManifest};
|
|
19
20
|
use crate::config::{Auth, Config};
|
|
20
21
|
use crate::utils::args::ArgExt as _;
|
|
22
|
+
use crate::utils::build_vcs::collect_git_metadata;
|
|
23
|
+
use crate::utils::ci::is_ci;
|
|
21
24
|
|
|
22
25
|
const EXPERIMENTAL_WARNING: &str =
|
|
23
26
|
"[EXPERIMENTAL] The \"build snapshots\" command is experimental. \
|
|
@@ -47,6 +50,7 @@ pub fn make_command(command: Command) -> Command {
|
|
|
47
50
|
.help("The application identifier.")
|
|
48
51
|
.required(true),
|
|
49
52
|
)
|
|
53
|
+
.git_metadata_args()
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
struct ImageInfo {
|
|
@@ -80,6 +84,13 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
|
80
84
|
anyhow::bail!("Path is not a directory: {}", dir_path.display());
|
|
81
85
|
}
|
|
82
86
|
|
|
87
|
+
// Collect git metadata if running in CI, unless explicitly enabled or disabled.
|
|
88
|
+
let should_collect_git_metadata =
|
|
89
|
+
matches.get_flag("force_git_metadata") || (!matches.get_flag("no_git_metadata") && is_ci());
|
|
90
|
+
|
|
91
|
+
// Always collect git metadata, but only perform automatic inference when enabled
|
|
92
|
+
let vcs_info = collect_git_metadata(matches, &config, should_collect_git_metadata);
|
|
93
|
+
|
|
83
94
|
debug!("Scanning for images in: {}", dir_path.display());
|
|
84
95
|
debug!("Organization: {org}");
|
|
85
96
|
debug!("Project: {project}");
|
|
@@ -114,6 +125,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
|
114
125
|
let manifest = SnapshotsManifest {
|
|
115
126
|
app_id: app_id.clone(),
|
|
116
127
|
images: manifest_entries,
|
|
128
|
+
vcs_info,
|
|
117
129
|
};
|
|
118
130
|
|
|
119
131
|
// POST manifest to API
|
|
@@ -290,6 +302,7 @@ fn upload_images(
|
|
|
290
302
|
};
|
|
291
303
|
auth
|
|
292
304
|
})
|
|
305
|
+
.configure_reqwest(|r| r.connect_timeout(Duration::from_secs(10)))
|
|
293
306
|
.build()?;
|
|
294
307
|
|
|
295
308
|
let mut scope = Usecase::new("preprod").scope();
|
|
@@ -374,7 +387,8 @@ fn upload_images(
|
|
|
374
387
|
eprintln!("There were errors uploading images:");
|
|
375
388
|
let mut error_count = 0;
|
|
376
389
|
for error in errors {
|
|
377
|
-
|
|
390
|
+
let error = anyhow::Error::new(error);
|
|
391
|
+
eprintln!(" {}", style(format!("{error:#}")).red());
|
|
378
392
|
error_count += 1;
|
|
379
393
|
}
|
|
380
394
|
anyhow::bail!("Failed to upload {error_count} out of {image_count} images")
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
use std::borrow::Cow;
|
|
2
1
|
use std::io::Write as _;
|
|
3
2
|
use std::path::Path;
|
|
4
3
|
use std::thread;
|
|
@@ -8,7 +7,6 @@ use anyhow::{anyhow, bail, Context as _, Result};
|
|
|
8
7
|
use clap::{Arg, ArgAction, ArgMatches, Command};
|
|
9
8
|
use indicatif::ProgressStyle;
|
|
10
9
|
use log::{debug, info, warn};
|
|
11
|
-
use sha1_smol::Digest;
|
|
12
10
|
use symbolic::common::ByteView;
|
|
13
11
|
use zip::write::SimpleFileOptions;
|
|
14
12
|
use zip::{DateTime, ZipWriter};
|
|
@@ -22,17 +20,13 @@ use crate::utils::build::{handle_asset_catalogs, ipa_to_xcarchive, is_apple_app,
|
|
|
22
20
|
use crate::utils::build::{
|
|
23
21
|
is_aab_file, is_apk_file, is_zip_file, normalize_directory, write_version_metadata,
|
|
24
22
|
};
|
|
23
|
+
use crate::utils::build_vcs::collect_git_metadata;
|
|
25
24
|
use crate::utils::chunks::{upload_chunks, Chunk, ASSEMBLE_POLL_INTERVAL};
|
|
26
25
|
use crate::utils::ci::is_ci;
|
|
27
26
|
use crate::utils::fs::get_sha1_checksums;
|
|
28
27
|
use crate::utils::fs::TempDir;
|
|
29
28
|
use crate::utils::fs::TempFile;
|
|
30
29
|
use crate::utils::progress::ProgressBar;
|
|
31
|
-
use crate::utils::vcs::{
|
|
32
|
-
self, get_github_base_ref, get_github_head_ref, get_github_pr_number, get_provider_from_remote,
|
|
33
|
-
get_repo_from_remote_preserve_case, git_repo_base_ref, git_repo_base_repo_name_preserve_case,
|
|
34
|
-
git_repo_head_ref, git_repo_remote_url,
|
|
35
|
-
};
|
|
36
30
|
|
|
37
31
|
pub fn make_command(command: Command) -> Command {
|
|
38
32
|
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
|
|
@@ -54,51 +48,7 @@ pub fn make_command(command: Command) -> Command {
|
|
|
54
48
|
.action(ArgAction::Append)
|
|
55
49
|
.required(true),
|
|
56
50
|
)
|
|
57
|
-
.
|
|
58
|
-
Arg::new("head_sha")
|
|
59
|
-
.long("head-sha")
|
|
60
|
-
.value_parser(parse_sha_allow_empty)
|
|
61
|
-
.help("The VCS commit sha to use for the upload. If not provided, the current commit sha will be used.")
|
|
62
|
-
)
|
|
63
|
-
.arg(
|
|
64
|
-
Arg::new("base_sha")
|
|
65
|
-
.long("base-sha")
|
|
66
|
-
.value_parser(parse_sha_allow_empty)
|
|
67
|
-
.help("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.")
|
|
68
|
-
)
|
|
69
|
-
.arg(
|
|
70
|
-
Arg::new("vcs_provider")
|
|
71
|
-
.long("vcs-provider")
|
|
72
|
-
.help("The VCS provider to use for the upload. If not provided, the current provider will be used.")
|
|
73
|
-
)
|
|
74
|
-
.arg(
|
|
75
|
-
Arg::new("head_repo_name")
|
|
76
|
-
.long("head-repo-name")
|
|
77
|
-
.help("The name of the git repository to use for the upload (e.g. organization/repository). If not provided, the current repository will be used.")
|
|
78
|
-
)
|
|
79
|
-
.arg(
|
|
80
|
-
Arg::new("base_repo_name")
|
|
81
|
-
.long("base-repo-name")
|
|
82
|
-
.help("The name of the git repository to use for the upload (e.g. organization/repository). If not provided, the current repository will be used.")
|
|
83
|
-
)
|
|
84
|
-
.arg(
|
|
85
|
-
Arg::new("head_ref")
|
|
86
|
-
.long("head-ref")
|
|
87
|
-
.help("The reference (branch) to use for the upload. If not provided, the current reference will be used.")
|
|
88
|
-
)
|
|
89
|
-
.arg(
|
|
90
|
-
Arg::new("base_ref")
|
|
91
|
-
.long("base-ref")
|
|
92
|
-
.help("The base reference (branch) to use for the upload. If not provided, the merge-base with the remote tracking branch will be used.")
|
|
93
|
-
)
|
|
94
|
-
.arg(
|
|
95
|
-
Arg::new("pr_number")
|
|
96
|
-
.long("pr-number")
|
|
97
|
-
.value_parser(clap::value_parser!(u32))
|
|
98
|
-
.help("The pull request number to use for the upload. If not provided and running \
|
|
99
|
-
in a pull_request-triggered GitHub Actions workflow, the PR number will be automatically \
|
|
100
|
-
detected from GitHub Actions environment variables.")
|
|
101
|
-
)
|
|
51
|
+
.git_metadata_args()
|
|
102
52
|
.arg(
|
|
103
53
|
Arg::new("build_configuration")
|
|
104
54
|
.long("build-configuration")
|
|
@@ -119,22 +69,6 @@ pub fn make_command(command: Command) -> Command {
|
|
|
119
69
|
for each other.",
|
|
120
70
|
)
|
|
121
71
|
)
|
|
122
|
-
.arg(
|
|
123
|
-
Arg::new("force_git_metadata")
|
|
124
|
-
.long("force-git-metadata")
|
|
125
|
-
.action(ArgAction::SetTrue)
|
|
126
|
-
.conflicts_with("no_git_metadata")
|
|
127
|
-
.help("Force collection and sending of git metadata (branch, commit, etc.). \
|
|
128
|
-
If neither this nor --no-git-metadata is specified, git metadata is \
|
|
129
|
-
automatically collected when running in most CI environments.")
|
|
130
|
-
)
|
|
131
|
-
.arg(
|
|
132
|
-
Arg::new("no_git_metadata")
|
|
133
|
-
.long("no-git-metadata")
|
|
134
|
-
.action(ArgAction::SetTrue)
|
|
135
|
-
.conflicts_with("force_git_metadata")
|
|
136
|
-
.help("Disable collection and sending of git metadata.")
|
|
137
|
-
)
|
|
138
72
|
}
|
|
139
73
|
|
|
140
74
|
/// Parse plugin info from SENTRY_PIPELINE environment variable.
|
|
@@ -309,181 +243,6 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
|
309
243
|
Ok(())
|
|
310
244
|
}
|
|
311
245
|
|
|
312
|
-
/// Collects git metadata from arguments and VCS introspection.
|
|
313
|
-
///
|
|
314
|
-
/// When `auto_collect` is false, only explicitly provided values are collected;
|
|
315
|
-
/// automatic inference from git repository and CI environment is skipped.
|
|
316
|
-
fn collect_git_metadata(
|
|
317
|
-
matches: &ArgMatches,
|
|
318
|
-
config: &Config,
|
|
319
|
-
auto_collect: bool,
|
|
320
|
-
) -> VcsInfo<'static> {
|
|
321
|
-
let head_sha = matches
|
|
322
|
-
.get_one::<Option<Digest>>("head_sha")
|
|
323
|
-
.map(|d| d.as_ref().cloned())
|
|
324
|
-
.or_else(|| auto_collect.then(|| vcs::find_head_sha().ok()))
|
|
325
|
-
.flatten();
|
|
326
|
-
|
|
327
|
-
let cached_remote = config.get_cached_vcs_remote();
|
|
328
|
-
let (vcs_provider, head_repo_name, head_ref, base_ref, base_repo_name) = {
|
|
329
|
-
let repo = if auto_collect {
|
|
330
|
-
git2::Repository::open_from_env().ok()
|
|
331
|
-
} else {
|
|
332
|
-
None
|
|
333
|
-
};
|
|
334
|
-
let repo_ref = repo.as_ref();
|
|
335
|
-
let remote_url = repo_ref.and_then(|repo| git_repo_remote_url(repo, &cached_remote).ok());
|
|
336
|
-
|
|
337
|
-
let vcs_provider = matches
|
|
338
|
-
.get_one("vcs_provider")
|
|
339
|
-
.cloned()
|
|
340
|
-
.or_else(|| {
|
|
341
|
-
auto_collect
|
|
342
|
-
.then(|| remote_url.as_ref().map(|url| get_provider_from_remote(url)))?
|
|
343
|
-
})
|
|
344
|
-
.unwrap_or_default();
|
|
345
|
-
|
|
346
|
-
let head_repo_name = matches
|
|
347
|
-
.get_one("head_repo_name")
|
|
348
|
-
.cloned()
|
|
349
|
-
.or_else(|| {
|
|
350
|
-
auto_collect.then(|| {
|
|
351
|
-
remote_url
|
|
352
|
-
.as_ref()
|
|
353
|
-
.map(|url| get_repo_from_remote_preserve_case(url))
|
|
354
|
-
})?
|
|
355
|
-
})
|
|
356
|
-
.unwrap_or_default();
|
|
357
|
-
|
|
358
|
-
let head_ref = matches
|
|
359
|
-
.get_one("head_ref")
|
|
360
|
-
.cloned()
|
|
361
|
-
.or_else(|| auto_collect.then(get_github_head_ref)?)
|
|
362
|
-
.or_else(|| {
|
|
363
|
-
auto_collect.then(|| {
|
|
364
|
-
repo_ref.and_then(|r| match git_repo_head_ref(r) {
|
|
365
|
-
Ok(ref_name) => {
|
|
366
|
-
debug!("Found current branch reference: {ref_name}");
|
|
367
|
-
Some(ref_name)
|
|
368
|
-
}
|
|
369
|
-
Err(e) => {
|
|
370
|
-
debug!("No valid branch reference found (likely detached HEAD): {e}");
|
|
371
|
-
None
|
|
372
|
-
}
|
|
373
|
-
})
|
|
374
|
-
})?
|
|
375
|
-
})
|
|
376
|
-
.unwrap_or_default();
|
|
377
|
-
|
|
378
|
-
let base_ref = matches
|
|
379
|
-
.get_one("base_ref")
|
|
380
|
-
.cloned()
|
|
381
|
-
.or_else(|| auto_collect.then(get_github_base_ref)?)
|
|
382
|
-
.or_else(|| {
|
|
383
|
-
auto_collect.then(|| {
|
|
384
|
-
repo_ref.and_then(|r| match git_repo_base_ref(r, &cached_remote) {
|
|
385
|
-
Ok(base_ref_name) => {
|
|
386
|
-
debug!("Found base reference: {base_ref_name}");
|
|
387
|
-
Some(base_ref_name)
|
|
388
|
-
}
|
|
389
|
-
Err(e) => {
|
|
390
|
-
info!("Could not detect base branch reference: {e}");
|
|
391
|
-
None
|
|
392
|
-
}
|
|
393
|
-
})
|
|
394
|
-
})?
|
|
395
|
-
})
|
|
396
|
-
.unwrap_or_default();
|
|
397
|
-
|
|
398
|
-
let base_repo_name = matches
|
|
399
|
-
.get_one("base_repo_name")
|
|
400
|
-
.cloned()
|
|
401
|
-
.or_else(|| {
|
|
402
|
-
auto_collect.then(|| {
|
|
403
|
-
repo_ref.and_then(|r| match git_repo_base_repo_name_preserve_case(r) {
|
|
404
|
-
Ok(Some(base_repo_name)) => {
|
|
405
|
-
debug!("Found base repository name: {base_repo_name}");
|
|
406
|
-
Some(base_repo_name)
|
|
407
|
-
}
|
|
408
|
-
Ok(None) => {
|
|
409
|
-
debug!("No base repository found - not a fork");
|
|
410
|
-
None
|
|
411
|
-
}
|
|
412
|
-
Err(e) => {
|
|
413
|
-
warn!("Could not detect base repository name: {e}");
|
|
414
|
-
None
|
|
415
|
-
}
|
|
416
|
-
})
|
|
417
|
-
})?
|
|
418
|
-
})
|
|
419
|
-
.unwrap_or_default();
|
|
420
|
-
|
|
421
|
-
(
|
|
422
|
-
vcs_provider,
|
|
423
|
-
head_repo_name,
|
|
424
|
-
head_ref,
|
|
425
|
-
base_ref,
|
|
426
|
-
base_repo_name,
|
|
427
|
-
)
|
|
428
|
-
};
|
|
429
|
-
|
|
430
|
-
let base_sha_from_user = matches.get_one::<Option<Digest>>("base_sha").is_some();
|
|
431
|
-
let base_ref_from_user = matches.get_one::<String>("base_ref").is_some();
|
|
432
|
-
|
|
433
|
-
let mut base_sha = matches
|
|
434
|
-
.get_one::<Option<Digest>>("base_sha")
|
|
435
|
-
.map(|d| d.as_ref().cloned())
|
|
436
|
-
.or_else(|| {
|
|
437
|
-
if auto_collect {
|
|
438
|
-
Some(
|
|
439
|
-
vcs::find_base_sha(&cached_remote)
|
|
440
|
-
.inspect_err(|e| debug!("Error finding base SHA: {e}"))
|
|
441
|
-
.ok()
|
|
442
|
-
.flatten(),
|
|
443
|
-
)
|
|
444
|
-
} else {
|
|
445
|
-
None
|
|
446
|
-
}
|
|
447
|
-
})
|
|
448
|
-
.flatten();
|
|
449
|
-
|
|
450
|
-
let mut base_ref = base_ref;
|
|
451
|
-
|
|
452
|
-
// If base_sha equals head_sha and both were auto-inferred, skip setting base_sha and base_ref
|
|
453
|
-
if !base_sha_from_user
|
|
454
|
-
&& !base_ref_from_user
|
|
455
|
-
&& base_sha.is_some()
|
|
456
|
-
&& head_sha.is_some()
|
|
457
|
-
&& base_sha == head_sha
|
|
458
|
-
{
|
|
459
|
-
debug!(
|
|
460
|
-
"Base SHA equals head SHA ({}), and both were auto-inferred. Skipping base_sha and base_ref, but keeping head_sha.",
|
|
461
|
-
base_sha.expect("base_sha is Some at this point")
|
|
462
|
-
);
|
|
463
|
-
base_sha = None;
|
|
464
|
-
base_ref = "".into();
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
let pr_number = matches.get_one("pr_number").copied().or_else(|| {
|
|
468
|
-
if auto_collect {
|
|
469
|
-
get_github_pr_number()
|
|
470
|
-
} else {
|
|
471
|
-
None
|
|
472
|
-
}
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
VcsInfo {
|
|
476
|
-
head_sha,
|
|
477
|
-
base_sha,
|
|
478
|
-
vcs_provider: Cow::Owned(vcs_provider),
|
|
479
|
-
head_repo_name: Cow::Owned(head_repo_name),
|
|
480
|
-
base_repo_name: Cow::Owned(base_repo_name),
|
|
481
|
-
head_ref: Cow::Owned(head_ref),
|
|
482
|
-
base_ref: Cow::Owned(base_ref),
|
|
483
|
-
pr_number,
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
|
|
487
246
|
fn handle_file(
|
|
488
247
|
path: &Path,
|
|
489
248
|
byteview: &ByteView,
|
|
@@ -709,22 +468,6 @@ fn upload_file(
|
|
|
709
468
|
}
|
|
710
469
|
}
|
|
711
470
|
|
|
712
|
-
/// Utility function to parse a SHA1 digest, allowing empty strings.
|
|
713
|
-
///
|
|
714
|
-
/// Empty strings result in Ok(None), otherwise we return the parsed digest
|
|
715
|
-
/// or an error if the SHA is invalid.
|
|
716
|
-
fn parse_sha_allow_empty(sha: &str) -> Result<Option<Digest>> {
|
|
717
|
-
if sha.is_empty() {
|
|
718
|
-
return Ok(None);
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
let digest = sha
|
|
722
|
-
.parse()
|
|
723
|
-
.with_context(|| format!("{sha} is not a valid SHA1 digest"))?;
|
|
724
|
-
|
|
725
|
-
Ok(Some(digest))
|
|
726
|
-
}
|
|
727
|
-
|
|
728
471
|
#[cfg(not(windows))]
|
|
729
472
|
#[cfg(test)]
|
|
730
473
|
mod tests {
|
|
@@ -86,6 +86,7 @@ pub trait ArgExt: Sized {
|
|
|
86
86
|
fn project_arg(self, multiple: bool) -> Self;
|
|
87
87
|
fn release_arg(self) -> Self;
|
|
88
88
|
fn version_arg(self, global: bool) -> Self;
|
|
89
|
+
fn git_metadata_args(self) -> Self;
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
impl ArgExt for Command {
|
|
@@ -142,4 +143,70 @@ impl ArgExt for Command {
|
|
|
142
143
|
.help("The version of the release"),
|
|
143
144
|
)
|
|
144
145
|
}
|
|
146
|
+
|
|
147
|
+
fn git_metadata_args(self) -> Command {
|
|
148
|
+
use crate::utils::build_vcs::parse_sha_allow_empty;
|
|
149
|
+
|
|
150
|
+
self.arg(
|
|
151
|
+
Arg::new("head_sha")
|
|
152
|
+
.long("head-sha")
|
|
153
|
+
.value_parser(parse_sha_allow_empty)
|
|
154
|
+
.help("The VCS commit sha to use for the upload. If not provided, the current commit sha will be used.")
|
|
155
|
+
)
|
|
156
|
+
.arg(
|
|
157
|
+
Arg::new("base_sha")
|
|
158
|
+
.long("base-sha")
|
|
159
|
+
.value_parser(parse_sha_allow_empty)
|
|
160
|
+
.help("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.")
|
|
161
|
+
)
|
|
162
|
+
.arg(
|
|
163
|
+
Arg::new("vcs_provider")
|
|
164
|
+
.long("vcs-provider")
|
|
165
|
+
.help("The VCS provider to use for the upload. If not provided, the current provider will be used.")
|
|
166
|
+
)
|
|
167
|
+
.arg(
|
|
168
|
+
Arg::new("head_repo_name")
|
|
169
|
+
.long("head-repo-name")
|
|
170
|
+
.help("The name of the git repository to use for the upload (e.g. organization/repository). If not provided, the current repository will be used.")
|
|
171
|
+
)
|
|
172
|
+
.arg(
|
|
173
|
+
Arg::new("base_repo_name")
|
|
174
|
+
.long("base-repo-name")
|
|
175
|
+
.help("The name of the git repository to use for the upload (e.g. organization/repository). If not provided, the current repository will be used.")
|
|
176
|
+
)
|
|
177
|
+
.arg(
|
|
178
|
+
Arg::new("head_ref")
|
|
179
|
+
.long("head-ref")
|
|
180
|
+
.help("The reference (branch) to use for the upload. If not provided, the current reference will be used.")
|
|
181
|
+
)
|
|
182
|
+
.arg(
|
|
183
|
+
Arg::new("base_ref")
|
|
184
|
+
.long("base-ref")
|
|
185
|
+
.help("The base reference (branch) to use for the upload. If not provided, the merge-base with the remote tracking branch will be used.")
|
|
186
|
+
)
|
|
187
|
+
.arg(
|
|
188
|
+
Arg::new("pr_number")
|
|
189
|
+
.long("pr-number")
|
|
190
|
+
.value_parser(clap::value_parser!(u32))
|
|
191
|
+
.help("The pull request number to use for the upload. If not provided and running \
|
|
192
|
+
in a pull_request-triggered GitHub Actions workflow, the PR number will be automatically \
|
|
193
|
+
detected from GitHub Actions environment variables.")
|
|
194
|
+
)
|
|
195
|
+
.arg(
|
|
196
|
+
Arg::new("force_git_metadata")
|
|
197
|
+
.long("force-git-metadata")
|
|
198
|
+
.action(ArgAction::SetTrue)
|
|
199
|
+
.conflicts_with("no_git_metadata")
|
|
200
|
+
.help("Force collection and sending of git metadata (branch, commit, etc.). \
|
|
201
|
+
If neither this nor --no-git-metadata is specified, git metadata is \
|
|
202
|
+
automatically collected when running in most CI environments.")
|
|
203
|
+
)
|
|
204
|
+
.arg(
|
|
205
|
+
Arg::new("no_git_metadata")
|
|
206
|
+
.long("no-git-metadata")
|
|
207
|
+
.action(ArgAction::SetTrue)
|
|
208
|
+
.conflicts_with("force_git_metadata")
|
|
209
|
+
.help("Disable collection and sending of git metadata.")
|
|
210
|
+
)
|
|
211
|
+
}
|
|
145
212
|
}
|