use tatara_rust_ast::CrateScaffold;
#[derive(Clone, Debug, Default)]
pub struct CaixaConfig {
pub description: Option<String>,
pub attach_auto_release: bool,
}
pub fn attach_caixa_biblioteca(scaffold: &mut CrateScaffold, config: &CaixaConfig) {
if !scaffold.files.iter().any(|f| f.path == "caixa.lisp") {
scaffold.add_file(
"caixa.lisp",
render_caixa_biblioteca(
&scaffold.name,
&scaffold.version,
config.description.as_deref(),
),
);
}
if config.attach_auto_release
&& !scaffold
.files
.iter()
.any(|f| f.path == ".github/workflows/auto-release.yml")
{
scaffold.add_file(
".github/workflows/auto-release.yml",
render_auto_release_workflow(),
);
}
}
#[must_use]
pub fn render_caixa_biblioteca(name: &str, version: &str, description: Option<&str>) -> String {
let desc = description.unwrap_or("Generated by tatara-rust-ast.");
let repo = format!("https://github.com/pleme-io/{name}");
format!(
r#";; caixa.lisp — generated by tatara-rust-caixa (tatara-rust-ast).
;;
;; Consumed by `pleme-doc-gen` for the SDLC pipeline (Cargo.toml +
;; .pleme-io-release.toml + CI shims + nix module trio + flake.nix).
;; Re-emit with `pleme-doc-gen caixa --source caixa.lisp --out .`.
(defcaixa {name}
:kind "Biblioteca"
:ecosystem "rust-single-crate"
:package {{ :name "{name}"
:version "{version}"
:license "MIT"
:description "{desc}"
:repository "{repo}"
:homepage "{repo}"
:categories [ "development-tools::procedural-macro-helpers" ]
:keywords [ "tatara" "macro" "derive" "generated" ] }}
:ci-config {{ :bump {{ :default-type "patch" }}
:publish {{ :no-verify false }} }}
:workflows [ :auto-release ]
:stacks [ ]
:depends-on [ ]
:exposes [ :rust-crate ]
:publish-to-git true)
"#
)
}
#[must_use]
pub fn render_auto_release_workflow() -> String {
r#"# Auto-emitted by tatara-rust-caixa.
# The reusable substrate workflow does auto-bump → tag → publish to crates.io.
on:
push:
branches: [main]
workflow_dispatch:
inputs:
bump-type:
description: "patch | minor | major"
required: false
default: patch
jobs:
release:
uses: pleme-io/substrate/.github/workflows/cargo-auto-release.yml@main
with:
bump-type: ${{ inputs.bump-type || 'patch' }}
regenerate-cargo-nix: "false"
secrets: inherit
"#
.to_string()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn attaches_caixa_lisp() {
let mut s = CrateScaffold::new("my-derive", "0.1.0");
attach_caixa_biblioteca(
&mut s,
&CaixaConfig {
description: Some("Test crate".into()),
attach_auto_release: false,
},
);
let files = s.to_files();
assert!(files.contains_key("caixa.lisp"));
let lisp = files.get("caixa.lisp").unwrap();
assert!(lisp.contains("(defcaixa my-derive"));
assert!(lisp.contains(r#":kind "Biblioteca""#));
assert!(lisp.contains(r#":ecosystem "rust-single-crate""#));
assert!(lisp.contains(r#":name "my-derive""#));
assert!(lisp.contains(r#":version "0.1.0""#));
assert!(lisp.contains("Test crate"));
}
#[test]
fn emits_every_keyword_pleme_doc_gen_parser_consumes() {
let lisp = render_caixa_biblioteca("foo-derive", "1.2.3", Some("Foo macro."));
assert!(lisp.starts_with(";;") || lisp.contains("(defcaixa foo-derive"));
for kw in [":kind", ":ecosystem", ":package", ":ci-config", ":workflows"] {
assert!(
lisp.contains(kw),
"caixa.lisp missing required keyword `{kw}` for pleme-doc-gen parser"
);
}
for pkg_key in [":name", ":version", ":license", ":description", ":repository"] {
assert!(
lisp.contains(pkg_key),
"caixa.lisp :package missing `{pkg_key}`"
);
}
assert!(lisp.contains(r#":ecosystem "rust-single-crate""#));
}
#[test]
fn attaches_workflow_when_enabled() {
let mut s = CrateScaffold::new("x", "0.1.0");
attach_caixa_biblioteca(
&mut s,
&CaixaConfig {
attach_auto_release: true,
..Default::default()
},
);
assert!(
s.to_files()
.contains_key(".github/workflows/auto-release.yml")
);
}
#[test]
fn idempotent() {
let mut s = CrateScaffold::new("x", "0.1.0");
s.add_file("caixa.lisp", "custom");
attach_caixa_biblioteca(&mut s, &CaixaConfig::default());
assert_eq!(s.to_files()["caixa.lisp"], "custom");
}
#[test]
fn workflow_references_substrate_reusable() {
let w = render_auto_release_workflow();
assert!(w.contains("uses: pleme-io/substrate/.github/workflows/cargo-auto-release.yml"));
assert!(w.contains(r#"regenerate-cargo-nix: "false""#));
assert!(w.contains("secrets: inherit"));
}
}