From 9b8e62361f7f67f870217b4446552467518c6a5a Mon Sep 17 00:00:00 2001 From: Chris Alfano Date: Mon, 18 May 2026 19:17:07 -0400 Subject: [PATCH] chore(deploy): retire Helm chart and Helm-based GHA workflows GitOps via cfp-sandbox-cluster + the local Kustomize manifests at deploy/kustomize/ are now the canonical deploy path. The Helm chart and the two Helm-driving workflows are dead weight. - Delete deploy/charts/codeforphilly/ (entire chart + values files) - Delete .github/workflows/deploy-{staging,production}.yml - Rewrite docs/operations/deploy.md to describe the Kustomize+GitOps flow (preserving boot sequence, probes, env var reference, bucket reqs, rollback semantics). The Helm-specific install/upgrade/values sections are gone. - runbook.md: replace `helm history/rollback/upgrade` recovery commands with GitOps deploy-PR revert + `kubectl set image` hotfix; reword the CFP_DATA_REMOTE boot-failure row to point at the SealedSecret. - secrets.md: update the "where they live in the cluster" section to describe SealedSecrets in the cluster repo; drop the trailing helm-install example. - monitoring.md, cutover.md: small touch-ups removing Helm references. plans/deploy.md is left untouched per the plans protocol (frozen at status: done). Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/deploy-production.yml | 131 ---------------- .github/workflows/deploy-staging.yml | 125 --------------- deploy/charts/codeforphilly/Chart.yaml | 14 -- .../charts/codeforphilly/templates/NOTES.txt | 26 ---- .../codeforphilly/templates/_helpers.tpl | 50 ------ .../codeforphilly/templates/configmap.yaml | 23 --- .../codeforphilly/templates/deployment.yaml | 123 --------------- .../codeforphilly/templates/ingress.yaml | 35 ----- .../codeforphilly/templates/pvc-data.yaml | 17 --- .../codeforphilly/templates/pvc-private.yaml | 17 --- .../codeforphilly/templates/service.yaml | 15 -- .../templates/serviceaccount.yaml | 12 -- .../codeforphilly/values.production.yaml | 47 ------ .../charts/codeforphilly/values.staging.yaml | 48 ------ deploy/charts/codeforphilly/values.yaml | 144 ------------------ 15 files changed, 827 deletions(-) delete mode 100644 .github/workflows/deploy-production.yml delete mode 100644 .github/workflows/deploy-staging.yml delete mode 100644 deploy/charts/codeforphilly/Chart.yaml delete mode 100644 deploy/charts/codeforphilly/templates/NOTES.txt delete mode 100644 deploy/charts/codeforphilly/templates/_helpers.tpl delete mode 100644 deploy/charts/codeforphilly/templates/configmap.yaml delete mode 100644 deploy/charts/codeforphilly/templates/deployment.yaml delete mode 100644 deploy/charts/codeforphilly/templates/ingress.yaml delete mode 100644 deploy/charts/codeforphilly/templates/pvc-data.yaml delete mode 100644 deploy/charts/codeforphilly/templates/pvc-private.yaml delete mode 100644 deploy/charts/codeforphilly/templates/service.yaml delete mode 100644 deploy/charts/codeforphilly/templates/serviceaccount.yaml delete mode 100644 deploy/charts/codeforphilly/values.production.yaml delete mode 100644 deploy/charts/codeforphilly/values.staging.yaml delete mode 100644 deploy/charts/codeforphilly/values.yaml diff --git a/.github/workflows/deploy-production.yml b/.github/workflows/deploy-production.yml deleted file mode 100644 index 044e34f..0000000 --- a/.github/workflows/deploy-production.yml +++ /dev/null @@ -1,131 +0,0 @@ -name: Deploy (production) - -# Production deploys run only on annotated/lightweight tags shaped like -# `v1.2.3`. Same image, different cluster, different values. -on: - push: - tags: - - "v*.*.*" - workflow_dispatch: - inputs: - tag: - description: "Image tag to deploy (must already exist in GHCR)" - required: true - -concurrency: - group: deploy-production - cancel-in-progress: false - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -permissions: - contents: read - packages: write - id-token: write - -jobs: - build: - if: github.event_name == 'push' - runs-on: ubuntu-latest - outputs: - image-tag: ${{ steps.meta.outputs.image-tag }} - steps: - - uses: actions/checkout@v6 - - - name: Compute image tag - id: meta - run: | - tag="${GITHUB_REF_NAME}" - echo "image-tag=$tag" >> "$GITHUB_OUTPUT" - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to GHCR - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and push - uses: docker/build-push-action@v6 - with: - context: . - file: Dockerfile - push: true - platforms: linux/amd64 - provenance: false - tags: | - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.image-tag }} - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:production-latest - cache-from: type=gha - cache-to: type=gha,mode=max - labels: | - org.opencontainers.image.revision=${{ github.sha }} - org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} - - deploy: - # When triggered by a tag push, depend on build; for workflow_dispatch the - # tag must already exist in GHCR, so we skip the build job. - needs: [build] - if: always() && (needs.build.result == 'success' || github.event_name == 'workflow_dispatch') - runs-on: ubuntu-latest - environment: - name: production - url: https://codeforphilly.org - steps: - - uses: actions/checkout@v6 - - - name: Install kubectl - uses: azure/setup-kubectl@v4 - with: - version: v1.31.0 - - - name: Install Helm - uses: azure/setup-helm@v4 - with: - version: v3.16.2 - - - name: Configure kubeconfig - run: | - mkdir -p "$HOME/.kube" - echo "${{ secrets.KUBECONFIG_PRODUCTION }}" | base64 -d > "$HOME/.kube/config" - chmod 600 "$HOME/.kube/config" - kubectl version --client - - - name: Resolve image tag - id: tag - run: | - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - echo "image-tag=${{ github.event.inputs.tag }}" >> "$GITHUB_OUTPUT" - else - echo "image-tag=${{ needs.build.outputs.image-tag }}" >> "$GITHUB_OUTPUT" - fi - - - name: Helm upgrade - run: | - helm upgrade --install codeforphilly \ - deploy/charts/codeforphilly \ - --namespace codeforphilly \ - --create-namespace \ - -f deploy/charts/codeforphilly/values.production.yaml \ - --set image.tag=${{ steps.tag.outputs.image-tag }} \ - --atomic \ - --timeout 5m \ - --wait - - - name: Smoke check - run: | - for i in 1 2 3 4 5 6; do - if curl -fsS https://codeforphilly.org/api/health >/dev/null; then - echo "OK" - exit 0 - fi - echo "Try $i: not ready, sleeping 10s" - sleep 10 - done - echo "Production health check failed" - exit 1 diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows/deploy-staging.yml deleted file mode 100644 index ebd7c6b..0000000 --- a/.github/workflows/deploy-staging.yml +++ /dev/null @@ -1,125 +0,0 @@ -name: Deploy (staging) - -on: - push: - branches: [main] - workflow_dispatch: - -concurrency: - # Cancel an in-flight deploy if a newer commit lands — only the latest gets - # rolled out to staging. - group: deploy-staging - cancel-in-progress: false - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -permissions: - contents: read - packages: write - id-token: write - -jobs: - # Build + push the image. Tag with both the commit sha and `staging-latest`. - build: - runs-on: ubuntu-latest - outputs: - image-tag: ${{ steps.meta.outputs.image-tag }} - image-digest: ${{ steps.push.outputs.digest }} - steps: - - uses: actions/checkout@v6 - - - name: Compute image tag - id: meta - run: | - tag="sha-${GITHUB_SHA::12}" - echo "image-tag=$tag" >> "$GITHUB_OUTPUT" - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to GHCR - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and push - id: push - uses: docker/build-push-action@v6 - with: - context: . - file: Dockerfile - push: true - platforms: linux/amd64 - provenance: false - tags: | - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.image-tag }} - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:staging-latest - cache-from: type=gha - cache-to: type=gha,mode=max - labels: | - org.opencontainers.image.revision=${{ github.sha }} - org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} - - # Deploy via `helm upgrade --install` against the staging cluster. Gated by - # the `staging` environment so first-time runs require an approval and so - # secrets are scoped per-environment. - deploy: - needs: build - runs-on: ubuntu-latest - environment: - name: staging - url: https://codeforphilly-rewrite-staging.k8s.phl.io - steps: - - uses: actions/checkout@v6 - - - name: Install kubectl - uses: azure/setup-kubectl@v4 - with: - version: v1.31.0 - - - name: Install Helm - uses: azure/setup-helm@v4 - with: - version: v3.16.2 - - - name: Configure kubeconfig - # KUBECONFIG_STAGING is a base64-encoded kubeconfig stored as a repo - # secret. The cluster service account it points to should have rights - # only in the codeforphilly-staging namespace. - run: | - mkdir -p "$HOME/.kube" - echo "${{ secrets.KUBECONFIG_STAGING }}" | base64 -d > "$HOME/.kube/config" - chmod 600 "$HOME/.kube/config" - kubectl version --client - - - name: Helm upgrade - run: | - helm upgrade --install codeforphilly-staging \ - deploy/charts/codeforphilly \ - --namespace codeforphilly-staging \ - --create-namespace \ - -f deploy/charts/codeforphilly/values.staging.yaml \ - --set image.tag=${{ needs.build.outputs.image-tag }} \ - --atomic \ - --timeout 5m \ - --wait - - - name: Smoke check - run: | - # The --wait above only waits for k8s to report ready; hit the - # public ingress to confirm end-to-end. Retries because cert-manager - # may still be re-checking TLS for a fresh cert. - for i in 1 2 3 4 5 6; do - if curl -fsS https://codeforphilly-rewrite-staging.k8s.phl.io/api/health >/dev/null; then - echo "OK" - exit 0 - fi - echo "Try $i: not ready, sleeping 10s" - sleep 10 - done - echo "Staging health check failed" - exit 1 diff --git a/deploy/charts/codeforphilly/Chart.yaml b/deploy/charts/codeforphilly/Chart.yaml deleted file mode 100644 index 1c5952c..0000000 --- a/deploy/charts/codeforphilly/Chart.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v2 -name: codeforphilly -description: CodeForPhilly modernization — Fastify + Vite/React + gitsheets, single replica -type: application -# version: chart SemVer — bumped per Chart change. -version: 0.1.0 -# appVersion: bumped per image release; CI overrides with --set image.tag. -appVersion: "0.0.0" -home: https://codeforphilly.org -sources: - - https://github.com/CodeForPhilly/codeforphilly-rewrite -maintainers: - - name: Code for Philly - url: https://codeforphilly.org diff --git a/deploy/charts/codeforphilly/templates/NOTES.txt b/deploy/charts/codeforphilly/templates/NOTES.txt deleted file mode 100644 index 639590f..0000000 --- a/deploy/charts/codeforphilly/templates/NOTES.txt +++ /dev/null @@ -1,26 +0,0 @@ -{{- if .Values.ingress.enabled }} -Application installed. Public URL(s): -{{- range .Values.ingress.hosts }} - https://{{ .host }} -{{- end }} - -Health checks: - curl https://{{ (index .Values.ingress.hosts 0).host }}/api/health - curl https://{{ (index .Values.ingress.hosts 0).host }}/api/health/ready - -{{- else }} -Application installed (no ingress). Port-forward to test: - kubectl port-forward -n {{ .Release.Namespace }} svc/{{ include "codeforphilly.fullname" . }} 8080:{{ .Values.service.port }} - curl http://localhost:8080/api/health -{{- end }} - -Secrets contract: - Provide a k8s Secret named {{ (index .Values.secretEnvFrom 0).name | default "codeforphilly-secrets" }} - with the keys enumerated in docs/operations/deploy.md ("Secret contract"). - -{{- if .Values.deployKey.secretName }} -SSH deploy key: - Provide a Secret named {{ .Values.deployKey.secretName }} containing key - "id_ed25519" (PEM-encoded ed25519 private key with push access to - CFP_DATA_REMOTE). -{{- end }} diff --git a/deploy/charts/codeforphilly/templates/_helpers.tpl b/deploy/charts/codeforphilly/templates/_helpers.tpl deleted file mode 100644 index 5bfe66e..0000000 --- a/deploy/charts/codeforphilly/templates/_helpers.tpl +++ /dev/null @@ -1,50 +0,0 @@ -{{- define "codeforphilly.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{- define "codeforphilly.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{- define "codeforphilly.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{- define "codeforphilly.labels" -}} -helm.sh/chart: {{ include "codeforphilly.chart" . }} -{{ include "codeforphilly.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} - -{{- define "codeforphilly.selectorLabels" -}} -app.kubernetes.io/name: {{ include "codeforphilly.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} - -{{- define "codeforphilly.serviceAccountName" -}} -{{- if .Values.serviceAccount.create -}} -{{- default (include "codeforphilly.fullname" .) .Values.serviceAccount.name -}} -{{- else -}} -{{- default "default" .Values.serviceAccount.name -}} -{{- end -}} -{{- end -}} - -{{- define "codeforphilly.dataPvcName" -}} -{{- default (printf "%s-data" (include "codeforphilly.fullname" .)) .Values.dataRepo.pvc.name -}} -{{- end -}} - -{{- define "codeforphilly.privatePvcName" -}} -{{- default (printf "%s-private" (include "codeforphilly.fullname" .)) .Values.privateStorage.pvc.name -}} -{{- end -}} diff --git a/deploy/charts/codeforphilly/templates/configmap.yaml b/deploy/charts/codeforphilly/templates/configmap.yaml deleted file mode 100644 index 9a2449d..0000000 --- a/deploy/charts/codeforphilly/templates/configmap.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "codeforphilly.fullname" . }}-env - labels: - {{- include "codeforphilly.labels" . | nindent 4 }} -data: - # Static env values from values.yaml `env:` block. - {{- range $k, $v := .Values.env }} - {{ $k }}: {{ $v | quote }} - {{- end }} - STORAGE_BACKEND: {{ .Values.storage.backend | quote }} - CFP_DATA_BRANCH: {{ .Values.dataRepo.branch | quote }} - {{- range $k, $v := .Values.publicEnv }} - {{- if $v }} - {{ $k }}: {{ $v | quote }} - {{- end }} - {{- end }} - {{- if .Values.deployKey.secretName }} - # Tell git to use the mounted SSH key. accept-new keeps first-connect simple; - # populate deployKey.knownHostsConfigMap for strict host-key checking. - GIT_SSH_COMMAND: "ssh -i {{ .Values.deployKey.mountPath }}/id_ed25519 -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new {{- if .Values.deployKey.knownHostsConfigMap }} -o UserKnownHostsFile={{ .Values.deployKey.mountPath }}/known_hosts{{- end }}" - {{- end }} diff --git a/deploy/charts/codeforphilly/templates/deployment.yaml b/deploy/charts/codeforphilly/templates/deployment.yaml deleted file mode 100644 index 4589a43..0000000 --- a/deploy/charts/codeforphilly/templates/deployment.yaml +++ /dev/null @@ -1,123 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "codeforphilly.fullname" . }} - labels: - {{- include "codeforphilly.labels" . | nindent 4 }} -spec: - # replicas: 1 is a hard constraint per specs/architecture.md (in-process - # write mutex serializes mutations). - replicas: {{ .Values.replicaCount }} - strategy: - # Recreate (not RollingUpdate) so the old pod releases the write lock - # before the new one starts. Two pods writing to the same gitsheets repo - # would corrupt state. - type: Recreate - selector: - matchLabels: - {{- include "codeforphilly.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - {{- include "codeforphilly.selectorLabels" . | nindent 8 }} - annotations: - # Roll the pod whenever the ConfigMap changes — values-driven env - # tweaks shouldn't require image bumps to take effect. - checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - serviceAccountName: {{ include "codeforphilly.serviceAccountName" . }} - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: api - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - ports: - - name: http - containerPort: 3001 - protocol: TCP - envFrom: - - configMapRef: - name: {{ include "codeforphilly.fullname" . }}-env - {{- range .Values.secretEnvFrom }} - - secretRef: - name: {{ .name }} - {{- end }} - livenessProbe: - httpGet: - path: {{ .Values.probes.liveness.path }} - port: http - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.liveness.timeoutSeconds }} - failureThreshold: {{ .Values.probes.liveness.failureThreshold }} - readinessProbe: - httpGet: - path: {{ .Values.probes.readiness.path }} - port: http - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - failureThreshold: {{ .Values.probes.readiness.failureThreshold }} - resources: - {{- toYaml .Values.resources | nindent 12 }} - volumeMounts: - {{- if .Values.dataRepo.pvc.enabled }} - - name: data - mountPath: {{ .Values.env.CFP_DATA_REPO_PATH | default "/app/data" }} - {{- end }} - {{- if and (eq .Values.storage.backend "filesystem") .Values.privateStorage.pvc.enabled }} - - name: private-storage - mountPath: {{ .Values.env.CFP_PRIVATE_STORAGE_PATH | default "/app/private-storage" }} - {{- end }} - {{- if .Values.deployKey.secretName }} - - name: deploy-key - mountPath: {{ .Values.deployKey.mountPath }} - readOnly: true - {{- end }} - volumes: - {{- if .Values.dataRepo.pvc.enabled }} - - name: data - persistentVolumeClaim: - claimName: {{ include "codeforphilly.dataPvcName" . }} - {{- end }} - {{- if and (eq .Values.storage.backend "filesystem") .Values.privateStorage.pvc.enabled }} - - name: private-storage - persistentVolumeClaim: - claimName: {{ include "codeforphilly.privatePvcName" . }} - {{- end }} - {{- if .Values.deployKey.secretName }} - - name: deploy-key - secret: - secretName: {{ .Values.deployKey.secretName }} - defaultMode: 0400 - items: - - key: id_ed25519 - path: id_ed25519 - {{- if .Values.deployKey.knownHostsConfigMap }} - - name: deploy-key-known-hosts - configMap: - name: {{ .Values.deployKey.knownHostsConfigMap }} - {{- end }} - {{- end }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/deploy/charts/codeforphilly/templates/ingress.yaml b/deploy/charts/codeforphilly/templates/ingress.yaml deleted file mode 100644 index 87e3dbe..0000000 --- a/deploy/charts/codeforphilly/templates/ingress.yaml +++ /dev/null @@ -1,35 +0,0 @@ -{{- if .Values.ingress.enabled -}} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ include "codeforphilly.fullname" . }} - labels: - {{- include "codeforphilly.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if .Values.ingress.className }} - ingressClassName: {{ .Values.ingress.className }} - {{- end }} - {{- with .Values.ingress.tls }} - tls: - {{- toYaml . | nindent 4 }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - pathType: {{ .pathType }} - backend: - service: - name: {{ include "codeforphilly.fullname" $ }} - port: - number: {{ $.Values.service.port }} - {{- end }} - {{- end }} -{{- end }} diff --git a/deploy/charts/codeforphilly/templates/pvc-data.yaml b/deploy/charts/codeforphilly/templates/pvc-data.yaml deleted file mode 100644 index 41b3016..0000000 --- a/deploy/charts/codeforphilly/templates/pvc-data.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.dataRepo.pvc.enabled -}} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ include "codeforphilly.dataPvcName" . }} - labels: - {{- include "codeforphilly.labels" . | nindent 4 }} -spec: - accessModes: - - {{ .Values.dataRepo.pvc.accessMode }} - resources: - requests: - storage: {{ .Values.dataRepo.pvc.size }} - {{- if .Values.dataRepo.pvc.storageClass }} - storageClassName: {{ .Values.dataRepo.pvc.storageClass }} - {{- end }} -{{- end }} diff --git a/deploy/charts/codeforphilly/templates/pvc-private.yaml b/deploy/charts/codeforphilly/templates/pvc-private.yaml deleted file mode 100644 index 1be2a24..0000000 --- a/deploy/charts/codeforphilly/templates/pvc-private.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if and (eq .Values.storage.backend "filesystem") .Values.privateStorage.pvc.enabled -}} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ include "codeforphilly.privatePvcName" . }} - labels: - {{- include "codeforphilly.labels" . | nindent 4 }} -spec: - accessModes: - - {{ .Values.privateStorage.pvc.accessMode }} - resources: - requests: - storage: {{ .Values.privateStorage.pvc.size }} - {{- if .Values.privateStorage.pvc.storageClass }} - storageClassName: {{ .Values.privateStorage.pvc.storageClass }} - {{- end }} -{{- end }} diff --git a/deploy/charts/codeforphilly/templates/service.yaml b/deploy/charts/codeforphilly/templates/service.yaml deleted file mode 100644 index e513ee6..0000000 --- a/deploy/charts/codeforphilly/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "codeforphilly.fullname" . }} - labels: - {{- include "codeforphilly.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: {{ .Values.service.targetPort }} - protocol: TCP - name: http - selector: - {{- include "codeforphilly.selectorLabels" . | nindent 4 }} diff --git a/deploy/charts/codeforphilly/templates/serviceaccount.yaml b/deploy/charts/codeforphilly/templates/serviceaccount.yaml deleted file mode 100644 index 290f510..0000000 --- a/deploy/charts/codeforphilly/templates/serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "codeforphilly.serviceAccountName" . }} - labels: - {{- include "codeforphilly.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/deploy/charts/codeforphilly/values.production.yaml b/deploy/charts/codeforphilly/values.production.yaml deleted file mode 100644 index cdf5f24..0000000 --- a/deploy/charts/codeforphilly/values.production.yaml +++ /dev/null @@ -1,47 +0,0 @@ -# Production environment overrides. -# Apply with: -# helm upgrade --install codeforphilly deploy/charts/codeforphilly \ -# --namespace codeforphilly --create-namespace \ -# -f deploy/charts/codeforphilly/values.production.yaml \ -# --set image.tag= - -ingress: - hosts: - - host: codeforphilly.org - paths: - - path: / - pathType: Prefix - - host: www.codeforphilly.org - paths: - - path: / - pathType: Prefix - tls: - - secretName: codeforphilly-tls - hosts: - - codeforphilly.org - - www.codeforphilly.org - -# Production uses the S3-compatible bucket per specs/behaviors/private-storage.md. -storage: - backend: s3 - -# Concrete S3 endpoint + bucket are filled in once the production bucket is -# provisioned. Until then this file is the contract. -publicEnv: - CFP_DATA_REMOTE: git@github.com:CodeForPhilly/codeforphilly-data.git - # S3_ENDPOINT / S3_BUCKET / S3_REGION populated at provisioning time. - -deployKey: - secretName: codeforphilly-data-deploy-key - -resources: - requests: - cpu: 200m - memory: 512Mi - limits: - cpu: 2000m - memory: 1Gi - -# Tune heap for the production resource budget. -env: - NODE_OPTIONS: "--max-old-space-size=768" diff --git a/deploy/charts/codeforphilly/values.staging.yaml b/deploy/charts/codeforphilly/values.staging.yaml deleted file mode 100644 index 452a6cb..0000000 --- a/deploy/charts/codeforphilly/values.staging.yaml +++ /dev/null @@ -1,48 +0,0 @@ -# Staging environment overrides. -# Apply with: -# helm upgrade --install codeforphilly-staging deploy/charts/codeforphilly \ -# --namespace codeforphilly-staging --create-namespace \ -# -f deploy/charts/codeforphilly/values.staging.yaml \ -# --set image.tag= - -ingress: - hosts: - - host: codeforphilly-rewrite-staging.k8s.phl.io - paths: - - path: / - pathType: Prefix - tls: - - secretName: codeforphilly-staging-tls - hosts: - - codeforphilly-rewrite-staging.k8s.phl.io - -# Staging starts on the filesystem private-store backend — no bucket required -# to stand up. Flip to s3 once a staging bucket is provisioned (see -# docs/operations/deploy.md#bucket-provisioning). -storage: - backend: filesystem - -privateStorage: - pvc: - enabled: true - size: 1Gi - -publicEnv: - # Point at the public scrubbed snapshot for staging by default so we never - # leak production data through the staging UI. Swap to the real data repo - # once cutover-prep wires staging to a real (still-private) data remote. - CFP_DATA_REMOTE: https://github.com/CodeForPhilly/codeforphilly-data-snapshot.git - -# Staging deploy key is optional — the snapshot repo is public, so an SSH key -# is only needed when CFP_DATA_REMOTE is the real (private) data remote. -deployKey: - secretName: "" - -# Smaller footprint for staging. -resources: - requests: - cpu: 50m - memory: 256Mi - limits: - cpu: 500m - memory: 512Mi diff --git a/deploy/charts/codeforphilly/values.yaml b/deploy/charts/codeforphilly/values.yaml deleted file mode 100644 index 8ecdc28..0000000 --- a/deploy/charts/codeforphilly/values.yaml +++ /dev/null @@ -1,144 +0,0 @@ -# Default values for the codeforphilly chart. -# Per specs/architecture.md: single replica, Recreate strategy. -# Per-environment overrides live in values.staging.yaml + values.production.yaml. - -image: - repository: ghcr.io/codeforphilly/codeforphilly-rewrite - # tag is set by CI via --set image.tag=. Leave blank in checked-in values. - tag: "" - pullPolicy: IfNotPresent - -imagePullSecrets: [] - -# Single replica is a hard architectural constraint (write mutex serializes -# gitsheets commits in-process). Recreate strategy guarantees no concurrent -# old/new pods can both hold the lock. -replicaCount: 1 - -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - create: true - annotations: {} - name: "" - -podAnnotations: {} -podSecurityContext: - fsGroup: 1000 -securityContext: - runAsNonRoot: true - runAsUser: 1000 - runAsGroup: 1000 - readOnlyRootFilesystem: false # gitsheets writes the working tree - allowPrivilegeEscalation: false - capabilities: - drop: [ALL] - -service: - type: ClusterIP - port: 80 - targetPort: 3001 - -ingress: - enabled: true - className: nginx - annotations: - cert-manager.io/cluster-issuer: letsencrypt-prod - hosts: - - host: codeforphilly-rewrite.example.invalid - paths: - - path: / - pathType: Prefix - tls: - - secretName: codeforphilly-tls - hosts: - - codeforphilly-rewrite.example.invalid - -resources: - requests: - cpu: 100m - memory: 384Mi - limits: - cpu: 1000m - memory: 768Mi - -# PVC holding the data repo working tree. Mounted at CFP_DATA_REPO_PATH. -dataRepo: - pvc: - enabled: true - name: "" # defaults to "-data" - accessMode: ReadWriteOnce - size: 5Gi - storageClass: "" # leave empty for cluster default - # Branch to track on CFP_DATA_REMOTE. - branch: main - -# Filesystem private-store PVC (only used when storage.backend=filesystem). -# In staging we start on filesystem; production should flip to s3 once a -# bucket exists. See specs/behaviors/private-storage.md. -privateStorage: - pvc: - enabled: false - name: "" # defaults to "-private" - accessMode: ReadWriteOnce - size: 1Gi - storageClass: "" - -# Storage backend selection. One of: s3 | filesystem. -storage: - backend: s3 - -# Non-secret config; secrets are injected via secretEnvFrom below. -env: - NODE_ENV: production - PORT: "3001" - CFP_DATA_REPO_PATH: /app/data - CFP_WEB_DIST_PATH: /app/apps/web/dist - CFP_PRIVATE_STORAGE_PATH: /app/private-storage - # Push daemon identity used for any commits the API makes. - GIT_AUTHOR_NAME: CodeForPhilly API - GIT_AUTHOR_EMAIL: api@codeforphilly.org - -# Optional non-secret env that depends on per-env wiring. -publicEnv: - CFP_DATA_REMOTE: "" # set in values.staging.yaml / values.production.yaml - S3_ENDPOINT: "" - S3_BUCKET: "" - S3_REGION: "" - GITHUB_OAUTH_CLIENT_ID: "" - -# Names of existing k8s Secrets (one per environment) to mount as envFrom. -# Each Secret should populate the variables enumerated in -# docs/operations/secrets.md. -secretEnvFrom: - - name: codeforphilly-secrets - -# SSH deploy key for pushing to CFP_DATA_REMOTE. The Secret must be created -# out-of-band (sealed-secrets) and contain a single key named "id_ed25519". -# Set deployKey.secretName="" to disable mounting (e.g. when CFP_DATA_REMOTE -# is https:// with a token in the URL). -deployKey: - secretName: codeforphilly-data-deploy-key - mountPath: /etc/cfp-data-deploy-key - knownHostsConfigMap: "" # optional ConfigMap holding known_hosts - -probes: - liveness: - path: /api/health - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 3 - failureThreshold: 3 - readiness: - path: /api/health/ready - # Boot loads gitsheets + private store before binding; first probe should - # already be 200, but give 90s headroom for cold cache. - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 3 - failureThreshold: 18 - -nodeSelector: {} -tolerations: [] -affinity: {}