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