anodizer_core/config/docker.rs
1use std::collections::HashMap;
2
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6use super::release::{SkipPushConfig, skip_push_schema};
7use super::{StringOrBool, deserialize_string_or_bool_opt};
8
9// Use `DockerV2Config` (canonical) for docker image builds.
10
11/// Per-pipe retry configuration for `docker.retry` / `docker_manifest.retry`.
12///
13/// **Deprecated**: prefer the top-level `retry:` block ([`super::RetryConfig`])
14/// which applies to docker pipes (and every other network-bound stage) via
15/// `Project.Retry`. When a per-pipe block is present alongside the top-level
16/// block, the per-pipe values win for back-compat, but
17/// `stage-docker::resolve_retry_params` emits a one-shot deprecation warning.
18/// New configs should leave this field unset.
19//
20// Note: `#[deprecated]` on the type cascades through derive-generated impls
21// (Default, Serialize, JsonSchema, ...) and is hard to silence cleanly, so the
22// deprecation lives in (a) this rustdoc prose, (b) the runtime `tracing::warn!`
23// fired once per process by `stage-docker::resolve_retry_params`, and (c) the
24// schemars-generated JSON-schema description carries the same prose for
25// editor / IDE consumers.
26#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
27#[serde(default)]
28pub struct DockerRetryConfig {
29 /// Number of retry attempts for failed docker push operations
30 /// (default: 10, set in `crates/stage-docker/src/lib.rs::resolve_retry_settings`).
31 pub attempts: Option<u32>,
32 /// Duration string for the initial retry delay (default: `"10s"`).
33 /// Examples: `"1s"`, `"500ms"`.
34 pub delay: Option<String>,
35 /// Maximum delay between retries (default: `"5m"`). Caps the exponential
36 /// backoff so attempt-9 with a 10s base does not stretch to ~42 min.
37 /// Example: `"30s"`.
38 pub max_delay: Option<String>,
39}
40
41// ---------------------------------------------------------------------------
42// DockerV2Config
43// ---------------------------------------------------------------------------
44
45/// Docker V2 configuration — the canonical Docker build API.
46///
47/// Notable surface:
48/// - `images` + `tags` (cleaner separation than a single `image_templates` list)
49/// - `annotations` map for OCI annotations (`--annotation`)
50/// - `build_args` map for build-time variables
51/// - `skip` as a [`StringOrBool`] template for conditional opt-out
52/// - `sbom` as a [`StringOrBool`] — when truthy, adds `--sbom=true` to buildx
53/// - `flags` for arbitrary extra `docker build` flags
54/// - `platforms` is the only target selector — no per-arch field overrides
55#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
56#[serde(default, deny_unknown_fields)]
57pub struct DockerV2Config {
58 /// Unique identifier for this Docker V2 config.
59 pub id: Option<String>,
60 /// Build IDs filter: only include binary artifacts whose metadata `id` is in this list.
61 pub ids: Option<Vec<String>>,
62 /// Path to the Dockerfile relative to the project root.
63 pub dockerfile: String,
64 /// Base image names (e.g., ["ghcr.io/owner/app"]). Combined with `tags` to form full references.
65 pub images: Vec<String>,
66 /// Tag suffixes (e.g., ["latest", "{{ .Version }}"]). Each image is tagged with each tag.
67 pub tags: Vec<String>,
68 /// OCI labels to apply to the image via `--label key=value` flags.
69 pub labels: Option<HashMap<String, String>>,
70 /// OCI annotations to apply via `--annotation key=value` flags.
71 pub annotations: Option<HashMap<String, String>>,
72 /// Extra files to copy into the Docker build context.
73 pub extra_files: Option<Vec<String>>,
74 /// Target platforms for multi-arch builds (e.g., ["linux/amd64", "linux/arm64"]).
75 pub platforms: Option<Vec<String>>,
76 /// Build arguments passed as `--build-arg KEY=VALUE`.
77 pub build_args: Option<HashMap<String, String>>,
78 /// Retry configuration for docker push operations.
79 pub retry: Option<DockerRetryConfig>,
80 /// Arbitrary extra flags passed to the docker build command.
81 pub flags: Option<Vec<String>>,
82 /// When truthy, skip this docker build entirely. Supports templates.
83 /// Accepts the legacy `disable:` spelling via serde alias for back-compat
84 /// with imported GoReleaser configs (GR's docker config field is
85 /// `pkg/config/config.go:1149` `Disable string`).
86 #[serde(
87 default,
88 alias = "disable",
89 deserialize_with = "deserialize_string_or_bool_opt"
90 )]
91 pub skip: Option<StringOrBool>,
92 /// When truthy, adds `--sbom=true` to buildx. Supports templates.
93 #[serde(deserialize_with = "deserialize_string_or_bool_opt", default)]
94 pub sbom: Option<StringOrBool>,
95 // No `skip_push` field — use the canonical `skip:` (DEC-6) to suppress
96 // the publish step (matches every other publisher / pipe in anodizer).
97}
98
99// ---------------------------------------------------------------------------
100// DockerDigestConfig
101// ---------------------------------------------------------------------------
102
103/// Controls docker image digest file creation.
104///
105/// After each docker image push, a digest file (containing the sha256 digest)
106/// is written to the dist directory. This config controls whether that happens
107/// and how the files are named.
108#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
109#[serde(default)]
110pub struct DockerDigestConfig {
111 /// When truthy, disable docker digest artifact creation.
112 #[serde(deserialize_with = "deserialize_string_or_bool_opt", default)]
113 pub skip: Option<StringOrBool>,
114 /// Template for the digest artifact filename.
115 /// Default: tag-based naming (e.g., "ghcr.io_owner_app_v1.0.0.digest").
116 pub name_template: Option<String>,
117}
118
119// ---------------------------------------------------------------------------
120// DockerManifestConfig
121// ---------------------------------------------------------------------------
122
123/// Deprecated: prefer `docker_v2` (which produces multi-arch manifests via
124/// the `platforms:` field automatically). `DockerManifestConfig` is retained
125/// for back-compat with imported GoReleaser configs and for the niche case
126/// of stitching together manifest lists from images that were not built by
127/// `docker_v2` in the same run.
128///
129/// Mirrors GoReleaser commit e09e23a, which marked the v1 docker / docker
130/// manifest pipes deprecated in favour of the v2 buildx flow. The rustdoc
131/// here is the load-bearing surface for the deprecation: it flows into the
132/// schemars-generated JSON Schema (consumed by IDEs / editor tooling) and
133/// rustdoc HTML, both of which are how downstream config authors discover
134/// that the v2 pipe is the preferred entry point.
135#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
136#[serde(default)]
137pub struct DockerManifestConfig {
138 /// Template for the manifest name, e.g. "ghcr.io/owner/app:{{ .Version }}".
139 pub name_template: String,
140 /// Image references to include in the manifest.
141 pub image_templates: Vec<String>,
142 /// Extra flags for `docker manifest create`.
143 pub create_flags: Option<Vec<String>>,
144 /// Extra flags for `docker manifest push`.
145 pub push_flags: Option<Vec<String>>,
146 /// Skip push: true, false, or "auto" (skip for prereleases).
147 #[schemars(schema_with = "skip_push_schema")]
148 pub skip_push: Option<SkipPushConfig>,
149 /// Unique identifier for this manifest config.
150 pub id: Option<String>,
151 /// Docker backend for manifest commands: "docker" (default) or "podman".
152 #[serde(rename = "use")]
153 pub use_backend: Option<String>,
154 /// Retry configuration for manifest push (handles transient registry errors).
155 pub retry: Option<DockerRetryConfig>,
156}