oranda/config/components/artifacts/
mod.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4use crate::config::{ApplyLayer, ApplyValExt};
5
6mod package_managers;
7pub use package_managers::{PackageManagersConfig, PackageManagersLayer};
8
9#[derive(Debug, Deserialize, JsonSchema)]
10#[serde(rename_all = "lowercase")]
11enum ArtifactSystem {
12    Windows,
13    Windows64,
14    WindowsArm,
15
16    Mac,
17    MacPpc,
18    Mac32,
19    MacSilicon,
20
21    Linux,
22    LinuxUbuntu,
23    LinuxDebian,
24    LinuxMandriva,
25    LinuxRedhat,
26    LinuxFedora,
27    LinuxSuse,
28    LinuxGentoo,
29
30    Ios,
31    Android,
32
33    Freebsd,
34}
35
36/// Info about downloadable artifacts / installers / package-managers (complete version)
37#[derive(Debug, Clone)]
38pub struct ArtifactsConfig {
39    pub auto: bool,
40    pub cargo_dist: bool,
41    pub match_package_names: bool,
42    pub package_managers: PackageManagersConfig,
43    pub hidden: Vec<String>,
44}
45
46/// Setting for downloadable artifacts, installers, and package-managers
47#[derive(Debug, Default, Serialize, Deserialize, JsonSchema)]
48#[serde(deny_unknown_fields)]
49pub struct ArtifactsLayer {
50    /// Whether to enable auto-detection of artifacts/installers in your Releases
51    ///
52    /// This allows us to look at the assets listed in a Release and use their
53    /// names to guess their platforms and what they're for.
54    ///
55    /// If `cargo_dist` is also enabled, that data source will be preferred over this one
56    /// for the assets that cargo-dist knows about, as it should presumably be more reliable.
57    ///
58    /// Artifact auto-detection currently includes the following concepts:
59    ///
60    /// * **platforms**: if an artifact name contains a [rust target triple][triple] then we will
61    ///   assume it's specific to that platform. Otherwise we will infer platform using extension
62    ///   (with rules like "ps1 scripts are for windows, sh scripts are for unix").
63    /// * **archives**: if a platform-specific artifact name ends with an archive format
64    ///   (.tar.*, .zip .7z, .rar...) then we will assume it contains the binaries
65    ///    for that platform and recommend its download accordingly.
66    /// * **scripts**: if an artifact name contains "install" and ends with ".sh" or ".ps1"
67    ///   we will assume it's an install script and generate an appropriate `curl | sh` for
68    ///   it (`irm | iex` for ps1)
69    /// * **bundles**: if an artifact name ends with a known format for some kind of
70    ///   installer/bundle we will recommend its download at a higher priority, assuming
71    ///   this is a very good way to install your app. This includes ".msi", ".app", ".dmg",
72    ///   ".deb", ".rpm", ".pkg.tar.*", ".flatpak", and ".snap".
73    ///
74    /// [triple]: https://doc.rust-lang.org/nightly/rustc/platform-support.html
75    pub auto: Option<bool>,
76    /// Whether to enable cargo-dist integration
77    ///
78    /// If enabled, we will check every Release of your project for a dist-manifest.json
79    /// and use that as the authoritative source of information on the artifacts uploaded to your
80    /// Release.
81    ///
82    /// This integration only works if `project.repository` points to a GitHub repo (see that field's
83    /// docs for details).
84    ///
85    /// We default this to true if we find `[workspace.metadata.dist]` in your Cargo.toml
86    pub cargo_dist: Option<bool>,
87    /// Whether to only show releases that contain the project name in their tag name
88    ///
89    /// This is useful if you have multiple projects in the same repo and want to only
90    /// show releases for that specific project on the generated project page.
91    ///
92    /// This defaults to false.
93    pub match_package_names: Option<bool>,
94    /// Snippets saying how to install your project using various package-managers
95    ///
96    /// These are grouped into "preferred" and "additional"
97    ///
98    /// - "additional" packages only show up on the install page
99    /// - "preferred" packages show up as options in the install widget
100    ///
101    /// Both are ordered maps of "label": "one-liner script"
102    ///
103    /// For example:
104    ///
105    /// ```json
106    /// {
107    ///   "components": {
108    ///     "artifacts": {
109    ///       "package_managers": {
110    ///         "preferred": {
111    ///           "npm": "npm -i @axodotdev/axolotlsay",
112    ///           "cargo": "cargo install axolotlsay"
113    ///         },
114    ///         "additional": {
115    ///           "binstall": "cargo binstall axolotlsay"
116    ///         }
117    ///       }
118    ///     }
119    ///   }
120    /// }
121    /// ```
122    ///
123    /// If a package_manager has the same name as an auto-detected installer,
124    /// it will overwrite the auto-detected result, allowing you to specify something
125    /// more preferrable (relevant to cargo-dist npm packages).
126    pub package_managers: Option<PackageManagersLayer>,
127    /// Artifact/installer listings to supress from the install widget's tabs
128    /// and the install page's package-manager/script listings.
129    ///
130    /// Currently this won't supress them from the install page's "downloads" table
131    ///
132    /// Example (hide auto-detect shell scripts): `"hidden": ["shell", "powershell"]`
133    pub hidden: Option<Vec<String>>,
134}
135
136impl Default for ArtifactsConfig {
137    fn default() -> Self {
138        ArtifactsConfig {
139            auto: false,
140            cargo_dist: false,
141            match_package_names: false,
142            package_managers: PackageManagersConfig::default(),
143            hidden: vec![],
144        }
145    }
146}
147impl ApplyLayer for ArtifactsConfig {
148    type Layer = ArtifactsLayer;
149    fn apply_layer(&mut self, layer: Self::Layer) {
150        // This is intentionally written slightly cumbersome to make you update this
151        let ArtifactsLayer {
152            auto,
153            cargo_dist,
154            match_package_names,
155            package_managers,
156            hidden,
157        } = layer;
158
159        self.auto.apply_val(auto);
160        self.cargo_dist.apply_val(cargo_dist);
161        self.match_package_names.apply_val(match_package_names);
162        self.package_managers.apply_val_layer(package_managers);
163        // In the future this might want to be `extend`
164        self.hidden.apply_val(hidden);
165    }
166}
167
168impl ArtifactsConfig {
169    pub fn has_some(&self) -> bool {
170        self.cargo_dist || self.auto || !self.package_managers.is_empty()
171    }
172}