use std::path::PathBuf;
use schemars::JsonSchema;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use crate::{
CommitSha, ConfigKey, DepKind, Diagnostic, GroupName, PackageId, PublishPlan, Severity,
TagName, Version,
};
pub const SCHEMA_VERSION: u32 = 1;
pub trait Report: Serialize + DeserializeOwned + Send + Sync + 'static {
const COMMAND: &'static str;
fn schema_version(&self) -> u32;
fn diagnostics(&self) -> &[Diagnostic];
}
impl Report for PublishPlan {
const COMMAND: &'static str = "plan-publish";
fn schema_version(&self) -> u32 {
self.schema_version
}
fn diagnostics(&self) -> &[Diagnostic] {
&self.diagnostics
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct VersionReport {
pub schema_version: u32,
pub bumps: Vec<BumpRecord>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub lockfile_refresh_results: Option<Vec<LockfileRefreshResult>>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub diagnostics: Vec<Diagnostic>,
}
impl Report for VersionReport {
const COMMAND: &'static str = "version";
fn schema_version(&self) -> u32 {
self.schema_version
}
fn diagnostics(&self) -> &[Diagnostic] {
&self.diagnostics
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct BumpRecord {
pub package: PackageId,
pub from: Version,
pub to: Version,
pub severity: Severity,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub governed_by: Option<ConfigKey>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reason: Option<BumpReason>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "camelCase")]
#[non_exhaustive]
pub enum BumpReason {
Changeset {
changesets: Vec<String>,
},
Inference {
commits: usize,
remapped: bool,
},
FixedGroupUnion {
group: GroupName,
},
LinkedGroupUnion {
group: GroupName,
},
Cascade {
via: PackageId,
dep_kind: DepKind,
spec: String,
dependency_to: Version,
},
PeerEscalation {
via: PackageId,
spec: String,
},
PreRelease {
tag: String,
},
NewGroupMember {
group: GroupName,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct LockfileRefreshResult {
pub filename: PathBuf,
pub refresh_command: String,
pub success: bool,
pub exit_code: Option<i32>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct StatusReport {
pub schema_version: u32,
pub packages: Vec<StatusPackageRecord>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub diagnostics: Vec<Diagnostic>,
}
impl Report for StatusReport {
const COMMAND: &'static str = "status";
fn schema_version(&self) -> u32 {
self.schema_version
}
fn diagnostics(&self) -> &[Diagnostic] {
&self.diagnostics
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct StatusPackageRecord {
pub package: PackageId,
pub current_version: Version,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_tag: Option<TagName>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub pending_severity: Option<Severity>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub changed_since_last_tag: bool,
pub pending_changesets: Vec<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct SnapshotReport {
pub schema_version: u32,
pub snapshot_tag: String,
pub bumps: Vec<BumpRecord>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub diagnostics: Vec<Diagnostic>,
}
impl Report for SnapshotReport {
const COMMAND: &'static str = "snapshot";
fn schema_version(&self) -> u32 {
self.schema_version
}
fn diagnostics(&self) -> &[Diagnostic] {
&self.diagnostics
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct ComposePrBodyReport {
pub schema_version: u32,
pub pr_body: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub diagnostics: Vec<Diagnostic>,
}
impl Report for ComposePrBodyReport {
const COMMAND: &'static str = "compose-pr-body";
fn schema_version(&self) -> u32 {
self.schema_version
}
fn diagnostics(&self) -> &[Diagnostic] {
&self.diagnostics
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct ValidateReport {
pub schema_version: u32,
pub valid: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub diagnostics: Vec<Diagnostic>,
}
impl Report for ValidateReport {
const COMMAND: &'static str = "validate";
fn schema_version(&self) -> u32 {
self.schema_version
}
fn diagnostics(&self) -> &[Diagnostic] {
&self.diagnostics
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct TagReport {
pub schema_version: u32,
pub created_tags: Vec<CreatedTag>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub diagnostics: Vec<Diagnostic>,
}
impl Report for TagReport {
const COMMAND: &'static str = "tag";
fn schema_version(&self) -> u32 {
self.schema_version
}
fn diagnostics(&self) -> &[Diagnostic] {
&self.diagnostics
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct CreatedTag {
pub package: PackageId,
pub tag_name: TagName,
pub sha: CommitSha,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct InitReport {
pub schema_version: u32,
pub initialized: bool,
pub config_path: PathBuf,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub diagnostics: Vec<Diagnostic>,
}
impl Report for InitReport {
const COMMAND: &'static str = "init";
fn schema_version(&self) -> u32 {
self.schema_version
}
fn diagnostics(&self) -> &[Diagnostic] {
&self.diagnostics
}
}