Repository: akuity/kargo
Pull request #3997: chore: document accepted values for certain crd fields
Author: login: fykaa
Labels: name: area/documentation
description: Affects documentation
name: kind/chore
description: Something that just needs to get done
name: priority/normal
description: This is the priority for most work
name: area/crds
description: Affects custom resource definitions
Created: 2025-05-06T18:05:42Z | Merged: 2025-05-15T17:01:04Z

closes https://github.com/akuity/kargo/issues/3221


Diff:
diff --git a/api/v1alpha1/generated.proto b/api/v1alpha1/generated.proto
index 62760ccc7f..54a1e86f7d 100644
--- a/api/v1alpha1/generated.proto
+++ b/api/v1alpha1/generated.proto
@@ -463,6 +463,14 @@ message FreightSources {
   // made available to the Stage. This field is optional. When left unspecified,
   // the field is implicitly treated as if its value were "OneOf".
   //
+  // Accepted Values:
+  //
+  // - "All": Freight must be be verified and, if applicable, soaked in all
+  //   upstream Stages to be considered available for promotion.
+  // - "OneOf": Freight must be verified and, if applicable, soaked in at least
+  //    one upstream Stage to be considered available for promotion.
+  // - "": Treated the same as "OneOf".
+  //
   // +kubebuilder:validation:Optional
   optional string availabilityStrategy = 4;
 }
@@ -539,7 +547,25 @@ message GitSubscription {
   // commit of interest in the repository specified by the RepoURL field. This
   // field is optional. When left unspecified, the field is implicitly treated
   // as if its value were "NewestFromBranch".
-  // Accepted values: Lexical, NewestFromBranch, NewestTag, SemVer
+  //
+  // Accepted values:
+  //
+  // - "NewestFromBranch": Selects the latest commit on the branch specified
+  //   by the Branch field or the default branch if none is specified. This is
+  //   the default strategy.
+  //
+  // - "SemVer": Selects the commit referenced by the the semantically greatest
+  //   tag. The SemverConstraint field can optionally be used to narrow the set
+  //   of tags eligible for selection.
+  //
+  // - "Lexical": Selects the commit referenced by the lexicographically
+  //   greatest tag. Useful when tags embed a _leading_ date or timestamp. The
+  //   AllowTags and IgnoreTags fields can optionally be used to narrow the set
+  //   of tags eligible for selection.
+  //
+  // - "NewestTag": Selects the commit referenced by the most recently created
+  //   tag. The AllowTags and IgnoreTags fields can optionally be used to
+  //   narrow the set of tags eligible for selection.
   //
   // +kubebuilder:default=NewestFromBranch
   optional string commitSelectionStrategy = 2;
@@ -609,6 +635,7 @@ message GitSubscription {
   //   2. Glob patterns (prefix the pattern with "glob:"; ex. "glob:*.yaml")
   //   3. Regular expressions (prefix the pattern with "regex:" or "regexp:";
   //      ex. "regexp:^.*\.yaml$")
+  //
   // Paths selected by IncludePaths may be unselected by ExcludePaths. This
   // is a useful method for including a broad set of paths and then excluding a
   // subset of them.
@@ -750,7 +777,26 @@ message ImageSubscription {
   // of the image specified by the RepoURL field. This field is optional. When
   // left unspecified, the field is implicitly treated as if its value were
   // "SemVer".
-  // Accepted values: Digest, Lexical, NewestBuild, SemVer
+  //
+  // Accepted values:
+  //
+  // - "Digest": Selects the image currently referenced by the tag specified
+  //   (unintuitively) by the SemverConstraint field.
+  //
+  // - "Lexical": Selects the image referenced by the lexicographically greatest
+  //   tag. Useful when tags embed a leading date or timestamp. The AllowTags
+  //   and IgnoreTags fields can optionally be used to narrow the set of tags
+  //   eligible for selection.
+  //
+  // - "NewestBuild": Selects the image that was most recently pushed to the
+  //   repository. The AllowTags and IgnoreTags fields can optionally be used
+  //   to narrow the set of tags eligible for selection. This is the least
+  //   efficient and is likely to cause rate limiting affecting this Warehouse
+  //   and possibly others. This strategy should be avoided.
+  //
+  // - "SemVer": Selects the image with the semantically greatest tag. The
+  //   AllowTags and IgnoreTags fields can optionally be used to narrow the set
+  //   of tags eligible for selection.
   //
   // +kubebuilder:default=SemVer
   optional string imageSelectionStrategy = 3;
@@ -1505,7 +1551,12 @@ message WarehouseSpec {
   // FreightCreationPolicy describes how Freight is created by this Warehouse.
   // This field is optional. When left unspecified, the field is implicitly
   // treated as if its value were "Automatic".
-  // Accepted values: Automatic, Manual
+  //
+  // Accepted values:
+  //
+  // - "Automatic": New Freight is created automatically when any new artifact
+  //   is discovered.
+  // - "Manual": New Freight is never created automatically.
   //
   // +kubebuilder:default=Automatic
   // +kubebuilder:validation:Optional
diff --git a/api/v1alpha1/stage_types.go b/api/v1alpha1/stage_types.go
index d445988e2d..9ec5dddd7b 100644
--- a/api/v1alpha1/stage_types.go
+++ b/api/v1alpha1/stage_types.go
@@ -301,6 +301,14 @@ type FreightSources struct {
 	// made available to the Stage. This field is optional. When left unspecified,
 	// the field is implicitly treated as if its value were "OneOf".
 	//
+	// Accepted Values:
+	//
+	// - "All": Freight must be be verified and, if applicable, soaked in all
+	//   upstream Stages to be considered available for promotion.
+	// - "OneOf": Freight must be verified and, if applicable, soaked in at least
+	//    one upstream Stage to be considered available for promotion.
+	// - "": Treated the same as "OneOf".
+	//
 	// +kubebuilder:validation:Optional
 	AvailabilityStrategy FreightAvailabilityStrategy `json:"availabilityStrategy,omitempty" protobuf:"bytes,4,opt,name=availabilityStrategy"`
 }
diff --git a/api/v1alpha1/warehouse_types.go b/api/v1alpha1/warehouse_types.go
index 55c332d581..21ba090197 100644
--- a/api/v1alpha1/warehouse_types.go
+++ b/api/v1alpha1/warehouse_types.go
@@ -67,7 +67,12 @@ type WarehouseSpec struct {
 	// FreightCreationPolicy describes how Freight is created by this Warehouse.
 	// This field is optional. When left unspecified, the field is implicitly
 	// treated as if its value were "Automatic".
-	// Accepted values: Automatic, Manual
+	//
+	// Accepted values:
+	//
+	// - "Automatic": New Freight is created automatically when any new artifact
+	//   is discovered.
+	// - "Manual": New Freight is never created automatically.
 	//
 	// +kubebuilder:default=Automatic
 	// +kubebuilder:validation:Optional
@@ -112,7 +117,25 @@ type GitSubscription struct {
 	// commit of interest in the repository specified by the RepoURL field. This
 	// field is optional. When left unspecified, the field is implicitly treated
 	// as if its value were "NewestFromBranch".
-	// Accepted values: Lexical, NewestFromBranch, NewestTag, SemVer
+	//
+	// Accepted values:
+	//
+	// - "NewestFromBranch": Selects the latest commit on the branch specified
+	//   by the Branch field or the default branch if none is specified. This is
+	//   the default strategy.
+	//
+	// - "SemVer": Selects the commit referenced by the the semantically greatest
+	//   tag. The SemverConstraint field can optionally be used to narrow the set
+	//   of tags eligible for selection.
+	//
+	// - "Lexical": Selects the commit referenced by the lexicographically
+	//   greatest tag. Useful when tags embed a _leading_ date or timestamp. The
+	//   AllowTags and IgnoreTags fields can optionally be used to narrow the set
+	//   of tags eligible for selection.
+	//
+	// - "NewestTag": Selects the commit referenced by the most recently created
+	//   tag. The AllowTags and IgnoreTags fields can optionally be used to
+	//   narrow the set of tags eligible for selection.
 	//
 	// +kubebuilder:default=NewestFromBranch
 	CommitSelectionStrategy CommitSelectionStrategy `json:"commitSelectionStrategy,omitempty" protobuf:"bytes,2,opt,name=commitSelectionStrategy"`
@@ -175,6 +198,7 @@ type GitSubscription struct {
 	//   2. Glob patterns (prefix the pattern with "glob:"; ex. "glob:*.yaml")
 	//   3. Regular expressions (prefix the pattern with "regex:" or "regexp:";
 	//      ex. "regexp:^.*\.yaml$")
+	//
 	// Paths selected by IncludePaths may be unselected by ExcludePaths. This
 	// is a useful method for including a broad set of paths and then excluding a
 	// subset of them.
@@ -229,7 +253,26 @@ type ImageSubscription struct {
 	// of the image specified by the RepoURL field. This field is optional. When
 	// left unspecified, the field is implicitly treated as if its value were
 	// "SemVer".
-	// Accepted values: Digest, Lexical, NewestBuild, SemVer
+	//
+	// Accepted values:
+	//
+	// - "Digest": Selects the image currently referenced by the tag specified
+	//   (unintuitively) by the SemverConstraint field.
+	//
+	// - "Lexical": Selects the image referenced by the lexicographically greatest
+	//   tag. Useful when tags embed a leading date or timestamp. The AllowTags
+	//   and IgnoreTags fields can optionally be used to narrow the set of tags
+	//   eligible for selection.
+	//
+	// - "NewestBuild": Selects the image that was most recently pushed to the
+	//   repository. The AllowTags and IgnoreTags fields can optionally be used
+	//   to narrow the set of tags eligible for selection. This is the least
+	//   efficient and is likely to cause rate limiting affecting this Warehouse
+	//   and possibly others. This strategy should be avoided.
+	//
+	// - "SemVer": Selects the image with the semantically greatest tag. The
+	//   AllowTags and IgnoreTags fields can optionally be used to narrow the set
+	//   of tags eligible for selection.
 	//
 	// +kubebuilder:default=SemVer
 	ImageSelectionStrategy ImageSelectionStrategy `json:"imageSelectionStrategy,omitempty" protobuf:"bytes,3,opt,name=imageSelectionStrategy"`
diff --git a/charts/kargo/resources/crds/kargo.akuity.io_stages.yaml b/charts/kargo/resources/crds/kargo.akuity.io_stages.yaml
index e51e5e56ce..653d5caa3b 100644
--- a/charts/kargo/resources/crds/kargo.akuity.io_stages.yaml
+++ b/charts/kargo/resources/crds/kargo.akuity.io_stages.yaml
@@ -290,6 +290,14 @@ spec:
                             AvailabilityStrategy specifies the semantics for how requested Freight is
                             made available to the Stage. This field is optional. When left unspecified,
                             the field is implicitly treated as if its value were "OneOf".
+
+                            Accepted Values:
+
+                            - "All": Freight must be be verified and, if applicable, soaked in all
+                              upstream Stages to be considered available for promotion.
+                            - "OneOf": Freight must be verified and, if applicable, soaked in at least
+                               one upstream Stage to be considered available for promotion.
+                            - "": Treated the same as "OneOf".
                           enum:
                           - All
                           - OneOf
diff --git a/charts/kargo/resources/crds/kargo.akuity.io_warehouses.yaml b/charts/kargo/resources/crds/kargo.akuity.io_warehouses.yaml
index eba019f898..7e81de8be5 100644
--- a/charts/kargo/resources/crds/kargo.akuity.io_warehouses.yaml
+++ b/charts/kargo/resources/crds/kargo.akuity.io_warehouses.yaml
@@ -52,7 +52,12 @@ spec:
                   FreightCreationPolicy describes how Freight is created by this Warehouse.
                   This field is optional. When left unspecified, the field is implicitly
                   treated as if its value were "Automatic".
-                  Accepted values: Automatic, Manual
+
+                  Accepted values:
+
+                  - "Automatic": New Freight is created automatically when any new artifact
+                    is discovered.
+                  - "Manual": New Freight is never created automatically.
                 enum:
                 - Automatic
                 - Manual
@@ -163,7 +168,25 @@ spec:
                             commit of interest in the repository specified by the RepoURL field. This
                             field is optional. When left unspecified, the field is implicitly treated
                             as if its value were "NewestFromBranch".
-                            Accepted values: Lexical, NewestFromBranch, NewestTag, SemVer
+
+                            Accepted values:
+
+                            - "NewestFromBranch": Selects the latest commit on the branch specified
+                              by the Branch field or the default branch if none is specified. This is
+                              the default strategy.
+
+                            - "SemVer": Selects the commit referenced by the the semantically greatest
+                              tag. The SemverConstraint field can optionally be used to narrow the set
+                              of tags eligible for selection.
+
+                            - "Lexical": Selects the commit referenced by the lexicographically
+                              greatest tag. Useful when tags embed a _leading_ date or timestamp. The
+                              AllowTags and IgnoreTags fields can optionally be used to narrow the set
+                              of tags eligible for selection.
+
+                            - "NewestTag": Selects the commit referenced by the most recently created
+                              tag. The AllowTags and IgnoreTags fields can optionally be used to
+                              narrow the set of tags eligible for selection.
                           enum:
                           - Lexical
                           - NewestFromBranch
@@ -221,6 +244,7 @@ spec:
                               2. Glob patterns (prefix the pattern with "glob:"; ex. "glob:*.yaml")
                               3. Regular expressions (prefix the pattern with "regex:" or "regexp:";
                                  ex. "regexp:^.*\.yaml$")
+
                             Paths selected by IncludePaths may be unselected by ExcludePaths. This
                             is a useful method for including a broad set of paths and then excluding a
                             subset of them.
@@ -311,7 +335,26 @@ spec:
                             of the image specified by the RepoURL field. This field is optional. When
                             left unspecified, the field is implicitly treated as if its value were
                             "SemVer".
-                            Accepted values: Digest, Lexical, NewestBuild, SemVer
+
+                            Accepted values:
+
+                            - "Digest": Selects the image currently referenced by the tag specified
+                              (unintuitively) by the SemverConstraint field.
+
+                            - "Lexical": Selects the image referenced by the lexicographically greatest
+                              tag. Useful when tags embed a leading date or timestamp. The AllowTags
+                              and IgnoreTags fields can optionally be used to narrow the set of tags
+                              eligible for selection.
+
+                            - "NewestBuild": Selects the image that was most recently pushed to the
+                              repository. The AllowTags and IgnoreTags fields can optionally be used
+                              to narrow the set of tags eligible for selection. This is the least
+                              efficient and is likely to cause rate limiting affecting this Warehouse
+                              and possibly others. This strategy should be avoided.
+
+                            - "SemVer": Selects the image with the semantically greatest tag. The
+                              AllowTags and IgnoreTags fields can optionally be used to narrow the set
+                              of tags eligible for selection.
                           enum:
                           - Digest
                           - Lexical
diff --git a/internal/image/selector.go b/internal/image/selector.go
index 34d2c8fd5f..6e8718cf85 100644
--- a/internal/image/selector.go
+++ b/internal/image/selector.go
@@ -18,7 +18,7 @@ const (
 	// tag.
 	SelectionStrategyDigest SelectionStrategy = "Digest"
 	// SelectionStrategyLexical represents an image selection strategy that is
-	// useful for finding the the image referenced by the tag that is lexically
+	// useful for finding the image referenced by the tag that is lexically
 	// last among those matched by a regular expression and not explicitly
 	// ignored. This strategy is useful for finding the images referenced by the
 	// latest in a series of tag that are suffixed with a predictably formatted
diff --git a/ui/src/gen/api/v1alpha1/generated_pb.ts b/ui/src/gen/api/v1alpha1/generated_pb.ts
index b1ec83c257..cfd048a680 100644
--- a/ui/src/gen/api/v1alpha1/generated_pb.ts
+++ b/ui/src/gen/api/v1alpha1/generated_pb.ts
@@ -1034,6 +1034,14 @@ export type FreightSources = Message<"github.com.akuity.kargo.api.v1alpha1.Freig
    * made available to the Stage. This field is optional. When left unspecified,
    * the field is implicitly treated as if its value were "OneOf".
    *
+   * Accepted Values:
+   *
+   * - "All": Freight must be be verified and, if applicable, soaked in all
+   *   upstream Stages to be considered available for promotion.
+   * - "OneOf": Freight must be verified and, if applicable, soaked in at least
+   *    one upstream Stage to be considered available for promotion.
+   * - "": Treated the same as "OneOf".
+   *
    * +kubebuilder:validation:Optional
    *
    * @generated from field: optional string availabilityStrategy = 4;
@@ -1210,7 +1218,25 @@ export type GitSubscription = Message<"github.com.akuity.kargo.api.v1alpha1.GitS
    * commit of interest in the repository specified by the RepoURL field. This
    * field is optional. When left unspecified, the field is implicitly treated
    * as if its value were "NewestFromBranch".
-   * Accepted values: Lexical, NewestFromBranch, NewestTag, SemVer
+   *
+   * Accepted values:
+   *
+   * - "NewestFromBranch": Selects the latest commit on the branch specified
+   *   by the Branch field or the default branch if none is specified. This is
+   *   the default strategy.
+   *
+   * - "SemVer": Selects the commit referenced by the the semantically greatest
+   *   tag. The SemverConstraint field can optionally be used to narrow the set
+   *   of tags eligible for selection.
+   *
+   * - "Lexical": Selects the commit referenced by the lexicographically
+   *   greatest tag. Useful when tags embed a _leading_ date or timestamp. The
+   *   AllowTags and IgnoreTags fields can optionally be used to narrow the set
+   *   of tags eligible for selection.
+   *
+   * - "NewestTag": Selects the commit referenced by the most recently created
+   *   tag. The AllowTags and IgnoreTags fields can optionally be used to
+   *   narrow the set of tags eligible for selection.
    *
    * +kubebuilder:default=NewestFromBranch
    *
@@ -1308,6 +1334,7 @@ export type GitSubscription = Message<"github.com.akuity.kargo.api.v1alpha1.GitS
    *   2. Glob patterns (prefix the pattern with "glob:"; ex. "glob:*.yaml")
    *   3. Regular expressions (prefix the pattern with "regex:" or "regexp:";
    *      ex. "regexp:^.*\.yaml$")
+   *
    * Paths selected by IncludePaths may be unselected by ExcludePaths. This
    * is a useful method for including a broad set of paths and then excluding a
    * subset of them.
@@ -1595,7 +1622,26 @@ export type ImageSubscription = Message<"github.com.akuity.kargo.api.v1alpha1.Im
    * of the image specified by the RepoURL field. This field is optional. When
    * left unspecified, the field is implicitly treated as if its value were
    * "SemVer".
-   * Accepted values: Digest, Lexical, NewestBuild, SemVer
+   *
+   * Accepted values:
+   *
+   * - "Digest": Selects the image currently referenced by the tag specified
+   *   (unintuitively) by the SemverConstraint field.
+   *
+   * - "Lexical": Selects the image referenced by the lexicographically greatest
+   *   tag. Useful when tags embed a leading date or timestamp. The AllowTags
+   *   and IgnoreTags fields can optionally be used to narrow the set of tags
+   *   eligible for selection.
+   *
+   * - "NewestBuild": Selects the image that was most recently pushed to the
+   *   repository. The AllowTags and IgnoreTags fields can optionally be used
+   *   to narrow the set of tags eligible for selection. This is the least
+   *   efficient and is likely to cause rate limiting affecting this Warehouse
+   *   and possibly others. This strategy should be avoided.
+   *
+   * - "SemVer": Selects the image with the semantically greatest tag. The
+   *   AllowTags and IgnoreTags fields can optionally be used to narrow the set
+   *   of tags eligible for selection.
    *
    * +kubebuilder:default=SemVer
    *
@@ -3194,7 +3240,12 @@ export type WarehouseSpec = Message<"github.com.akuity.kargo.api.v1alpha1.Wareho
    * FreightCreationPolicy describes how Freight is created by this Warehouse.
    * This field is optional. When left unspecified, the field is implicitly
    * treated as if its value were "Automatic".
-   * Accepted values: Automatic, Manual
+   *
+   * Accepted values:
+   *
+   * - "Automatic": New Freight is created automatically when any new artifact
+   *   is discovered.
+   * - "Manual": New Freight is never created automatically.
    *
    * +kubebuilder:default=Automatic
    * +kubebuilder:validation:Optional
diff --git a/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json b/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json
index 5cb6eb4eeb..beaaa22506 100644
--- a/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json
+++ b/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json
@@ -186,7 +186,7 @@
                 "description": "Sources describes where the requested Freight may be obtained from. This is\na required field.",
                 "properties": {
                   "availabilityStrategy": {
-                    "description": "AvailabilityStrategy specifies the semantics for how requested Freight is\nmade available to the Stage. This field is optional. When left unspecified,\nthe field is implicitly treated as if its value were \"OneOf\".",
+                    "description": "AvailabilityStrategy specifies the semantics for how requested Freight is\nmade available to the Stage. This field is optional. When left unspecified,\nthe field is implicitly treated as if its value were \"OneOf\".\n\nAccepted Values:\n\n- \"All\": Freight must be be verified and, if applicable, soaked in all\n  upstream Stages to be considered available for promotion.\n- \"OneOf\": Freight must be verified and, if applicable, soaked in at least\n   one upstream Stage to be considered available for promotion.\n- \"\": Treated the same as \"OneOf\".",
                     "enum": [
                       "All",
                       "OneOf",
diff --git a/ui/src/gen/schema/warehouses.kargo.akuity.io_v1alpha1.json b/ui/src/gen/schema/warehouses.kargo.akuity.io_v1alpha1.json
index 31d2df54cf..1e1c1affb3 100644
--- a/ui/src/gen/schema/warehouses.kargo.akuity.io_v1alpha1.json
+++ b/ui/src/gen/schema/warehouses.kargo.akuity.io_v1alpha1.json
@@ -18,7 +18,7 @@
       "properties": {
         "freightCreationPolicy": {
           "default": "Automatic",
-          "description": "FreightCreationPolicy describes how Freight is created by this Warehouse.\nThis field is optional. When left unspecified, the field is implicitly\ntreated as if its value were \"Automatic\".\nAccepted values: Automatic, Manual",
+          "description": "FreightCreationPolicy describes how Freight is created by this Warehouse.\nThis field is optional. When left unspecified, the field is implicitly\ntreated as if its value were \"Automatic\".\n\nAccepted values:\n\n- \"Automatic\": New Freight is created automatically when any new artifact\n  is discovered.\n- \"Manual\": New Freight is never created automatically.",
           "enum": [
             "Automatic",
             "Manual"
@@ -87,7 +87,7 @@
                   },
                   "commitSelectionStrategy": {
                     "default": "NewestFromBranch",
-                    "description": "CommitSelectionStrategy specifies the rules for how to identify the newest\ncommit of interest in the repository specified by the RepoURL field. This\nfield is optional. When left unspecified, the field is implicitly treated\nas if its value were \"NewestFromBranch\".\nAccepted values: Lexical, NewestFromBranch, NewestTag, SemVer",
+                    "description": "CommitSelectionStrategy specifies the rules for how to identify the newest\ncommit of interest in the repository specified by the RepoURL field. This\nfield is optional. When left unspecified, the field is implicitly treated\nas if its value were \"NewestFromBranch\".\n\nAccepted values:\n\n- \"NewestFromBranch\": Selects the latest commit on the branch specified\n  by the Branch field or the default branch if none is specified. This is\n  the default strategy.\n\n- \"SemVer\": Selects the commit referenced by the the semantically greatest\n  tag. The SemverConstraint field can optionally be used to narrow the set\n  of tags eligible for selection.\n\n- \"Lexical\": Selects the commit referenced by the lexicographically\n  greatest tag. Useful when tags embed a _leading_ date or timestamp. The\n  AllowTags and IgnoreTags fields can optionally be used to narrow the set\n  of tags eligible for selection.\n\n- \"NewestTag\": Selects the commit referenced by the most recently created\n  tag. The AllowTags and IgnoreTags fields can optionally be used to\n  narrow the set of tags eligible for selection.",
                     "enum": [
                       "Lexical",
                       "NewestFromBranch",
@@ -119,7 +119,7 @@
                     "type": "array"
                   },
                   "includePaths": {
-                    "description": "IncludePaths is a list of selectors that designate paths in the repository\nthat should trigger the production of new Freight when changes are detected\ntherein. When specified, only changes in the identified paths will trigger\nFreight production. When not specified, changes in any path will trigger\nFreight production. Selectors may be defined using:\n  1. Exact paths to files or directories (ex. \"charts/foo\")\n  2. Glob patterns (prefix the pattern with \"glob:\"; ex. \"glob:*.yaml\")\n  3. Regular expressions (prefix the pattern with \"regex:\" or \"regexp:\";\n     ex. \"regexp:^.*\\.yaml$\")\nPaths selected by IncludePaths may be unselected by ExcludePaths. This\nis a useful method for including a broad set of paths and then excluding a\nsubset of them.",
+                    "description": "IncludePaths is a list of selectors that designate paths in the repository\nthat should trigger the production of new Freight when changes are detected\ntherein. When specified, only changes in the identified paths will trigger\nFreight production. When not specified, changes in any path will trigger\nFreight production. Selectors may be defined using:\n  1. Exact paths to files or directories (ex. \"charts/foo\")\n  2. Glob patterns (prefix the pattern with \"glob:\"; ex. \"glob:*.yaml\")\n  3. Regular expressions (prefix the pattern with \"regex:\" or \"regexp:\";\n     ex. \"regexp:^.*\\.yaml$\")\n\nPaths selected by IncludePaths may be unselected by ExcludePaths. This\nis a useful method for including a broad set of paths and then excluding a\nsubset of them.",
                     "items": {
                       "type": "string"
                     },
@@ -180,7 +180,7 @@
                   },
                   "imageSelectionStrategy": {
                     "default": "SemVer",
-                    "description": "ImageSelectionStrategy specifies the rules for how to identify the newest version\nof the image specified by the RepoURL field. This field is optional. When\nleft unspecified, the field is implicitly treated as if its value were\n\"SemVer\".\nAccepted values: Digest, Lexical, NewestBuild, SemVer",
+                    "description": "ImageSelectionStrategy specifies the rules for how to identify the newest version\nof the image specified by the RepoURL field. This field is optional. When\nleft unspecified, the field is implicitly treated as if its value were\n\"SemVer\".\n\nAccepted values:\n\n- \"Digest\": Selects the image currently referenced by the tag specified\n  (unintuitively) by the SemverConstraint field.\n\n- \"Lexical\": Selects the image referenced by the lexicographically greatest\n  tag. Useful when tags embed a leading date or timestamp. The AllowTags\n  and IgnoreTags fields can optionally be used to narrow the set of tags\n  eligible for selection.\n\n- \"NewestBuild\": Selects the image that was most recently pushed to the\n  repository. The AllowTags and IgnoreTags fields can optionally be used\n  to narrow the set of tags eligible for selection. This is the least\n  efficient and is likely to cause rate limiting affecting this Warehouse\n  and possibly others. This strategy should be avoided.\n\n- \"SemVer\": Selects the image with the semantically greatest tag. The\n  AllowTags and IgnoreTags fields can optionally be used to narrow the set\n  of tags eligible for selection.",
                     "enum": [
                       "Digest",
                       "Lexical",


Reviews:
user: login: krancour
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-06T19:18:42Z
user: login: fykaa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T11:14:54Z
user: login: krancour
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-08T20:43:19Z
user: login: krancour
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-08T20:44:14Z
user: login: krancour
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-14T16:43:12Z
user: login: krancour
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-14T16:46:11Z
user: login: krancour
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-14T16:53:04Z
user: login: krancour
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-14T17:07:46Z
user: login: krancour
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-15T15:41:12Z
user: login: krancour
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-15T15:45:16Z
user: login: fykaa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T15:45:38Z
user: login: fykaa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T15:49:11Z
user: login: krancour
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-15T16:27:02Z
user: login: krancour
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-15T16:40:57Z

Review comments:
diff_hunk: @@ -300,6 +300,7 @@ type FreightSources struct {
 	// AvailabilityStrategy specifies the semantics for how requested Freight is
 	// made available to the Stage. This field is optional. When left unspecified,
 	// the field is implicitly treated as if its value were "OneOf".
+	// Accepted Values: "All", "OneOf", ""
path: api/v1alpha1/stage_types.go
user: login: krancour
body: Is this the only place where we use enumerated values without defining what they are?

It is probably worthwhile to explain, as we do for image selection strategies, what the meaning of each value is.
created_at: 2025-05-06T19:18:42Z
author_association: MEMBER
diff_hunk: @@ -300,6 +300,7 @@ type FreightSources struct {
 	// AvailabilityStrategy specifies the semantics for how requested Freight is
 	// made available to the Stage. This field is optional. When left unspecified,
 	// the field is implicitly treated as if its value were "OneOf".
+	// Accepted Values: "All", "OneOf", ""
path: api/v1alpha1/stage_types.go
user: login: fykaa
body: > Is this the only place where we use enumerated values without defining what they are?

Yes, for the enumerated values used in the Warehouse API, we fixed this in [PR #2969](https://github.com/akuity/kargo/pull/2969). Outside of that, only Stages use enums for the following fields:

* `ImageUpdateValueType`

  ```go
  // +kubebuilder:validation:Enum={ImageAndTag,Tag,ImageAndDigest,Digest}
  type ImageUpdateValueType string
  ```

* `FreightOriginKind`

  ```go
  // +kubebuilder:validation:Enum={Warehouse}
  type FreightOriginKind string
  ```

* `FreightAvailabilityStrategy`

  ```go
  // +kubebuilder:validation:Enum={All,OneOf,""}
  type FreightAvailabilityStrategy string
  ```

Of these, only `FreightAvailabilityStrategy` defines multiple accepted values.

---

> It is probably worthwhile to explain, as we do for image selection strategies, what the meaning of each value is.

I don't see explanation in the `imageSelectionStrategy`: 
```
// ImageSelectionStrategy specifies the rules for how to identify the newest version
	// of the image specified by the RepoURL field. This field is optional. When
	// left unspecified, the field is implicitly treated as if its value were
	// "SemVer".
	// Accepted values: Digest, Lexical, NewestBuild, SemVer
	//
	// +kubebuilder:default=SemVer
	ImageSelectionStrategy ImageSelectionStrategy `json:"imageSelectionStrategy,omitempty" protobuf:"bytes,3,opt,name=imageSelectionStrategy"`
```

do you want something like: 
```
// AvailabilityStrategy specifies how requested Freight is made available to the Stage.
// This field is optional. If not specified, it defaults to "OneOf".
//
// Accepted Values:
// - "All": All requested Freight must be available before proceeding.
// - "OneOf": At least one requested Freight must be available before proceeding.
// - "": Treated the same as "OneOf" (for backward compatibility).
```
created_at: 2025-05-08T11:14:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -300,6 +300,7 @@ type FreightSources struct {
 	// AvailabilityStrategy specifies the semantics for how requested Freight is
 	// made available to the Stage. This field is optional. When left unspecified,
 	// the field is implicitly treated as if its value were "OneOf".
+	// Accepted Values: "All", "OneOf", ""
path: api/v1alpha1/stage_types.go
user: login: krancour
body: > I don't see explanation in the imageSelectionStrategy:

🤦‍♂️ It's defined somewhere internally:

https://github.com/akuity/kargo/blob/dfc75c46d0467ba1e98fec7abf9907976bfd0185/internal/image/selector.go#L13-L39

These explanations really ought to be copied into `warehouse_types.go` so that they'll show up in the generated docs.

Looks like similar is true for commit selection strategies are also missing explanations of their values.


created_at: 2025-05-08T20:43:19Z
author_association: MEMBER
diff_hunk: @@ -300,6 +300,7 @@ type FreightSources struct {
 	// AvailabilityStrategy specifies the semantics for how requested Freight is
 	// made available to the Stage. This field is optional. When left unspecified,
 	// the field is implicitly treated as if its value were "OneOf".
+	// Accepted Values: "All", "OneOf", ""
path: api/v1alpha1/stage_types.go
user: login: krancour
body: > do you want something like:

Yes. Exactly this for any field that accepts only certain values. We should list the allowed values and explain what they mean.
created_at: 2025-05-08T20:44:14Z
author_association: MEMBER
diff_hunk: @@ -301,7 +301,13 @@ type FreightSources struct {
 	// made available to the Stage. This field is optional. When left unspecified,
 	// the field is implicitly treated as if its value were "OneOf".
 	//
-	// +kubebuilder:validation:Optional
+	// Accepted Values:
+	//
+	// - "All": All requested Freight must be available before proceeding.
+	// - "OneOf": At least one requested Freight must be available before proceeding.
+	// - "": Treated the same as "OneOf" (for backward compatibility).
path: api/v1alpha1/stage_types.go
user: login: krancour
body: These descriptions aren't accurate.

These strategies don't have to do with determining Freight's availability for promotion to a given Stage based on its availability for promotion (which is recursive!)

These strategies have to do with determining Freight's availability for promotion to a given Stage on the basis of having been verified and, if applicable, adequately soaked in either _at least one_ vs _all_ upstream Stages.

```suggestion
	// - "All": Freight must be be verified and, if applicable, soaked in all
	//   upstream Stages to be considered available for promotion.
	// - "OneOf": Freight must be verified and, if applicable, soaked in at least
	//    one upstream Stage to be considered available for promotion.
	// - "": Treated the same as "OneOf".
```
created_at: 2025-05-14T16:43:12Z
author_association: MEMBER
diff_hunk: @@ -67,9 +67,14 @@ type WarehouseSpec struct {
 	// FreightCreationPolicy describes how Freight is created by this Warehouse.
 	// This field is optional. When left unspecified, the field is implicitly
 	// treated as if its value were "Automatic".
-	// Accepted values: Automatic, Manual
+	//
+	// Accepted values:
+	//
+	// - "Automatic": Freight is automatically created in response to detected changes in the source repository.
+	// - "Manual": Freight must be created explicitly by a user or an external system.
path: api/v1alpha1/warehouse_types.go
user: login: krancour
body: "The source repository" seems to assume there's only one. Many, if not most, Warehouses subscribe to multiple repositories.

"or an external system" also promotes an idea that is contrary to Kargo's ethos. Other systems are presumably the overleveraged CI systems that weren't well suited to the use cases Kargo was created to address. We don't want to inadvertently promote this method of doing things.

```suggestion
	// - "Automatic": New Freight is created automatically when any new artifact
	//   is discovered.
	// - "Manual": New Freight is never created automatically.
```
created_at: 2025-05-14T16:46:10Z
author_association: MEMBER
diff_hunk: @@ -112,9 +117,22 @@ type GitSubscription struct {
 	// commit of interest in the repository specified by the RepoURL field. This
 	// field is optional. When left unspecified, the field is implicitly treated
 	// as if its value were "NewestFromBranch".
-	// Accepted values: Lexical, NewestFromBranch, NewestTag, SemVer
+	//
+	// Accepted values:
+	//
+	// - `"NewestFromBranch"`: Selects the latest commit on the specified branch,
+	//   or the default branch if none is specified. This is the default strategy.
+	//
+	// - `"SemVer"`: Selects the commit pointed to by the tag with the highest
+	//   semantic version. An optional constraint can narrow the version range.
+	//
+	// - `"Lexical"`: Selects the commit referenced by the lexicographically greatest
+	//   tag. Useful when tags encode timestamps or dates.
+	//
+	// - `"NewestTag"`: Selects the commit pointed to by the most recently created tag.
path: api/v1alpha1/warehouse_types.go
user: login: krancour
body: ```suggestion
	// - "NewestFromBranch": Selects the latest commit on the branch specified
	//   by the Branch field or the default branch if none is specified. This is
	//   the default strategy.
	//
	// - "SemVer": Selects the commit referenced by the the semantically greatest
	//   tag. The SemverConstraint field can optionally be used to narrow the set
	//   of tags eligible for selection.
	//
	// - "Lexical": Selects the commit referenced by the lexicographically
	//   greatest tag. Useful when tags embed a _leading_ date or timestamp. The
	//   AllowTags and IgnoreTags fields can optionally be used to narrow the set
	//   of tags eligible for selection.
	//
	// - "NewestTag": Selects the commit referenced by the most recently created
	//   tag. The AllowTags and IgnoreTags fields can optionally be used to
	//   narrow the set of tags eligible for selection.
```

created_at: 2025-05-14T16:53:03Z
author_association: MEMBER
diff_hunk: @@ -229,9 +248,23 @@ type ImageSubscription struct {
 	// of the image specified by the RepoURL field. This field is optional. When
 	// left unspecified, the field is implicitly treated as if its value were
 	// "SemVer".
-	// Accepted values: Digest, Lexical, NewestBuild, SemVer
+	//
+	// Accepted values:
+	//
+	// - `"Digest"`: Selects the image by resolving the digest of a tag (e.g., `latest`).
+	//   Requires the constraint to match an exact tag name.
+	//
+	// - `"Lexical"`: Selects the image whose tag is lexically last among those matched
+	//   by a regex. Best suited for tags with timestamp suffixes.
+	//
+	// - `"NewestBuild"`: Selects the image that was most recently pushed to the registry.
+	//   This is the least efficient method and should be constrained with regex when used.
+	//
+	// - `"SemVer"`: Selects the image with the highest semantic version tag.
+	//   An optional constraint may restrict the version range.
path: api/v1alpha1/warehouse_types.go
user: login: krancour
body: The descriptions you used reference various constraints and other options without specifying their field names.

"Lexicographically _greatest_" reads better than "lexicographically last."

Caution against NewestBuild needs to be scarier.

Recommend this:

```suggestion
	// - "Digest": Selects the image currently referenced by the tag specified
	//   (unintuitively) by the SemverConstraint field.
	//
	// - "Lexical": Selects the image referenced by the lexicographically greatest
	//   tag. Useful when tags embed a leading date or timestamp. The AllowTags
	//   and IgnoreTags fields can optionally be used to narrow the set of tags
	//   eligible for selection.
	//
	// - "NewestBuild": Selects the image that was most recently pushed to the
	//   repository. The AllowTags and IgnoreTags fields can optionally be used
	//   to narrow the set of tags eligible for selection. This is the least
	//   efficient and is likely to cause rate limiting affecting this Warehouse
	//   and possibly others. This strategy should be avoided.
	//
	// - "SemVer": Selects the image with the semantically greatest tag. The
	//   AllowTags and IgnoreTags fields can optionally be used to narrow the set
	//   of tags eligible for selection.
```
created_at: 2025-05-14T17:07:46Z
author_association: MEMBER
diff_hunk: @@ -286,15 +286,27 @@ spec:
                         a required field.
                       properties:
                         availabilityStrategy:
+                          allOf:
+                          - enum:
+                            - All
+                            - OneOf
+                            - ""
+                          - enum:
+                            - All
+                            - OneOf
+                            - ""
path: charts/kargo/resources/crds/kargo.akuity.io_stages.yaml
user: login: krancour
body: I notice this is duplicated now. I think I know why... I'll link to here from the spot where I think it happened.
created_at: 2025-05-15T15:41:11Z
author_association: MEMBER
diff_hunk: @@ -301,7 +301,15 @@ type FreightSources struct {
 	// made available to the Stage. This field is optional. When left unspecified,
 	// the field is implicitly treated as if its value were "OneOf".
 	//
-	// +kubebuilder:validation:Optional
+	// Accepted Values:
+	//
+	// - "All": Freight must be be verified and, if applicable, soaked in all
+	//   upstream Stages to be considered available for promotion.
+	// - "OneOf": Freight must be verified and, if applicable, soaked in at least
+	//    one upstream Stage to be considered available for promotion.
+	// - "": Treated the same as "OneOf".
+	//
path: api/v1alpha1/stage_types.go
user: login: krancour
body: Not sure why we were getting rid of the optional marker? Tentatively putting it back...

But the enum marker definitely needs to go. It's already set on the FreightAvailabilityStrategy type itself up on line 115. Adding it here as well seems to be the cause of this [duplication](https://github.com/akuity/kargo/pull/3997/files#r2091484772).

I believe this applies in some other spots in the PR as well.

```suggestion
	// +kubebuilder:validation:Optional
```
created_at: 2025-05-15T15:45:16Z
author_association: MEMBER
diff_hunk: @@ -286,15 +286,27 @@ spec:
                         a required field.
                       properties:
                         availabilityStrategy:
+                          allOf:
+                          - enum:
+                            - All
+                            - OneOf
+                            - ""
+                          - enum:
+                            - All
+                            - OneOf
+                            - ""
path: charts/kargo/resources/crds/kargo.akuity.io_stages.yaml
user: login: fykaa
body: Yes, I am removing the extra validation:enum I added
created_at: 2025-05-15T15:45:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -301,7 +301,15 @@ type FreightSources struct {
 	// made available to the Stage. This field is optional. When left unspecified,
 	// the field is implicitly treated as if its value were "OneOf".
 	//
-	// +kubebuilder:validation:Optional
+	// Accepted Values:
+	//
+	// - "All": Freight must be be verified and, if applicable, soaked in all
+	//   upstream Stages to be considered available for promotion.
+	// - "OneOf": Freight must be verified and, if applicable, soaked in at least
+	//    one upstream Stage to be considered available for promotion.
+	// - "": Treated the same as "OneOf".
+	//
path: api/v1alpha1/stage_types.go
user: login: fykaa
body: This was a mistake. I will add that back and remove extra enum markers I added
created_at: 2025-05-15T15:49:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -301,6 +301,13 @@ type FreightSources struct {
 	// made available to the Stage. This field is optional. When left unspecified,
 	// the field is implicitly treated as if its value were "OneOf".
 	//
+	// Accepted Values:
+	//
+	// - "All": Freight must be be verified and, if applicable, soaked in all
+	//   upstream Stages to be considered available for promotion.
+	// - "OneOf": Freight must be verified and, if applicable, soaked in at least
+	//    one upstream Stage to be considered available for promotion.
+	// - "": Treated the same as "OneOf".
path: api/v1alpha1/stage_types.go
user: login: krancour
body: Sorry. I know this means running codegen again, but these are all more readable if we leave a line between the free-form comments and the kubebuilder markers.
```suggestion
	// - "": Treated the same as "OneOf".

```
created_at: 2025-05-15T16:27:02Z
author_association: MEMBER

PR comments:
user: login: netlify[bot]
created_at: 2025-05-06T18:06:00Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *docs-kargo-io* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 27bf43be5c112b0cb40942adbf521d07f5c7514e |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/projects/docs-kargo-io/deploys/68261715cb76860008123ef6 |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-3997.docs.kargo.io](https://deploy-preview-3997.docs.kargo.io) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTM5OTcuZG9jcy5rYXJnby5pbyJ9.7lQmM3lL_G3-86D0VOtc2vCJgAx_1OMkM9RzClvDTfo)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---
<!-- [docs-kargo-io Preview](https://deploy-preview-3997.docs.kargo.io) -->
_To edit notification comments on pull requests, go to your [Netlify project configuration](https://app.netlify.com/projects/docs-kargo-io/configuration/notifications#deploy-notifications)._
author_association: NONE
user: login: codecov[bot]
created_at: 2025-05-06T18:10:20Z
body: ## [Codecov](https://app.codecov.io/gh/akuity/kargo/pull/3997?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 52.76%. Comparing base [(`2d4510d`)](https://app.codecov.io/gh/akuity/kargo/commit/2d4510d49e396fbb6f8fef4326065071c4d9ec4b?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity) to head [(`27bf43b`)](https://app.codecov.io/gh/akuity/kargo/commit/27bf43be5c112b0cb40942adbf521d07f5c7514e?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity).
> Report is 39 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #3997      +/-   ##
==========================================
- Coverage   53.21%   52.76%   -0.46%     
==========================================
  Files         312      321       +9     
  Lines       28383    28785     +402     
==========================================
+ Hits        15104    15188      +84     
- Misses      12489    12804     +315     
- Partials      790      793       +3     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/akuity/kargo/pull/3997?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=akuity).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE