Skip to main content

anodizer_core/config/
homebrew_core.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4use super::{CommitAuthorConfig, StringOrBool, deserialize_string_or_bool_opt};
5
6/// homebrew-core formula-bump publisher configuration.
7///
8/// Bumps an EXISTING formula in `Homebrew/homebrew-core` (or any formula
9/// repository override) purely through the GitHub API — no clone, no `brew`
10/// invocation. The formula file's `url` (or `tag:`/`revision:` pair),
11/// `sha256`, and `version` stanzas are rewritten to the new release, the
12/// change is committed to a branch, and a pull request is opened against the
13/// formula repository. Each `homebrew_cores[]` entry bumps one formula.
14///
15/// Every field is optional: the formula name defaults to the crate name, the
16/// target repository defaults to `Homebrew/homebrew-core`, the formula path
17/// defaults to the sharded core layout (`Formula/<letter>/<name>.rb`, falling
18/// back to the flat `Formula/<name>.rb`), and the download URL defaults to
19/// the GitHub source tarball for the release tag.
20///
21/// ```yaml
22/// homebrew_cores:
23///   - name: my-tool
24/// ```
25#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
26#[serde(default, deny_unknown_fields)]
27pub struct HomebrewCoreConfig {
28    /// Unique identifier for selecting this entry from the CLI (`--id=...`).
29    pub id: Option<String>,
30
31    /// Crate scoping: when set, the formula `name` default is derived from
32    /// the first crate named here instead of the workspace's primary crate.
33    /// The workspace per-crate pattern — one `homebrew_cores[]` entry per
34    /// crate, each scoped by `ids:`.
35    pub ids: Option<Vec<String>>,
36
37    /// Formula name (templated). Defaults to the scoped crate name (see
38    /// `ids:`), then the workspace's primary crate name, then the project
39    /// name.
40    pub name: Option<String>,
41
42    /// Target formula repository. Defaults to `Homebrew/homebrew-core`.
43    /// Carries the auth token override (`repository.token`), the base
44    /// branch (`repository.branch`, default: the repo's default branch),
45    /// and PR settings (`repository.pull_request.draft` / `.body`).
46    ///
47    /// ```yaml
48    /// homebrew_cores:
49    ///   - repository: { owner: my-org, name: my-formulas }
50    /// ```
51    pub repository: Option<super::RepositoryConfig>,
52
53    /// Formula file path inside the repository (templated). Defaults to the
54    /// homebrew-core sharded layout `Formula/<first-letter>/<name>.rb`,
55    /// falling back to the flat `Formula/<name>.rb` used by most personal
56    /// taps when the sharded path does not exist.
57    pub path: Option<String>,
58
59    /// Templated download URL written into the formula's `url` stanza.
60    /// Defaults to the GitHub source tarball for the release tag:
61    /// `https://github.com/<owner>/<repo>/archive/refs/tags/<tag>.tar.gz`
62    /// (owner/repo derived from the crate's release repository, then the
63    /// git remote).
64    pub download_url: Option<String>,
65
66    /// Hex SHA-256 of the new download (templated). When unset, anodizer
67    /// downloads `download_url` and hashes it — the same behavior as
68    /// `brew bump-formula-pr` without `--sha256`.
69    pub sha256: Option<String>,
70
71    /// Templated commit message (also the PR title). Default:
72    /// `"<formula> <version>"` — the message form homebrew-core's CI
73    /// expects for version bumps.
74    pub commit_msg_template: Option<String>,
75
76    /// Commit author for the formula-bump commit, with optional signing.
77    /// Its `use_github_app_token` is the canonical homebrew-core knob: when
78    /// set, the `author`/`committer` fields are omitted from the contents-API
79    /// commit so GitHub attributes it to the token's own account — the
80    /// `<app-slug>[bot]` identity a GitHub App workflow needs to satisfy
81    /// homebrew-core's DCO/CLA policy. Otherwise the resolved `name`/`email`
82    /// (config → local git identity → the anodizer default) author the commit.
83    ///
84    /// Note: `signing` has no effect here — formula bumps commit through the
85    /// GitHub contents API, which GitHub signs server-side; the git `-c
86    /// commit.gpgsign` path the tap/winget/krew publishers use does not apply.
87    ///
88    /// ```yaml
89    /// homebrew_cores:
90    ///   - commit_author:
91    ///       use_github_app_token: true
92    /// ```
93    pub commit_author: Option<CommitAuthorConfig>,
94
95    /// Commit straight to the base branch instead of opening a pull
96    /// request. Accepts bool or template string. Only honored for formula
97    /// repositories you can push to — bumps targeting
98    /// `Homebrew/homebrew-core` always go through a fork + PR, because
99    /// homebrew-core never accepts direct pushes.
100    ///
101    /// A back-compat alias for `repository.pull_request.enabled: false`, the
102    /// preferred spelling shared with the tap/scoop/nix publishers — either
103    /// one selects the direct-commit path (both are still overridden by the
104    /// always-fork-and-PR rule for `Homebrew/homebrew-core`).
105    #[serde(default, deserialize_with = "deserialize_string_or_bool_opt")]
106    pub direct_commit: Option<StringOrBool>,
107
108    /// When truthy, refresh the existing bump PR in place instead of skipping
109    /// it: a same-version re-cut force-resets the bump branch to the current
110    /// base and re-commits the rewritten formula, so the open PR carries this
111    /// run's content rather than a stale earlier attempt (and no duplicate PR
112    /// is opened). When falsy (default), an already-open bump PR is left
113    /// untouched and a warning names this toggle. Accepts bool or template
114    /// string. Mirrors `winget` / `krew` / `homebrew_cask`'s
115    /// `update_existing_pr`.
116    #[serde(default, deserialize_with = "deserialize_string_or_bool_opt")]
117    pub update_existing_pr: Option<StringOrBool>,
118
119    /// Skip this publisher. Accepts bool or template string.
120    /// Accepts the legacy `disable:` spelling via serde alias for back-compat.
121    #[serde(
122        default,
123        alias = "disable",
124        deserialize_with = "deserialize_string_or_bool_opt"
125    )]
126    pub skip: Option<StringOrBool>,
127
128    /// Override whether this publisher failing should fail the overall release.
129    ///
130    /// Default: `false` — the bump is a PR that can be re-opened by hand, so
131    /// a failure here is logged but does not abort the release. Set to
132    /// `true` to fail the release on any error.
133    #[serde(default, skip_serializing_if = "Option::is_none")]
134    pub required: Option<bool>,
135
136    /// Template-conditional gate: when the rendered result is falsy
137    /// (`"false"` / `"0"` / `"no"` / empty), this entry is skipped.
138    /// Render failure hard-errors.
139    #[serde(rename = "if")]
140    pub if_condition: Option<String>,
141
142    /// When `true`, a triggered rollback leaves the opened pull request in
143    /// place rather than closing it. Default `false`.
144    pub retain_on_rollback: Option<bool>,
145}