Skip to content

Commit

Permalink
apple-codesign: survive network brownout
Browse files Browse the repository at this point in the history
Notarization performs a lot of polling requests.
Some may fail due to network problems.
Only the last request result is required for succefull notarization.
Therefore we can safely ignore non-fatal errors until timeout is exceded.

Fixes #169
  • Loading branch information
basilevs committed Dec 9, 2024
1 parent 2312b1e commit 46dfdba
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 15 deletions.
6 changes: 6 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"image": "mcr.microsoft.com/devcontainers/universal:2",
"features": {
"ghcr.io/devcontainers/features/rust:1": {}
}
}
64 changes: 49 additions & 15 deletions apple-codesign/src/notarization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use {
log::warn,
sha2::Digest,
std::{
error::Error,
fs::File,
io::{Read, Seek, SeekFrom, Write},
path::{Path, PathBuf},
Expand Down Expand Up @@ -381,27 +382,34 @@ impl Notarizer {
let start_time = std::time::Instant::now();

loop {
let status = self.get_submission(submission_id)?;

let elapsed = start_time.elapsed();

warn!(
"poll state after {}s: {:?}",
elapsed.as_secs(),
status.data.attributes.status
);

if status.data.attributes.status != notary_api::SubmissionResponseStatus::InProgress {
warn!("Notary API Server has finished processing the uploaded asset");

return Ok(status);
match self.get_submission(submission_id) {
Ok(status) => {
let elapsed = start_time.elapsed();

warn!(
"poll state after {}s: {:?}",
elapsed.as_secs(),
status.data.attributes.status
);

if status.data.attributes.status != notary_api::SubmissionResponseStatus::InProgress {
warn!("Notary API Server has finished processing the uploaded asset");

return Ok(status);
}
},
Err(e) => {
if !is_transient_error(&e) {
return Err(e)
}
}
}

let elapsed = start_time.elapsed();
if elapsed >= wait_limit {
warn!("reached wait limit after {}s", elapsed.as_secs());
return Err(AppleCodesignError::NotarizeWaitLimitReached);
}

std::thread::sleep(self.wait_poll_interval);
}
}
Expand Down Expand Up @@ -441,3 +449,29 @@ impl Notarizer {
Ok(self.client()?.list_submissions()?)
}
}

fn is_transient_error(root: &(dyn Error + 'static)) -> bool {
if let Some::<&reqwest::Error>(reqwest_error) = root.downcast_ref::<reqwest::Error>() {
if reqwest_error.is_timeout() {
warn(reqwest_error, 0);
return true;
}
if reqwest_error.is_connect() {
warn(reqwest_error, 0);
return true;
}
}

if let Some(source) = root.source() {
return is_transient_error(source)
}

return false
}

fn warn(error: &(dyn Error + 'static), indent: usize) {
warn!("{}{}", " ".repeat(indent), error);
if let Some(source) = error.source() {
warn(source, indent + 1);
}
}

0 comments on commit 46dfdba

Please sign in to comment.