Provide an endpoint to create shields.io badges

This commit is contained in:
Dominik Nakamura 2021-10-18 00:02:41 +09:00
parent 6cd7256ee8
commit 3f273f07a9
No known key found for this signature in database
GPG key ID: E4C6A749B2491910
3 changed files with 81 additions and 0 deletions

View file

@ -23,6 +23,7 @@ use crate::models::SubjectPath;
enum StatusFormat { enum StatusFormat {
Html, Html,
Svg, Svg,
ShieldsIoJson,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -63,6 +64,10 @@ impl App {
"/repo/:site/:qual/:name/status.svg", "/repo/:site/:qual/:name/status.svg",
Route::RepoStatus(StatusFormat::Svg), Route::RepoStatus(StatusFormat::Svg),
); );
router.add(
"/repo/:site/:qual/:name/shieldsio.json",
Route::RepoStatus(StatusFormat::ShieldsIoJson),
);
router.add("/crate/:name", Route::CrateRedirect); router.add("/crate/:name", Route::CrateRedirect);
router.add( router.add(
@ -73,6 +78,10 @@ impl App {
"/crate/:name/:version/status.svg", "/crate/:name/:version/status.svg",
Route::CrateStatus(StatusFormat::Svg), Route::CrateStatus(StatusFormat::Svg),
); );
router.add(
"/crate/:name/:version/shieldsio.json",
Route::CrateStatus(StatusFormat::ShieldsIoJson),
);
App { App {
logger, logger,
@ -342,6 +351,7 @@ impl App {
match format { match format {
StatusFormat::Svg => views::badge::response(analysis_outcome.as_ref()), StatusFormat::Svg => views::badge::response(analysis_outcome.as_ref()),
StatusFormat::Html => views::html::status::render(analysis_outcome, subject_path), StatusFormat::Html => views::html::status::render(analysis_outcome, subject_path),
StatusFormat::ShieldsIoJson => views::shieldsio::response(analysis_outcome.as_ref()),
} }
} }

View file

@ -1,2 +1,3 @@
pub mod badge; pub mod badge;
pub mod html; pub mod html;
pub mod shieldsio;

View file

@ -0,0 +1,70 @@
use std::borrow::Cow;
use hyper::header::CONTENT_TYPE;
use hyper::{Body, Response};
use serde_json::json;
use crate::engine::AnalyzeDependenciesOutcome;
struct EndpointData<'a> {
message: Cow<'a, str>,
color: &'a str,
}
fn data(analysis_outcome: Option<&AnalyzeDependenciesOutcome>) -> EndpointData<'_> {
match analysis_outcome {
Some(outcome) => {
if outcome.any_always_insecure() {
EndpointData {
message: "insecure".into(),
color: "#e05d44",
}
} else {
let (outdated, total) = outcome.outdated_ratio();
if outdated > 0 {
EndpointData {
message: format!("{} of {} outdated", outdated, total).into(),
color: "#dfb317",
}
} else if total > 0 {
if outcome.any_insecure() {
EndpointData {
message: "maybe insecure".into(),
color: "#88bb11",
}
} else {
EndpointData {
message: "up to date".into(),
color: "#44cc11",
}
}
} else {
EndpointData {
message: "none".into(),
color: "#44cc11",
}
}
}
}
None => EndpointData {
message: "unknown".into(),
color: "#9f9f9f",
},
}
}
pub fn response(analysis_outcome: Option<&AnalyzeDependenciesOutcome>) -> Response<Body> {
let data = data(analysis_outcome);
let json = json! {{
"schemaVersion": 1,
"label": "dependencies",
"message": data.message,
"color": data.color
}};
Response::builder()
.header(CONTENT_TYPE, "application/json; charset=utf-8")
.body(Body::from(json.to_string()))
.unwrap()
}