feat(ci): Create a new workflow to validate the generated openAPI spec file (openapi_spec.json) (#1323)

Co-authored-by: kritikmodi <kritik.modi@juspay.in>
Co-authored-by: pixincreate@work <69745008+pixincreate@users.noreply.github.com>
Co-authored-by: Narayan Bhat <narayan.bhat@juspay.in>
Co-authored-by: Sanchith Hegde <22217505+SanchithHegde@users.noreply.github.com>
This commit is contained in:
Kritik Modi
2023-06-06 19:14:42 +05:30
committed by GitHub
parent 1322aa7579
commit 6730fe32cb
9 changed files with 2074 additions and 635 deletions

View File

@ -384,3 +384,4 @@ jobs:
- name: Spell check - name: Spell check
uses: crate-ci/typos@master uses: crate-ci/typos@master

View File

@ -0,0 +1,37 @@
name: Validate Generated OpenAPI Spec File
on:
pull_request:
merge_group:
types:
- checks_requested
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
validate_json:
name: Validate generated openapi spec file
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3.1.0
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
- name: Generate the spec file
shell: bash
run: cargo run --features openapi -- generate-openapi-spec
- name: Install swagger-cli
shell: bash
run: npm install -g @apidevtools/swagger-cli
- name: Validate the json file
shell: bash
run: swagger-cli validate ./openapi/openapi_spec.json

928
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -15,13 +15,13 @@ pub struct CustomerRequest {
#[serde(default = "unknown_merchant", skip)] #[serde(default = "unknown_merchant", skip)]
pub merchant_id: String, pub merchant_id: String,
/// The customer's name /// The customer's name
#[schema(max_length = 255, example = "Jon Test")] #[schema(max_length = 255, value_type = Option<String>, example = "Jon Test")]
pub name: Option<Secret<String>>, pub name: Option<Secret<String>>,
/// The customer's email address /// The customer's email address
#[schema(value_type = Option<String>,max_length = 255, example = "JonTest@test.com")] #[schema(value_type = Option<String>, max_length = 255, example = "JonTest@test.com")]
pub email: Option<pii::Email>, pub email: Option<pii::Email>,
/// The customer's phone number /// The customer's phone number
#[schema(value_type = Option<String>,max_length = 255, example = "9999999999")] #[schema(value_type = Option<String>, max_length = 255, example = "9999999999")]
pub phone: Option<Secret<String>>, pub phone: Option<Secret<String>>,
/// An arbitrary string that you can attach to a customer object. /// An arbitrary string that you can attach to a customer object.
#[schema(max_length = 255, example = "First Customer")] #[schema(max_length = 255, example = "First Customer")]
@ -55,7 +55,7 @@ pub struct CustomerResponse {
#[schema(max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")] #[schema(max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: String, pub customer_id: String,
/// The customer's name /// The customer's name
#[schema(max_length = 255, example = "Jon Test")] #[schema(max_length = 255, value_type = Option<String>, example = "Jon Test")]
pub name: crypto::OptionalEncryptableName, pub name: crypto::OptionalEncryptableName,
/// The customer's email address /// The customer's email address
#[schema(value_type = Option<String>,max_length = 255, example = "JonTest@test.com")] #[schema(value_type = Option<String>,max_length = 255, example = "JonTest@test.com")]

View File

@ -726,14 +726,20 @@ pub enum BankRedirectData {
}, },
} }
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct AchBillingDetails { pub struct AchBillingDetails {
/// The Email ID for ACH billing
#[schema(value_type = String, example = "example@me.com")]
pub email: Email, pub email: Email,
} }
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct SepaAndBacsBillingDetails { pub struct SepaAndBacsBillingDetails {
/// The Email ID for SEPA and BACS billing
#[schema(value_type = String, example = "example@me.com")]
pub email: Email, pub email: Email,
/// The billing name for SEPA and BACS billing
#[schema(value_type = String, example = "Jane Doe")]
pub name: Secret<String>, pub name: Secret<String>,
} }
@ -762,13 +768,19 @@ pub struct BankRedirectBilling {
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum BankTransferData { pub enum BankTransferData {
AchBankTransfer { AchBankTransfer {
/// The billing details for ACH Bank Transfer
billing_details: AchBillingDetails, billing_details: AchBillingDetails,
}, },
SepaBankTransfer { SepaBankTransfer {
/// The billing details for SEPA
billing_details: SepaAndBacsBillingDetails, billing_details: SepaAndBacsBillingDetails,
/// The two-letter ISO country code for SEPA and BACS
#[schema(value_type = CountryAlpha2, example = "US")]
country: api_enums::CountryAlpha2, country: api_enums::CountryAlpha2,
}, },
BacsBankTransfer { BacsBankTransfer {
/// The billing details for SEPA
billing_details: SepaAndBacsBillingDetails, billing_details: SepaAndBacsBillingDetails,
}, },
} }
@ -1082,48 +1094,65 @@ pub enum NextActionData {
}, },
} }
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct BankTransferNextStepsData { pub struct BankTransferNextStepsData {
/// The instructions for performing a bank transfer
#[serde(flatten)] #[serde(flatten)]
pub bank_transfer_instructions: BankTransferInstructions, pub bank_transfer_instructions: BankTransferInstructions,
/// The details received by the receiver
pub receiver: ReceiverDetails, pub receiver: ReceiverDetails,
} }
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum BankTransferInstructions { pub enum BankTransferInstructions {
/// The credit transfer for ACH transactions
AchCreditTransfer(Box<AchTransfer>), AchCreditTransfer(Box<AchTransfer>),
/// The instructions for SEPA bank transactions
SepaBankInstructions(Box<SepaBankTransferInstructions>), SepaBankInstructions(Box<SepaBankTransferInstructions>),
/// The instructions for BACS bank transactions
BacsBankInstructions(Box<BacsBankTransferInstructions>), BacsBankInstructions(Box<BacsBankTransferInstructions>),
} }
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct SepaBankTransferInstructions { pub struct SepaBankTransferInstructions {
#[schema(value_type = String, example = "Jane Doe")]
pub account_holder_name: Secret<String>, pub account_holder_name: Secret<String>,
#[schema(value_type = String, example = "1024419982")]
pub bic: Secret<String>, pub bic: Secret<String>,
pub country: String, pub country: String,
#[schema(value_type = String, example = "123456789")]
pub iban: Secret<String>, pub iban: Secret<String>,
} }
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct BacsBankTransferInstructions { pub struct BacsBankTransferInstructions {
#[schema(value_type = String, example = "Jane Doe")]
pub account_holder_name: Secret<String>, pub account_holder_name: Secret<String>,
#[schema(value_type = String, example = "10244123908")]
pub account_number: Secret<String>, pub account_number: Secret<String>,
#[schema(value_type = String, example = "012")]
pub sort_code: Secret<String>, pub sort_code: Secret<String>,
} }
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct AchTransfer { pub struct AchTransfer {
#[schema(value_type = String, example = "122385736258")]
pub account_number: Secret<String>, pub account_number: Secret<String>,
pub bank_name: String, pub bank_name: String,
#[schema(value_type = String, example = "012")]
pub routing_number: Secret<String>, pub routing_number: Secret<String>,
#[schema(value_type = String, example = "234")]
pub swift_code: Secret<String>, pub swift_code: Secret<String>,
} }
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct ReceiverDetails { pub struct ReceiverDetails {
/// The amount received by receiver
amount_received: i64, amount_received: i64,
/// The amount charged by ACH
amount_charged: Option<i64>, amount_charged: Option<i64>,
/// The amount remaining to be sent via ACH
amount_remaining: Option<i64>, amount_remaining: Option<i64>,
} }
@ -1296,7 +1325,7 @@ pub struct PaymentsResponse {
pub connector_label: Option<String>, pub connector_label: Option<String>,
/// The business country of merchant for this payment /// The business country of merchant for this payment
#[schema(value_type = CountryAlpha2)] #[schema(value_type = CountryAlpha2, example = "US")]
pub business_country: api_enums::CountryAlpha2, pub business_country: api_enums::CountryAlpha2,
/// The business label of merchant for this payment /// The business label of merchant for this payment
@ -1563,6 +1592,7 @@ pub struct Metadata {
pub order_category: Option<String>, pub order_category: Option<String>,
/// Redirection response coming in request as metadata field only for redirection scenarios /// Redirection response coming in request as metadata field only for redirection scenarios
#[schema(value_type = Option<RedirectResponse>)]
pub redirect_response: Option<RedirectResponse>, pub redirect_response: Option<RedirectResponse>,
/// Allowed payment method types for a payment intent /// Allowed payment method types for a payment intent
@ -1572,6 +1602,7 @@ pub struct Metadata {
#[derive(Default, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone, ToSchema)] #[derive(Default, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct RedirectResponse { pub struct RedirectResponse {
#[schema(value_type = Option<String>)]
pub param: Option<Secret<String>>, pub param: Option<Secret<String>>,
#[schema(value_type = Option<Object>)] #[schema(value_type = Option<Object>)]
pub json_payload: Option<pii::SecretSerdeValue>, pub json_payload: Option<pii::SecretSerdeValue>,

View File

@ -22,7 +22,7 @@ olap = []
oltp = [] oltp = []
kv_store = [] kv_store = []
accounts_cache = [] accounts_cache = []
openapi = ["olap", "oltp"] openapi = ["olap", "oltp", "dep:oas3"]
vergen = ["router_env/vergen"] vergen = ["router_env/vergen"]
multiple_mca = ["api_models/multiple_mca"] multiple_mca = ["api_models/multiple_mca"]
dummy_connector = ["api_models/dummy_connector"] dummy_connector = ["api_models/dummy_connector"]
@ -62,6 +62,7 @@ mime = "0.3.17"
moka = { version = "0.10", features = ["future"] } moka = { version = "0.10", features = ["future"] }
nanoid = "0.4.0" nanoid = "0.4.0"
num_cpus = "1.15.0" num_cpus = "1.15.0"
oas3 = { version = "0.2.1", optional = true }
once_cell = "1.17.1" once_cell = "1.17.1"
rand = "0.8.5" rand = "0.8.5"
regex = "1.7.3" regex = "1.7.3"

View File

@ -13,13 +13,13 @@ async fn main() -> ApplicationResult<()> {
{ {
use router::configs::settings::Subcommand; use router::configs::settings::Subcommand;
if let Some(Subcommand::GenerateOpenapiSpec) = cmd_line.subcommand { if let Some(Subcommand::GenerateOpenapiSpec) = cmd_line.subcommand {
let file_path = "openapi/generated.json"; let file_path = "openapi/openapi_spec.json";
#[allow(clippy::expect_used)] #[allow(clippy::expect_used)]
std::fs::write( std::fs::write(
file_path, file_path,
<router::openapi::ApiDoc as utoipa::OpenApi>::openapi() <router::openapi::ApiDoc as utoipa::OpenApi>::openapi()
.to_pretty_json() .to_pretty_json()
.expect("Failed to generate serialize OpenAPI specification as JSON"), .expect("Failed to serialize OpenAPI specification as JSON"),
) )
.expect("Failed to write OpenAPI specification to file"); .expect("Failed to write OpenAPI specification to file");
println!("Successfully saved OpenAPI specification file at '{file_path}'"); println!("Successfully saved OpenAPI specification file at '{file_path}'");

View File

@ -222,6 +222,16 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::payments::PaymentsCancelRequest, api_models::payments::PaymentsCancelRequest,
api_models::payments::PaymentListConstraints, api_models::payments::PaymentListConstraints,
api_models::payments::PaymentListResponse, api_models::payments::PaymentListResponse,
api_models::payments::BankTransferData,
api_models::payments::BankTransferNextStepsData,
api_models::payments::SepaAndBacsBillingDetails,
api_models::payments::AchBillingDetails,
api_models::payments::BankTransferInstructions,
api_models::payments::ReceiverDetails,
api_models::payments::AchTransfer,
api_models::payments::SepaBankTransferInstructions,
api_models::payments::BacsBankTransferInstructions,
api_models::payments::RedirectResponse,
api_models::refunds::RefundListRequest, api_models::refunds::RefundListRequest,
api_models::refunds::RefundListResponse, api_models::refunds::RefundListResponse,
api_models::mandates::MandateRevokedResponse, api_models::mandates::MandateRevokedResponse,

File diff suppressed because it is too large Load Diff