github.com/microsoft/fabrikate@v1.0.0-alpha.1.0.20210115014322-dc09194d0885/testdata/generate-yaml/helm_repos/prometheus/REVIEW_GUIDELINES.md (about)

     1  # Chart Review Guidelines
     2  
     3  Anyone is welcome to review pull requests. Besides our [technical requirements](https://github.com/helm/charts/blob/master/CONTRIBUTING.md#technical-requirements) and [best practices](https://github.com/helm/helm/tree/master/docs/chart_best_practices), here's an overview of process and review guidelines.
     4  
     5  ## Process
     6  
     7  The process to get a pull request merged is fairly simple. First, all required tests need to pass and the contributor needs to have a signed [DCO](https://www.helm.sh/blog/helm-dco/index.html). See [Charts Testing](https://github.com/helm/charts/blob/master/test/README.md) for details on our CI system and how you can provide custom values for testing. If there is a problem with some part of the test, such as a timeout issue, please contact one of the charts repository maintainers by commenting `cc @helm/charts-maintainers`.
     8  
     9  The charts repository uses the OWNERS files to provide merge access. If a chart has an OWNERS file, an approver listed in that file can approve the pull request. If the chart does not have an OWNERS file, an approver in the OWNERS file at the root of the repository can approve the pull request.
    10  
    11  To approve the pull request, an approver needs to leave a comment of `/lgtm` on the pull request. Once this is in place some tags (`lgtm` and `approved`) will be added to the pull request and a bot will come along and perform the merge.
    12  
    13  Note, if a reviewer who is not an approver in an OWNERS file leaves a comment of `/lgtm` a `lgtm` label will be added but a merge will not happen.
    14  
    15  ## Immutability
    16  
    17  Chart releases must be immutable. Any change to a chart warrants a chart version bump even if it is only changes to the documentation.
    18  
    19  ## Chart Metadata
    20  
    21  The `Chart.yaml` should be as complete as possible. The following fields are mandatory:
    22  
    23  * name (same as chart's directory)
    24  * home
    25  * version
    26  * appVersion
    27  * description
    28  * maintainers (name should be Github username)
    29  
    30  ## Dependencies
    31  
    32  Stable charts should not depend on charts in incubator.
    33  
    34  ## Names and Labels
    35  
    36  ### Metadata
    37  Resources and labels should follow some conventions. The standard resource metadata (`metadata.labels` and `spec.template.metadata.labels`) should be this:
    38  
    39  ```yaml
    40  name: {{ include "myapp.fullname" . }}
    41  labels:
    42    app.kubernetes.io/name: {{ include "myapp.name" . }}
    43    app.kubernetes.io/instance: {{ .Release.Name }}
    44    app.kubernetes.io/managed-by: {{ .Release.Service }}
    45    helm.sh/chart: {{ include "myapp.chart" . }}
    46  ```
    47  
    48  If a chart has multiple components, a `app.kubernetes.io/component` label should be added (e. g. `app.kubernetes.io/component: server`). The resource name should get the component as suffix (e. g. `name: {{ include "myapp.fullname" . }}-server`).
    49  
    50  Note that templates have to be namespaced. With Helm 2.7+, `helm create` does this out-of-the-box. The `app.kubernetes.io/name` label should use the `name` template, not `fullname` as is still the case with older charts.
    51  
    52  ### Deployments, StatefulSets, DaemonSets Selectors
    53  
    54  `spec.selector.matchLabels` must be specified should follow some conventions. The standard selector should be this:
    55  
    56  ```yaml
    57  selector:
    58    matchLabels:
    59      app.kubernetes.io/name: {{ include "myapp.name" . }}
    60      app.kubernetes.io/instance: {{ .Release.Name }}
    61  ```
    62  
    63  If a chart has multiple components, a `component` label should be added to the selector (see above).
    64  
    65  `spec.selector.matchLabels` defined in `Deployments`/`StatefulSets`/`DaemonSets` `>=v1/beta2` **must not** contain `helm.sh/chart` label or any label containing a version of the chart, because the selector is immutable.
    66  The chart label string contains the version, so if it is specified, whenever the the Chart.yaml version changes, Helm's attempt to change this immutable field would cause the upgrade to fail.
    67  
    68  #### Fixing Selectors
    69  
    70  ##### For Deployments, StatefulSets, DaemonSets apps/v1beta1 or extensions/v1beta1
    71  
    72  - If it does not specify `spec.selector.matchLabels`, set it
    73  - Remove `helm.sh/chart` label in `spec.selector.matchLabels` if it exists
    74  - Bump patch version of the Chart
    75  
    76  ##### For Deployments, StatefulSets, DaemonSets >=apps/v1beta2
    77  
    78  - Remove `helm.sh/chart` label in `spec.selector.matchLabels` if it exists
    79  - Bump major version of the Chart as it is a breaking change
    80  
    81  ### Service Selectors
    82  
    83  Label selectors for services must have both `app.kubernetes.io/name` and `app.kubernetes.io/instance` labels.
    84  
    85  ```yaml
    86  selector:
    87    app.kubernetes.io/name: {{ include "myapp.name" . }}
    88    app.kubernetes.io/instance: {{ .Release.Name }}
    89  ```
    90  
    91  If a chart has multiple components, a `app.kubernetes.io/component` label should be added to the selector (see above).
    92  
    93  ### Persistence Labels
    94  
    95  ### StatefulSet
    96  
    97  In case of a `Statefulset`, `spec.volumeClaimTemplates.metadata.labels` must have both `app.kubernetes.io/name` and `app.kubernetes.io/instance` labels, and **must not** contain `helm.sh/chart` label or any label containing a version of the chart, because `spec.volumeClaimTemplates` is immutable.
    98  
    99  ```yaml
   100  labels:
   101    app.kubernetes.io/name: {{ include "myapp.name" . }}
   102    app.kubernetes.io/instance: {{ .Release.Name }}
   103  ```
   104  
   105  If a chart has multiple components, a `app.kubernetes.io/component` label should be added to the selector (see above).
   106  
   107  ### PersistentVolumeClaim
   108  
   109  In case of a `PersistentVolumeClaim`, unless special needs, `matchLabels` should not be specified
   110  because it would prevent automatic `PersistentVolume` provisioning.
   111  
   112  ## Formatting
   113  
   114  * Yaml file should be indented with two spaces.
   115  * List indentation style should be consistent.
   116  * There should be a single space after `{{` and before `}}`.
   117  
   118  ## Configuration
   119  
   120  * Docker images should be configurable. Image tags should use stable versions.
   121  
   122  ```yaml
   123  image:
   124    repository: myapp
   125    tag: 1.2.3
   126    pullPolicy: IfNotPresent
   127  ```
   128  
   129  * The use of the `default` function should be avoided if possible in favor of defaults in `values.yaml`.
   130  * It is usually best to not specify defaults for resources and to just provide sensible values that are commented out as a recommendation, especially when resources are rather high. This makes it easier to test charts on small clusters or Minikube. Setting resources should generally be a conscious choice of the user.
   131  
   132  ## Persistence
   133  
   134  * Persistence should be enabled by default
   135  * PVCs should support specifying an existing claim
   136  * Storage class should be empty by default so that the default storage class is used
   137  * All options should be shown in README.md
   138  * Example persistence section in values.yaml:
   139  
   140  ```yaml
   141  persistence:
   142    enabled: true
   143    ## If defined, storageClassName: <storageClass>
   144    ## If set to "-", storageClassName: "", which disables dynamic provisioning
   145    ## If undefined (the default) or set to null, no storageClassName spec is
   146    ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
   147    ##   GKE, AWS & OpenStack)
   148    ##
   149    storageClass: ""
   150    accessMode: ReadWriteOnce
   151    size: 10Gi
   152    # existingClaim: ""
   153  ```
   154  
   155  * Example pod spec within a deployment:
   156  
   157  ```yaml
   158  volumes:
   159    - name: data
   160    {{- if .Values.persistence.enabled }}
   161      persistentVolumeClaim:
   162        claimName: {{ .Values.persistence.existingClaim | default (include "myapp.fullname" .) }}
   163    {{- else }}
   164      emptyDir: {}
   165    {{- end -}}
   166  ```
   167  
   168  * Example pvc.yaml:
   169  
   170  ```yaml
   171  {{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }}
   172  kind: PersistentVolumeClaim
   173  apiVersion: v1
   174  metadata:
   175    name: {{ include "myapp.fullname" . }}
   176    labels:
   177      app.kubernetes.io/name: {{ include "myapp.name" . }}
   178      app.kubernetes.io/instance: {{ .Release.Name }}
   179      app.kubernetes.io/managed-by: {{ .Release.Service }}
   180      helm.sh/chart: {{ include "myapp.chart" . }}
   181  spec:
   182    accessModes:
   183      - {{ .Values.persistence.accessMode | quote }}
   184    resources:
   185      requests:
   186        storage: {{ .Values.persistence.size | quote }}
   187  {{- if .Values.persistence.storageClass }}
   188  {{- if (eq "-" .Values.persistence.storageClass) }}
   189    storageClassName: ""
   190  {{- else }}
   191    storageClassName: "{{ .Values.persistence.storageClass }}"
   192  {{- end }}
   193  {{- end }}
   194  {{- end }}
   195  ```
   196  
   197  ## AutoScaling / HorizontalPodAutoscaler
   198  
   199  * Autoscaling should be disabled by default
   200  * All options should be shown in README.md
   201  
   202  * Example autoscaling section in values.yaml:
   203  
   204  ```yaml
   205  autoscaling:
   206    enabled: false
   207    minReplicas: 1
   208    maxReplicas: 5
   209    targetCPUUtilizationPercentage: 50
   210    targetMemoryUtilizationPercentage: 50
   211  ```
   212  
   213  * Example hpa.yaml:
   214  
   215  ```yaml
   216  {{- if .Values.autoscaling.enabled }}
   217  apiVersion: autoscaling/v2beta1
   218  kind: HorizontalPodAutoscaler
   219  metadata:
   220    name: {{ include "myapp.fullname" . }}
   221    labels:
   222      app.kubernetes.io/name: {{ include "myapp.name" . }}
   223      app.kubernetes.io/instance: {{ .Release.Name }}
   224      app.kubernetes.io/managed-by: {{ .Release.Service }}
   225      helm.sh/chart: {{ include "myapp.chart" . }}
   226      app.kubernetes.io/component: "{{ .Values.name }}"
   227  spec:
   228    scaleTargetRef:
   229      apiVersion: apps/v1
   230      kind: Deployment
   231      name: {{ include "myapp.fullname" . }}
   232    minReplicas: {{ .Values.autoscaling.minReplicas }}
   233    maxReplicas: {{ .Values.autoscaling.maxReplicas }}
   234    metrics:
   235      - type: Resource
   236        resource:
   237          name: cpu
   238          targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
   239      - type: Resource
   240        resource:
   241          name: memory
   242          targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
   243  {{- end }}
   244  ```
   245  
   246  ## Ingress
   247  
   248  * See the [Ingress resource documentation](https://kubernetes.io/docs/concepts/services-networking/ingress/) for a broader concept overview
   249  * Ingress should be disabled by default
   250  * Example ingress section in values.yaml:
   251  
   252  ```yaml
   253  ingress:
   254    enabled: false
   255    annotations: {}
   256      # kubernetes.io/ingress.class: nginx
   257      # kubernetes.io/tls-acme: "true"
   258    path: /
   259    hosts:
   260      - chart-example.test
   261    tls: []
   262    #  - secretName: chart-example-tls
   263    #    hosts:
   264    #      - chart-example.test
   265  ```
   266  
   267  * Example ingress.yaml:
   268  
   269  ```yaml
   270  {{- if .Values.ingress.enabled -}}
   271  apiVersion: extensions/v1beta1
   272  kind: Ingress
   273  metadata:
   274    name: {{ include "myapp.fullname" }}
   275    labels:
   276      app.kubernetes.io/name: {{ include "myapp.name" . }}
   277      app.kubernetes.io/instance: {{ .Release.Name }}
   278      app.kubernetes.io/managed-by: {{ .Release.Service }}
   279      helm.sh/chart: {{ include "myapp.chart" . }}
   280  {{- with .Values.ingress.annotations }}
   281    annotations:
   282  {{ toYaml . | indent 4 }}
   283  {{- end }}
   284  spec:
   285  {{- if .Values.ingress.tls }}
   286    tls:
   287    {{- range .Values.ingress.tls }}
   288      - hosts:
   289        {{- range .hosts }}
   290          - {{ . | quote }}
   291        {{- end }}
   292        secretName: {{ .secretName }}
   293    {{- end }}
   294  {{- end }}
   295    rules:
   296    {{- range .Values.ingress.hosts }}
   297      - host: {{ . | quote }}
   298        http:
   299          paths:
   300            - path: {{ .Values.ingress.path }}
   301              backend:
   302                serviceName: {{ include "myapp.fullname" }}
   303                servicePort: http
   304    {{- end }}
   305  {{- end }}
   306  ```
   307  
   308  * Example prepend logic for getting an application URL in NOTES.txt:
   309  
   310  ```
   311  {{- if .Values.ingress.enabled }}
   312  {{- range .Values.ingress.hosts }}
   313    http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }}
   314  {{- end }}
   315  ```
   316  
   317  ## Documentation
   318  
   319  `README.md` and `NOTES.txt` are mandatory. `README.md` should contain a table listing all configuration options. `NOTES.txt` should provide accurate and useful information how the chart can be used/accessed.
   320  
   321  ## Compatibility
   322  
   323  We officially support compatibility with the current and the previous minor version of Kubernetes. Generated resources should use the latest possible API versions compatible with these versions. For extended backwards compatibility conditional logic based on capabilities may be used (see [built-in objects](https://github.com/helm/helm/blob/master/docs/chart_template_guide/builtin_objects.md)).
   324  
   325  ## Kubernetes Native Workloads
   326  
   327  While reviewing Charts that contain workloads such as [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/), [StatefulSets](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/), [DaemonSets](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) and [Jobs](https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/) the below points should be considered.  These are to be seen as best practices rather than strict enforcement.
   328  
   329  1. Any workload that are stateless and long running (servers) in nature are to be created as Deployments.  Deployments in turn create ReplicaSets.
   330  2. Unless there is a compelling reason, ReplicaSets or ReplicationControllers should be avoided as workload types.
   331  3. Workloads that are stateful in nature such as databases, key-value stores, message queues, in-memory caches are to be created as StatefulSets
   332  4. It is recommended that Deployments and StatefulSets configure their workloads with a [Pod Disruption Budget](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/) for high availability.
   333  5. For workloads such as databases, KV stores, etc., that replicate data, it is recommended to configure interpod anti-affinity.
   334  6. It is recommended to have a default workload update strategy configured that is suitable for this chart.
   335  7. Batch workloads are to be created using Jobs.
   336  8. It is best to always create workloads with the latest supported [api version](https://v1-8.docs.kubernetes.io/docs/api-reference/v1.8/) as older version are either deprecated or soon to be deprecated.
   337  9. It is generally not advisable to provide hard [resource limits](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container) to workloads and leave it configurable unless the workload requires such quantity bare minimum to function.
   338  10. As much as possible complex pre-app setups are configured using [init containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/).
   339  
   340  More [configuration](https://kubernetes.io/docs/concepts/configuration/overview/) best practices.