From cb13342ca1ce94f0d04837348b5c67557f948fbe Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Thu, 27 Mar 2025 20:29:15 -0400 Subject: [PATCH 01/45] WIP: begin templates for deployment --- deployment/route96/.helmignore | 23 ++++ deployment/route96/Chart.yaml | 24 ++++ deployment/route96/templates/deployment.yaml | 35 ++++++ deployment/route96/templates/pvc.yaml | 11 ++ deployment/route96/values.yaml | 110 +++++++++++++++++++ 5 files changed, 203 insertions(+) create mode 100644 deployment/route96/.helmignore create mode 100644 deployment/route96/Chart.yaml create mode 100644 deployment/route96/templates/deployment.yaml create mode 100644 deployment/route96/templates/pvc.yaml create mode 100644 deployment/route96/values.yaml diff --git a/deployment/route96/.helmignore b/deployment/route96/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/deployment/route96/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/deployment/route96/Chart.yaml b/deployment/route96/Chart.yaml new file mode 100644 index 0000000..7e2ebbe --- /dev/null +++ b/deployment/route96/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: route96 +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml new file mode 100644 index 0000000..b64200d --- /dev/null +++ b/deployment/route96/templates/deployment.yaml @@ -0,0 +1,35 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-deployment + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + app.kubernetes.io/name: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + spec: + containers: + - name: my-container + image: nginx + volumeMounts: + - name: {{ .Release.Name }}-storage + mountPath: /data + # TODO: Specify ports + volumes: + - name: {{ .Release.Name }}-storage + persistentVolumeClaim: + claimName: {{ .Release.Name }}-pvc + +#TODO: Add service +#TODO: Add HPA +#TODO: Add PDB +#TODO: Clean template syntax issues and naming. \ No newline at end of file diff --git a/deployment/route96/templates/pvc.yaml b/deployment/route96/templates/pvc.yaml new file mode 100644 index 0000000..ca49902 --- /dev/null +++ b/deployment/route96/templates/pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Release.Name }}-pvc + namespace: {{ .Release.Namespace }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.persistence.size | default "1Gi" }} diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml new file mode 100644 index 0000000..87ee480 --- /dev/null +++ b/deployment/route96/values.yaml @@ -0,0 +1,110 @@ +# Default values for route96. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +persistence: + size: 1Gi + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +livenessProbe: + httpGet: + path: / + port: http +readinessProbe: + httpGet: + path: / + port: http + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} \ No newline at end of file From 356bce92411efddc5c860c3a604401b77e1d8614 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 28 Mar 2025 21:20:16 -0400 Subject: [PATCH 02/45] complete helm chart templates and values --- deployment/route96/templates/deployment.yaml | 41 +++++-- deployment/route96/templates/hpa.yaml | 21 ++++ deployment/route96/templates/ingress.yaml | 21 ++++ deployment/route96/templates/pdb.yaml | 12 ++ deployment/route96/templates/service.yaml | 15 +++ deployment/route96/values.yaml | 109 +++---------------- 6 files changed, 111 insertions(+), 108 deletions(-) create mode 100644 deployment/route96/templates/hpa.yaml create mode 100644 deployment/route96/templates/ingress.yaml create mode 100644 deployment/route96/templates/pdb.yaml create mode 100644 deployment/route96/templates/service.yaml diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index b64200d..6f1a714 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -1,13 +1,13 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: {{ .Release.Name }}-deployment + name: "{{ .Release.Name }}-deployment" namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }} spec: - replicas: {{ .Values.replicas }} + replicas: {{ .Values.replicaCount }} selector: matchLabels: app.kubernetes.io/name: {{ .Release.Name }} @@ -19,17 +19,34 @@ spec: spec: containers: - name: my-container - image: nginx + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }} + resources: + requests: + memory: "64Mi" + cpu: "250m" + limits: + memory: "128Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 30 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + timeoutSeconds: 3 + ports: + - containerPort: 80 + protocol: TCP volumeMounts: - - name: {{ .Release.Name }}-storage + - name: "{{ .Release.Name }}-storage" mountPath: /data - # TODO: Specify ports volumes: - - name: {{ .Release.Name }}-storage + - name: "{{ .Release.Name }}-storage" persistentVolumeClaim: - claimName: {{ .Release.Name }}-pvc - -#TODO: Add service -#TODO: Add HPA -#TODO: Add PDB -#TODO: Clean template syntax issues and naming. \ No newline at end of file + claimName: "{{ .Release.Name }}-pvc" diff --git a/deployment/route96/templates/hpa.yaml b/deployment/route96/templates/hpa.yaml new file mode 100644 index 0000000..eb211ef --- /dev/null +++ b/deployment/route96/templates/hpa.yaml @@ -0,0 +1,21 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ .Release.Name }}-hpa + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ .Release.Name }}-deployment + minReplicas: {{ .Values.autoscaling.minReplicas | default 1 }} + maxReplicas: {{ .Values.autoscaling.maxReplicas | default 10 }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage | default 80 }} \ No newline at end of file diff --git a/deployment/route96/templates/ingress.yaml b/deployment/route96/templates/ingress.yaml new file mode 100644 index 0000000..6279907 --- /dev/null +++ b/deployment/route96/templates/ingress.yaml @@ -0,0 +1,21 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-ingress + namespace: {{ .Release.Namespace }} + annotations: + kubernetes.io/ingress.class: {{ .Values.ingress.className }} +spec: + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ .Release.Name }}-service + port: + number: 80 +{{- end -}} \ No newline at end of file diff --git a/deployment/route96/templates/pdb.yaml b/deployment/route96/templates/pdb.yaml new file mode 100644 index 0000000..e73186f --- /dev/null +++ b/deployment/route96/templates/pdb.yaml @@ -0,0 +1,12 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ .Release.Name }}-pdb + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + minAvailable: {{ .Values.pdb.minAvailable | default 1 }} + selector: + matchLabels: + app.kubernetes.io/name: {{ .Release.Name }} \ No newline at end of file diff --git a/deployment/route96/templates/service.yaml b/deployment/route96/templates/service.yaml new file mode 100644 index 0000000..f97912b --- /dev/null +++ b/deployment/route96/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-service + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + selector: + app.kubernetes.io/name: {{ .Release.Name }} + ports: + - protocol: TCP + port: 80 + targetPort: 80 + type: ClusterIP \ No newline at end of file diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index 87ee480..edb30f3 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -1,110 +1,27 @@ -# Default values for route96. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 +replicaCount: 3 image: repository: nginx pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "" - -imagePullSecrets: [] -nameOverride: "" -fullnameOverride: "" + tag: latest -serviceAccount: - # Specifies whether a service account should be created - create: true - # Automatically mount a ServiceAccount's API credentials? - automount: true - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" +pdb: + minAvailable: 1 -podAnnotations: {} -podLabels: {} +autoscaling: + minReplicas: 1 + maxReplicas: 1 + targetCPUUtilizationPercentage: 80 -podSecurityContext: {} - # fsGroup: 2000 +persistence: + size: "1Gi" -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 service: type: ClusterIP port: 80 ingress: - enabled: false - className: "" - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: - - path: / - pathType: ImplementationSpecific - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -persistence: - size: 1Gi - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - -livenessProbe: - httpGet: - path: / - port: http -readinessProbe: - httpGet: - path: / - port: http - -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - -# Additional volumes on the output Deployment definition. -volumes: [] -# - name: foo -# secret: -# secretName: mysecret -# optional: false - -# Additional volumeMounts on the output Deployment definition. -volumeMounts: [] -# - name: foo -# mountPath: "/etc/foo" -# readOnly: true - -nodeSelector: {} - -tolerations: [] - -affinity: {} \ No newline at end of file + enabled: true + className: "nginx" + host: "blossom.plur.app" \ No newline at end of file From 0f549c7b3b9f6d2d239de8545bf77b0f80aa1542 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 28 Mar 2025 21:41:04 -0400 Subject: [PATCH 03/45] add postgres dependency for blossom to use --- deployment/manifests.yaml | 153 ++++++++++++++++++ deployment/route96/Chart.lock | 6 + deployment/route96/Chart.yaml | 18 +-- .../route96/charts/postgresql-16.6.0.tgz | Bin 0 -> 81557 bytes deployment/route96/manifests.yaml | 0 deployment/route96/templates/deployment.yaml | 4 +- deployment/route96/templates/hpa.yaml | 1 + deployment/route96/templates/ingress.yaml | 3 + deployment/route96/templates/pdb.yaml | 1 + deployment/route96/templates/pvc.yaml | 3 + deployment/route96/templates/service.yaml | 1 + deployment/route96/values.yaml | 13 +- 12 files changed, 190 insertions(+), 13 deletions(-) create mode 100644 deployment/manifests.yaml create mode 100644 deployment/route96/Chart.lock create mode 100644 deployment/route96/charts/postgresql-16.6.0.tgz create mode 100644 deployment/route96/manifests.yaml diff --git a/deployment/manifests.yaml b/deployment/manifests.yaml new file mode 100644 index 0000000..f5ce860 --- /dev/null +++ b/deployment/manifests.yaml @@ -0,0 +1,153 @@ +--- +# Source: route96/templates/pdb.yaml +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: blossom-pdb + namespace: plur + labels: + app.kubernetes.io/part-of: blossom + app.kubernetes.io/managed-by: Helm +spec: + minAvailable: 1 + selector: + matchLabels: + app.kubernetes.io/name: blossom +--- +# Source: route96/templates/pvc.yaml +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: blossom-pvc + namespace: plur + labels: + app.kubernetes.io/part-of: blossom + app.kubernetes.io/managed-by: Helm +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +# Source: route96/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: blossom-service + namespace: plur + labels: + app.kubernetes.io/part-of: blossom + app.kubernetes.io/managed-by: Helm +spec: + selector: + app.kubernetes.io/name: blossom + ports: + - protocol: TCP + port: 80 + targetPort: 80 + type: ClusterIP +--- +# Source: route96/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: "blossom-deployment" + namespace: plur + labels: + app.kubernetes.io/name: blossom + app.kubernetes.io/part-of: blossom + app.kubernetes.io/managed-by: Helm +spec: + replicas: 3 + selector: + matchLabels: + app.kubernetes.io/name: blossom + template: + metadata: + labels: + app.kubernetes.io/name: blossom + app.kubernetes.io/part-of: blossom + app.kubernetes.io/managed-by: Helm + spec: + containers: + - name: my-container + image: "nginx:0.1.0" + imagePullPolicy: IfNotPresent + resources: + requests: + memory: "64Mi" + cpu: "250m" + limits: + memory: "128Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 30 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + timeoutSeconds: 3 + ports: + - containerPort: 80 + protocol: TCP + volumeMounts: + - name: "blossom-storage" + mountPath: /data + volumes: + - name: "blossom-storage" + persistentVolumeClaim: + claimName: "blossom-pvc" +--- +# Source: route96/templates/hpa.yaml +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: blossom-hpa + namespace: plur + labels: + app.kubernetes.io/part-of: blossom + app.kubernetes.io/managed-by: Helm +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: blossom-deployment + minReplicas: 1 + maxReplicas: 1 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 +--- +# Source: route96/templates/ingress.yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: blossom-ingress + namespace: plur + annotations: + kubernetes.io/ingress.class: nginx + labels: + app.kubernetes.io/part-of: blossom + app.kubernetes.io/managed-by: Helm +spec: + rules: + - host: blossom.plur.app + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: blossom-service + port: + number: 80 diff --git a/deployment/route96/Chart.lock b/deployment/route96/Chart.lock new file mode 100644 index 0000000..42e65f9 --- /dev/null +++ b/deployment/route96/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 16.6.0 +digest: sha256:aa966801c3271263886f5b91f05d4db0f68547a308625899abdfa5b9142cba60 +generated: "2025-03-28T21:33:08.253925-04:00" diff --git a/deployment/route96/Chart.yaml b/deployment/route96/Chart.yaml index 7e2ebbe..c31bc83 100644 --- a/deployment/route96/Chart.yaml +++ b/deployment/route96/Chart.yaml @@ -1,15 +1,7 @@ apiVersion: v2 name: route96 -description: A Helm chart for Kubernetes +description: The Helm chart for deploying the Blossom media server from Verse's route96 repository. -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. type: application # This is the chart version. This version number should be incremented each time you make changes @@ -21,4 +13,10 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "1.16.0" +appVersion: "0.1.0" + +dependencies: + - name: postgresql + version: 16.6.0 + repository: https://charts.bitnami.com/bitnami + condition: postgresql.enabled \ No newline at end of file diff --git a/deployment/route96/charts/postgresql-16.6.0.tgz b/deployment/route96/charts/postgresql-16.6.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..865acadee30f59e1a872f84f12eaeae096f457aa GIT binary patch literal 81557 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

^*uU1$(n zj(i_8UqU06tmSmTSHXg^R}R_|5loXnN%!W8ZIIdHOY?pC%)9^dbH`Hm|IMwO{%>pZ z*+cw?J9+Ml{%_9hA9HuWQH;lVs@(rM!3y4jti-n~m+`^{HlsJ!C;#<&8Jkf(%nf7@ zS4!ZG7PO|4bXUkAZetCbxseo-m-hG&8qfBE(q3^JH*q#H^c_iNy(H4^3dqH#fM2;5s zX&Y;yAV;8{%i={`ZAN7d91;Iy=3UgZ&l3VqRgWAdopw6abzU4+($5q z1=Lc#;Y@&JuHm@l3xOVL_i%S{(IA)eSRd#(Xl;3TFpdofmGw(wO`ap8ED$K6as&&lcXHrJI+ zEt%h$y-gNpd4;zoUop9qj;V%ZN=RbjEOV0{s>=Pj?K+x1^Pd0vfW;slq`@2(Aa(vf zI~#8Px9#rE&cpftE}r{+{$Ik`PZR81N52L5=DzG{8Emr_>;=@my3IikWxyp|u{3UI z$;UW7l=#k7spWQ8pE-z{Id@lC(RA8hzN92F zxBX`lpC!w+|J>Z(boc+Qo$UwzpF4T}^!vXg*t;>Yz|LOwmU27T0PaPuenqoiw~2)q z#2oX!sEI{MD>pT<5Y2uiyMFCOyp5&1xrnEw_T9gw;n~06!g_0d8*ePA1#aVS)$+w* zA$Ml^a=TM=bMqHDWw&qs@};-;+NVkWCt&S(Ke2EEsJi%%I~zN0{-@2I2l?+#o_iqw zaTfT4h&RT1LH`1m544+J^B7)~$$C72GYIT-JmPWykQvz>_l^!^9@c7m5J}6T7sClC zy@VkN=O6J^x&rZUM+vb>@lE{Y#)7lmf>fKzT0}bp0rQlClPoF6Zq~+rRPD||3~ZBL zk>NdhN5r!+pkY<}7*RE!9q5#l(=>>)Q6SP?4x-^Oq=;A;P)=mlL?~3kqd;UtLPi~6 zijrw~7Uq&2y`(JJPB=UHS&9!TX}Pe5q1&=DMxUD;$xa^!lSt;g#kiY!rNboX!45i& z!c4WI>$umOVz)ro5;Dx!jklo;&^4WPFT1^P8enA3Tqz*Bt0cX^`Mh|ZVeoQY7&|a# zei!xzG`!cOpugipTHk4AVlhjm|a#SM6#a|wm$CUFdHQ8b*&_?ZGRW_9Rq zxT^y7o4p~Y!kl598O~crAi48MO{ix!Q$M-b_8Zod+4lN3@!5yNG}xWz#U_$ Date: Fri, 28 Mar 2025 21:45:21 -0400 Subject: [PATCH 04/45] remove postgres subchart in favor of externalizing dependency --- deployment/route96/Chart.lock | 6 ------ deployment/route96/Chart.yaml | 6 ------ deployment/route96/charts/postgresql-16.6.0.tgz | Bin 81557 -> 0 bytes deployment/route96/values.yaml | 10 ---------- 4 files changed, 22 deletions(-) delete mode 100644 deployment/route96/charts/postgresql-16.6.0.tgz diff --git a/deployment/route96/Chart.lock b/deployment/route96/Chart.lock index 42e65f9..e69de29 100644 --- a/deployment/route96/Chart.lock +++ b/deployment/route96/Chart.lock @@ -1,6 +0,0 @@ -dependencies: -- name: postgresql - repository: https://charts.bitnami.com/bitnami - version: 16.6.0 -digest: sha256:aa966801c3271263886f5b91f05d4db0f68547a308625899abdfa5b9142cba60 -generated: "2025-03-28T21:33:08.253925-04:00" diff --git a/deployment/route96/Chart.yaml b/deployment/route96/Chart.yaml index c31bc83..7a48a87 100644 --- a/deployment/route96/Chart.yaml +++ b/deployment/route96/Chart.yaml @@ -14,9 +14,3 @@ version: 0.1.0 # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. appVersion: "0.1.0" - -dependencies: - - name: postgresql - version: 16.6.0 - repository: https://charts.bitnami.com/bitnami - condition: postgresql.enabled \ No newline at end of file diff --git a/deployment/route96/charts/postgresql-16.6.0.tgz b/deployment/route96/charts/postgresql-16.6.0.tgz deleted file mode 100644 index 865acadee30f59e1a872f84f12eaeae096f457aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81557 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

^*uU1$(n zj(i_8UqU06tmSmTSHXg^R}R_|5loXnN%!W8ZIIdHOY?pC%)9^dbH`Hm|IMwO{%>pZ z*+cw?J9+Ml{%_9hA9HuWQH;lVs@(rM!3y4jti-n~m+`^{HlsJ!C;#<&8Jkf(%nf7@ zS4!ZG7PO|4bXUkAZetCbxseo-m-hG&8qfBE(q3^JH*q#H^c_iNy(H4^3dqH#fM2;5s zX&Y;yAV;8{%i={`ZAN7d91;Iy=3UgZ&l3VqRgWAdopw6abzU4+($5q z1=Lc#;Y@&JuHm@l3xOVL_i%S{(IA)eSRd#(Xl;3TFpdofmGw(wO`ap8ED$K6as&&lcXHrJI+ zEt%h$y-gNpd4;zoUop9qj;V%ZN=RbjEOV0{s>=Pj?K+x1^Pd0vfW;slq`@2(Aa(vf zI~#8Px9#rE&cpftE}r{+{$Ik`PZR81N52L5=DzG{8Emr_>;=@my3IikWxyp|u{3UI z$;UW7l=#k7spWQ8pE-z{Id@lC(RA8hzN92F zxBX`lpC!w+|J>Z(boc+Qo$UwzpF4T}^!vXg*t;>Yz|LOwmU27T0PaPuenqoiw~2)q z#2oX!sEI{MD>pT<5Y2uiyMFCOyp5&1xrnEw_T9gw;n~06!g_0d8*ePA1#aVS)$+w* zA$Ml^a=TM=bMqHDWw&qs@};-;+NVkWCt&S(Ke2EEsJi%%I~zN0{-@2I2l?+#o_iqw zaTfT4h&RT1LH`1m544+J^B7)~$$C72GYIT-JmPWykQvz>_l^!^9@c7m5J}6T7sClC zy@VkN=O6J^x&rZUM+vb>@lE{Y#)7lmf>fKzT0}bp0rQlClPoF6Zq~+rRPD||3~ZBL zk>NdhN5r!+pkY<}7*RE!9q5#l(=>>)Q6SP?4x-^Oq=;A;P)=mlL?~3kqd;UtLPi~6 zijrw~7Uq&2y`(JJPB=UHS&9!TX}Pe5q1&=DMxUD;$xa^!lSt;g#kiY!rNboX!45i& z!c4WI>$umOVz)ro5;Dx!jklo;&^4WPFT1^P8enA3Tqz*Bt0cX^`Mh|ZVeoQY7&|a# zei!xzG`!cOpugipTHk4AVlhjm|a#SM6#a|wm$CUFdHQ8b*&_?ZGRW_9Rq zxT^y7o4p~Y!kl598O~crAi48MO{ix!Q$M-b_8Zod+4lN3@!5yNG}xWz#U_$ Date: Fri, 28 Mar 2025 21:46:13 -0400 Subject: [PATCH 05/45] remove lingering manifest test files --- deployment/manifests.yaml | 153 ------------------------------ deployment/route96/manifests.yaml | 0 2 files changed, 153 deletions(-) delete mode 100644 deployment/manifests.yaml delete mode 100644 deployment/route96/manifests.yaml diff --git a/deployment/manifests.yaml b/deployment/manifests.yaml deleted file mode 100644 index f5ce860..0000000 --- a/deployment/manifests.yaml +++ /dev/null @@ -1,153 +0,0 @@ ---- -# Source: route96/templates/pdb.yaml -apiVersion: policy/v1 -kind: PodDisruptionBudget -metadata: - name: blossom-pdb - namespace: plur - labels: - app.kubernetes.io/part-of: blossom - app.kubernetes.io/managed-by: Helm -spec: - minAvailable: 1 - selector: - matchLabels: - app.kubernetes.io/name: blossom ---- -# Source: route96/templates/pvc.yaml -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: blossom-pvc - namespace: plur - labels: - app.kubernetes.io/part-of: blossom - app.kubernetes.io/managed-by: Helm -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -# Source: route96/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: blossom-service - namespace: plur - labels: - app.kubernetes.io/part-of: blossom - app.kubernetes.io/managed-by: Helm -spec: - selector: - app.kubernetes.io/name: blossom - ports: - - protocol: TCP - port: 80 - targetPort: 80 - type: ClusterIP ---- -# Source: route96/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: "blossom-deployment" - namespace: plur - labels: - app.kubernetes.io/name: blossom - app.kubernetes.io/part-of: blossom - app.kubernetes.io/managed-by: Helm -spec: - replicas: 3 - selector: - matchLabels: - app.kubernetes.io/name: blossom - template: - metadata: - labels: - app.kubernetes.io/name: blossom - app.kubernetes.io/part-of: blossom - app.kubernetes.io/managed-by: Helm - spec: - containers: - - name: my-container - image: "nginx:0.1.0" - imagePullPolicy: IfNotPresent - resources: - requests: - memory: "64Mi" - cpu: "250m" - limits: - memory: "128Mi" - cpu: "500m" - livenessProbe: - httpGet: - path: / - port: 80 - initialDelaySeconds: 30 - timeoutSeconds: 5 - readinessProbe: - httpGet: - path: / - port: 80 - initialDelaySeconds: 5 - timeoutSeconds: 3 - ports: - - containerPort: 80 - protocol: TCP - volumeMounts: - - name: "blossom-storage" - mountPath: /data - volumes: - - name: "blossom-storage" - persistentVolumeClaim: - claimName: "blossom-pvc" ---- -# Source: route96/templates/hpa.yaml -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: blossom-hpa - namespace: plur - labels: - app.kubernetes.io/part-of: blossom - app.kubernetes.io/managed-by: Helm -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: blossom-deployment - minReplicas: 1 - maxReplicas: 1 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 ---- -# Source: route96/templates/ingress.yaml -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: blossom-ingress - namespace: plur - annotations: - kubernetes.io/ingress.class: nginx - labels: - app.kubernetes.io/part-of: blossom - app.kubernetes.io/managed-by: Helm -spec: - rules: - - host: blossom.plur.app - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: blossom-service - port: - number: 80 diff --git a/deployment/route96/manifests.yaml b/deployment/route96/manifests.yaml deleted file mode 100644 index e69de29..0000000 From 13e31132e9f09fffa05994de859b9e60ca89c67b Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 28 Mar 2025 21:54:37 -0400 Subject: [PATCH 06/45] Add a basic readme with some details, to begin with --- deployment/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 deployment/README.md diff --git a/deployment/README.md b/deployment/README.md new file mode 100644 index 0000000..09867e9 --- /dev/null +++ b/deployment/README.md @@ -0,0 +1,10 @@ +# Deployment +Verse utilizes a combination of Helm and ArgoCD to deploy this application to its Kubernetes cluster. Configuration for this deployment pattern requires the following: + 1. The repository has a helm chart, and all required/desired templates, written and stored in its `/deployment/` directory. + 2. An ArgoCD Application has been created that targets this repository's `/deployment/` directory. + +## To Deploy a change + 1. Update the `/deployment/Chart.yaml`'s `AppVersion` file, to contain the tag for the new Docker image. + 2. Merge this update to main. + 3. In ArgoCD, if auto-sync is not enabled for the Application that was created (the one targeting this repo), execute the sync operation for this Application. + 4. You should then see the new version of the application replace the old one, in ArgoCD. This reflects what is happening in the cluster. \ No newline at end of file From 30e1ff19ee0241c80f87df0ba51603592538a786 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 16:28:52 -0400 Subject: [PATCH 07/45] WIP: configure gitversion --- .github/workflows/docker-publish.yml | 37 ++++++++++++++++++++ GitVersion.yml | 10 ++++++ deployment/route96/Chart.yaml | 4 +-- deployment/route96/templates/deployment.yaml | 2 +- deployment/route96/values.yaml | 3 +- 5 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 GitVersion.yml diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 345b39e..5006fbf 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -3,6 +3,8 @@ name: Build and Publish Docker image on: push: branches: ['main'] + pull_request: + branches: ['main'] env: REGISTRY: ghcr.io @@ -10,6 +12,41 @@ env: IMAGE_NAME: ${{ github.repository }} jobs: + + get-version: + name: Determine Version + runs-on: ubuntu-latest + permissions: + checks: write + contents: write + id-token: write + pull-requests: write + security-events: write + statuses: write + outputs: + SemVer: ${{ steps.get-version.outputs.SemVer }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install GitVersion + uses: gittools/actions/gitversion/setup@v3.2.0 + with: + versionSpec: "6.2.x" + + - name: Determine Version + id: get-version + uses: gittools/actions/gitversion/execute@v3.2.0 + with: + useConfigFile: true + + - name: Add version to Github Actions Summary + run: | + echo "#Version:" >> $GITHUB_STEP_SUMMARY + echo ${{ steps.get-version.outputs.SemVer }} >> $GITHUB_STEP_SUMMARY + push_to_registry: name: Push Docker image to GHCR runs-on: ubuntu-latest diff --git a/GitVersion.yml b/GitVersion.yml new file mode 100644 index 0000000..04ae66f --- /dev/null +++ b/GitVersion.yml @@ -0,0 +1,10 @@ +mode: ContinuousDelivery +branches: + pull-request: + mode: ContinuousDeployment + tag: pr- + track-merge-target: true +ignore: + sha: [] +merge-message-formats: {} +tag-prefix: "" \ No newline at end of file diff --git a/deployment/route96/Chart.yaml b/deployment/route96/Chart.yaml index 7a48a87..f062b35 100644 --- a/deployment/route96/Chart.yaml +++ b/deployment/route96/Chart.yaml @@ -7,10 +7,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 +version: 1.0.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "0.1.0" +appVersion: "1.0.0" diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index 9edf585..2da2145 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -21,7 +21,7 @@ spec: spec: containers: - name: my-container - image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}" + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }} resources: requests: diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index d02c830..571b2fd 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -2,6 +2,7 @@ replicaCount: 3 image: repository: nginx + tag: NA pullPolicy: IfNotPresent pdb: @@ -23,4 +24,4 @@ service: ingress: enabled: true className: "nginx" - host: "blossom.plur.app" + host: "blossom.plur.app" \ No newline at end of file From 9b0559543f6022f70c5c38e8cba00afd99cceeb8 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 16:30:56 -0400 Subject: [PATCH 08/45] limit image pushes to merge-to-main only --- .github/workflows/docker-publish.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 5006fbf..d28af07 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -48,6 +48,7 @@ jobs: echo ${{ steps.get-version.outputs.SemVer }} >> $GITHUB_STEP_SUMMARY push_to_registry: + if: github.ref == 'refs/heads/main' name: Push Docker image to GHCR runs-on: ubuntu-latest permissions: From 375dd755f3956b5f0d14b2ed99e755e493012112 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 16:39:38 -0400 Subject: [PATCH 09/45] WIP: test gitversion --- .github/workflows/docker-publish.yml | 4 +--- GitVersion.yml | 10 ---------- 2 files changed, 1 insertion(+), 13 deletions(-) delete mode 100644 GitVersion.yml diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index d28af07..282667f 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -13,7 +13,7 @@ env: jobs: - get-version: + get_version: name: Determine Version runs-on: ubuntu-latest permissions: @@ -39,8 +39,6 @@ jobs: - name: Determine Version id: get-version uses: gittools/actions/gitversion/execute@v3.2.0 - with: - useConfigFile: true - name: Add version to Github Actions Summary run: | diff --git a/GitVersion.yml b/GitVersion.yml deleted file mode 100644 index 04ae66f..0000000 --- a/GitVersion.yml +++ /dev/null @@ -1,10 +0,0 @@ -mode: ContinuousDelivery -branches: - pull-request: - mode: ContinuousDeployment - tag: pr- - track-merge-target: true -ignore: - sha: [] -merge-message-formats: {} -tag-prefix: "" \ No newline at end of file From a5d4c34b4fc3221775b86a31f09156294abaa004 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 16:50:20 -0400 Subject: [PATCH 10/45] build but don't push always --- .github/workflows/docker-publish.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 282667f..442c0c8 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -46,7 +46,7 @@ jobs: echo ${{ steps.get-version.outputs.SemVer }} >> $GITHUB_STEP_SUMMARY push_to_registry: - if: github.ref == 'refs/heads/main' + needs: get_version name: Push Docker image to GHCR runs-on: ubuntu-latest permissions: @@ -73,17 +73,21 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | - # Tag with branch name and short SHA on push to main - type=ref,event=branch,suffix=-{{sha}} - # Tag with 'latest' on push to main (default branch) - type=raw,value=latest,enable={{is_default_branch}} + type=raw,value=${{ needs.get_version.outputs.SemVer }} + type=raw,value=latest + # Always build the image, as a test, but only push on a merge to main - name: Build and push Docker image + id: build-and-push-image uses: docker/build-push-action@v6 with: context: . - # Push only when on the main branch (effectively, as the trigger is on: push: branches: [main]) push: ${{ github.ref == 'refs/heads/main' }} tags: ${{ steps.meta.outputs.tags }} # Use labels generated by metadata-action (includes OCI standard labels) - labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file + labels: ${{ steps.meta.outputs.labels }} + + - name: Add built image to Github Actions Summary + run: | + echo "# Image Built:" >> $GITHUB_STEP_SUMMARY + echo ${{ steps.build-and-push-image.outputs.metadata }} >> $GITHUB_STEP_SUMMARY \ No newline at end of file From 9baeb43dcf2c29e8992e4eb0a04e426e83a2b4d2 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 19:25:43 -0400 Subject: [PATCH 11/45] WIP: release on merge --- .github/workflows/docker-publish.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 442c0c8..8d68d69 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -90,4 +90,22 @@ jobs: - name: Add built image to Github Actions Summary run: | echo "# Image Built:" >> $GITHUB_STEP_SUMMARY - echo ${{ steps.build-and-push-image.outputs.metadata }} >> $GITHUB_STEP_SUMMARY \ No newline at end of file + echo $IMAGE_NAME:${{ steps.meta.outputs.tags[1] }} >> $GITHUB_STEP_SUMMARY + + # update_helm_deployment: + # needs: get_version + # name: Push Docker image to GHCR + # runs-on: ubuntu-latest + # permissions: + # # Required to read the repository contents. + # contents: write + # # Required to push packages (Docker images) to GHCR. + # packages: write + # steps: + + # TODO: Update the appVersion and chartVersion in deployment/route96/Charts.yaml, + # to use get_version.outputs.SemVer + + # TODO: Update the image.tag in deployment/route96/values.yaml to use get_version.outputs.SemVer. + + # TODO: Merge the updated branch to the release branch, which ArgoCD has been set to auto-sync against. \ No newline at end of file From 30d8cb547e361db1038c51265fcf2a08595ef9b6 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 19:27:28 -0400 Subject: [PATCH 12/45] WIP: release on merge --- .github/workflows/docker-publish.yml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 8d68d69..2fcfa10 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -1,5 +1,9 @@ name: Build and Publish Docker image +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + on: push: branches: ['main'] @@ -77,15 +81,15 @@ jobs: type=raw,value=latest # Always build the image, as a test, but only push on a merge to main - - name: Build and push Docker image - id: build-and-push-image - uses: docker/build-push-action@v6 - with: - context: . - push: ${{ github.ref == 'refs/heads/main' }} - tags: ${{ steps.meta.outputs.tags }} - # Use labels generated by metadata-action (includes OCI standard labels) - labels: ${{ steps.meta.outputs.labels }} + # - name: Build and push Docker image + # id: build-and-push-image + # uses: docker/build-push-action@v6 + # with: + # context: . + # push: ${{ github.ref == 'refs/heads/main' }} + # tags: ${{ steps.meta.outputs.tags }} + # # Use labels generated by metadata-action (includes OCI standard labels) + # labels: ${{ steps.meta.outputs.labels }} - name: Add built image to Github Actions Summary run: | From 88d425b6581e3b8d287507d95a5402d1749e312e Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 19:28:43 -0400 Subject: [PATCH 13/45] WIP: release on merge --- .github/workflows/docker-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 2fcfa10..851b6bd 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -94,7 +94,7 @@ jobs: - name: Add built image to Github Actions Summary run: | echo "# Image Built:" >> $GITHUB_STEP_SUMMARY - echo $IMAGE_NAME:${{ steps.meta.outputs.tags[1] }} >> $GITHUB_STEP_SUMMARY + echo $IMAGE_NAME:${{ needs.get_version.outputs.SemVer }} >> $GITHUB_STEP_SUMMARY # update_helm_deployment: # needs: get_version From b842df21c5240dd3597c27a7701713064e8f34ee Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 19:33:11 -0400 Subject: [PATCH 14/45] WIP: release on merge --- .github/workflows/docker-publish.yml | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 851b6bd..b82e152 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -46,7 +46,7 @@ jobs: - name: Add version to Github Actions Summary run: | - echo "#Version:" >> $GITHUB_STEP_SUMMARY + echo "# Version:" >> $GITHUB_STEP_SUMMARY echo ${{ steps.get-version.outputs.SemVer }} >> $GITHUB_STEP_SUMMARY push_to_registry: @@ -81,17 +81,19 @@ jobs: type=raw,value=latest # Always build the image, as a test, but only push on a merge to main - # - name: Build and push Docker image - # id: build-and-push-image - # uses: docker/build-push-action@v6 - # with: - # context: . - # push: ${{ github.ref == 'refs/heads/main' }} - # tags: ${{ steps.meta.outputs.tags }} - # # Use labels generated by metadata-action (includes OCI standard labels) - # labels: ${{ steps.meta.outputs.labels }} + - name: Build and push Docker image + id: build-and-push-image + if: github.ref == 'refs/heads/main' + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + # Use labels generated by metadata-action (includes OCI standard labels) + labels: ${{ steps.meta.outputs.labels }} - name: Add built image to Github Actions Summary + if: steps.build-and-push-image.outcome == 'success' run: | echo "# Image Built:" >> $GITHUB_STEP_SUMMARY echo $IMAGE_NAME:${{ needs.get_version.outputs.SemVer }} >> $GITHUB_STEP_SUMMARY From 01d723105af13c1c65f22a384f67ba9b0ac5a667 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 19:52:28 -0400 Subject: [PATCH 15/45] WIP: release on merge --- .github/workflows/docker-publish.yml | 32 ++++++++++++++++------------ 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index b82e152..9a3b5d4 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -80,7 +80,6 @@ jobs: type=raw,value=${{ needs.get_version.outputs.SemVer }} type=raw,value=latest - # Always build the image, as a test, but only push on a merge to main - name: Build and push Docker image id: build-and-push-image if: github.ref == 'refs/heads/main' @@ -91,24 +90,29 @@ jobs: tags: ${{ steps.meta.outputs.tags }} # Use labels generated by metadata-action (includes OCI standard labels) labels: ${{ steps.meta.outputs.labels }} - - - name: Add built image to Github Actions Summary + + - name: Output image details if: steps.build-and-push-image.outcome == 'success' run: | - echo "# Image Built:" >> $GITHUB_STEP_SUMMARY - echo $IMAGE_NAME:${{ needs.get_version.outputs.SemVer }} >> $GITHUB_STEP_SUMMARY + echo "Built and pushed the following images:" + echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' + + # - name: Add built image to Github Actions Summary + # if: steps.build-and-push-image.outcome == 'success' + # run: | + # echo "# Image Built:" >> $GITHUB_STEP_SUMMARY + # echo $IMAGE_NAME:${{ needs.get_version.outputs.SemVer }} >> $GITHUB_STEP_SUMMARY # update_helm_deployment: - # needs: get_version - # name: Push Docker image to GHCR - # runs-on: ubuntu-latest - # permissions: - # # Required to read the repository contents. - # contents: write - # # Required to push packages (Docker images) to GHCR. - # packages: write - # steps: + # name: Make Release + # needs: push_to_registry + # if: github.ref == 'refs/heads/main' + # runs-on: ubuntu-latest + # permissions: + # contents: write + # steps: + # TODO: Update the appVersion and chartVersion in deployment/route96/Charts.yaml, # to use get_version.outputs.SemVer From 31855e2132d3e4cde5322e7411557765c1574d04 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 19:53:44 -0400 Subject: [PATCH 16/45] WIP: release on merge --- .github/workflows/docker-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 9a3b5d4..21817f7 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -95,7 +95,7 @@ jobs: if: steps.build-and-push-image.outcome == 'success' run: | echo "Built and pushed the following images:" - echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' + echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' >> $GITHUB_STEP_SUMMARY # - name: Add built image to Github Actions Summary # if: steps.build-and-push-image.outcome == 'success' From cf27861f9cb1a24a2e91c4763c0705761c434370 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 19:55:54 -0400 Subject: [PATCH 17/45] WIP: release on merge --- .github/workflows/docker-publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 21817f7..8677f47 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -92,9 +92,9 @@ jobs: labels: ${{ steps.meta.outputs.labels }} - name: Output image details - if: steps.build-and-push-image.outcome == 'success' + # if: steps.build-and-push-image.outcome == 'success' run: | - echo "Built and pushed the following images:" + echo "# Built and pushed the following images:" >> $GITHUB_STEP_SUMMARY echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' >> $GITHUB_STEP_SUMMARY # - name: Add built image to Github Actions Summary From 44b5d567df1ba45dd3e52939614cb6bf40187e21 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 20:20:09 -0400 Subject: [PATCH 18/45] WIP: testing --- .github/workflows/docker-publish.yml | 63 +++++++++++++++------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 8677f47..2b8f9df 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -12,11 +12,9 @@ on: env: REGISTRY: ghcr.io - # IMAGE_NAME is derived from the repository name IMAGE_NAME: ${{ github.repository }} jobs: - get_version: name: Determine Version runs-on: ubuntu-latest @@ -30,6 +28,7 @@ jobs: outputs: SemVer: ${{ steps.get-version.outputs.SemVer }} steps: + - name: Checkout uses: actions/checkout@v4 with: @@ -44,22 +43,21 @@ jobs: id: get-version uses: gittools/actions/gitversion/execute@v3.2.0 - - name: Add version to Github Actions Summary + - name: Output Version run: | echo "# Version:" >> $GITHUB_STEP_SUMMARY echo ${{ steps.get-version.outputs.SemVer }} >> $GITHUB_STEP_SUMMARY push_to_registry: needs: get_version + if: github.ref == 'refs/heads/main' name: Push Docker image to GHCR runs-on: ubuntu-latest permissions: - # Required to read the repository contents. contents: read - # Required to push packages (Docker images) to GHCR. packages: write - steps: + - name: Check out the repo uses: actions/checkout@v4 @@ -72,7 +70,6 @@ jobs: - name: Extract metadata (tags, labels) for Docker id: meta - # Using v5 for metadata-action uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} @@ -82,40 +79,48 @@ jobs: - name: Build and push Docker image id: build-and-push-image - if: github.ref == 'refs/heads/main' uses: docker/build-push-action@v6 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} - # Use labels generated by metadata-action (includes OCI standard labels) labels: ${{ steps.meta.outputs.labels }} - - name: Output image details - # if: steps.build-and-push-image.outcome == 'success' + - name: Output Image Details + if: steps.build-and-push-image.outcome == 'success' run: | echo "# Built and pushed the following images:" >> $GITHUB_STEP_SUMMARY echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' >> $GITHUB_STEP_SUMMARY - - # - name: Add built image to Github Actions Summary - # if: steps.build-and-push-image.outcome == 'success' - # run: | - # echo "# Image Built:" >> $GITHUB_STEP_SUMMARY - # echo $IMAGE_NAME:${{ needs.get_version.outputs.SemVer }} >> $GITHUB_STEP_SUMMARY - - # update_helm_deployment: - # name: Make Release + + merge_to_release: + name: Merge to Release + needs: get_version # needs: push_to_registry # if: github.ref == 'refs/heads/main' - # runs-on: ubuntu-latest - # permissions: - # contents: write - # steps: + runs-on: ubuntu-latest + permissions: + contents: write + steps: - - # TODO: Update the appVersion and chartVersion in deployment/route96/Charts.yaml, - # to use get_version.outputs.SemVer + - name: Apply semver-sha to version + shell: bash + run: | + git config --global user.name "$verse-ci" + git config --global user.email "$ci@verse.app" + git checkout release + git merge -Xtheirs --no-commit main - # TODO: Update the image.tag in deployment/route96/values.yaml to use get_version.outputs.SemVer. + - name: Apply Newest Version + shell: bash + run: | + yq -i '.version = "${{ needs.get_version.outputs.SemVer }}"' ./deployment/route96/Chart.yaml + yq -i '.appVersion = "${{ needs.get_version.outputs.SemVer }}"' ./deployment/route96/Chart.yaml + yq -i '.image.tag = "${{ needs.get_version.outputs.SemVer }}"' ./deployment/route96/values.yaml - # TODO: Merge the updated branch to the release branch, which ArgoCD has been set to auto-sync against. \ No newline at end of file + - name: Commit and push + shell: bash + run: | + git tag ${{ needs.get_version.outputs.SemVer }} + git commit -a -m "Version ${{ needs.get_version.outputs.SemVer }} Release" + git push + git push --tags From ef8890a04dca4f259c34d2f71625caf87592700e Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 20:23:04 -0400 Subject: [PATCH 19/45] WIP: testing --- .github/workflows/docker-publish.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 2b8f9df..004a92d 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -102,7 +102,10 @@ jobs: contents: write steps: - - name: Apply semver-sha to version + - name: Check Out the Repo + uses: actions/checkout@v4 + + - name: Merge main Branch Locally shell: bash run: | git config --global user.name "$verse-ci" @@ -117,7 +120,7 @@ jobs: yq -i '.appVersion = "${{ needs.get_version.outputs.SemVer }}"' ./deployment/route96/Chart.yaml yq -i '.image.tag = "${{ needs.get_version.outputs.SemVer }}"' ./deployment/route96/values.yaml - - name: Commit and push + - name: Commit and Push to Trigger Release shell: bash run: | git tag ${{ needs.get_version.outputs.SemVer }} From a302438bb82cebd5f980dc4b1ab9b9544d2bf9d3 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 20:25:13 -0400 Subject: [PATCH 20/45] WIP: testing --- .github/workflows/docker-publish.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 004a92d..d9f3b11 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -104,6 +104,8 @@ jobs: - name: Check Out the Repo uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Merge main Branch Locally shell: bash From 1e38d731fa9808972bb4420860d166a0b7ef49ed Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 20:26:26 -0400 Subject: [PATCH 21/45] WIP: testing --- .github/workflows/docker-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index d9f3b11..a2a9435 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -113,7 +113,7 @@ jobs: git config --global user.name "$verse-ci" git config --global user.email "$ci@verse.app" git checkout release - git merge -Xtheirs --no-commit main + git merge -Xtheirs --no-commit origin/main - name: Apply Newest Version shell: bash From 1e614a23a8fcce304d48c5e7a636f46839d4f29c Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 20:27:48 -0400 Subject: [PATCH 22/45] WIP: testing --- .github/workflows/docker-publish.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index a2a9435..99fae26 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -118,6 +118,8 @@ jobs: - name: Apply Newest Version shell: bash run: | + pwd + ls -la yq -i '.version = "${{ needs.get_version.outputs.SemVer }}"' ./deployment/route96/Chart.yaml yq -i '.appVersion = "${{ needs.get_version.outputs.SemVer }}"' ./deployment/route96/Chart.yaml yq -i '.image.tag = "${{ needs.get_version.outputs.SemVer }}"' ./deployment/route96/values.yaml From efb7f78c8ea197f72ffbc97bd4c4c14fa70c7321 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 20:29:56 -0400 Subject: [PATCH 23/45] WIP: testing --- .github/workflows/docker-publish.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 99fae26..0829f01 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -113,13 +113,12 @@ jobs: git config --global user.name "$verse-ci" git config --global user.email "$ci@verse.app" git checkout release - git merge -Xtheirs --no-commit origin/main + git merge -Xtheirs --no-commit origin/configure-kubernetes-deployment +# git merge -Xtheirs --no-commit origin/main - name: Apply Newest Version shell: bash run: | - pwd - ls -la yq -i '.version = "${{ needs.get_version.outputs.SemVer }}"' ./deployment/route96/Chart.yaml yq -i '.appVersion = "${{ needs.get_version.outputs.SemVer }}"' ./deployment/route96/Chart.yaml yq -i '.image.tag = "${{ needs.get_version.outputs.SemVer }}"' ./deployment/route96/values.yaml From ffeac4c86ada14ab33337a33e2ee9e4c00917d62 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Fri, 4 Apr 2025 20:43:26 -0400 Subject: [PATCH 24/45] update deployment with correct env vars --- .github/workflows/docker-publish.yml | 8 +++---- deployment/route96/templates/deployment.yaml | 24 ++++++++++++++++++- .../route96/templates/sealed-secret.yaml | 1 + deployment/route96/templates/service.yaml | 2 +- deployment/route96/values.yaml | 2 +- 5 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 deployment/route96/templates/sealed-secret.yaml diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 0829f01..4d0d85e 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -94,9 +94,8 @@ jobs: merge_to_release: name: Merge to Release - needs: get_version - # needs: push_to_registry - # if: github.ref == 'refs/heads/main' + needs: push_to_registry + if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest permissions: contents: write @@ -113,8 +112,7 @@ jobs: git config --global user.name "$verse-ci" git config --global user.email "$ci@verse.app" git checkout release - git merge -Xtheirs --no-commit origin/configure-kubernetes-deployment -# git merge -Xtheirs --no-commit origin/main + git merge -Xtheirs --no-commit origin/main - name: Apply Newest Version shell: bash diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index 2da2145..3d0a09f 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -23,6 +23,28 @@ spec: - name: my-container image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }} + env: # TODO: Translate these to the value.yaml file, and template here. + - name: APP__LISTEN + value: 0.0.0.0:8000 + - name: APP__DATABASE + value: postgres://postgres:root@db:5432/route96 # TODO: Update the connection string here + - name: APP__STORAGE_DIR + value: /app/data + - name: APP__MAX_UPLOAD_BYTES + value: 5000000000 + - name: APP__PUBLIC_URL + value: http://localhost:8000 # TODO: check in with Daniel on this config, since the Ingress manifest will control it. + - name: APP__NIP29_RELAY__URL + value: wss://communities.nos.social + - name: APP__NIP29_RELAY__PRIVATE_KEY + value: 6b911fd37cdf5c81d4c0adb1ab7fa822ed253ab0ad9aa18d77257c88b29b718e # TODO: this will need to come from a sealed secret, replace with prod value. + - name: APP__NIP29_RELAY__CACHE_EXPIRATION + value: 300 + - name: SECRET_VALUE_EXAMPLE + valueFrom: + secretKeyRef: + name: "{{ .Release.Name }}-secret" # TODO: match this name up with sealed-secret.yaml + key: secret-key resources: requests: memory: "64Mi" @@ -43,7 +65,7 @@ spec: initialDelaySeconds: 5 timeoutSeconds: 3 ports: - - containerPort: 80 + - containerPort: 8000 protocol: TCP volumeMounts: - name: "{{ .Release.Name }}-storage" diff --git a/deployment/route96/templates/sealed-secret.yaml b/deployment/route96/templates/sealed-secret.yaml new file mode 100644 index 0000000..d8de25b --- /dev/null +++ b/deployment/route96/templates/sealed-secret.yaml @@ -0,0 +1 @@ +# TODO: Create a sealed-secret here, for the target cluster, containing the secret values needed. \ No newline at end of file diff --git a/deployment/route96/templates/service.yaml b/deployment/route96/templates/service.yaml index 7966559..be1d5a1 100644 --- a/deployment/route96/templates/service.yaml +++ b/deployment/route96/templates/service.yaml @@ -12,5 +12,5 @@ spec: ports: - protocol: TCP port: 80 - targetPort: 80 + targetPort: 8000 type: ClusterIP \ No newline at end of file diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index 571b2fd..73ab2f7 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -1,7 +1,7 @@ replicaCount: 3 image: - repository: nginx + repository: ghcr.io/verse-pbc/route96 tag: NA pullPolicy: IfNotPresent From 76778616a49abdac247425713ff532f8dd9c3f4a Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Sat, 5 Apr 2025 15:48:55 -0400 Subject: [PATCH 25/45] WIP: Still getting details from Daniel about it --- deployment/route96/templates/deployment.yaml | 19 +++++++++++++------ .../route96/templates/sealed-secret.yaml | 6 +++++- deployment/route96/values.yaml | 2 +- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index 3d0a09f..f554d13 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -29,22 +29,29 @@ spec: - name: APP__DATABASE value: postgres://postgres:root@db:5432/route96 # TODO: Update the connection string here - name: APP__STORAGE_DIR - value: /app/data + value: /app/data # This needs to match the volumeMount and volume below. - name: APP__MAX_UPLOAD_BYTES value: 5000000000 - name: APP__PUBLIC_URL value: http://localhost:8000 # TODO: check in with Daniel on this config, since the Ingress manifest will control it. - name: APP__NIP29_RELAY__URL value: wss://communities.nos.social - - name: APP__NIP29_RELAY__PRIVATE_KEY - value: 6b911fd37cdf5c81d4c0adb1ab7fa822ed253ab0ad9aa18d77257c88b29b718e # TODO: this will need to come from a sealed secret, replace with prod value. - name: APP__NIP29_RELAY__CACHE_EXPIRATION value: 300 - - name: SECRET_VALUE_EXAMPLE + - name: MARIADB_DATABASE # TODO: Do I need this as well as APP__DATABASE? + value: route96 + - name: APP__DATABASE + value: postgres://blossom@verse-postgres-blossom-cluster-do-user-5049766-0.l.db.ondigitalocean.com:25060/route96 + - name: MARIADB_ROOT_PASSWORD # TODO: Is this how it is set in the application? + valueFrom: + secretKeyRef: + name: "{{ .Release.Name }}-secret" # TODO: match this name up with sealed-secret.yaml + key: database_password + - name: APP__NIP29_RELAY__PRIVATE_KEY valueFrom: secretKeyRef: name: "{{ .Release.Name }}-secret" # TODO: match this name up with sealed-secret.yaml - key: secret-key + key: app_nip29_relay_private_key resources: requests: memory: "64Mi" @@ -69,7 +76,7 @@ spec: protocol: TCP volumeMounts: - name: "{{ .Release.Name }}-storage" - mountPath: /data + mountPath: /app/data volumes: - name: "{{ .Release.Name }}-storage" persistentVolumeClaim: diff --git a/deployment/route96/templates/sealed-secret.yaml b/deployment/route96/templates/sealed-secret.yaml index d8de25b..da09734 100644 --- a/deployment/route96/templates/sealed-secret.yaml +++ b/deployment/route96/templates/sealed-secret.yaml @@ -1 +1,5 @@ -# TODO: Create a sealed-secret here, for the target cluster, containing the secret values needed. \ No newline at end of file +# TODO: Create a sealed-secret here, for the target cluster, containing the secret values needed. +# Looks like we will need these: +# - Postgres password +# - Postgres CA cert +# - APP__NIP29_RELAY__PRIVATE_KEY value \ No newline at end of file diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index 73ab2f7..143fa5d 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -14,7 +14,7 @@ autoscaling: targetCPUUtilizationPercentage: 80 persistence: - size: "1Gi" + size: "10Gi" service: From 006ec0a2b5fc24acb53a43aaa35adce12b273f74 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Sun, 6 Apr 2025 15:08:31 -0400 Subject: [PATCH 26/45] First pass at deployment manifests completed --- ...er-publish.yml => publish-and-release.yml} | 2 +- .gitignore | 4 +- deployment/route96/templates/deployment.yaml | 68 ++++++++++--------- deployment/route96/templates/hpa.yaml | 8 +-- deployment/route96/templates/ingress.yaml | 8 +-- deployment/route96/templates/pdb.yaml | 8 +-- deployment/route96/templates/pvc.yaml | 8 +-- .../route96/templates/sealed-secret.yaml | 23 +++++-- deployment/route96/templates/service.yaml | 8 +-- deployment/route96/values.yaml | 5 +- 10 files changed, 79 insertions(+), 63 deletions(-) rename .github/workflows/{docker-publish.yml => publish-and-release.yml} (98%) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/publish-and-release.yml similarity index 98% rename from .github/workflows/docker-publish.yml rename to .github/workflows/publish-and-release.yml index 4d0d85e..a9b184a 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/publish-and-release.yml @@ -1,4 +1,4 @@ -name: Build and Publish Docker image +name: Publish Image and Release Deployment concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.gitignore b/.gitignore index f3a364a..2621638 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ target/ data/ -.idea/ \ No newline at end of file +.idea/ + +local/ \ No newline at end of file diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index f554d13..c01d959 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -1,64 +1,58 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: "{{ .Release.Name }}-deployment" - namespace: {{ .Release.Namespace }} + name: blossom-deployment + namespace: blossom labels: - app.kubernetes.io/name: {{ .Release.Name }} - app.kubernetes.io/part-of: {{ .Release.Name }} + app.kubernetes.io/name: blossom + app.kubernetes.io/part-of: blossom app.kubernetes.io/managed-by: Helm spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: - app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/name: blossom template: metadata: labels: - app.kubernetes.io/name: {{ .Release.Name }} - app.kubernetes.io/part-of: {{ .Release.Name }} + app.kubernetes.io/name: blossom + app.kubernetes.io/part-of: blossom app.kubernetes.io/managed-by: Helm spec: containers: - name: my-container image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }} - env: # TODO: Translate these to the value.yaml file, and template here. + env: - name: APP__LISTEN - value: 0.0.0.0:8000 - - name: APP__DATABASE - value: postgres://postgres:root@db:5432/route96 # TODO: Update the connection string here + value: 0.0.0.0:8000 - name: APP__STORAGE_DIR - value: /app/data # This needs to match the volumeMount and volume below. + value: /app/data # This needs to match the volumeMount and volume below. - name: APP__MAX_UPLOAD_BYTES - value: 5000000000 + value: 5000000000 - name: APP__PUBLIC_URL - value: http://localhost:8000 # TODO: check in with Daniel on this config, since the Ingress manifest will control it. + value: http://localhost:8000 # TODO: check in with Daniel on this config, since the Ingress manifest will control it. - name: APP__NIP29_RELAY__URL - value: wss://communities.nos.social + value: wss://communities.nos.social - name: APP__NIP29_RELAY__CACHE_EXPIRATION - value: 300 - - name: MARIADB_DATABASE # TODO: Do I need this as well as APP__DATABASE? - value: route96 - - name: APP__DATABASE - value: postgres://blossom@verse-postgres-blossom-cluster-do-user-5049766-0.l.db.ondigitalocean.com:25060/route96 - - name: MARIADB_ROOT_PASSWORD # TODO: Is this how it is set in the application? - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-secret" # TODO: match this name up with sealed-secret.yaml - key: database_password + value: 300 - name: APP__NIP29_RELAY__PRIVATE_KEY valueFrom: secretKeyRef: - name: "{{ .Release.Name }}-secret" # TODO: match this name up with sealed-secret.yaml + name: "blossom-secret" key: app_nip29_relay_private_key + - name: APP__DATABASE + valueFrom: + secretKeyRef: + name: "blossom-secret" + key: database_connection_string resources: requests: - memory: "64Mi" - cpu: "250m" + memory: "512Mi" + cpu: "1" limits: - memory: "128Mi" - cpu: "500m" + memory: "1028Mi" + cpu: "2" livenessProbe: httpGet: path: / @@ -75,9 +69,17 @@ spec: - containerPort: 8000 protocol: TCP volumeMounts: - - name: "{{ .Release.Name }}-storage" + - name: "blossom-storage" mountPath: /app/data + - name: database-cacert + mountPath: /app/ca.pem volumes: - - name: "{{ .Release.Name }}-storage" + - name: "blossom-storage" persistentVolumeClaim: - claimName: "{{ .Release.Name }}-pvc" + claimName: "blossom-pvc" + - name: database-cacert + secret: + secretName: "blossom-secret" + items: + - key: database_cacert + path: ca.pem diff --git a/deployment/route96/templates/hpa.yaml b/deployment/route96/templates/hpa.yaml index 6f1f2ba..4704fa1 100644 --- a/deployment/route96/templates/hpa.yaml +++ b/deployment/route96/templates/hpa.yaml @@ -1,16 +1,16 @@ apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: - name: {{ .Release.Name }}-hpa - namespace: {{ .Release.Namespace }} + name: blossom-hpa + namespace: blossom labels: - app.kubernetes.io/part-of: {{ .Release.Name }} + app.kubernetes.io/part-of: blossom app.kubernetes.io/managed-by: Helm spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment - name: {{ .Release.Name }}-deployment + name: blossom-deployment minReplicas: {{ .Values.autoscaling.minReplicas | default 1 }} maxReplicas: {{ .Values.autoscaling.maxReplicas | default 10 }} metrics: diff --git a/deployment/route96/templates/ingress.yaml b/deployment/route96/templates/ingress.yaml index 8d25a36..1f0a8bf 100644 --- a/deployment/route96/templates/ingress.yaml +++ b/deployment/route96/templates/ingress.yaml @@ -2,12 +2,12 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: {{ .Release.Name }}-ingress - namespace: {{ .Release.Namespace }} + name: blossom-ingress + namespace: blossom annotations: kubernetes.io/ingress.class: {{ .Values.ingress.className }} labels: - app.kubernetes.io/part-of: {{ .Release.Name }} + app.kubernetes.io/part-of: blossom app.kubernetes.io/managed-by: Helm spec: rules: @@ -18,7 +18,7 @@ spec: pathType: Prefix backend: service: - name: {{ .Release.Name }}-service + name: blossom-service port: number: 80 {{- end -}} \ No newline at end of file diff --git a/deployment/route96/templates/pdb.yaml b/deployment/route96/templates/pdb.yaml index 625f85a..09b7eb7 100644 --- a/deployment/route96/templates/pdb.yaml +++ b/deployment/route96/templates/pdb.yaml @@ -1,13 +1,13 @@ apiVersion: policy/v1 kind: PodDisruptionBudget metadata: - name: {{ .Release.Name }}-pdb - namespace: {{ .Release.Namespace }} + name: blossom-pdb + namespace: blossom labels: - app.kubernetes.io/part-of: {{ .Release.Name }} + app.kubernetes.io/part-of: blossom app.kubernetes.io/managed-by: Helm spec: minAvailable: {{ .Values.pdb.minAvailable | default 1 }} selector: matchLabels: - app.kubernetes.io/name: {{ .Release.Name }} \ No newline at end of file + app.kubernetes.io/name: blossom \ No newline at end of file diff --git a/deployment/route96/templates/pvc.yaml b/deployment/route96/templates/pvc.yaml index bb9209e..7eecb66 100644 --- a/deployment/route96/templates/pvc.yaml +++ b/deployment/route96/templates/pvc.yaml @@ -1,14 +1,14 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ .Release.Name }}-pvc - namespace: {{ .Release.Namespace }} + name: blossom-pvc + namespace: blossom labels: - app.kubernetes.io/part-of: {{ .Release.Name }} + app.kubernetes.io/part-of: blossom app.kubernetes.io/managed-by: Helm spec: accessModes: - - ReadWriteOnce + - ReadWriteMany resources: requests: storage: {{ .Values.persistence.size | default "1Gi" }} diff --git a/deployment/route96/templates/sealed-secret.yaml b/deployment/route96/templates/sealed-secret.yaml index da09734..7be1da2 100644 --- a/deployment/route96/templates/sealed-secret.yaml +++ b/deployment/route96/templates/sealed-secret.yaml @@ -1,5 +1,18 @@ -# TODO: Create a sealed-secret here, for the target cluster, containing the secret values needed. -# Looks like we will need these: -# - Postgres password -# - Postgres CA cert -# - APP__NIP29_RELAY__PRIVATE_KEY value \ No newline at end of file +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + name: blossom-secret + namespace: blossom +spec: + encryptedData: + app_nip29_relay_private_key: AgBRSuOFpZs8CkrfTan7BRC2wAMW3u8Gb+dXcRhEDqmw3u2Ri5a4mHAW0ylSAv2EZdjfk/ukKO5nQevhLpbF/K5iPQqbdwc7BPIlLlOR1/uqOIBLV3R9ql4/fSLpCmcO9wVQwH3VKPkRQ/a9V8YCy1JEqPM7gHZn6DhxX0hggWn2jhfIm5duaVwOqZyzxDyqFGLiM31q9PS93r+ws0BDdKotd36q7Mdwa672NB/kdp5lEF/RKqbfygSuwvuNhgtXUxquccPYByyqYyxROLL4Q6IPQfDEcLuaiO9QGXoNda3/0DwsEvfg1W267NXVkcYAT9UISoCk3qKGUT1YLO3eLOc1AQopyyVobuKvNlBgT1jGyg0sonam+GD9mz6eA0vUvaC8ERV43ylXGQuBKKrtwJZ9dLGi1Ib2VACIQseU9fsptcQxdnUQ19uKJ59Zh+e1u66vrQbTVuHFpkfexlnsUSYPT43IwuoCoA2FGFIKj4SEloGM3DRO2QRdedkk9uUh8jdJN8ZtBpYcXJKf4Nn9n8hlOwXtT1afJofhhKe/b3LF9V0zOJwa9roRz3bWNSBjxNRrRgswESRbsienjre9Q+Kfw0dP0/yEyi8XwlFFxyuvW+qZtX7oPtD4SK/W7DhlQ/OtIgMAkmc9I1OXJkpJgA11smIki0vQmiD12DaydnYI4qt1ByVfa+EVUEoSUgUbgHvYWSbd9kZfLIu+Yo5HqpFDVQrGJsFZcUhnydh0Wu6URaZV15zh9MOhehxU10zVwEYx/i9xK0C+cEVgR9NnT274 + database_cacert: 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 + database_connection_string: AgBbW8Zs/TllwgOvGEV2X08JnD0bVhax98OOlOfAuOlaQWU2faTlDrabVPk8bUvTxIHCZtc2i7Xx7q3396QnQpCq6ytai7rAsSKY4tb5cFikIjle3FFj5aMD1ph41mEKmopYMWDGrwQj0D2M+y34Et/lzA3/xvmUDTOpzB5+ecxjius4136V8fDDBUyJkSfjL1FW9iZtgk4wPxJhDlw66BDv/naL/gwGMVcFulhsx9RNuzITl5C/cKi5dXZ1AvpB6xUkZUygG9pBrx6xuNNK2T0AjTT0ls5jaPX1yQ7UJwb7NpSwpTDreW+zQs3cFd3tSKZ+Rn6HL2CHgxNrlf80Jrvi8ynd08szNU9uAOZL5raSECFPfnjEBGdCCTg+qrYSZQYvdpaJfKxnp1nWtQNVnOKcv+UehWDFnfFA0ZO+WnQz5auY8stZEaOGTk/XaipvgqjTjnFqOZcnq3Y7bUTtHTN7uvJ/eo9auRHF+6kaxL59H12iyh3vwQMTz5soiNaYVJlFjUHKeHFG+Yc0GbTBPGHauIyN2c9ftNearGgE1XKFqZePZB1JmyN0h8QBVw2HFrX9i73K6VXwbhGTTA/wraKfzbjZqaj6r4lsw0WlQNi7OrZX0Aoi5RO2qi9U6JgHnZF+jQbifVWSzfm5LfNb1hrtSsFfKnhNmGCY9TjxfoIWC8+C2mMHKYpNgW/SzQgd36o+mnVLaiaNvV6+d5oXL8dTZgkwxWfy18AEPd9rGZZ0YnaF/0mz7QfDwtnT6K9MtjmHR65PTjijzquLdz7CPkQr3T1ort38Qt/o+VBuXSo3gmy26hB1+Sa1vcAGU9I3GF9ujd0BG47hC9BWDzcdfsfxlpHSq316w5PM57ldgng4qsU/KtbdINlaQyHoVQ5ylP4vec0v7zYVgg4VVwxaIhzlNnY2K0RL28vsugKFIlmfhCBt02/gBFSFYoQZ + template: + metadata: + name: blossom-secret + namespace: blossom + type: Opaque + + + diff --git a/deployment/route96/templates/service.yaml b/deployment/route96/templates/service.yaml index be1d5a1..c4de661 100644 --- a/deployment/route96/templates/service.yaml +++ b/deployment/route96/templates/service.yaml @@ -1,14 +1,14 @@ apiVersion: v1 kind: Service metadata: - name: {{ .Release.Name }}-service - namespace: {{ .Release.Namespace }} + name: blossom-service + namespace: blossom labels: - app.kubernetes.io/part-of: {{ .Release.Name }} + app.kubernetes.io/part-of: blossom app.kubernetes.io/managed-by: Helm spec: selector: - app.kubernetes.io/name: {{ .Release.Name }} + app.kubernetes.io/name: blossom ports: - protocol: TCP port: 80 diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index 143fa5d..060b3a2 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -1,4 +1,4 @@ -replicaCount: 3 +replicaCount: 1 image: repository: ghcr.io/verse-pbc/route96 @@ -16,12 +16,11 @@ autoscaling: persistence: size: "10Gi" - service: type: ClusterIP port: 80 ingress: - enabled: true + enabled: false className: "nginx" host: "blossom.plur.app" \ No newline at end of file From 701b60a09c67d82932d1c66ccf2aa0a4710311f7 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Mon, 7 Apr 2025 19:51:39 -0400 Subject: [PATCH 27/45] deploy latest image for now --- .github/workflows/publish-and-release.yml | 1 + deployment/route96/values.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-and-release.yml b/.github/workflows/publish-and-release.yml index a9b184a..aed6237 100644 --- a/.github/workflows/publish-and-release.yml +++ b/.github/workflows/publish-and-release.yml @@ -5,6 +5,7 @@ concurrency: cancel-in-progress: true on: + workflow_dispatch: push: branches: ['main'] pull_request: diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index 060b3a2..4fbf6de 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -2,7 +2,7 @@ replicaCount: 1 image: repository: ghcr.io/verse-pbc/route96 - tag: NA + tag: latest pullPolicy: IfNotPresent pdb: From 18068485a776e216cc7d52b73674aaa07598bd87 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Mon, 7 Apr 2025 19:55:04 -0400 Subject: [PATCH 28/45] some manifest edits --- deployment/route96/templates/deployment.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index c01d959..516fcf5 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -27,15 +27,15 @@ spec: - name: APP__LISTEN value: 0.0.0.0:8000 - name: APP__STORAGE_DIR - value: /app/data # This needs to match the volumeMount and volume below. + value: /app/data - name: APP__MAX_UPLOAD_BYTES - value: 5000000000 + value: "5000000000" - name: APP__PUBLIC_URL - value: http://localhost:8000 # TODO: check in with Daniel on this config, since the Ingress manifest will control it. + value: http://localhost:8000 - name: APP__NIP29_RELAY__URL value: wss://communities.nos.social - name: APP__NIP29_RELAY__CACHE_EXPIRATION - value: 300 + value: "300" - name: APP__NIP29_RELAY__PRIVATE_KEY valueFrom: secretKeyRef: From ccbbcb148924faddf6beb32a5fe07212916b55be Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Mon, 7 Apr 2025 20:04:37 -0400 Subject: [PATCH 29/45] Use a single replica with ReadWriteOnce for now --- deployment/route96/templates/pvc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/route96/templates/pvc.yaml b/deployment/route96/templates/pvc.yaml index 7eecb66..8f13336 100644 --- a/deployment/route96/templates/pvc.yaml +++ b/deployment/route96/templates/pvc.yaml @@ -8,7 +8,7 @@ metadata: app.kubernetes.io/managed-by: Helm spec: accessModes: - - ReadWriteMany + - ReadWriteOnce resources: requests: storage: {{ .Values.persistence.size | default "1Gi" }} From 0bf5a4db1a0099958a6835147b413763c683eac1 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Mon, 7 Apr 2025 20:38:19 -0400 Subject: [PATCH 30/45] Add config --- deployment/route96/templates/config.yaml | 16 ++++++++++++++++ deployment/route96/templates/deployment.yaml | 13 +++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 deployment/route96/templates/config.yaml diff --git a/deployment/route96/templates/config.yaml b/deployment/route96/templates/config.yaml new file mode 100644 index 0000000..f634c29 --- /dev/null +++ b/deployment/route96/templates/config.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: blossom-config + namespace: blossom +data: + config.yaml: | + listen: "REPLACED_BY_ENV" + database: "REPLACED_BY_ENV" + storage_dir: "REPLACED_BY_ENV" + max_upload_bytes: 0 + public_url: "REPLACED_BY_ENV" + nip29_relay: + url: "REPLACED_BY_ENV" + private_key: "REPLACED_BY_ENV" + cache_expiration: 0 diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index 516fcf5..25e48e9 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -69,17 +69,22 @@ spec: - containerPort: 8000 protocol: TCP volumeMounts: - - name: "blossom-storage" + - name: blossom-config + mountPath: /app/config.yaml + - name: blossom-storage mountPath: /app/data - name: database-cacert mountPath: /app/ca.pem volumes: - - name: "blossom-storage" + - name: blossom-config + configMap: + name: blossom-config + - name: blossom-storage persistentVolumeClaim: - claimName: "blossom-pvc" + claimName: blossom-pvc - name: database-cacert secret: - secretName: "blossom-secret" + secretName: blossom-secret items: - key: database_cacert path: ca.pem From ba9dc89ffedad94eeae4e542e6c6a9343ad7a613 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Mon, 7 Apr 2025 20:45:11 -0400 Subject: [PATCH 31/45] fix configmap mount path --- deployment/route96/templates/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index 25e48e9..665003b 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -70,7 +70,7 @@ spec: protocol: TCP volumeMounts: - name: blossom-config - mountPath: /app/config.yaml + mountPath: /app/ - name: blossom-storage mountPath: /app/data - name: database-cacert From 55a31b0a5fc21eeab762a2387f4f078b4681fb85 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Tue, 8 Apr 2025 20:10:00 -0400 Subject: [PATCH 32/45] temp entrypoint for container --- Dockerfile | 3 ++- docker-compose.yml | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0dd2329..657e99f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,4 +56,5 @@ RUN chown -R appuser:appgroup /lib USER appuser RUN ./bin/route96 --version -ENTRYPOINT ["./bin/route96"] \ No newline at end of file +# ENTRYPOINT ["./bin/route96"] +ENTRYPOINT ["tail", "-f", "/dev/null"] diff --git a/docker-compose.yml b/docker-compose.yml index 0d9d63c..b57e3a8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,15 +18,17 @@ services: - "db:/var/lib/postgresql/data" app: - platform: linux/arm64 - build: - context: . - dockerfile: Dockerfile.arm64 - args: - # Only including essential features: - # - blossom: Core API functionality - # - ranges: For better file serving (partial downloads/streaming) - FEATURES: "blossom,ranges" + image: ghcr.io/verse-pbc/route96:latest + # platform: linux/amd64 + # platform: linux/arm64 + # build: + # context: . + # dockerfile: Dockerfile.arm64 + # args: + # # Only including essential features: + # # - blossom: Core API functionality + # # - ranges: For better file serving (partial downloads/streaming) + # FEATURES: "blossom,ranges" environment: RUST_LOG: debug # Config values overridden by environment variables - all using double underscores From 6179109366c7954a8b0b5402401287188504a793 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Tue, 8 Apr 2025 20:27:49 -0400 Subject: [PATCH 33/45] WIP: test image --- deployment/route96/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index 4fbf6de..9d23717 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -2,7 +2,7 @@ replicaCount: 1 image: repository: ghcr.io/verse-pbc/route96 - tag: latest + tag: bentest pullPolicy: IfNotPresent pdb: From 87baf5597406e2e47a6efc1363464684a1e2c5e6 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Tue, 8 Apr 2025 20:57:40 -0400 Subject: [PATCH 34/45] WIP: test images --- .github/workflows/publish-and-release.yml | 4 ++-- Dockerfile.arm64 | 3 ++- deployment/route96/values.yaml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish-and-release.yml b/.github/workflows/publish-and-release.yml index aed6237..bf55a7c 100644 --- a/.github/workflows/publish-and-release.yml +++ b/.github/workflows/publish-and-release.yml @@ -51,7 +51,7 @@ jobs: push_to_registry: needs: get_version - if: github.ref == 'refs/heads/main' + # if: github.ref == 'refs/heads/main' name: Push Docker image to GHCR runs-on: ubuntu-latest permissions: @@ -96,7 +96,7 @@ jobs: merge_to_release: name: Merge to Release needs: push_to_registry - if: github.ref == 'refs/heads/main' + # if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest permissions: contents: write diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index ceb116a..3959342 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -87,4 +87,5 @@ COPY --from=build /app/build . COPY --from=ui_builder /app/src/dist ui COPY --from=build /app/ffmpeg/lib/ /lib RUN ./bin/route96 --version -ENTRYPOINT ["./bin/route96"] \ No newline at end of file +# ENTRYPOINT ["./bin/route96"] +ENTRYPOINT ["tail", "-f", "/dev/null"] \ No newline at end of file diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index 9d23717..4fbf6de 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -2,7 +2,7 @@ replicaCount: 1 image: repository: ghcr.io/verse-pbc/route96 - tag: bentest + tag: latest pullPolicy: IfNotPresent pdb: From 1eff130271d0492726638384c4cae02710797e62 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Tue, 8 Apr 2025 21:33:22 -0400 Subject: [PATCH 35/45] avoid overwriting /app --- Dockerfile | 3 +-- Dockerfile.arm64 | 3 +-- deployment/route96/templates/deployment.yaml | 3 ++- docker-compose.yml | 27 ++++++++++---------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index b39ae04..d41ecf6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,5 +58,4 @@ RUN ls -l /app && ls -l /app/bin USER appuser RUN ./bin/route96 --version -# ENTRYPOINT ["./bin/route96"] -ENTRYPOINT ["tail", "-f", "/dev/null"] +ENTRYPOINT ["./bin/route96"] \ No newline at end of file diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index 3959342..ceb116a 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -87,5 +87,4 @@ COPY --from=build /app/build . COPY --from=ui_builder /app/src/dist ui COPY --from=build /app/ffmpeg/lib/ /lib RUN ./bin/route96 --version -# ENTRYPOINT ["./bin/route96"] -ENTRYPOINT ["tail", "-f", "/dev/null"] \ No newline at end of file +ENTRYPOINT ["./bin/route96"] \ No newline at end of file diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index 665003b..8f8add3 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -70,7 +70,8 @@ spec: protocol: TCP volumeMounts: - name: blossom-config - mountPath: /app/ + mountPath: /app/config.yaml + subPath: config.yaml - name: blossom-storage mountPath: /app/data - name: database-cacert diff --git a/docker-compose.yml b/docker-compose.yml index 8f36aff..0d9d63c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,26 +18,27 @@ services: - "db:/var/lib/postgresql/data" app: - image: ghcr.io/verse-pbc/route96:latest - # platform: linux/amd64 - # platform: linux/arm64 - # build: - # context: . - # dockerfile: Dockerfile.arm64 - # args: - # # Only including essential features: - # # - blossom: Core API functionality - # # - ranges: For better file serving (partial downloads/streaming) - # FEATURES: "blossom,ranges" + platform: linux/arm64 + build: + context: . + dockerfile: Dockerfile.arm64 + args: + # Only including essential features: + # - blossom: Core API functionality + # - ranges: For better file serving (partial downloads/streaming) + FEATURES: "blossom,ranges" environment: - # Config values overridden by environment variables - keeping only essential/sensitive ones + RUST_LOG: debug + # Config values overridden by environment variables - all using double underscores + APP__LISTEN: 0.0.0.0:8000 APP__DATABASE: postgres://postgres:root@db:5432/route96 APP__STORAGE_DIR: /app/data + APP__MAX_UPLOAD_BYTES: 5000000000 APP__PUBLIC_URL: http://localhost:8000 # Nested values with double underscores APP__NIP29_RELAY__URL: ws://host.docker.internal:8080 - # Test key (pubkey: 385c3a6ec0b9d57a4330dbd6284989be5bd00e41c535f9ca39b6ae7c521b81cd) - replace if needed APP__NIP29_RELAY__PRIVATE_KEY: 6b911fd37cdf5c81d4c0adb1ab7fa822ed253ab0ad9aa18d77257c88b29b718e + APP__NIP29_RELAY__CACHE_EXPIRATION: 300 ports: - "8000:8000" volumes: From f5fde075a4aa3a55ae01ba92106abca5b985539d Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Tue, 8 Apr 2025 22:16:09 -0400 Subject: [PATCH 36/45] WIP: more testing --- deployment/route96/templates/config.yaml | 2 +- deployment/route96/templates/deployment.yaml | 4 ++-- deployment/route96/values.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/deployment/route96/templates/config.yaml b/deployment/route96/templates/config.yaml index f634c29..dc05b58 100644 --- a/deployment/route96/templates/config.yaml +++ b/deployment/route96/templates/config.yaml @@ -4,7 +4,7 @@ metadata: name: blossom-config namespace: blossom data: - config.yaml: | + config: | listen: "REPLACED_BY_ENV" database: "REPLACED_BY_ENV" storage_dir: "REPLACED_BY_ENV" diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index 8f8add3..27a3b03 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -22,7 +22,7 @@ spec: containers: - name: my-container image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }} + imagePullPolicy: {{ .Values.image.pullPolicy | default "Always" }} env: - name: APP__LISTEN value: 0.0.0.0:8000 @@ -71,7 +71,7 @@ spec: volumeMounts: - name: blossom-config mountPath: /app/config.yaml - subPath: config.yaml + subPath: config - name: blossom-storage mountPath: /app/data - name: database-cacert diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index 4fbf6de..88a9d28 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -3,7 +3,7 @@ replicaCount: 1 image: repository: ghcr.io/verse-pbc/route96 tag: latest - pullPolicy: IfNotPresent + pullPolicy: Always pdb: minAvailable: 1 From 8742f9bdb9f1e96cff69ef8e352ec49925a25dd0 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Tue, 8 Apr 2025 22:29:00 -0400 Subject: [PATCH 37/45] fix CI --- .github/workflows/publish-and-release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-and-release.yml b/.github/workflows/publish-and-release.yml index bf55a7c..5170904 100644 --- a/.github/workflows/publish-and-release.yml +++ b/.github/workflows/publish-and-release.yml @@ -113,7 +113,8 @@ jobs: git config --global user.name "$verse-ci" git config --global user.email "$ci@verse.app" git checkout release - git merge -Xtheirs --no-commit origin/main + git merge -Xtheirs --no-commit origin/configure-kubernetes-deployment +# TODO: Adjust this back to origin/main after dev - name: Apply Newest Version shell: bash From dbba478f951b081d9bda1e50e354584c00715cb3 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Sun, 13 Apr 2025 17:16:33 -0400 Subject: [PATCH 38/45] add healthcheck updates --- deployment/route96/templates/config.yaml | 2 +- deployment/route96/templates/deployment.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/deployment/route96/templates/config.yaml b/deployment/route96/templates/config.yaml index dc05b58..bb4eaed 100644 --- a/deployment/route96/templates/config.yaml +++ b/deployment/route96/templates/config.yaml @@ -8,7 +8,7 @@ data: listen: "REPLACED_BY_ENV" database: "REPLACED_BY_ENV" storage_dir: "REPLACED_BY_ENV" - max_upload_bytes: 0 + max_upload_bytes: 5000000000 public_url: "REPLACED_BY_ENV" nip29_relay: url: "REPLACED_BY_ENV" diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index 27a3b03..5ed12c9 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -55,14 +55,14 @@ spec: cpu: "2" livenessProbe: httpGet: - path: / - port: 80 + path: /health + port: 8000 initialDelaySeconds: 30 timeoutSeconds: 5 readinessProbe: httpGet: - path: / - port: 80 + path: /health + port: 8000 initialDelaySeconds: 5 timeoutSeconds: 3 ports: From dfe008c76501c88fb6586325e67815f0cbddbb72 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Sun, 13 Apr 2025 17:23:13 -0400 Subject: [PATCH 39/45] see if the configs are overwriting --- deployment/route96/templates/config.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deployment/route96/templates/config.yaml b/deployment/route96/templates/config.yaml index bb4eaed..3276749 100644 --- a/deployment/route96/templates/config.yaml +++ b/deployment/route96/templates/config.yaml @@ -5,12 +5,12 @@ metadata: namespace: blossom data: config: | - listen: "REPLACED_BY_ENV" + listen: "0.0.0.0:8000" database: "REPLACED_BY_ENV" - storage_dir: "REPLACED_BY_ENV" + storage_dir: "/app/data" max_upload_bytes: 5000000000 - public_url: "REPLACED_BY_ENV" + public_url: "http://localhost:8000" nip29_relay: - url: "REPLACED_BY_ENV" + url: "wss://communities.nos.social" private_key: "REPLACED_BY_ENV" - cache_expiration: 0 + cache_expiration: 300 From 74c294be1734ae7ec4687549908db0d2feb8701e Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Sun, 13 Apr 2025 20:38:59 -0400 Subject: [PATCH 40/45] attempt to roll back image --- deployment/route96/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index 88a9d28..4cb55ed 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -2,7 +2,7 @@ replicaCount: 1 image: repository: ghcr.io/verse-pbc/route96 - tag: latest + tag: main-a97180d pullPolicy: Always pdb: From d2c4767f599209c05b4fa5ab29566eaf8dc1733d Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Sun, 13 Apr 2025 20:53:26 -0400 Subject: [PATCH 41/45] roll image further back --- deployment/route96/templates/config.yaml | 12 ++++++------ deployment/route96/values.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/deployment/route96/templates/config.yaml b/deployment/route96/templates/config.yaml index 3276749..dc05b58 100644 --- a/deployment/route96/templates/config.yaml +++ b/deployment/route96/templates/config.yaml @@ -5,12 +5,12 @@ metadata: namespace: blossom data: config: | - listen: "0.0.0.0:8000" + listen: "REPLACED_BY_ENV" database: "REPLACED_BY_ENV" - storage_dir: "/app/data" - max_upload_bytes: 5000000000 - public_url: "http://localhost:8000" + storage_dir: "REPLACED_BY_ENV" + max_upload_bytes: 0 + public_url: "REPLACED_BY_ENV" nip29_relay: - url: "wss://communities.nos.social" + url: "REPLACED_BY_ENV" private_key: "REPLACED_BY_ENV" - cache_expiration: 300 + cache_expiration: 0 diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index 4cb55ed..203c8f0 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -2,7 +2,7 @@ replicaCount: 1 image: repository: ghcr.io/verse-pbc/route96 - tag: main-a97180d + tag: main-ee8a383 pullPolicy: Always pdb: From 0bd8c2002979e1a32977eb8453d686d1abf79799 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Sun, 13 Apr 2025 21:07:00 -0400 Subject: [PATCH 42/45] use latest image again --- deployment/route96/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index 203c8f0..88a9d28 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -2,7 +2,7 @@ replicaCount: 1 image: repository: ghcr.io/verse-pbc/route96 - tag: main-ee8a383 + tag: latest pullPolicy: Always pdb: From 8960ce30830e86e01005b7c9bf86f1d1019480ce Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Mon, 14 Apr 2025 19:30:57 -0400 Subject: [PATCH 43/45] update configs to match new spec --- deployment/route96/templates/config.yaml | 3 ++- deployment/route96/templates/deployment.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/deployment/route96/templates/config.yaml b/deployment/route96/templates/config.yaml index dc05b58..ee8166c 100644 --- a/deployment/route96/templates/config.yaml +++ b/deployment/route96/templates/config.yaml @@ -7,7 +7,8 @@ data: config: | listen: "REPLACED_BY_ENV" database: "REPLACED_BY_ENV" - storage_dir: "REPLACED_BY_ENV" + filesystem: + storage_dir: "REPLACED_BY_ENV" max_upload_bytes: 0 public_url: "REPLACED_BY_ENV" nip29_relay: diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index 5ed12c9..254dbf3 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -26,7 +26,7 @@ spec: env: - name: APP__LISTEN value: 0.0.0.0:8000 - - name: APP__STORAGE_DIR + - name: APP__FILESYSTEM__STORAGE_DIR value: /app/data - name: APP__MAX_UPLOAD_BYTES value: "5000000000" From 4353f9c3c13e5821d612fe1d25f2854debf93052 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Mon, 14 Apr 2025 19:44:50 -0400 Subject: [PATCH 44/45] update workflow back to production values --- .github/workflows/publish-and-release.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish-and-release.yml b/.github/workflows/publish-and-release.yml index 5170904..aed6237 100644 --- a/.github/workflows/publish-and-release.yml +++ b/.github/workflows/publish-and-release.yml @@ -51,7 +51,7 @@ jobs: push_to_registry: needs: get_version - # if: github.ref == 'refs/heads/main' + if: github.ref == 'refs/heads/main' name: Push Docker image to GHCR runs-on: ubuntu-latest permissions: @@ -96,7 +96,7 @@ jobs: merge_to_release: name: Merge to Release needs: push_to_registry - # if: github.ref == 'refs/heads/main' + if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest permissions: contents: write @@ -113,8 +113,7 @@ jobs: git config --global user.name "$verse-ci" git config --global user.email "$ci@verse.app" git checkout release - git merge -Xtheirs --no-commit origin/configure-kubernetes-deployment -# TODO: Adjust this back to origin/main after dev + git merge -Xtheirs --no-commit origin/main - name: Apply Newest Version shell: bash From d0474d1ef8517ff857aad0aa311588c2eac27098 Mon Sep 17 00:00:00 2001 From: Ben Moody Date: Mon, 14 Apr 2025 20:09:18 -0400 Subject: [PATCH 45/45] fmt --- deployment/route96/templates/config.yaml | 2 +- deployment/route96/templates/deployment.yaml | 134 +++++++++--------- deployment/route96/templates/hpa.yaml | 21 +-- deployment/route96/templates/pdb.yaml | 4 +- deployment/route96/templates/pvc.yaml | 2 +- .../route96/templates/sealed-secret.yaml | 3 - deployment/route96/templates/service.yaml | 2 +- deployment/route96/values.yaml | 2 +- 8 files changed, 86 insertions(+), 84 deletions(-) diff --git a/deployment/route96/templates/config.yaml b/deployment/route96/templates/config.yaml index ee8166c..8da0483 100644 --- a/deployment/route96/templates/config.yaml +++ b/deployment/route96/templates/config.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: ConfigMap metadata: name: blossom-config - namespace: blossom + namespace: blossom data: config: | listen: "REPLACED_BY_ENV" diff --git a/deployment/route96/templates/deployment.yaml b/deployment/route96/templates/deployment.yaml index 254dbf3..29f6ef9 100644 --- a/deployment/route96/templates/deployment.yaml +++ b/deployment/route96/templates/deployment.yaml @@ -8,7 +8,7 @@ metadata: app.kubernetes.io/part-of: blossom app.kubernetes.io/managed-by: Helm spec: - replicas: {{ .Values.replicaCount }} + replicas: { { .Values.replicaCount } } selector: matchLabels: app.kubernetes.io/name: blossom @@ -20,72 +20,72 @@ spec: app.kubernetes.io/managed-by: Helm spec: containers: - - name: my-container - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy | default "Always" }} - env: - - name: APP__LISTEN - value: 0.0.0.0:8000 - - name: APP__FILESYSTEM__STORAGE_DIR - value: /app/data - - name: APP__MAX_UPLOAD_BYTES - value: "5000000000" - - name: APP__PUBLIC_URL - value: http://localhost:8000 - - name: APP__NIP29_RELAY__URL - value: wss://communities.nos.social - - name: APP__NIP29_RELAY__CACHE_EXPIRATION - value: "300" - - name: APP__NIP29_RELAY__PRIVATE_KEY - valueFrom: - secretKeyRef: - name: "blossom-secret" - key: app_nip29_relay_private_key - - name: APP__DATABASE - valueFrom: - secretKeyRef: - name: "blossom-secret" - key: database_connection_string - resources: - requests: - memory: "512Mi" - cpu: "1" - limits: - memory: "1028Mi" - cpu: "2" - livenessProbe: - httpGet: - path: /health - port: 8000 - initialDelaySeconds: 30 - timeoutSeconds: 5 - readinessProbe: - httpGet: - path: /health - port: 8000 - initialDelaySeconds: 5 - timeoutSeconds: 3 - ports: - - containerPort: 8000 - protocol: TCP - volumeMounts: + - name: my-container + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: { { .Values.image.pullPolicy | default "Always" } } + env: + - name: APP__LISTEN + value: 0.0.0.0:8000 + - name: APP__FILESYSTEM__STORAGE_DIR + value: /app/data + - name: APP__MAX_UPLOAD_BYTES + value: "5000000000" + - name: APP__PUBLIC_URL + value: http://localhost:8000 + - name: APP__NIP29_RELAY__URL + value: wss://communities.nos.social + - name: APP__NIP29_RELAY__CACHE_EXPIRATION + value: "300" + - name: APP__NIP29_RELAY__PRIVATE_KEY + valueFrom: + secretKeyRef: + name: "blossom-secret" + key: app_nip29_relay_private_key + - name: APP__DATABASE + valueFrom: + secretKeyRef: + name: "blossom-secret" + key: database_connection_string + resources: + requests: + memory: "512Mi" + cpu: "1" + limits: + memory: "1028Mi" + cpu: "2" + livenessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 30 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 5 + timeoutSeconds: 3 + ports: + - containerPort: 8000 + protocol: TCP + volumeMounts: + - name: blossom-config + mountPath: /app/config.yaml + subPath: config + - name: blossom-storage + mountPath: /app/data + - name: database-cacert + mountPath: /app/ca.pem + volumes: - name: blossom-config - mountPath: /app/config.yaml - subPath: config + configMap: + name: blossom-config - name: blossom-storage - mountPath: /app/data + persistentVolumeClaim: + claimName: blossom-pvc - name: database-cacert - mountPath: /app/ca.pem - volumes: - - name: blossom-config - configMap: - name: blossom-config - - name: blossom-storage - persistentVolumeClaim: - claimName: blossom-pvc - - name: database-cacert - secret: - secretName: blossom-secret - items: - - key: database_cacert - path: ca.pem + secret: + secretName: blossom-secret + items: + - key: database_cacert + path: ca.pem diff --git a/deployment/route96/templates/hpa.yaml b/deployment/route96/templates/hpa.yaml index 4704fa1..b21a672 100644 --- a/deployment/route96/templates/hpa.yaml +++ b/deployment/route96/templates/hpa.yaml @@ -11,12 +11,17 @@ spec: apiVersion: apps/v1 kind: Deployment name: blossom-deployment - minReplicas: {{ .Values.autoscaling.minReplicas | default 1 }} - maxReplicas: {{ .Values.autoscaling.maxReplicas | default 10 }} + minReplicas: { { .Values.autoscaling.minReplicas | default 1 } } + maxReplicas: { { .Values.autoscaling.maxReplicas | default 10 } } metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage | default 80 }} \ No newline at end of file + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: + { + { + .Values.autoscaling.targetCPUUtilizationPercentage | default 80, + }, + } diff --git a/deployment/route96/templates/pdb.yaml b/deployment/route96/templates/pdb.yaml index 09b7eb7..90081d2 100644 --- a/deployment/route96/templates/pdb.yaml +++ b/deployment/route96/templates/pdb.yaml @@ -7,7 +7,7 @@ metadata: app.kubernetes.io/part-of: blossom app.kubernetes.io/managed-by: Helm spec: - minAvailable: {{ .Values.pdb.minAvailable | default 1 }} + minAvailable: { { .Values.pdb.minAvailable | default 1 } } selector: matchLabels: - app.kubernetes.io/name: blossom \ No newline at end of file + app.kubernetes.io/name: blossom diff --git a/deployment/route96/templates/pvc.yaml b/deployment/route96/templates/pvc.yaml index 8f13336..9dbbbce 100644 --- a/deployment/route96/templates/pvc.yaml +++ b/deployment/route96/templates/pvc.yaml @@ -11,4 +11,4 @@ spec: - ReadWriteOnce resources: requests: - storage: {{ .Values.persistence.size | default "1Gi" }} + storage: { { .Values.persistence.size | default "1Gi" } } diff --git a/deployment/route96/templates/sealed-secret.yaml b/deployment/route96/templates/sealed-secret.yaml index 7be1da2..2b778af 100644 --- a/deployment/route96/templates/sealed-secret.yaml +++ b/deployment/route96/templates/sealed-secret.yaml @@ -13,6 +13,3 @@ spec: name: blossom-secret namespace: blossom type: Opaque - - - diff --git a/deployment/route96/templates/service.yaml b/deployment/route96/templates/service.yaml index c4de661..c9eb5b7 100644 --- a/deployment/route96/templates/service.yaml +++ b/deployment/route96/templates/service.yaml @@ -13,4 +13,4 @@ spec: - protocol: TCP port: 80 targetPort: 8000 - type: ClusterIP \ No newline at end of file + type: ClusterIP diff --git a/deployment/route96/values.yaml b/deployment/route96/values.yaml index 88a9d28..c2b7f13 100644 --- a/deployment/route96/values.yaml +++ b/deployment/route96/values.yaml @@ -23,4 +23,4 @@ service: ingress: enabled: false className: "nginx" - host: "blossom.plur.app" \ No newline at end of file + host: "blossom.plur.app"