---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ghp
  namespace: ghp
  annotations:
    # Wave 2: serve only after the wave-1 migrate Job completes.
    argocd.argoproj.io/sync-wave: "2"
    configmap.reloader.stakater.com/auto: "true"
    secret.reloader.stakater.com/reload: "ghp-github-app,ghp-app,ghp-tls,postgres-app"
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ghp
  strategy:
    rollingUpdate:
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: ghp
    spec:
      serviceAccountName: default
      automountServiceAccountToken: true
      securityContext:
        runAsNonRoot: true
        runAsUser: 65532
        runAsGroup: 65532
        fsGroup: 65532
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: ghp
          image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/ghp:v0.20.0-unkin4
          imagePullPolicy: IfNotPresent
          # Drop the image's default --migrate so replicas never race migrations;
          # schema is applied by the wave-1 migrate hook Job instead.
          command: ["/ghp", "serve"]
          ports:
            - containerPort: 8443
              name: https
              protocol: TCP
            - containerPort: 8080
              name: http
              protocol: TCP
            - containerPort: 9136
              name: metrics
              protocol: TCP
          envFrom:
            - configMapRef:
                name: ghp-env
                optional: false
          env:
            # DSN assembled from the CNPG-generated postgres-app Secret; $(VAR)
            # expansion resolves the two env entries defined above it.
            - name: GHP_DB_USER
              valueFrom:
                secretKeyRef:
                  name: postgres-app
                  key: username
            - name: GHP_DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: postgres-app
                  key: password
            - name: GHP_DATABASE_DSN
              value: "postgres://$(GHP_DB_USER):$(GHP_DB_PASSWORD)@postgres-rw.ghp.svc:5432/ghp?sslmode=require"
            - name: GHP_GITHUB_APP_ID
              valueFrom:
                secretKeyRef:
                  name: ghp-github-app
                  key: app_id
            - name: GHP_GITHUB_CLIENT_ID
              valueFrom:
                secretKeyRef:
                  name: ghp-github-app
                  key: client_id
            - name: GHP_GITHUB_CLIENT_SECRET
              valueFrom:
                secretKeyRef:
                  name: ghp-github-app
                  key: client_secret
            - name: GHP_ENCRYPTION_KEY
              valueFrom:
                secretKeyRef:
                  name: ghp-app
                  key: encryption_key
            # Static admin service token for machine callers (the Vault ghp
            # secrets engine authenticates with it to mint scoped tokens).
            # optional: ghp runs fine without it until Ben seeds `service_token`
            # into kv/kubernetes/namespace/ghp/default/app; the ghp-app reloader
            # annotation then rolls this Deployment to pick it up.
            - name: GHP_AUTH_SERVICE_TOKENS
              valueFrom:
                secretKeyRef:
                  name: ghp-app
                  key: service_token
                  optional: true
          volumeMounts:
            - name: github-app
              mountPath: /etc/ghp/github-app
              readOnly: true
            - name: tls
              mountPath: /etc/ghp/tls
              readOnly: true
            - name: tmp
              mountPath: /tmp
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /metrics
              port: metrics
              # Plain HTTP: ghp only serves metrics over TLS in TLS mode
              # (hasTLS). In reverse-proxy/plain mode the metrics server is
              # cleartext, so probe with HTTP.
              scheme: HTTP
            initialDelaySeconds: 30
            periodSeconds: 30
            successThreshold: 1
            timeoutSeconds: 5
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /metrics
              port: metrics
              # Plain HTTP: ghp only serves metrics over TLS in TLS mode
              # (hasTLS). In reverse-proxy/plain mode the metrics server is
              # cleartext, so probe with HTTP.
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 5
            successThreshold: 1
            timeoutSeconds: 5
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL
          resources:
            limits:
              cpu: "2"
              memory: 2Gi
            requests:
              cpu: "1"
              memory: 512Mi
      volumes:
        - name: github-app
          secret:
            secretName: ghp-github-app
        - name: tls
          secret:
            secretName: ghp-tls
        # Writable scratch: root FS is read-only. Disk-backed (not memory medium)
        # so codeload tarball staging doesn't count against the pod memory limit.
        - name: tmp
          emptyDir:
            sizeLimit: 2Gi
      restartPolicy: Always
