anodizer-core 0.21.0

Core configuration, context, and template engine for the anodizer release tool
Documentation
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use super::super::{
    Amd64Variant, PostPublishPollConfig, StringOrBool, deserialize_string_or_bool_opt,
};
use super::RepositoryConfig;

// ---------------------------------------------------------------------------
// ChocolateyConfig
// ---------------------------------------------------------------------------

#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct ChocolateyConfig {
    /// Override the package name (default: crate name).
    pub name: Option<String>,
    /// Build IDs filter: only include artifacts whose `id` is in this list.
    pub ids: Option<Vec<String>>,
    /// Unified project repo config (owner/name). Used to derive
    /// `<projectUrl>` (the Chocolatey gallery link) and download URLs.
    /// `<projectUrl>` resolves through `project_url:` (if set) → derived
    /// `https://github.com/{repository.owner}/{repository.name}`.
    pub repository: Option<RepositoryConfig>,
    /// URL shown as the package source in the Chocolatey gallery.
    pub package_source_url: Option<String>,
    /// Package owners (Chocolatey gallery user).
    pub owners: Option<String>,
    /// Package title (default: project name).
    pub title: Option<String>,
    /// Package author(s) displayed in the Chocolatey gallery.
    pub authors: Option<String>,
    /// Project homepage URL.
    pub project_url: Option<String>,
    /// Custom URL template for download URLs (overrides release URL).
    pub url_template: Option<String>,
    /// URL to the package icon image shown in the Chocolatey gallery.
    pub icon_url: Option<String>,
    /// Copyright notice.
    pub copyright: Option<String>,
    /// Package description (supports markdown).
    pub description: Option<String>,
    /// SPDX license expression (e.g. "MIT", "Apache-2.0", "MIT OR Apache-2.0").
    /// Not emitted as a nuspec element — Chocolatey CLI does not support the
    /// NuGet `<license>` element (it warns CHCU0002: "use <licenseUrl>
    /// instead") — it gates the `<licenseUrl>` derivation: a single
    /// identifier derives a LICENSE blob URL; a compound expression has no
    /// single canonical file, so set `license_url` explicitly.
    pub license: Option<String>,
    /// Optional explicit `<licenseUrl>` — Chocolatey's only supported license
    /// metadata. When unset, anodizer derives a real GitHub
    /// `…/blob/<tag>/LICENSE` URL from `repository` (what ripgrep / fd /
    /// gh ship); when no repository is known or `license` is a compound SPDX
    /// expression, no `<licenseUrl>` is emitted.
    /// anodizer never synthesizes an `opensource.org/licenses/<spdx>` URL —
    /// it 404s for compound SPDX and gets the package rejected at moderation.
    pub license_url: Option<String>,
    /// Require license acceptance before install.
    pub require_license_acceptance: Option<bool>,
    /// Source code project URL (`<projectSourceUrl>`). Defaults to the derived
    /// `repository` URL when unset.
    pub project_source_url: Option<String>,
    /// Documentation URL.
    pub docs_url: Option<String>,
    /// Bug tracker URL (`<bugTrackerUrl>`). Defaults to `{repository}/issues`
    /// when unset.
    pub bug_tracker_url: Option<String>,
    /// Tags for the Chocolatey gallery (joined with single spaces in the
    /// emitted nuspec). Always a typed list — the legacy
    /// space-separated-string form was dropped now for
    /// IDE-completion friendliness and to remove whitespace ambiguity.
    pub tags: Option<Vec<String>>,
    /// Short summary of the package.
    pub summary: Option<String>,
    /// Release notes for this version.
    pub release_notes: Option<String>,
    /// Package dependencies with optional version constraints.
    pub dependencies: Option<Vec<ChocolateyDependency>>,
    /// Chocolatey API key for `choco push`. Falls back to `CHOCOLATEY_API_KEY` env var.
    pub api_key: Option<String>,
    /// Push source URL (default: "https://push.chocolatey.org/").
    pub source_repo: Option<String>,
    /// Skip pushing to the Chocolatey community repository. Bool, string, or
    /// template expression (e.g. `"{{ IsSnapshot }}"`). Accepts the legacy
    /// `skip_publish:` spelling for back-compat with configs;
    /// canonical name is `skip:` to align with every other publisher.
    #[serde(
        default,
        alias = "skip_publish",
        deserialize_with = "deserialize_string_or_bool_opt"
    )]
    pub skip: Option<StringOrBool>,
    /// Artifact selection: "archive" (default), "msi", or "nsis".
    #[serde(rename = "use")]
    pub use_artifact: Option<String>,
    /// amd64 microarchitecture variant filter (`v1` / `v2` / `v3` / `v4`).
    /// Only artifacts matching this variant are included. Default: `v1`.
    /// Typed as [`Amd64Variant`], so any value outside `v1`..`v4` is
    /// rejected when the config is parsed.
    pub amd64_variant: Option<Amd64Variant>,
    /// Post-publish moderation-queue polling settings. Polling is
    /// disabled by default — Chocolatey's community moderation queue
    /// routinely takes hours to days, and blocking a CI workflow on
    /// that wait is wrong. Opt in per-publisher with
    /// `post_publish_poll: { enabled: true }` when running locally and
    /// willing to wait, or disable globally via `--no-post-publish-poll`.
    pub post_publish_poll: Option<PostPublishPollConfig>,
    /// When true, re-push the nupkg even when a version is already in the
    /// community moderation queue (PackageStatus=Submitted). Chocolatey's API
    /// accepts re-pushes of in-moderation versions; the new nupkg replaces the
    /// queued one. When false (default), the push is skipped and a warning is
    /// emitted so the operator sees that the publisher did not push.
    #[serde(deserialize_with = "deserialize_string_or_bool_opt", default)]
    pub republish_in_moderation: Option<StringOrBool>,
    /// Override whether this publisher failing should fail the overall release.
    ///
    /// Default: `false` — a failure here is logged but does not abort the release.
    /// Set to `true` to fail the release on any error.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub required: Option<bool>,
    /// Template-conditional gate: when the rendered result is falsy
    /// (`"false"` / `"0"` / `"no"` / empty), the Chocolatey publisher is
    /// skipped. Render failure hard-errors. Config key: `chocolateys[].if:`.
    #[serde(rename = "if")]
    pub if_condition: Option<String>,
    /// When `true`, a triggered rollback leaves this publisher's work in
    /// place rather than attempting to undo it. Default `false`.
    pub retain_on_rollback: Option<bool>,
}

/// Chocolatey package dependency with optional version constraint.
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct ChocolateyDependency {
    /// Chocolatey package ID of the dependency.
    pub id: String,
    /// Minimum version constraint for the dependency (e.g., "[1.0.0,)").
    pub version: Option<String>,
}