Skip to content
133 changes: 88 additions & 45 deletions api/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::fmt;
use std::path::Path;
use std::sync::mpsc::Sender;

Expand All @@ -11,6 +12,38 @@ use tokio::fs;
use crate::call_api::CallApi;
use crate::message;

#[derive(Debug)]
pub enum ApiErrorEndpoint {
CreateBundleUpload,
GetQuarantiningConfig,
PutBundleToS3,
TelemetryUploadMetrics,
}

impl ApiErrorEndpoint {
pub fn unknown_error_reason(&self) -> String {
match self {
Self::CreateBundleUpload => "unknown_create_bundle_upload".into(),
Self::GetQuarantiningConfig => "unknown_get_quarantining_config".into(),
Self::PutBundleToS3 => "unknown_put_bundle_to_s3".into(),
Self::TelemetryUploadMetrics => "unknown_telemetry_upload_metrics".into(),
}
}
}

impl fmt::Display for ApiErrorEndpoint {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::CreateBundleUpload => write!(f, "Error in create bundle upload endpoint"),
Self::GetQuarantiningConfig => write!(f, "Error in get quarantine config endpoint"),
Self::PutBundleToS3 => write!(f, "Error in put bundle to s3 endpoint"),
Self::TelemetryUploadMetrics => write!(f, "Error in telemetry upload metrics endpoint"),
}
}
}

impl std::error::Error for ApiErrorEndpoint {}

pub struct ApiClient {
pub api_host: String,
pub telemetry_host: String,
Expand Down Expand Up @@ -150,6 +183,7 @@ impl ApiClient {
}
.call_api()
.await
.map_err(|e| e.context(ApiErrorEndpoint::CreateBundleUpload))
}

pub async fn get_quarantining_config(
Expand Down Expand Up @@ -192,6 +226,7 @@ impl ApiClient {
}
.call_api()
.await
.map_err(|e| e.context(ApiErrorEndpoint::GetQuarantiningConfig))
}

pub async fn put_bundle_to_s3<U: AsRef<str>, B: AsRef<Path>>(
Expand Down Expand Up @@ -231,6 +266,7 @@ impl ApiClient {
}
.call_api()
.await
.map_err(|e| e.context(ApiErrorEndpoint::PutBundleToS3))
}

pub async fn telemetry_upload_metrics(
Expand Down Expand Up @@ -285,6 +321,7 @@ impl ApiClient {
}
.call_api()
.await
.map_err(|e| e.context(ApiErrorEndpoint::TelemetryUploadMetrics))
}

async fn deserialize_response<MessageType: DeserializeOwned>(
Expand Down Expand Up @@ -453,21 +490,23 @@ mod tests {
api_client.api_host.clone_from(&state.host);

assert!(
api_client
.get_quarantining_config(&message::GetQuarantineConfigRequest {
repo: context::repo::RepoUrlParts {
host: String::from("host"),
owner: String::from("owner"),
name: String::from("name"),
},
org_url_slug: String::from("org_url_slug"),
test_identifiers: vec![],
remote_urls: vec![],
})
.await
.unwrap_err()
.to_string()
.contains("501 Not Implemented")
format!(
"{:?}",
api_client
.get_quarantining_config(&message::GetQuarantineConfigRequest {
repo: context::repo::RepoUrlParts {
host: String::from("host"),
owner: String::from("owner"),
name: String::from("name"),
},
org_url_slug: String::from("org_url_slug"),
test_identifiers: vec![],
remote_urls: vec![],
})
.await
.unwrap_err()
)
.contains("501 Not Implemented")
);
assert_eq!(CALL_COUNT.load(Ordering::Relaxed), 1);
}
Expand Down Expand Up @@ -499,21 +538,23 @@ mod tests {
api_client.api_host.clone_from(&state.host);

assert!(
api_client
.get_quarantining_config(&message::GetQuarantineConfigRequest {
repo: context::repo::RepoUrlParts {
host: String::from("api_host"),
owner: String::from("owner"),
name: String::from("name"),
},
remote_urls: vec![],
org_url_slug: String::from("org_url_slug"),
test_identifiers: vec![],
})
.await
.unwrap_err()
.to_string()
.contains("500 Internal Server Error")
format!(
"{:?}",
api_client
.get_quarantining_config(&message::GetQuarantineConfigRequest {
repo: context::repo::RepoUrlParts {
host: String::from("api_host"),
owner: String::from("owner"),
name: String::from("name"),
},
remote_urls: vec![],
org_url_slug: String::from("org_url_slug"),
test_identifiers: vec![],
})
.await
.unwrap_err()
)
.contains("500 Internal Server Error")
);
assert_eq!(CALL_COUNT.load(Ordering::Relaxed), 6);
}
Expand All @@ -540,21 +581,23 @@ mod tests {
api_client.api_host.clone_from(&state.host);

assert!(
api_client
.get_quarantining_config(&message::GetQuarantineConfigRequest {
repo: context::repo::RepoUrlParts {
host: String::from("api_host"),
owner: String::from("owner"),
name: String::from("name"),
},
remote_urls: vec![],
org_url_slug: String::from("org_url_slug"),
test_identifiers: vec![],
})
.await
.unwrap_err()
.to_string()
.contains("404 Not Found")
format!(
"{:?}",
api_client
.get_quarantining_config(&message::GetQuarantineConfigRequest {
repo: context::repo::RepoUrlParts {
host: String::from("api_host"),
owner: String::from("owner"),
name: String::from("name"),
},
remote_urls: vec![],
org_url_slug: String::from("org_url_slug"),
test_identifiers: vec![],
})
.await
.unwrap_err()
)
.contains("404 Not Found")
);
}
}
8 changes: 7 additions & 1 deletion cli/src/upload_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::path::PathBuf;
use std::sync::mpsc::Sender;

use api::client::ApiClient;
use api::client::{ApiClient, ApiErrorEndpoint};
use api::{client::get_api_host, urls::url_for_test_case};
use bundle::{BundleMeta, BundlerUtil, Test, unzip_tarball};
use clap::{ArgAction, Args};
Expand Down Expand Up @@ -296,6 +296,12 @@
return status.to_string().replace(' ', "_").to_lowercase();
}
}

for cause in error.chain() {
if let Some(endpoint_context) = cause.downcast_ref::<ApiErrorEndpoint>() {
return endpoint_context.unknown_error_reason();
}
}
"unknown".into()
}

Expand Down Expand Up @@ -448,7 +454,7 @@
.quarantine_results
.clone();

// trunk-ignore(clippy/assigning_clones)

Check notice on line 457 in cli/src/upload_command.rs

View workflow job for this annotation

GitHub Actions / Trunk Check

trunk(ignore-does-nothing)

[new] trunk-ignore(clippy/assigning_clones) is not suppressing a lint issue
meta.failed_tests = quarantine_context.failures.clone();

let upload_started_at = chrono::Utc::now();
Expand Down
14 changes: 12 additions & 2 deletions context/src/env/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,9 @@ impl<'a> CIInfoParser<'a> {
CIPlatform::GitLabCI => self.parse_gitlab_ci(),
CIPlatform::Drone => self.parse_drone(),
CIPlatform::BitbucketPipelines => self.parse_bitbucket_pipelines(),
CIPlatform::CircleCI => self.parse_circleci(),
CIPlatform::Custom => self.parse_custom_info(),
CIPlatform::CircleCI
| CIPlatform::TravisCI
CIPlatform::TravisCI
| CIPlatform::Webappio
| CIPlatform::AWSCodeBuild
| CIPlatform::AzurePipelines
Expand Down Expand Up @@ -466,6 +466,16 @@ impl<'a> CIInfoParser<'a> {
// via apply_repo_overrides(), or users can set them via CUSTOM env vars.
}

fn parse_circleci(&mut self) {
self.ci_info.job_url = self.get_env_var("CIRCLE_BUILD_URL");
self.ci_info.branch = self.get_env_var("CIRCLE_BRANCH");
self.ci_info.pr_number = Self::parse_pr_number(self.get_env_var("CIRCLE_PR_NUMBER"));
self.ci_info.actor = self.get_env_var("CIRCLE_USERNAME");

self.ci_info.workflow = self.get_env_var("CIRCLE_WORKFLOW_ID");
self.ci_info.job = self.get_env_var("CIRCLE_JOB");
}

fn get_env_var<T: AsRef<str>>(&self, env_var: T) -> Option<String> {
self.env_vars
.get(env_var.as_ref())
Expand Down
Loading