diff --git a/src/deploy.rs b/src/deploy.rs index efbafdd..7c23a78 100644 --- a/src/deploy.rs +++ b/src/deploy.rs @@ -19,17 +19,20 @@ use serde::{Deserialize, Serialize}; use tokio::sync::oneshot; use crate::errors::*; +use crate::page::Page; use crate::AppCtx; pub mod routes { pub struct Deploy { pub update: &'static str, + pub info: &'static str, } impl Deploy { pub const fn new() -> Self { Self { update: "/api/v1/update", + info: "/api/v1/info", } } } @@ -41,27 +44,76 @@ pub struct DeployEvent { pub branch: String, } -#[my_codegen::post(path = "crate::V1_API_ROUTES.deploy.update")] -async fn update(payload: web::Json, ctx: AppCtx) -> ServiceResult { +fn find_page<'a>(secret: &str, ctx: &'a AppCtx) -> Option<&'a Page> { for page in ctx.settings.pages.iter() { - if page.secret == payload.secret { - let (tx, rx) = oneshot::channel(); - let page = page.clone(); - web::block(move || { - tx.send(page.update()).unwrap(); - }) - .await - .unwrap(); - rx.await.unwrap()?; - return Ok(HttpResponse::Ok()); + if page.secret == secret { + return Some(page); } } + None +} - Err(ServiceError::WebsiteNotFound) +#[my_codegen::post(path = "crate::V1_API_ROUTES.deploy.update")] +async fn update(payload: web::Json, ctx: AppCtx) -> ServiceResult { + if let Some(page) = find_page(&payload.secret, &ctx) { + let (tx, rx) = oneshot::channel(); + let page = page.clone(); + web::block(move || { + tx.send(page.update()).unwrap(); + }) + .await + .unwrap(); + rx.await.unwrap()?; + Ok(HttpResponse::Ok()) + } else { + Err(ServiceError::WebsiteNotFound) + } +} + +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +pub struct DeploySecret { + pub secret: String, +} + +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +pub struct DeployInfo { + pub head: String, + pub remote: String, + pub commit: String, +} + +impl DeployInfo { + pub fn from_page(page: &Page) -> ServiceResult { + let repo = page.open_repo()?; + let head = page.get_deploy_branch(&repo)?; + let commit = Page::get_deploy_commit(&repo)?.to_string(); + let remote = Page::get_deploy_remote(&repo)?; + let remote = remote.url().unwrap().to_owned(); + + Ok(Self { + head, + remote, + commit, + }) + } +} + +#[my_codegen::post(path = "crate::V1_API_ROUTES.deploy.info")] +async fn deploy_info( + payload: web::Json, + ctx: AppCtx, +) -> ServiceResult { + if let Some(page) = find_page(&payload.secret, &ctx) { + let resp = DeployInfo::from_page(page)?; + Ok(HttpResponse::Ok().json(resp)) + } else { + Err(ServiceError::WebsiteNotFound) + } } pub fn services(cfg: &mut web::ServiceConfig) { cfg.service(update); + cfg.service(deploy_info); } #[cfg(test)] @@ -75,7 +127,7 @@ mod tests { #[actix_rt::test] async fn deploy_update_works() { - let ctx = tests::get_data().await; + let (_dir, ctx) = tests::get_data().await; println!("[log] test configuration {:#?}", ctx.settings); let app = get_app!(ctx).await; let page = ctx.settings.pages.get(0); @@ -91,7 +143,7 @@ mod tests { post_request!(&payload, V1_API_ROUTES.deploy.update).to_request(), ) .await; - assert!(tests::check_status(resp, StatusCode::OK).await); + check_status!(resp, StatusCode::OK); payload.secret = page.branch.clone(); @@ -100,6 +152,40 @@ mod tests { post_request!(&payload, V1_API_ROUTES.deploy.update).to_request(), ) .await; - assert!(tests::check_status(resp, StatusCode::NOT_FOUND).await); + check_status!(resp, StatusCode::NOT_FOUND); + } + + #[actix_rt::test] + async fn deploy_info_works() { + let (_dir, ctx) = tests::get_data().await; + println!("[log] test configuration {:#?}", ctx.settings); + let page = ctx.settings.pages.get(0); + let page = page.unwrap(); + let app = get_app!(ctx).await; + + let mut payload = DeploySecret { + secret: page.secret.clone(), + }; + + let resp = test::call_service( + &app, + post_request!(&payload, V1_API_ROUTES.deploy.info).to_request(), + ) + .await; + + check_status!(resp, StatusCode::OK); + + let response: DeployInfo = actix_web::test::read_body_json(resp).await; + assert_eq!(response.head, page.branch); + assert_eq!(response.remote, page.repo); + + payload.secret = page.branch.clone(); + + let resp = test::call_service( + &app, + post_request!(&payload, V1_API_ROUTES.deploy.info).to_request(), + ) + .await; + check_status!(resp, StatusCode::NOT_FOUND); } } diff --git a/src/errors.rs b/src/errors.rs index 0d23bc8..ce9183d 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -123,6 +123,9 @@ pub enum ServiceError { #[display(fmt = "Git Error {}", _0)] GitError(GitError), + + #[display(fmt = "Branch {} not found", _0)] + BranchNotFound(#[error(not(source))] String), } impl From for ServiceError { @@ -180,6 +183,7 @@ impl ResponseError for ServiceError { ServiceError::UnauthorizedOperation(_) => StatusCode::UNAUTHORIZED, ServiceError::BadRequest(_) => StatusCode::BAD_REQUEST, ServiceError::GitError(_) => StatusCode::BAD_REQUEST, + ServiceError::BranchNotFound(_) => StatusCode::CONFLICT, } } }