Skip to content

DON'T MERGE: Proof we don't test sentry-cli files upload #2495

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
162 changes: 3 additions & 159 deletions src/commands/files/upload.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
use std::collections::BTreeMap;
use std::ffi::OsStr;
use std::fs;
use std::io::Read;
use std::path::Path;
use std::sync::Arc;
use std::time::Duration;

use anyhow::{bail, format_err, Result};
use anyhow::Result;
use clap::{Arg, ArgAction, ArgMatches, Command};
use log::warn;
use symbolic::debuginfo::sourcebundle::SourceFileType;

use crate::api::Api;
use crate::config::Config;
use crate::constants::DEFAULT_MAX_WAIT;
use crate::utils::args::validate_distribution;
use crate::utils::file_search::ReleaseFileSearch;
use crate::utils::file_upload::{
initialize_legacy_release_upload, FileUpload, SourceFile, UploadContext,
};
use crate::utils::fs::{decompress_gzip_content, is_gzip_compressed, path_as_url};
use crate::utils::progress::ProgressBarMode;

pub fn make_command(command: Command) -> Command {
command
Expand Down Expand Up @@ -123,144 +105,6 @@ pub fn make_command(command: Command) -> Command {
)
}

pub fn execute(matches: &ArgMatches) -> Result<()> {
let config = Config::current();
let release = config.get_release_with_legacy_fallback(matches)?;
let org = config.get_org(matches)?;
let project = config.get_project(matches).ok();
let api = Api::current();
let authenticated_api = api.authenticated()?;
let chunk_upload_options = authenticated_api.get_chunk_upload_options(&org)?;

let dist = matches.get_one::<String>("dist").map(String::as_str);
let mut headers = BTreeMap::new();
if let Some(header_list) = matches.get_many::<String>("file-headers") {
for header in header_list {
if !header.contains(':') {
bail!("Invalid header. Needs to be in key:value format");
}
let (key, value) = header.split_once(':').unwrap();
headers.insert(key.trim().to_string(), value.trim().to_string());
}
};

let wait_for_secs = matches.get_one::<u64>("wait_for").copied();
let wait = matches.get_flag("wait") || wait_for_secs.is_some();
let max_wait = wait_for_secs.map_or(DEFAULT_MAX_WAIT, Duration::from_secs);

let context = &UploadContext {
org: &org,
project: project.as_deref(),
release: Some(&release),
dist,
note: None,
wait,
max_wait,
dedupe: false,
chunk_upload_options: chunk_upload_options.as_ref(),
};

let path = Path::new(matches.get_one::<String>("path").unwrap());
// Batch files upload
if path.is_dir() {
let ignore_file = matches
.get_one::<String>("ignore_file")
.map(String::as_str)
.unwrap_or_default();
let ignores: Vec<_> = matches
.get_many::<String>("ignore")
.map(|ignores| ignores.map(|i| format!("!{i}")).collect())
.unwrap_or_default();
let extensions: Vec<_> = matches
.get_many::<String>("extensions")
.map(|extensions| extensions.map(|ext| ext.trim_start_matches('.')).collect())
.unwrap_or_default();

let sources = ReleaseFileSearch::new(path.to_path_buf())
.ignore_file(ignore_file)
.ignores(ignores)
.extensions(extensions)
.decompress(matches.get_flag("decompress"))
.collect_files()?;

let url_suffix = matches
.get_one::<String>("url_suffix")
.map(String::as_str)
.unwrap_or_default();
let mut url_prefix = matches
.get_one::<String>("url_prefix")
.map(String::as_str)
.unwrap_or("~");
// remove a single slash from the end. so ~/ becomes ~ and app:/// becomes app://
if url_prefix.ends_with('/') {
url_prefix = &url_prefix[..url_prefix.len() - 1];
}
let files = sources
.iter()
.map(|source| {
let local_path = source.path.strip_prefix(&source.base_path).unwrap();
let url = format!("{}/{}{}", url_prefix, path_as_url(local_path), url_suffix);

(
url.to_string(),
SourceFile {
url,
path: source.path.clone(),
contents: Arc::new(source.contents.clone()),
ty: SourceFileType::Source,
headers: headers.clone(),
messages: vec![],
already_uploaded: false,
},
)
})
.collect();

FileUpload::new(context).files(&files).upload()
}
// Single file upload
else {
initialize_legacy_release_upload(context)?;

let name = match matches.get_one::<String>("name") {
Some(name) => name,
None => Path::new(path)
.file_name()
.and_then(OsStr::to_str)
.ok_or_else(|| format_err!("No filename provided."))?,
};

let mut f = fs::File::open(path)?;
let mut contents = Vec::new();
f.read_to_end(&mut contents)?;

if matches.get_flag("decompress") && is_gzip_compressed(&contents) {
contents = decompress_gzip_content(&contents).unwrap_or_else(|_| {
warn!("Could not decompress: {}", name);
contents
});
}

if let Some(artifact) = authenticated_api
.region_specific(context.org)
.upload_release_file(
context,
&contents,
name,
Some(
headers
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect::<Vec<_>>()
.as_slice(),
),
ProgressBarMode::Request,
)?
{
println!("A {} ({} bytes)", artifact.sha1, artifact.size);
} else {
bail!("File already present!");
}
Ok(())
}
pub fn execute(_matches: &ArgMatches) -> Result<()> {
unimplemented!("CI should not pass with this change.");
}