use serde::Serialize;
pub const KNOWN_SCHEMA_VERSION: u32 = 1;
pub const DEFAULT_FRAGMENT_DIR: &str = "changelog/fragments";
pub const DEFAULT_CROSS_PLATFORM_TARGETS: [&str; 4] = [
"aarch64-apple-darwin",
"x86_64-apple-darwin",
"aarch64-unknown-linux-musl",
"x86_64-unknown-linux-musl",
];
macro_rules! wire_enum {
(
$(#[$emeta:meta])*
$name:ident { $($variant:ident => $wire:literal),+ $(,)? }
) => {
$(#[$emeta])*
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum $name {
$(
#[doc = concat!("Wire value `", $wire, "`.")]
$variant,
)+
}
impl $name {
#[must_use]
pub fn as_str(self) -> &'static str {
match self { $(Self::$variant => $wire),+ }
}
#[must_use]
pub fn parse(s: &str) -> Option<Self> {
match s { $($wire => Some(Self::$variant),)+ _ => None }
}
pub const VALID: &'static [&'static str] = &[$($wire),+];
}
impl serde::Serialize for $name {
fn serialize<S: serde::Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
ser.serialize_str(self.as_str())
}
}
};
}
wire_enum! {
Status { Draft => "draft", Approved => "approved" }
}
wire_enum! {
Maturity { Spike => "spike", Mvp => "mvp", Production => "production" }
}
wire_enum! {
Ecosystem {
Rust => "rust", Node => "node", Python => "python", Go => "go", Binary => "binary"
}
}
wire_enum! {
VersioningBase { Semver => "semver", Calver => "calver", Zerover => "zerover" }
}
wire_enum! {
ChangelogMode { Curated => "curated", Automated => "automated", Fragment => "fragment" }
}
wire_enum! {
ChangelogSource {
IssuectlTrailers => "issuectl-trailers",
ConventionalCommits => "conventional-commits",
Manual => "manual"
}
}
wire_enum! {
ReleaseModel { Gated => "gated", Auto => "auto" }
}
wire_enum! {
ReleaseLayout { Single => "single", Monorepo => "monorepo" }
}
wire_enum! {
ContributionProvenance { Dco => "dco", Cla => "cla", None => "none" }
}
wire_enum! {
ProvenanceLevel { None => "none", Keyless => "keyless", SlsaL3 => "slsa-l3" }
}
wire_enum! {
DependencyBot { Dependabot => "dependabot", Renovate => "renovate", None => "none" }
}
wire_enum! {
HealthBadge {
Ci => "ci", Registry => "registry", License => "license",
Coverage => "coverage", Scorecard => "scorecard", Discord => "discord"
}
}
wire_enum! {
DocsSite {
None => "none", Mkdocs => "mkdocs", Vitepress => "vitepress",
Docusaurus => "docusaurus", Sphinx => "sphinx", Mintlify => "mintlify"
}
}
wire_enum! {
Registry {
CratesIo => "crates.io", Npm => "npm", Pypi => "pypi", TestPypi => "testpypi",
GhReleases => "gh-releases", ProxyGolangOrg => "proxy.golang.org",
Homebrew => "homebrew"
}
}
wire_enum! {
Adapter {
CargoPublish => "cargo-publish", CargoDist => "cargo-dist",
ReleasePlease => "release-please", Changesets => "changesets",
GhActionPypiPublish => "gh-action-pypi-publish", Twine => "twine",
Goreleaser => "goreleaser", HomebrewTap => "homebrew-tap",
HomebrewCore => "homebrew-core", NpmPublish => "npm-publish", Manual => "manual"
}
}
wire_enum! {
DistributionAdapter {
CargoDist => "cargo-dist", Goreleaser => "goreleaser", Manual => "manual"
}
}
wire_enum! {
Installer {
Shell => "shell", Powershell => "powershell", Homebrew => "homebrew",
Msi => "msi", Npm => "npm"
}
}
impl Ecosystem {
#[must_use]
pub fn default_registry(self) -> Registry {
match self {
Self::Rust => Registry::CratesIo,
Self::Node => Registry::Npm,
Self::Python => Registry::Pypi,
Self::Go => Registry::ProxyGolangOrg,
Self::Binary => Registry::GhReleases,
}
}
#[must_use]
pub fn default_adapter(self, layout: ReleaseLayout) -> Adapter {
match self {
Self::Rust => Adapter::CargoPublish,
Self::Node => match layout {
ReleaseLayout::Monorepo => Adapter::Changesets,
ReleaseLayout::Single => Adapter::ReleasePlease,
},
Self::Python => Adapter::GhActionPypiPublish,
Self::Go => Adapter::Goreleaser,
Self::Binary => Adapter::Manual,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Target {
pub ecosystem: Ecosystem,
pub package: Option<String>,
pub registry: Registry,
pub adapter: Adapter,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Distribution {
pub adapter: DistributionAdapter,
pub gh_releases: bool,
pub installers: Vec<Installer>,
pub homebrew_tap: Option<String>,
pub platforms: Vec<String>,
pub extra_fields: serde_json::Map<String, serde_json::Value>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Changelog {
pub mode: ChangelogMode,
pub source: ChangelogSource,
pub fragment_dir: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Release {
pub model: ReleaseModel,
pub layout: ReleaseLayout,
}
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Contract {
pub schema_version: u32,
pub status: Status,
pub maturity: Maturity,
pub ecosystems: Vec<Ecosystem>,
pub targets: Vec<Target>,
pub distribution: Option<Distribution>,
pub versioning: VersioningBase,
pub versioning_pattern: Option<String>,
pub changelog: Changelog,
pub conventional_commits: bool,
pub release: Release,
pub contribution_provenance: ContributionProvenance,
pub provenance_level: ProvenanceLevel,
pub dependency_bot: DependencyBot,
pub health_badges: Vec<HealthBadge>,
pub license: String,
pub docs_site: DocsSite,
pub extra_fields: serde_json::Map<String, serde_json::Value>,
pub warnings: Vec<String>,
}