oranda/config/components/
mod.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4mod artifacts;
5mod changelog;
6mod funding;
7mod mdbooks;
8
9use crate::config::components::changelog::{ChangelogConfig, ChangelogLayer};
10pub use artifacts::{ArtifactsConfig, ArtifactsLayer, PackageManagersConfig, PackageManagersLayer};
11pub use funding::{FundingConfig, FundingLayer};
12pub use mdbooks::{MdBookConfig, MdBookLayer};
13
14use super::{ApplyBoolLayerExt, ApplyLayer, ApplyOptExt, BoolOr};
15
16/// Extra components (complete version)
17#[derive(Debug, Clone)]
18pub struct ComponentConfig {
19    /// Whether to enable the changelog page
20    ///
21    /// In the future this may become more complex, but for now this is it
22    pub changelog: Option<ChangelogConfig>,
23    /// The config for using mdbook for a "docs" page
24    ///
25    /// This defaults to Some(Default) and is set to None
26    /// if we fail to auto-detect necessary information or if the user
27    /// manually disables it.
28    pub mdbook: Option<MdBookConfig>,
29    /// The config for for the funding page
30    ///
31    /// This defaults to Some(Default) and is set to None
32    /// if we fail to auto-detect necessary information or if the user
33    /// manually disables it.
34    pub funding: Option<FundingConfig>,
35    /// The config for the "install" page and widget
36    ///
37    /// This defaults to Some(Default) and is set to None
38    /// if we fail to auto-detect necessary information or if the user
39    /// manually disables it.
40    pub artifacts: Option<ArtifactsConfig>,
41    /// Which source to fetch release data from.
42    pub source: Option<ReleasesSource>,
43}
44/// Extra components
45#[derive(Debug, Serialize, Deserialize, JsonSchema)]
46#[serde(deny_unknown_fields)]
47pub struct ComponentLayer {
48    /// Whether to enable the changelog page
49    ///
50    /// In the future this may become more complex, but for now this is just a bool
51    pub changelog: Option<BoolOr<ChangelogLayer>>,
52    /// The config for building and embedding an mdbook on your site
53    ///
54    /// The book will be linked as "docs" in the nav, and restyled to match
55    /// the theme you have for the rest of your oranda site. We use a vendored
56    /// copy of mdbook, and not the one you have installed on your system.
57    ///
58    /// This feature is enabled by default if we find a "book.toml" in
59    /// "./", "./book/", or "./docs/".
60    ///
61    /// It can be completely disabled by setting `"mdbook": false`.
62    ///  
63    /// More precise settings can be used with `"mdbook": { ... }`.
64    pub mdbook: Option<BoolOr<MdBookLayer>>,
65    /// The config for for the "funding" page
66    ///
67    /// This feature is enabled by default if we find a file at "funding.md"
68    /// or "./.github/FUNDING.yml".
69    ///
70    /// It can be completely disabled by setting `"funding": false`.
71    ///  
72    /// More precise settings can be used with `"funding": { ... }`.
73    pub funding: Option<BoolOr<FundingLayer>>,
74    /// The config for the "install" page and widget
75    ///
76    /// # Data Sources
77    ///
78    /// Once enabled we consider data for 3 possible data sources:
79    ///
80    /// * The `components.artifacts.package_managers` keys (see those configs for details)
81    /// * Your GitHub Releases (if we have a URL to a GitHub repo in `project.repository`)
82    /// * dist-manifest.json in your GitHub Releases (if cargo-dist support is enabled)
83    ///
84    /// These sources can give us:
85    ///
86    /// * Downloadable Files (`my-app-x86_64-pc-windows-msvc.zip`)
87    /// * Runnable One-Liners (`curl install.sh | sh`, `npm install ...`)
88    ///
89    /// Which can be known/assumed to be:
90    ///
91    /// * Runnable/Installable on specific platforms (don't recommend `install.sh` on windows)
92    /// * Preferred over others (install script nicer than downloadable tarballs)
93    /// * Have checksums (`my-app-x86_64-pc-windows-msvc.zip.sha256`)
94    /// * Be viewable (`install.sh`)
95    ///
96    /// GitHub Releses support will also get us a list of Releases these will be grouped into
97    /// We will try to intelligently pick a "Latest Release" to display up-front:
98    ///
99    /// * If there's cargo-dist releases, prefer the latest one of those (stable over prereleases)
100    ///     * This is a hack to make monorepos behave better while we don't fully support them
101    /// * Otherwise if there's a stable release, pick the latest stable release
102    /// * Otherwise pick the latest prerelease
103    ///
104    /// Otherwise we will place all of this under one artifical "current release".
105    ///
106    ///
107    /// ## Github Releases
108    ///
109    /// GitHub Releases integration is a fuzzy system of auto-detection based on the filenames
110    /// of assets we find uploaded to each GitHub Release. If we find a filename contains
111    /// something that looks like a target triple ("x86_64-pc-windows-msvc") we will assume
112    /// the artifact is only for that platform.
113    ///
114    /// If we find files with names like "..install..sh" we will assume those are curl-sh
115    /// installer scripts.
116    ///
117    /// If we find a platform-specific tarball/zip, we will assume it's an archive containing
118    /// prebuilt binaries for that platform.
119    ///
120    /// We also experimentally detect things like .deb files but it's only half-baked right now.
121    ///
122    ///
123    /// # The Install Page
124    ///
125    /// The Install Page will show up in your nav if this feature is at all enabled.
126    ///
127    /// It will show:
128    ///
129    /// 1. The Install Widget (see below)
130    /// 2. All the Runnable One-Liners for the Latest Release
131    /// 3. A table of downloadable artifacts (tarballs/zips) for the Latest Release.
132    ///
133    ///
134    /// # The Install Widget
135    ///
136    /// The Install Widget will show up on your front page and install page if
137    /// this feature is at all enabled. Although currently it will auto-hide
138    /// if there's absolutely nothing to show (#305).
139    ///
140    /// It will autodetect the user's current platform and try to recommend an installation method.
141    ///
142    /// If there are multiple supported platforms with different installation methods,
143    /// a "platform" dropdown will appear to override the auto-detect.
144    ///
145    /// If there are multiple installation options for a platform, we will present them as tabs,
146    /// roughly in decreasing order of preference (first tab is always best).
147    ///
148    /// Preference is currently fuzzy, but roughly:
149    ///
150    /// * platform-native solutions like msi's or debs will be recommended first
151    /// * installer scripts will be shown after that
152    /// * custom package_managers will be shown after that
153    /// * tarballs/zips will be shown last
154    ///
155    /// If no installation methods are found for the user's platform, they will be linked to
156    /// the install page and offered the platform dropdown to override.
157    ///
158    ///
159    /// # Enabling / Disabling
160    ///
161    /// This feature is enabled if:
162    ///
163    /// * cargo-dist support is enabled
164    ///   * `artifacts.cargo_dist: true` is set
165    ///   * we find `[workspace.metadata.dist]` in your Cargo.toml
166    /// * you set a package_manager in `artifacts.package_managers`
167    ///
168    /// It can be completely disabled by setting `"artifacts": false`.
169    ///  
170    /// More precise settings can be used with `"artifacts": { ... }`.
171    ///
172    /// FIXME(#397): there is currently an expressivity hole here: there is no way to *just*
173    /// turn on plain GitHub Releases integration. You either need to have cargo-dist
174    /// integration enabled, or add a random package_manager to make us enable it.
175    pub artifacts: Option<BoolOr<ArtifactsLayer>>,
176    /// Where we should attempt to fetch release data from.
177    pub source: Option<ReleasesSource>,
178}
179
180/// Denotes a host for releases. Historically, this has only been GitHub, but we now also
181/// support alternative providers.
182///
183/// - "github": Attempt to fetch releases from the GitHub repository the user set in their
184///   configuration.
185/// - "axodotdev": Attempt to fetch from axo Releases, using the GitHub repository the user
186///   has set in their configuration as the project name.
187#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
188#[serde(rename_all = "lowercase")]
189pub enum ReleasesSource {
190    GitHub,
191    Axodotdev,
192}
193
194impl Default for ComponentConfig {
195    fn default() -> Self {
196        ComponentConfig {
197            changelog: Some(ChangelogConfig::default()),
198            mdbook: Some(MdBookConfig::default()),
199            funding: Some(FundingConfig::default()),
200            artifacts: Some(ArtifactsConfig::default()),
201            source: Some(ReleasesSource::GitHub),
202        }
203    }
204}
205impl ApplyLayer for ComponentConfig {
206    type Layer = ComponentLayer;
207    fn apply_layer(&mut self, layer: Self::Layer) {
208        // This is intentionally written slightly cumbersome to make you update this
209        let ComponentLayer {
210            changelog,
211            mdbook,
212            funding,
213            artifacts,
214            source,
215        } = layer;
216        self.changelog.apply_bool_layer(changelog);
217        self.mdbook.apply_bool_layer(mdbook);
218        self.funding.apply_bool_layer(funding);
219        self.artifacts.apply_bool_layer(artifacts);
220        self.source.apply_opt(source);
221    }
222}
223impl ComponentConfig {
224    /// Convenience for checking if the artifacts component is actually enabled
225    /// because a ton of code was repeating this due to the extra Option.
226    pub fn artifacts_enabled(&self) -> bool {
227        self.artifacts
228            .as_ref()
229            .map(|a| a.has_some())
230            .unwrap_or(false)
231    }
232}