Skip to main content

anodizer_core/config/publishers/
winget.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4use super::super::{PostPublishPollConfig, StringOrBool, deserialize_string_or_bool_opt};
5use super::{CommitAuthorConfig, RepositoryConfig};
6
7// ---------------------------------------------------------------------------
8// WingetConfig
9// ---------------------------------------------------------------------------
10
11#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
12#[serde(default, deny_unknown_fields)]
13pub struct WingetConfig {
14    /// Override the package name (default: crate name).
15    pub name: Option<String>,
16    /// Package name as displayed (default: same as name).
17    pub package_name: Option<String>,
18    /// WinGet package identifier (e.g. "Publisher.AppName"). Auto-generated if empty.
19    pub package_identifier: Option<String>,
20    /// Publisher name (required).
21    pub publisher: Option<String>,
22    /// Publisher homepage URL shown in the WinGet manifest.
23    pub publisher_url: Option<String>,
24    /// Publisher support URL.
25    pub publisher_support_url: Option<String>,
26    /// Privacy policy URL.
27    pub privacy_url: Option<String>,
28    /// Author name.
29    pub author: Option<String>,
30    /// Copyright notice.
31    pub copyright: Option<String>,
32    /// Copyright URL.
33    pub copyright_url: Option<String>,
34    /// License identifier (required, e.g. "MIT").
35    pub license: Option<String>,
36    /// License URL.
37    pub license_url: Option<String>,
38    /// Short description (required, max 256 chars).
39    pub short_description: Option<String>,
40    /// Full package description displayed in the WinGet gallery.
41    pub description: Option<String>,
42    /// Project homepage URL.
43    pub homepage: Option<String>,
44    /// Custom URL template for download URLs (overrides release URL).
45    pub url_template: Option<String>,
46    /// Build IDs filter: only include artifacts whose `id` is in this list.
47    pub ids: Option<Vec<String>>,
48    /// Skip publishing. `"true"` always skips; `"auto"` skips for prereleases.
49    /// Accepts bool or template string.
50    #[serde(deserialize_with = "deserialize_string_or_bool_opt", default)]
51    pub skip_upload: Option<StringOrBool>,
52    /// Custom commit message template.
53    pub commit_msg_template: Option<String>,
54    /// Manifest file path (auto-generated if empty from publisher/name/version).
55    pub path: Option<String>,
56    /// Release notes for this version.
57    pub release_notes: Option<String>,
58    /// URL to full release notes.
59    pub release_notes_url: Option<String>,
60    /// Post-install notes shown to the user.
61    pub installation_notes: Option<String>,
62    /// Tags for package discovery (lowercased, spaces→hyphens).
63    pub tags: Option<Vec<String>>,
64    /// Package dependencies.
65    pub dependencies: Option<Vec<WingetDependency>>,
66    /// Unified repository config with branch, token, PR, git SSH support.
67    /// (Replaces the legacy `manifests_repo: WingetManifestsRepoConfig`.)
68    pub repository: Option<RepositoryConfig>,
69    /// Commit author with optional signing.
70    pub commit_author: Option<CommitAuthorConfig>,
71    /// Product code for the installer (used in Add/Remove Programs).
72    pub product_code: Option<String>,
73    /// Short invoke alias shown as the package `Moniker` (e.g. `rg` for
74    /// ripgrep, `fd` for fd). This is the command users type, NOT the
75    /// package/crate name. When unset, anodizer derives it from the single
76    /// published binary name; with multiple binaries and no override the
77    /// Moniker is omitted (winget treats it as optional).
78    ///
79    /// Example: `moniker: "rg"`.
80    pub moniker: Option<String>,
81    /// Documentation links rendered as the `Documentations[]` block on the
82    /// locale manifest. Each entry is a `{ label, url }` pair surfaced in the
83    /// winget gallery (real ripgrep emits a `FAQ` and a `User Guide` entry).
84    /// Omitted entirely when empty.
85    ///
86    /// Example:
87    /// ```yaml
88    /// documentations:
89    ///   - label: "User Guide"
90    ///     url: "https://github.com/owner/repo/blob/master/GUIDE.md"
91    /// ```
92    pub documentations: Option<Vec<WingetDocumentation>>,
93    /// Installer `UpgradeBehavior` for every installer entry. winget accepts
94    /// `install`, `uninstallPrevious`, and `deny`. Defaults to `install` —
95    /// the correct behavior for portable-zip CLI tools (`uninstallPrevious`
96    /// forces a clobbering reinstall).
97    ///
98    /// Example: `upgrade_behavior: "uninstallPrevious"`.
99    pub upgrade_behavior: Option<String>,
100    /// Silent-install switch string emitted as `InstallerSwitches.Silent` for
101    /// actual installers (`wix`/`msi`/`exe`/`nsis`). When unset, anodizer
102    /// derives the switch from the installer type (`/quiet` for msi, `/S` for
103    /// exe/nsis). Never emitted for `zip`/`portable` artifacts.
104    ///
105    /// Example: `silent_switch: "/qn"`.
106    pub silent_switch: Option<String>,
107    /// Artifact selection: "archive" (default), "msi", or "nsis".
108    #[serde(rename = "use")]
109    pub use_artifact: Option<String>,
110    /// amd64 microarchitecture variant filter (e.g. "v1", "v2", "v3", "v4").
111    /// Only artifacts matching this variant are included. Default: "v1".
112    pub amd64_variant: Option<String>,
113    /// Post-publish PR-validation polling settings. Polling is
114    /// disabled by default — winget-pkgs PR validation routinely
115    /// takes hours to days, and blocking a CI workflow on that wait
116    /// is wrong. Opt in per-publisher with
117    /// `post_publish_poll: { enabled: true }` when running locally and
118    /// willing to wait, or disable globally via `--no-post-publish-poll`.
119    pub post_publish_poll: Option<PostPublishPollConfig>,
120    /// When true, force-push the updated manifest to the existing PR branch
121    /// when a PR for the same head branch already exists. The PR content is
122    /// updated in place rather than creating a duplicate. When false (default),
123    /// the push is skipped and a warning is emitted so the operator sees that
124    /// the publisher did not update the PR.
125    #[serde(deserialize_with = "deserialize_string_or_bool_opt", default)]
126    pub update_existing_pr: Option<StringOrBool>,
127    /// Override whether this publisher failing should fail the overall release.
128    ///
129    /// Default: `false` — a failure here is logged but does not abort the release.
130    /// Set to `true` to fail the release on any error.
131    #[serde(default, skip_serializing_if = "Option::is_none")]
132    pub required: Option<bool>,
133    /// Template-conditional gate: when the rendered result is falsy
134    /// (`"false"` / `"0"` / `"no"` / empty), the WinGet publisher is
135    /// skipped. Render failure hard-errors. Config key: `winget[].if:`.
136    #[serde(rename = "if")]
137    pub if_condition: Option<String>,
138    /// When `true`, a triggered rollback leaves this publisher's work in
139    /// place rather than attempting to undo it. Default `false`.
140    pub retain_on_rollback: Option<bool>,
141}
142
143/// A single documentation link rendered into the winget locale manifest's
144/// `Documentations[]` block as `{ DocumentLabel, DocumentUrl }`.
145#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
146#[serde(default, deny_unknown_fields)]
147pub struct WingetDocumentation {
148    /// Display label for the link (e.g. `FAQ`, `User Guide`).
149    pub label: String,
150    /// Target URL for the documentation entry.
151    pub url: String,
152}
153
154/// WinGet package dependency.
155#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
156#[serde(default, deny_unknown_fields)]
157pub struct WingetDependency {
158    /// WinGet package identifier of the dependency (e.g., "Publisher.App").
159    pub package_identifier: String,
160    /// Minimum required version of the dependency.
161    pub minimum_version: Option<String>,
162}