Skip to content

Commit

Permalink
feat(api): Direct releases/{}/files POST request to region (#2002)
Browse files Browse the repository at this point in the history
Extends #1997 to releases files endpoint.

ref #1990
  • Loading branch information
szokeasaurusrex committed Mar 27, 2024
1 parent 489fba3 commit 0ae13ab
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 97 deletions.
141 changes: 70 additions & 71 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -904,77 +904,6 @@ impl<'a> AuthenticatedApi<'a> {
self.delete(&path)?.into_result().map(|_| ())
}

/// Uploads a new release file. The file is loaded directly from the file
/// system and uploaded as `name`.
pub fn upload_release_file(
&self,
context: &UploadContext,
contents: &[u8],
name: &str,
headers: Option<&[(String, String)]>,
progress_bar_mode: ProgressBarMode,
) -> ApiResult<Option<Artifact>> {
let release = context
.release()
.map_err(|err| ApiError::with_source(ApiErrorKind::ReleaseNotFound, err))?;

let path = if let Some(project) = context.project {
format!(
"/projects/{}/{}/releases/{}/files/",
PathArg(context.org),
PathArg(project),
PathArg(release)
)
} else {
format!(
"/organizations/{}/releases/{}/files/",
PathArg(context.org),
PathArg(release)
)
};
let mut form = curl::easy::Form::new();

let filename = Path::new(name)
.file_name()
.and_then(OsStr::to_str)
.unwrap_or("unknown.bin");
form.part("file")
.buffer(filename, contents.to_vec())
.add()?;
form.part("name").contents(name.as_bytes()).add()?;
if let Some(dist) = context.dist {
form.part("dist").contents(dist.as_bytes()).add()?;
}

if let Some(headers) = headers {
for (key, value) in headers {
form.part("header")
.contents(format!("{key}:{value}").as_bytes())
.add()?;
}
}

let resp = self
.api
.request(Method::Post, &path, None)?
.with_form_data(form)?
.with_retry(
self.api.config.get_max_retry_count().unwrap(),
&[
http::HTTP_STATUS_502_BAD_GATEWAY,
http::HTTP_STATUS_503_SERVICE_UNAVAILABLE,
http::HTTP_STATUS_504_GATEWAY_TIMEOUT,
],
)?
.progress_bar_mode(progress_bar_mode)?
.send()?;
if resp.status() == 409 {
Ok(None)
} else {
resp.convert_rnf(ApiErrorKind::ReleaseNotFound)
}
}

/// Creates a new release.
pub fn new_release(&self, org: &str, release: &NewRelease) -> ApiResult<ReleaseInfo> {
// for single project releases use the legacy endpoint that is project bound.
Expand Down Expand Up @@ -1743,6 +1672,76 @@ impl<'a> RegionSpecificApi<'a> {
.send()?
.convert()
}

/// Uploads a new release file. The file is loaded directly from the file
/// system and uploaded as `name`.
pub fn upload_release_file(
&self,
context: &UploadContext,
contents: &[u8],
name: &str,
headers: Option<&[(String, String)]>,
progress_bar_mode: ProgressBarMode,
) -> ApiResult<Option<Artifact>> {
let release = context
.release()
.map_err(|err| ApiError::with_source(ApiErrorKind::ReleaseNotFound, err))?;

let path = if let Some(project) = context.project {
format!(
"/projects/{}/{}/releases/{}/files/",
PathArg(context.org),
PathArg(project),
PathArg(release)
)
} else {
format!(
"/organizations/{}/releases/{}/files/",
PathArg(context.org),
PathArg(release)
)
};
let mut form = curl::easy::Form::new();

let filename = Path::new(name)
.file_name()
.and_then(OsStr::to_str)
.unwrap_or("unknown.bin");
form.part("file")
.buffer(filename, contents.to_vec())
.add()?;
form.part("name").contents(name.as_bytes()).add()?;
if let Some(dist) = context.dist {
form.part("dist").contents(dist.as_bytes()).add()?;
}

if let Some(headers) = headers {
for (key, value) in headers {
form.part("header")
.contents(format!("{key}:{value}").as_bytes())
.add()?;
}
}

let resp = self
.request(Method::Post, &path)?
.with_form_data(form)?
.with_retry(
self.api.api.config.get_max_retry_count().unwrap(),
&[
http::HTTP_STATUS_502_BAD_GATEWAY,
http::HTTP_STATUS_503_SERVICE_UNAVAILABLE,
http::HTTP_STATUS_504_GATEWAY_TIMEOUT,
],
)?
.progress_bar_mode(progress_bar_mode)?
.send()?;
if resp.status() == 409 {
Ok(None)
} else {
resp.convert_rnf(ApiErrorKind::ReleaseNotFound)
}
}
}

fn send_req<W: Write>(
Expand Down
29 changes: 16 additions & 13 deletions src/commands/files/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,19 +239,22 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
});
}

if let Some(artifact) = authenticated_api.upload_release_file(
context,
&contents,
name,
Some(
headers
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect::<Vec<_>>()
.as_slice(),
),
ProgressBarMode::Request,
)? {
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!");
Expand Down
28 changes: 15 additions & 13 deletions src/utils/file_upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,19 +282,21 @@ fn upload_files_parallel(
.ok();
}

authenticated_api.upload_release_file(
context,
&file.contents,
&file.url,
Some(
file.headers
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect::<Vec<_>>()
.as_slice(),
),
mode,
)?;
authenticated_api
.region_specific(context.org)
.upload_release_file(
context,
&file.contents,
&file.url,
Some(
file.headers
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect::<Vec<_>>()
.as_slice(),
),
mode,
)?;

Ok(())
})
Expand Down

0 comments on commit 0ae13ab

Please sign in to comment.