Skip to main content

anodizer_core/config/
aur_source.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4use super::publishers::CommitAuthorConfig;
5use super::{StringOrBool, deserialize_string_or_bool_opt};
6
7// ---------------------------------------------------------------------------
8// AurSourceConfig
9// ---------------------------------------------------------------------------
10
11#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
12#[serde(default, deny_unknown_fields)]
13pub struct AurSourceConfig {
14    /// Override the package name (default: crate name, no -bin suffix).
15    pub name: Option<String>,
16    /// Build IDs filter.
17    pub ids: Option<Vec<String>>,
18    /// Commit author with optional signing.
19    pub commit_author: Option<CommitAuthorConfig>,
20    /// Custom commit message template.
21    pub commit_msg_template: Option<String>,
22    /// Short description of the package.
23    pub description: Option<String>,
24    /// Project homepage URL.
25    pub homepage: Option<String>,
26    /// SPDX license identifier.
27    pub license: Option<String>,
28    /// Skip publishing. `"true"` always skips; `"auto"` skips for prereleases.
29    #[serde(deserialize_with = "deserialize_string_or_bool_opt", default)]
30    pub skip_upload: Option<StringOrBool>,
31    /// Custom URL template for download URLs.
32    pub url_template: Option<String>,
33    /// PKGBUILD maintainer entries.
34    pub maintainers: Option<Vec<String>>,
35    /// Contributors listed in PKGBUILD comments.
36    pub contributors: Option<Vec<String>>,
37    /// Packages this PKGBUILD provides.
38    pub provides: Option<Vec<String>>,
39    /// Packages this PKGBUILD conflicts with.
40    pub conflicts: Option<Vec<String>>,
41    /// Runtime dependencies.
42    pub depends: Option<Vec<String>>,
43    /// Optional dependencies.
44    pub optdepends: Option<Vec<String>>,
45    /// Build-time dependencies (source packages need these).
46    pub makedepends: Option<Vec<String>>,
47    /// Backup files to preserve on upgrade.
48    pub backup: Option<Vec<String>>,
49    /// Package release number (default: "1").
50    pub rel: Option<String>,
51    /// Custom `prepare()` function body for PKGBUILD.
52    pub prepare: Option<String>,
53    /// Custom `build()` function body for PKGBUILD.
54    pub build: Option<String>,
55    /// Custom `package()` function body for PKGBUILD.
56    pub package: Option<String>,
57    /// AUR SSH git URL override. Defaults to
58    /// `ssh://aur@aur.archlinux.org/<package>.git`, derived from the resolved
59    /// package name; set this only for a non-standard endpoint.
60    pub git_url: Option<String>,
61    /// Custom SSH command for git operations.
62    pub git_ssh_command: Option<String>,
63    /// Path to SSH private key file.
64    pub private_key: Option<String>,
65    /// Subdirectory in the git repo for committed files.
66    pub directory: Option<String>,
67    /// Skip this config.
68    /// Accepts the legacy `disable:` spelling via serde alias for back-compat.
69    #[serde(
70        alias = "disable",
71        deserialize_with = "deserialize_string_or_bool_opt",
72        default
73    )]
74    pub skip: Option<StringOrBool>,
75    /// Content for a .install file (post-install/pre-remove scripts).
76    pub install: Option<String>,
77    /// Explicit architecture list (default: auto-detect from artifacts).
78    pub arches: Option<Vec<String>>,
79    /// `x86_64` micro-architecture variant — `v1` (baseline), `v2`, `v3`
80    /// (AVX2), or `v4`. Constrained
81    /// to a typed enum because AUR source pkgs build from the upstream
82    /// tarball (no binary artifacts to filter), so the value's only role
83    /// is as the `Amd64` template var consumed by `prepare:` / `build:` /
84    /// `package:` script bodies — typos must fail at parse time, not
85    /// silently render an invalid string into the PKGBUILD.
86    /// When unset, defaults to `v1` at template-render time.
87    pub amd64_variant: Option<Amd64Variant>,
88    /// Override whether this publisher failing should fail the overall release.
89    ///
90    /// Default: `false` — a failure here is logged but does not abort the release.
91    /// Set to `true` to fail the release on any error.
92    #[serde(default, skip_serializing_if = "Option::is_none")]
93    pub required: Option<bool>,
94    /// Template-conditional gate: when the rendered result is falsy
95    /// (`"false"` / `"0"` / `"no"` / empty), the AUR source config is
96    /// skipped. Render failure hard-errors. The
97    /// `aur_sources[].if:`.
98    #[serde(rename = "if")]
99    pub if_condition: Option<String>,
100    /// When `true`, a triggered rollback leaves this publisher's work in
101    /// place rather than attempting to undo it. Default `false`.
102    pub retain_on_rollback: Option<bool>,
103}
104
105/// `x86_64` micro-architecture level — `v1` (baseline), `v2`, `v3`, or `v4`.
106/// Typed so a typo fails at config-parse time instead of flowing on as an
107/// arbitrary string. This is the ONE type for every `amd64_variant:` config
108/// field: [`BuildConfig::amd64_variant`](super::BuildConfig::amd64_variant) —
109/// where the declared level names a tuned group's artifacts and derived asset
110/// names — [`AurSourceConfig::amd64_variant`], where it constrains the
111/// `prepare:` / `build:` / `package:` template var surface to a known set
112/// (AUR source pkgs build from the upstream tarball, so an invalid value
113/// would otherwise render silently into the PKGBUILD), and the variant
114/// *selector* on every installer/packager/publisher config
115/// (dmg/msi/nsis/nfpm, homebrew/scoop/chocolatey/winget/krew/nix/aur), where
116/// a free-string typo would silently match only variant-less baseline
117/// archives and ship the untuned binary. Artifact metadata stays
118/// string-typed; selectors compare via [`Amd64Variant::as_str`].
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
120#[serde(rename_all = "snake_case")]
121pub enum Amd64Variant {
122    V1,
123    V2,
124    V3,
125    V4,
126}
127
128impl Amd64Variant {
129    /// Canonical lowercase string form (`"v1"`..`"v4"`). Matches the
130    /// `Goamd64` external surface and the value rendered into the PKGBUILD
131    /// `Amd64` template var.
132    pub fn as_str(&self) -> &'static str {
133        match self {
134            Amd64Variant::V1 => "v1",
135            Amd64Variant::V2 => "v2",
136            Amd64Variant::V3 => "v3",
137            Amd64Variant::V4 => "v4",
138        }
139    }
140}
141
142#[cfg(test)]
143mod tests {
144    use super::*;
145
146    #[test]
147    fn amd64_variant_as_str_covers_every_arm() {
148        assert_eq!(Amd64Variant::V1.as_str(), "v1");
149        assert_eq!(Amd64Variant::V2.as_str(), "v2");
150        assert_eq!(Amd64Variant::V3.as_str(), "v3");
151        assert_eq!(Amd64Variant::V4.as_str(), "v4");
152    }
153
154    #[test]
155    fn amd64_variant_deserializes_snake_case() {
156        // The `snake_case` serde rename is the load-bearing contract: a
157        // `v3` in YAML must parse to the typed variant so a typo fails at
158        // parse time instead of rendering an invalid PKGBUILD.
159        let v: Amd64Variant = serde_json::from_str("\"v3\"").expect("v3 parses");
160        assert_eq!(v, Amd64Variant::V3);
161        assert!(
162            serde_json::from_str::<Amd64Variant>("\"avx2\"").is_err(),
163            "an unknown variant must be rejected at parse time"
164        );
165    }
166
167    #[test]
168    fn skip_alias_disable_round_trips() {
169        // `disable:` is the legacy spelling; serde alias must map it onto
170        // `skip` so old configs keep working.
171        let cfg: AurSourceConfig =
172            serde_yaml_ng::from_str("disable: true").expect("legacy disable: parses");
173        assert!(matches!(cfg.skip, Some(StringOrBool::Bool(true))));
174    }
175}