anodizer_core/config/mod.rs
1use std::collections::{BTreeMap, HashMap};
2use std::path::PathBuf;
3
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7// ---------------------------------------------------------------------------
8// Include specification types
9// ---------------------------------------------------------------------------
10
11/// An include specification: either a plain path string or a structured from_file/from_url.
12///
13/// YAML examples:
14/// ```yaml
15/// includes:
16/// - ./defaults.yaml # plain string (backward compat)
17/// - from_file:
18/// path: ./config/release.yaml # structured file path
19/// - from_url:
20/// url: https://example.com/config.yaml # URL fetch
21/// headers:
22/// x-api-token: "${MYCOMPANY_TOKEN}" # env var expansion in headers
23/// ```
24#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
25#[serde(untagged)]
26pub enum IncludeSpec {
27 /// Plain string path (backward compatible): "path/to/file.yaml"
28 Path(String),
29 /// Structured file include with `from_file.path`.
30 FromFile { from_file: IncludeFilePath },
31 /// Structured URL include with `from_url.url` and optional headers.
32 FromUrl { from_url: IncludeUrlConfig },
33}
34
35/// File path for a structured include.
36#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
37#[serde(deny_unknown_fields)]
38pub struct IncludeFilePath {
39 /// Path to the include file (relative to the config file).
40 pub path: String,
41}
42
43/// URL configuration for a structured include.
44#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
45#[serde(deny_unknown_fields)]
46pub struct IncludeUrlConfig {
47 /// URL to fetch. If it does not start with `http://` or `https://`,
48 /// `https://raw.githubusercontent.com/` is prepended (GitHub shorthand).
49 pub url: String,
50 /// Optional HTTP headers. Values support `${VAR_NAME}` environment variable expansion.
51 pub headers: Option<HashMap<String, String>>,
52}
53
54// ---------------------------------------------------------------------------
55// Top-level config
56// ---------------------------------------------------------------------------
57
58/// `deny_unknown_fields` rejects typos and unknown config
59/// fields at parse time (strict YAML unmarshalling).
60#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
61#[serde(default, deny_unknown_fields)]
62pub struct Config {
63 /// Schema version. Currently supports 1 (implicit default) and 2.
64 pub version: Option<u32>,
65 /// Human-readable project name used in templates and release titles.
66 pub project_name: String,
67 /// Output directory for build artifacts (default: ./dist).
68 #[serde(default = "default_dist")]
69 pub dist: PathBuf,
70 /// Additional config files to merge into this config.
71 /// Supports plain string paths, `from_file:` for structured file paths,
72 /// and `from_url:` for fetching configs from URLs with optional headers.
73 pub includes: Option<Vec<IncludeSpec>>,
74 /// Environment file configuration. Accepts either:
75 /// - A list of `.env` file paths: `[".env", ".release.env"]`
76 /// - A struct with token file paths: `{ github_token: "~/.config/goreleaser/github_token" }`
77 pub env_files: Option<EnvFilesConfig>,
78 /// Default values applied to all crates unless overridden.
79 pub defaults: Option<Defaults>,
80 /// Hooks run before the release pipeline starts.
81 pub before: Option<HooksConfig>,
82 /// Hooks run after the release pipeline completes.
83 pub after: Option<HooksConfig>,
84 /// Hooks run when the release pipeline fails at ANY stage (build,
85 /// sign, publish, ...), after the failure policy (rollback / hold)
86 /// has executed, so `{{ .RolledBack }}` reflects the taken path.
87 ///
88 /// Notification / cleanup hooks: a hook's own failure is logged as a
89 /// warning and never masks the pipeline error. The failure context is
90 /// exposed both as template vars (`{{ .Error }}`, `{{ .RolledBack }}`)
91 /// and as `ANODIZER_*` env vars (`ANODIZER_ERROR`,
92 /// `ANODIZER_ROLLED_BACK`, `ANODIZER_VERSION`, `ANODIZER_TAG`) so
93 /// hooks can consume the error text without shell interpolation.
94 ///
95 /// ```yaml
96 /// on_error:
97 /// hooks:
98 /// - cmd: ./notify-release-failed.sh
99 /// ```
100 pub on_error: Option<HooksConfig>,
101 /// Hooks run after build/archive/sign/sbom/checksum complete but
102 /// immediately before the publish phase dispatches any publisher.
103 ///
104 /// Use cases: smoke-test artifacts against the staged dist tree,
105 /// run external validators (antivirus, vulnerability scanners),
106 /// stage external state, or abort the release before any
107 /// publisher writes to a registry.
108 ///
109 /// A non-zero exit code from any hook aborts the release before
110 /// publish runs. Hooks fire in declared order. Use `--skip=before-publish`
111 /// to bypass.
112 pub before_publish: Option<HooksConfig>,
113 /// List of crates in this project.
114 pub crates: Vec<CrateConfig>,
115 /// Changelog generation configuration.
116 pub changelog: Option<ChangelogConfig>,
117 /// Signing configurations for binaries, archives, and checksums.
118 #[serde(default, deserialize_with = "deserialize_signs")]
119 #[schemars(schema_with = "signs_schema")]
120 pub signs: Vec<SignConfig>,
121 /// Binary-specific signing configs (same shape as `signs` but only for
122 /// binary artifacts). The `artifacts` field on each entry is constrained
123 /// at parse time to `binary` / `none` (or omitted) — a broader filter on
124 /// `binary_signs` would silently match nothing because the loop only
125 /// iterates Binary artifacts. Constraint lives in `deserialize_binary_signs`.
126 #[serde(default, deserialize_with = "deserialize_binary_signs")]
127 #[schemars(schema_with = "signs_schema")]
128 pub binary_signs: Vec<SignConfig>,
129 /// Docker image signing configurations.
130 pub docker_signs: Option<Vec<DockerSignConfig>>,
131 // No `alias` attribute needed: unlike `signs`/`sign`, "upx" is already
132 // both singular and plural, so a separate alias adds no value.
133 /// UPX binary compression configurations.
134 #[serde(default, deserialize_with = "deserialize_upx")]
135 #[schemars(schema_with = "upx_schema")]
136 pub upx: Vec<UpxConfig>,
137 /// Snapshot release configuration (local/non-tag builds).
138 pub snapshot: Option<SnapshotConfig>,
139 /// Nightly release configuration.
140 pub nightly: Option<NightlyConfig>,
141 /// Announcement configuration (Slack, Discord, email, etc.).
142 pub announce: Option<AnnounceConfig>,
143 /// When true, log artifact file sizes after building.
144 pub report_sizes: Option<bool>,
145 /// Environment variables available to all template expressions.
146 ///
147 /// List of `KEY=VALUE` strings:
148 /// `env: ["MY_VAR=hello", "DEPLOY_ENV=staging"]`. Order is preserved so
149 /// chained env applications (sign + sbom + notarize) see entries in
150 /// declared order. Values are rendered through the template engine before
151 /// being set, so expressions like `{{ Tag }}` or `{{ Date }}` are
152 /// expanded.
153 #[serde(default)]
154 pub env: Option<Vec<String>>,
155 /// Custom template variables accessible as `{{ Var.<key> }}` in templates.
156 /// Provides a way to define reusable values, especially useful with config includes.
157 ///
158 /// Stored as a `BTreeMap` so rendering iterates in deterministic
159 /// (sorted) key order — without this guarantee, a value that references
160 /// another variable (`b: "{{ Var.a }}_v2"`) could render before its
161 /// dependency on a different process / host. The current resolver is
162 /// single-pass (one render per value), so cross-variable references
163 /// only resolve when the referenced key sorts earlier.
164 pub variables: Option<BTreeMap<String, String>>,
165 /// Generic artifact publisher configurations.
166 pub publishers: Option<Vec<PublisherConfig>>,
167 /// DockerHub description sync configurations.
168 pub dockerhub: Option<Vec<DockerHubConfig>>,
169 /// Artifactory upload configurations.
170 pub artifactories: Option<Vec<ArtifactoryConfig>>,
171 /// CloudSmith publisher configurations.
172 pub cloudsmiths: Option<Vec<CloudSmithConfig>>,
173 /// Top-level Homebrew Cask configurations.
174 /// `homebrew_casks` is a top-level array with its own
175 /// repository, commit_author, directory, skip_upload, hooks, dependencies,
176 /// conflicts, completions, manpages, structured uninstall/zap, etc.
177 pub homebrew_casks: Option<Vec<HomebrewCaskConfig>>,
178 /// Repo-committed files that embed the release version outside
179 /// `Cargo.toml` (e.g. a Helm `Chart.yaml`, an install doc, a README
180 /// badge), given as repo-root-relative path strings. At `tag` time each
181 /// listed file has its occurrences of the old version rewritten to the new
182 /// version — both the bare (`0.1.0`) and `v`-prefixed (`v0.1.0`) forms,
183 /// word-boundary anchored — and is staged into the same bump commit as
184 /// `Cargo.toml` / `Cargo.lock`, so these files never drift from the tag.
185 ///
186 /// ```yaml
187 /// version_files:
188 /// - charts/cfgd/Chart.yaml
189 /// - docs/installation.md
190 /// ```
191 pub version_files: Option<Vec<String>>,
192 /// Automatic semantic version tagging configuration.
193 pub tag: Option<TagConfig>,
194 /// Git-level tag discovery and sorting settings.
195 pub git: Option<GitConfig>,
196 /// Partial/split build configuration for fan-out CI pipelines.
197 pub partial: Option<PartialConfig>,
198 /// Independent workspace roots in a monorepo.
199 pub workspaces: Option<Vec<WorkspaceConfig>>,
200 /// Source archive configuration.
201 pub source: Option<SourceConfig>,
202 /// Software bill of materials (SBOM) generation configurations.
203 #[serde(default, deserialize_with = "deserialize_sboms")]
204 #[schemars(schema_with = "sboms_schema")]
205 pub sboms: Vec<SbomConfig>,
206 /// SLSA build-provenance / attestation configuration for binaries and
207 /// archives. In the default `subjects` mode, anodizer writes a subjects
208 /// manifest for `actions/attest-build-provenance`; in `emit` mode it
209 /// generates and signs a self-contained in-toto SLSA provenance statement.
210 /// When omitted (or `enabled: false`), the attestation stage is a no-op.
211 pub attestations: Option<AttestationConfig>,
212 /// GitHub release configuration shared by all crates.
213 pub release: Option<ReleaseConfig>,
214 /// Custom GitHub API/upload/download URLs for GitHub Enterprise installations.
215 pub github_urls: Option<GitHubUrlsConfig>,
216 /// Custom GitLab API/download URLs for self-hosted GitLab installations.
217 pub gitlab_urls: Option<GitLabUrlsConfig>,
218 /// Custom Gitea API/download URLs for self-hosted Gitea installations.
219 pub gitea_urls: Option<GiteaUrlsConfig>,
220 /// Force a specific token type for authentication.
221 /// When set, overrides automatic token detection from environment variables.
222 pub force_token: Option<ForceTokenKind>,
223 /// macOS code signing and notarization configuration.
224 pub notarize: Option<NotarizeConfig>,
225 /// Project metadata configuration (applied to metadata.json output files).
226 pub metadata: Option<MetadataConfig>,
227 /// Template files to render and include as release artifacts.
228 /// File contents are processed through the template engine.
229 pub template_files: Option<Vec<TemplateFileConfig>>,
230 /// Monorepo configuration.
231 /// When configured, tag discovery filters by tag_prefix and the working
232 /// directory is scoped to dir.
233 pub monorepo: Option<MonorepoConfig>,
234 /// Makeself self-extracting archive configurations.
235 #[serde(default, deserialize_with = "deserialize_makeselfs")]
236 #[schemars(schema_with = "makeselfs_schema")]
237 pub makeselfs: Vec<MakeselfConfig>,
238 /// `curl | sh` installer-script configurations. Each entry emits a
239 /// deterministic POSIX `install.sh` release asset that detects the host
240 /// OS + arch, downloads and sha256-verifies the matching archive, and
241 /// installs the binary.
242 #[serde(default, deserialize_with = "deserialize_install_scripts")]
243 #[schemars(schema_with = "install_scripts_schema")]
244 pub install_scripts: Vec<InstallScriptConfig>,
245 /// AppImage configurations. Each entry bundles a built Linux binary plus
246 /// its desktop integration into a single self-contained `.AppImage` via
247 /// linuxdeploy.
248 #[serde(default, deserialize_with = "deserialize_appimages")]
249 #[schemars(schema_with = "appimages_schema")]
250 pub appimages: Vec<AppImageConfig>,
251 /// Opt-in post-release verification gate. Runs LAST (after the release is
252 /// created and every publisher has run) and REPORTS post-publish defects —
253 /// missing assets, failed install smoke-tests, glibc-ceiling violations.
254 /// Because it runs after the irreversible publish, a failure exits
255 /// non-zero to flag CI but never undoes the release. Off unless
256 /// `verify_release.enabled: true`.
257 #[serde(default)]
258 pub verify_release: VerifyReleaseConfig,
259 /// Pre-publish preflight tuning. `preflight.strict: true` promotes
260 /// indeterminate probe outcomes (5xx / rate-limit / network failure /
261 /// undeterminable permissions) from warnings to hard blockers. The
262 /// probes themselves always run read-only before any publisher mutates
263 /// a registry; the default (lenient) behavior needs no config.
264 #[serde(default)]
265 pub preflight: PreflightConfig,
266 /// Source RPM configuration. Renamed from `srpm:` (singular) for spelling
267 /// parity with `Defaults.srpms` and the rest of the plural-name packaging
268 /// fields. The `srpm:` spelling is still accepted via serde alias for
269 /// back-compat.
270 #[serde(alias = "srpm")]
271 pub srpms: Option<SrpmConfig>,
272 /// Milestone closing configurations.
273 pub milestones: Option<Vec<MilestoneConfig>>,
274 /// Generic HTTP upload configurations.
275 pub uploads: Option<Vec<UploadConfig>>,
276 /// AUR source package publishing configurations (source-only PKGBUILD, not -bin).
277 pub aur_sources: Option<Vec<AurSourceConfig>>,
278 /// Top-level retry configuration applied to network-bound operations
279 /// (announcers, git providers, HTTP uploads, docker pipes). When omitted,
280 /// `RetryConfig::default()` is used (10 attempts, 10s base, 5m cap —
281 /// the project-level retry policy).
282 pub retry: Option<RetryConfig>,
283 /// MCP (Model Context Protocol) server registry publishing
284 /// configuration. When `name` is empty (the default), the publisher is
285 /// skipped. The `mcp:` publisher block.
286 #[serde(default)]
287 pub mcp: McpConfig,
288 /// SchemaStore publisher. Registers the project's JSON Schema(s) on
289 /// SchemaStore at release time. When `schemas` is empty (the default),
290 /// the publisher is skipped. The `schemastore:` publisher block.
291 #[serde(default)]
292 pub schemastore: crate::config::publishers::SchemastoreConfig,
293 /// NPM package registry publishing configurations. One entry per
294 /// published package. In the default `optional-deps` mode anodizer emits
295 /// npm's native per-platform packages (biome / git-cliff pattern); in
296 /// `postinstall` mode it emits a download shim (the `npms:`
297 /// parity).
298 pub npms: Option<Vec<NpmConfig>>,
299 /// GemFury (fury.io) deb/rpm/apk publishing configurations. Mirrors
300 /// The `gemfury:` block. The legacy spelling
301 /// `furies:` is accepted via serde alias; a one-time deprecation
302 /// warning is emitted by [`warn_on_legacy_furies_alias`].
303 #[serde(alias = "furies")]
304 pub gemfury: Option<Vec<GemFuryConfig>>,
305 /// PyPI publishing configurations. One entry per published project.
306 /// Emits native `py3-none-<platform>` binary wheels from the built
307 /// binaries (plus an optional `maturin sdist`) and uploads them via
308 /// PyPI's legacy (twine-protocol) upload API. The `pypis:` block.
309 pub pypis: Option<Vec<PypiConfig>>,
310 /// homebrew-core formula-bump configurations. One entry per formula.
311 /// Bumps an existing formula in `Homebrew/homebrew-core` (or a formula
312 /// repository override) via the GitHub API and opens a pull request.
313 /// The `homebrew_cores:` block.
314 pub homebrew_cores: Option<Vec<HomebrewCoreConfig>>,
315 /// Per-crate metadata derived from each crate's `Cargo.toml [package]`
316 /// table (description / license / homepage / authors). Populated at
317 /// config-load time by [`Config::populate_derived_metadata`], keyed by
318 /// crate name. NOT a user-facing YAML field — it backs the
319 /// crate-aware `meta_*_for` accessors so a plain Rust project gets its
320 /// publisher metadata without repeating it in a top-level `metadata:`
321 /// block. A hand-written `metadata:` field and per-publisher overrides
322 /// still win.
323 #[serde(skip)]
324 #[schemars(skip)]
325 pub derived_metadata: BTreeMap<String, MetadataConfig>,
326}
327
328/// Helper schema function for the signs field (accepts object or array).
329fn signs_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
330 let mut schema = generator.subschema_for::<Vec<SignConfig>>();
331 schema.ensure_object().insert(
332 "description".to_owned(),
333 "Artifact signing configurations (cosign, GPG, etc.). Accepts a single object or array."
334 .into(),
335 );
336 schema
337}
338
339/// Helper schema function for the upx field (accepts object or array).
340fn upx_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
341 let mut schema = generator.subschema_for::<Vec<UpxConfig>>();
342 schema.ensure_object().insert(
343 "description".to_owned(),
344 "UPX binary compression configurations. Accepts a single object or array.".into(),
345 );
346 schema
347}
348
349/// Helper schema function for the sboms field (accepts object or array).
350fn sboms_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
351 let mut schema = generator.subschema_for::<Vec<SbomConfig>>();
352 schema.ensure_object().insert(
353 "description".to_owned(),
354 "SBOM generation configurations. Accepts a single object or array.".into(),
355 );
356 schema
357}
358
359fn default_dist() -> PathBuf {
360 PathBuf::from("./dist")
361}
362
363impl Default for Config {
364 fn default() -> Self {
365 Config {
366 version: None,
367 project_name: String::new(),
368 dist: default_dist(),
369 includes: None,
370 env_files: None,
371 defaults: None,
372 before: None,
373 after: None,
374 on_error: None,
375 before_publish: None,
376 crates: Vec::new(),
377 changelog: None,
378 signs: Vec::new(),
379 binary_signs: Vec::new(),
380 docker_signs: None,
381 upx: Vec::new(),
382 snapshot: None,
383 nightly: None,
384 announce: None,
385 report_sizes: None,
386 env: None,
387 variables: None,
388 publishers: None,
389 dockerhub: None,
390 artifactories: None,
391 cloudsmiths: None,
392 homebrew_casks: None,
393 version_files: None,
394 tag: None,
395 git: None,
396 partial: None,
397 workspaces: None,
398 source: None,
399 sboms: Vec::new(),
400 attestations: None,
401 release: None,
402 github_urls: None,
403 gitlab_urls: None,
404 gitea_urls: None,
405 force_token: None,
406 notarize: None,
407 metadata: None,
408 template_files: None,
409 monorepo: None,
410 makeselfs: Vec::new(),
411 install_scripts: Vec::new(),
412 appimages: Vec::new(),
413 verify_release: VerifyReleaseConfig::default(),
414 preflight: PreflightConfig::default(),
415 srpms: None,
416 milestones: None,
417 uploads: None,
418 aur_sources: None,
419 retry: None,
420 mcp: McpConfig::default(),
421 schemastore: crate::config::publishers::SchemastoreConfig::default(),
422 npms: None,
423 gemfury: None,
424 pypis: None,
425 homebrew_cores: None,
426 derived_metadata: BTreeMap::new(),
427 }
428 }
429}
430
431mod accessors;
432
433mod schema;
434pub use schema::*;
435
436/// Run a deserialization closure on a worker thread sized large enough that
437/// the `Config` derive (60+ `Option<NestedStruct>` fields) cannot exhaust
438/// the host's main-thread stack.
439///
440/// Background: debug builds of `serde_yaml_ng::from_value::<Config>` and
441/// `toml::from_str::<Config>` consume several MiB of stack because each
442/// generated visitor branch for the giant struct lives in a single
443/// monomorphised frame and debug builds neither inline nor tail-call. The
444/// Windows main-thread default reservation is 1 MiB, so any debug-built
445/// integration test that triggers full-config deserialization overflows
446/// before reaching the visitor's body.
447///
448/// Routing every full-`Config` deserialization through this helper keeps
449/// every entry-point platform-agnostic without resorting to per-platform
450/// linker flags or `RUST_MIN_STACK`.
451pub fn deserialize_on_worker<F, T>(f: F) -> anyhow::Result<T>
452where
453 F: FnOnce() -> anyhow::Result<T> + Send + 'static,
454 T: Send + 'static,
455{
456 use anyhow::Context as _;
457
458 // 8 MiB matches the Linux/macOS process default and comfortably exceeds
459 // the ~2 MiB peak observed for debug `Config` deserialization.
460 const WORKER_STACK_SIZE: usize = 8 * 1024 * 1024;
461
462 let handle = std::thread::Builder::new()
463 .stack_size(WORKER_STACK_SIZE)
464 .name("anodizer-config-deserialize".to_string())
465 .spawn(f)
466 .context("failed to spawn config deserialization worker thread")?;
467 match handle.join() {
468 Ok(result) => result,
469 Err(payload) => std::panic::resume_unwind(payload),
470 }
471}
472
473mod validate;
474pub use validate::*;
475
476mod publish_axis;
477pub(crate) use publish_axis::*;
478
479mod legacy;
480pub use legacy::*;
481
482// ---------------------------------------------------------------------------
483// EnvFilesConfig — accepts list of .env paths OR structured token file paths
484// ---------------------------------------------------------------------------
485
486mod env_files;
487pub use env_files::*;
488
489// ---------------------------------------------------------------------------
490// Defaults
491// ---------------------------------------------------------------------------
492
493mod defaults;
494pub use defaults::*;
495
496// ---------------------------------------------------------------------------
497// BuildIgnore — exclude specific os/arch combos from builds
498// ---------------------------------------------------------------------------
499
500mod build;
501pub use build::*;
502
503// ---------------------------------------------------------------------------
504// ArchivesConfig — untagged enum: false => Disabled, array => Configs
505// ---------------------------------------------------------------------------
506
507mod archives;
508pub use archives::*;
509
510mod completions;
511pub use completions::*;
512
513// ---------------------------------------------------------------------------
514// ReleaseConfig
515// ---------------------------------------------------------------------------
516
517mod release;
518pub use release::*;
519
520// ---------------------------------------------------------------------------
521// Shared publisher config types: RepositoryConfig, CommitAuthorConfig
522// ---------------------------------------------------------------------------
523
524mod publishers;
525pub use publishers::*;
526
527// ---------------------------------------------------------------------------
528// DockerV2Config
529// ---------------------------------------------------------------------------
530
531mod docker;
532pub use docker::*;
533
534// ---------------------------------------------------------------------------
535// NfpmConfig
536// ---------------------------------------------------------------------------
537
538mod nfpm;
539pub use nfpm::*;
540
541// ---------------------------------------------------------------------------
542// SnapcraftConfig
543// ---------------------------------------------------------------------------
544
545mod snapcraft;
546pub use snapcraft::*;
547// ---------------------------------------------------------------------------
548// DmgConfig / MsiConfig / PkgConfig / NsisConfig / AppBundleConfig / FlatpakConfig
549// ---------------------------------------------------------------------------
550
551mod installers;
552pub use installers::*;
553
554// ---------------------------------------------------------------------------
555// BlobConfig (S3/GCS/Azure cloud storage)
556// ---------------------------------------------------------------------------
557
558mod blob;
559pub use blob::*;
560
561// ---------------------------------------------------------------------------
562// PartialConfig (split/merge CI fan-out)
563// ---------------------------------------------------------------------------
564
565mod partial;
566pub use partial::*;
567
568// ---------------------------------------------------------------------------
569// BinstallConfig
570// ---------------------------------------------------------------------------
571
572mod binstall;
573pub use binstall::*;
574
575// ---------------------------------------------------------------------------
576// NotarizeConfig (macOS code signing and notarization)
577// ---------------------------------------------------------------------------
578
579mod notarize;
580pub use notarize::*;
581// ---------------------------------------------------------------------------
582// SourceConfig
583// ---------------------------------------------------------------------------
584
585mod source;
586pub use source::*;
587
588// ---------------------------------------------------------------------------
589// SbomConfig
590// ---------------------------------------------------------------------------
591
592mod sbom;
593pub use sbom::*;
594
595// ---------------------------------------------------------------------------
596// AttestationConfig
597// ---------------------------------------------------------------------------
598
599mod attestation;
600pub use attestation::*;
601
602// ---------------------------------------------------------------------------
603// VersionSyncConfig
604// ---------------------------------------------------------------------------
605
606mod version_sync;
607pub use version_sync::*;
608
609// ---------------------------------------------------------------------------
610// ChangelogConfig
611// ---------------------------------------------------------------------------
612
613mod changelog;
614pub use changelog::*;
615// ---------------------------------------------------------------------------
616// SignConfig / DockerSignConfig — lifted to `crate::signing`
617// ---------------------------------------------------------------------------
618//
619// see `crate::signing` for the type definitions. The
620// re-exports below preserve the historical
621// `anodizer_core::config::{SignConfig, DockerSignConfig}` import paths
622// used by every stage that consumes a sign config.
623
624pub use crate::signing::{AuthenticodeConfig, DockerSignConfig, SignConfig, SignVerifyConfig};
625
626// ---------------------------------------------------------------------------
627// UpxConfig
628// ---------------------------------------------------------------------------
629
630mod upx;
631pub use upx::*;
632
633// ---------------------------------------------------------------------------
634// SnapshotConfig
635// ---------------------------------------------------------------------------
636
637mod snapshot_nightly;
638pub use snapshot_nightly::*;
639
640mod cargo_metadata;
641pub use cargo_metadata::derive_metadata_from_cargo_toml;
642
643mod workspace_deps;
644pub use workspace_deps::{
645 derive_depends_on_from_cargo_toml, discover_cargo_workspace_member_names,
646 extract_workspace_deps,
647};
648
649/// Extract the name portion of a `"Name <email>"` maintainer/author string,
650/// dropping any `<…>` email suffix. Returns `None` when the result is empty
651/// (e.g. a bare-email `<ada@example.com>`), so a derived Vendor / OCI `vendor`
652/// value is never emitted blank.
653pub fn maintainer_name_only(maintainer: &str) -> Option<String> {
654 let name = maintainer.split('<').next().unwrap_or(maintainer).trim();
655 (!name.is_empty()).then(|| name.to_string())
656}
657
658// ---------------------------------------------------------------------------
659// TemplateFileConfig
660// ---------------------------------------------------------------------------
661
662mod templatefiles;
663pub use templatefiles::*;
664
665// ---------------------------------------------------------------------------
666// AnnounceConfig
667// ---------------------------------------------------------------------------
668mod announce;
669pub use announce::*;
670// ---------------------------------------------------------------------------
671// DockerHub description sync
672// ---------------------------------------------------------------------------
673
674mod dockerhub;
675pub use dockerhub::*;
676
677// ---------------------------------------------------------------------------
678// Artifactory publisher
679// ---------------------------------------------------------------------------
680
681mod artifactory;
682pub use artifactory::*;
683
684// ---------------------------------------------------------------------------
685// CloudSmith publisher
686// ---------------------------------------------------------------------------
687
688mod cloudsmith;
689pub use cloudsmith::*;
690
691// ---------------------------------------------------------------------------
692// PublisherConfig
693// ---------------------------------------------------------------------------
694
695mod publisher;
696pub use publisher::*;
697
698// ---------------------------------------------------------------------------
699// HooksConfig
700// ---------------------------------------------------------------------------
701
702mod hooks;
703pub use hooks::*;
704
705// ---------------------------------------------------------------------------
706// GitConfig
707// ---------------------------------------------------------------------------
708
709mod git_config;
710pub use git_config::*;
711
712// ---------------------------------------------------------------------------
713// MonorepoConfig
714// ---------------------------------------------------------------------------
715
716mod monorepo;
717pub use monorepo::*;
718
719// ---------------------------------------------------------------------------
720// TagConfig
721// ---------------------------------------------------------------------------
722
723mod tag;
724pub use tag::*;
725
726// ---------------------------------------------------------------------------
727// WorkspaceConfig
728// ---------------------------------------------------------------------------
729
730mod workspace;
731pub use workspace::*;
732
733// ---------------------------------------------------------------------------
734// RetryConfig (top-level `retry:` block — bridges to crate::retry::RetryPolicy)
735// ---------------------------------------------------------------------------
736
737mod retry;
738pub use retry::*;
739
740// ---------------------------------------------------------------------------
741// PostPublishPollConfig (per-publisher post-publish polling)
742// ---------------------------------------------------------------------------
743
744mod post_publish_poll;
745pub use post_publish_poll::*;
746
747// ---------------------------------------------------------------------------
748// VerifyReleaseConfig (top-level `verify_release:` post-publish gate)
749// ---------------------------------------------------------------------------
750
751mod verify_release;
752pub use verify_release::*;
753
754// ---------------------------------------------------------------------------
755// PreflightConfig (top-level `preflight:` pre-publish probe tuning)
756// ---------------------------------------------------------------------------
757
758mod preflight;
759pub use preflight::*;
760
761// ---------------------------------------------------------------------------
762// StringOrBool — accepts bool or template string in YAML
763// ---------------------------------------------------------------------------
764
765mod string_or_bool;
766pub use string_or_bool::*;
767
768// ---------------------------------------------------------------------------
769// MakeselfConfig + SrpmConfig — lifted to `crate::packagers`
770// ---------------------------------------------------------------------------
771//
772// All packaging config types live in their own modules under
773// `crate::packagers`. The re-exports below preserve the historical
774// `anodizer_core::config::{MakeselfConfig, MakeselfFile, SrpmConfig}`
775// import paths used by stages and tests.
776
777pub use crate::packagers::{
778 AppImageConfig, AppImageExtra, InstallScriptConfig, MakeselfConfig, MakeselfFile,
779 RuntimeHarvest, SrpmConfig,
780};
781pub(crate) use crate::packagers::{
782 appimages_schema, deserialize_appimages, deserialize_install_scripts, deserialize_makeselfs,
783 install_scripts_schema, makeselfs_schema,
784};
785
786// ---------------------------------------------------------------------------
787// MilestoneConfig
788// ---------------------------------------------------------------------------
789
790mod milestone;
791pub use milestone::*;
792
793// ---------------------------------------------------------------------------
794// UploadConfig (generic HTTP upload)
795// ---------------------------------------------------------------------------
796
797mod upload;
798pub use upload::*;
799
800// ---------------------------------------------------------------------------
801// AurSourceConfig
802// ---------------------------------------------------------------------------
803
804mod aur_source;
805pub use aur_source::*;
806
807// ---------------------------------------------------------------------------
808// McpConfig (MCP registry publisher)
809// ---------------------------------------------------------------------------
810
811mod mcp;
812pub use mcp::*;
813
814// ---------------------------------------------------------------------------
815// NpmConfig (NPM package registry publisher)
816// ---------------------------------------------------------------------------
817
818mod npm;
819pub use npm::*;
820
821// ---------------------------------------------------------------------------
822// GemFuryConfig (Gemfury / fury.io publisher)
823// ---------------------------------------------------------------------------
824
825mod gemfury;
826pub use gemfury::*;
827
828// ---------------------------------------------------------------------------
829// PypiConfig (PyPI binary-wheel publisher)
830// ---------------------------------------------------------------------------
831
832mod pypi;
833pub use pypi::*;
834
835// ---------------------------------------------------------------------------
836// HomebrewCoreConfig (homebrew-core formula-bump publisher)
837// ---------------------------------------------------------------------------
838
839mod homebrew_core;
840pub use homebrew_core::*;
841
842// ---------------------------------------------------------------------------
843// Well-known config file discovery
844// ---------------------------------------------------------------------------
845
846mod discovery;
847pub use discovery::*;
848
849// ---------------------------------------------------------------------------
850// Tests
851// ---------------------------------------------------------------------------
852
853#[cfg(test)]
854mod tests;