diff --git a/.github/workflows/prod.yaml b/.github/workflows/prod.yaml new file mode 100644 index 0000000..f1d7040 --- /dev/null +++ b/.github/workflows/prod.yaml @@ -0,0 +1,130 @@ +--- +name: Prod + +on: + release: + types: + - released + - prereleased + +jobs: + build: + outputs: + image: ${{ steps.export.outputs.image }} + tag: ${{ steps.export.outputs.tag }} + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: main # Reference branch + + - name: Install (Buildx) + uses: docker/setup-buildx-action@v3 + + - name: Login (GCP) + uses: google-github-actions/auth@v2 + with: + credentials_json: ${{ secrets.CREDENTIALS_JSON }} + + - name: Install (Gcloud) + uses: google-github-actions/setup-gcloud@v1 + with: + project_id: crane-cloud-274413 + install_components: "gke-gcloud-auth-plugin" + + - name: Login (GCR) + run: gcloud auth configure-docker + + - id: meta + name: Tag + uses: docker/metadata-action@v3 + with: + flavor: | + latest=true + images: gcr.io/crane-cloud-274413/activity-logger + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha + + - name: Build + uses: docker/build-push-action@v2 + with: + cache-from: type=gha + cache-to: type=gha,mode=max + context: . + file: Dockerfile + labels: ${{ steps.meta.outputs.labels }} + push: true + tags: ${{ steps.meta.outputs.tags }} + + - id: export + name: Export + uses: actions/github-script@v5 + with: + script: | + const metadata = JSON.parse(`${{ steps.meta.outputs.json }}`) + const fullUrl = metadata.tags.find((t) => t.includes(':sha-')) + if (fullUrl == null) { + core.error('Unable to find sha tag of image') + } else { + const tag = fullUrl.split(':')[1] + core.setOutput('image', fullUrl) + core.setOutput('tag', tag) + } + + Production: + name: Deploy (Production) + + needs: + - build + + runs-on: ubuntu-latest + + env: + namespace: cranecloud-prod + + steps: + - name: Clone + uses: actions/checkout@v2 + + - name: Login (GCP) + uses: google-github-actions/auth@v2 + with: + credentials_json: ${{ secrets.CREDENTIALS_JSON }} + + - name: Install (Gcloud) + uses: google-github-actions/setup-gcloud@v1 + with: + project_id: crane-cloud-274413 + install_components: "gke-gcloud-auth-plugin" + + - name: Login (Kubernetes Cluster) + uses: google-github-actions/get-gke-credentials@v1 + with: + cluster_name: staging-cluster + location: us-central1-a + project_id: crane-cloud-274413 + + - name: Add Repo (cranecloud) + run: | + helm repo add cranecloud https://crane-cloud.github.io/helm-charts/ + + - name: Helm Release + run: | + helm upgrade --install \ + activity-logger cranecloud/cranecloud \ + --values helm/values.prod.yaml \ + --namespace $namespace \ + --set image.tag="${{ needs.build.outputs.tag }}" \ + --set environment.JWT_SALT="${{ secrets.PRODUCTION_JWT_SALT }}" \ + --timeout=300s + + - name: Monitor Rollout + run: | + kubectl rollout status deployment/activity-logger --timeout=300s --namespace $namespace diff --git a/.github/workflows/staging.yaml b/.github/workflows/staging.yaml index 9af8745..2e8c78d 100644 --- a/.github/workflows/staging.yaml +++ b/.github/workflows/staging.yaml @@ -5,7 +5,6 @@ on: push: branches: - develop - - ft-add-mongo-deployment workflow_dispatch: @@ -21,10 +20,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install (Buildx) - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - name: Login to Docker Hub uses: docker/login-action@v2 @@ -45,7 +44,7 @@ jobs: type=sha - name: Build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v5 with: cache-from: type=gha cache-to: type=gha,mode=max @@ -56,7 +55,7 @@ jobs: - id: export name: Export - uses: actions/github-script@v5 + uses: actions/github-script@v7 with: script: | const metadata = JSON.parse(`${{ steps.meta.outputs.json }}`) @@ -73,29 +72,43 @@ jobs: name: Deploy (Staging) needs: - - Build + - build runs-on: ubuntu-latest env: - namespace: cranecloud-microservice + namespace: cranecloud image: cranecloud/activity-logger steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - - uses: azure/k8s-set-context@v1 + - name: Login (GCP) + uses: google-github-actions/auth@v2 with: - kubeconfig: ${{ secrets.RENU_KUBECONFIG}} + credentials_json: ${{ secrets.CREDENTIALS_JSON }} - # - name: Add Repo (cranecloud-backend) - # run: | - # helm repo add cranecloud-backend https://crane-cloud.github.io/helm-charts/ + - name: Install (Gcloud) + uses: google-github-actions/setup-gcloud@v2 + with: + project_id: crane-cloud-274413 + install_components: "gke-gcloud-auth-plugin" + + - name: Login (Kubernetes Cluster) + uses: google-github-actions/get-gke-credentials@v2 + with: + cluster_name: staging-cluster + location: us-central1-a + project_id: crane-cloud-274413 + + - name: Add Repo (cranecloud) + run: | + helm repo add cranecloud https://crane-cloud.github.io/helm-charts/ - name: Helm Release run: | helm upgrade --install \ - activity-logger ./helm/chart \ + activity-logger cranecloud/cranecloud \ --values helm/values.staging.yaml \ --namespace $namespace \ --set image.tag="${{ needs.build.outputs.tag }}" \ diff --git a/Dockerfile b/Dockerfile index 56ad22e..69af18a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,18 +6,16 @@ ENV DEBIAN_FRONTEND='noninteractive' RUN apt-get update && apt install -y curl +COPY ./README.md /app/README.md + RUN pip install poetry ENV PATH="${PATH}:/root/.local/bin" -COPY ./pyproject.toml /app/pyproject.toml - -COPY ./poetry.lock /app/poetry.lock - +COPY . /app RUN poetry install -COPY . /app #for celery to have a different working directory COPY . /celery-app diff --git a/helm/chart/.helmignore b/helm/chart/.helmignore deleted file mode 100644 index 0e8a0eb..0000000 --- a/helm/chart/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# 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/helm/chart/Chart.yaml b/helm/chart/Chart.yaml deleted file mode 100644 index 2ac2414..0000000 --- a/helm/chart/Chart.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v2 -name: cranecloud -description: A Helm chart for cranecloud applications - -# 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.4 - -# 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. -appVersion: 1.16.0 diff --git a/helm/chart/templates/_helpers.tpl b/helm/chart/templates/_helpers.tpl deleted file mode 100644 index 6f379e7..0000000 --- a/helm/chart/templates/_helpers.tpl +++ /dev/null @@ -1,47 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "cranecloud.name" -}} -{{- default .Release.Name .Values.nameOverride .Chart.Name | trunc 63 | trimSuffix "-" }} -{{- end }} - - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "cranecloud.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "cranecloud.labels" -}} -helm.sh/chart: {{ include "cranecloud.chart" . }} -{{ include "cranecloud.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "cranecloud.selectorLabels" -}} -app: {{ include "cranecloud.name" . }} -app.kubernetes.io/name: {{ include "cranecloud.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "cranecloud.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "cranecloud.name" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/helm/chart/templates/celery-deployment.yaml b/helm/chart/templates/celery-deployment.yaml deleted file mode 100644 index 0f4a067..0000000 --- a/helm/chart/templates/celery-deployment.yaml +++ /dev/null @@ -1,54 +0,0 @@ -{{- if .Values.celery.create -}} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "cranecloud.name" . }}-celery - labels: - {{- include "cranecloud.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.celery.replicaCount }} - selector: - matchLabels: - {{- include "cranecloud.selectorLabels" . | nindent 6 }} - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 25% - type: RollingUpdate - template: - metadata: - {{- with .Values.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "cranecloud.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "cranecloud.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ include "cranecloud.name" . }}-celery - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - command: {{ .Values.celery.command | toYaml | nindent 12}} - env: - - name: test - value: test - {{- range $key, $value := .Values.environment }} - - name: {{ $key }} - value: {{ $value | quote }} - {{- end }} - ports: - - name: celery-worker - containerPort: {{ .Values.celery.port }} - protocol: TCP - resources: - {{- toYaml .Values.resources | nindent 12 }} -{{- end }} diff --git a/helm/chart/templates/deployment.yaml b/helm/chart/templates/deployment.yaml deleted file mode 100644 index fecab82..0000000 --- a/helm/chart/templates/deployment.yaml +++ /dev/null @@ -1,76 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "cranecloud.name" . }} - labels: - {{- include "cranecloud.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - {{- include "cranecloud.selectorLabels" . | nindent 6 }} - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 25% - type: RollingUpdate - template: - metadata: - {{- with .Values.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "cranecloud.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "cranecloud.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ include "cranecloud.name" . }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - {{- range $key, $value := .Values.environment }} - - name: {{ $key }} - value: {{ $value | quote }} - {{- end }} - - ports: - - name: backend-api - containerPort: 8000 - protocol: TCP - resources: - {{- toYaml .Values.resources | nindent 12 }} - - name: nginx - image: nginx:1.21.6 - imagePullPolicy: IfNotPresent - ports: - - name: http - containerPort: 80 - volumeMounts: - - name: nginx-proxy-config - mountPath: /etc/nginx/conf.d/default.conf - subPath: nginx.conf - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} - volumes: - - name: nginx-proxy-config - configMap: - name: {{ .Release.Name }}-nginx-configmap \ No newline at end of file diff --git a/helm/chart/templates/mongo.yaml b/helm/chart/templates/mongo.yaml deleted file mode 100644 index f7cd0b4..0000000 --- a/helm/chart/templates/mongo.yaml +++ /dev/null @@ -1,51 +0,0 @@ -{{- if .Values.mongo.create -}} -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: mongo - labels: - {{- include "cranecloud.labels" . | nindent 4 }} -spec: - serviceName: mongo - replicas: {{ .Values.mongo.replicas }} - selector: - matchLabels: - app: mongo - template: - metadata: - labels: - app: mongo - spec: - containers: - - name: mongo - image: mongo:latest - ports: - - containerPort: 27017 - name: mongo - volumeMounts: - - name: mongo-data - mountPath: /data/db - volumeClaimTemplates: - - metadata: - name: mongo-data - spec: - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: {{ .Values.mongo.storage }} ---- -apiVersion: v1 -kind: Service -metadata: - name: mongo - labels: - {{- include "cranecloud.labels" . | nindent 4 }} -spec: - clusterIP: None - selector: - app: mongo - ports: - - port: {{ .Values.mongo.port }} - name: mongo - targetPort: mongo -{{- end }} diff --git a/helm/chart/templates/nginx-configmap.yaml b/helm/chart/templates/nginx-configmap.yaml deleted file mode 100644 index cd42607..0000000 --- a/helm/chart/templates/nginx-configmap.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ .Release.Name }}-nginx-configmap -data: - nginx.conf: |- -{{ tpl .Values.nginxConf . | indent 4 }} \ No newline at end of file diff --git a/helm/chart/templates/redis.yaml b/helm/chart/templates/redis.yaml deleted file mode 100644 index 26ac599..0000000 --- a/helm/chart/templates/redis.yaml +++ /dev/null @@ -1,51 +0,0 @@ -{{- if .Values.redis.create -}} -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis - labels: - {{- include "cranecloud.labels" . | nindent 4 }} -spec: - serviceName: redis - replicas: {{ .Values.redis.replicas }} - selector: - matchLabels: - app: redis - template: - metadata: - labels: - app: redis - spec: - containers: - - name: redis - image: redis:latest - ports: - - containerPort: 6379 - name: redis - volumeMounts: - - name: redis-data - mountPath: /data - volumeClaimTemplates: - - metadata: - name: redis-data - spec: - accessModes: [ "ReadWriteOnce" ] - resources: - requests: - storage: {{ .Values.redis.storage }} ---- -apiVersion: v1 -kind: Service -metadata: - name: redis - labels: - {{- include "cranecloud.labels" . | nindent 4 }} -spec: - clusterIP: None - selector: - app: redis - ports: - - port: {{ .Values.redis.port }} - name: redis - targetPort: redis -{{- end }} diff --git a/helm/chart/templates/service.yaml b/helm/chart/templates/service.yaml deleted file mode 100644 index a1dde64..0000000 --- a/helm/chart/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "cranecloud.name" . }} - labels: - {{- include "cranecloud.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "cranecloud.selectorLabels" . | nindent 4 }} diff --git a/helm/chart/templates/serviceaccount.yaml b/helm/chart/templates/serviceaccount.yaml deleted file mode 100644 index f59da51..0000000 --- a/helm/chart/templates/serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "cranecloud.serviceAccountName" . }} - labels: - {{- include "cranecloud.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/helm/chart/values.yaml b/helm/chart/values.yaml deleted file mode 100644 index 3d2ba19..0000000 --- a/helm/chart/values.yaml +++ /dev/null @@ -1,99 +0,0 @@ -# Default values for cranecloud-backend. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 - -image: - repository: gcr.io/crane-cloud-274413/cranecloud-backend - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: latest - -imagePullSecrets: [] -nameOverride: "cranecloud" - -serviceAccount: - # Specifies whether a service account should be created - create: false - # 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 name template - name: "" - -podAnnotations: {} - -podSecurityContext: {} - # fsGroup: 2000 - -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 - -service: - type: ClusterIP - port: 80 - -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 - -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -nginxConf: - server { - listen 80; - server_name localhost; - - location / { - proxy_pass http://localhost:5000/; - proxy_set_header Host "localhost"; - } - } - -environment: - APP: "test-app" - - -celery: - create: false - command: - - "python" - - "run" - port: 5002 - -redis: - create: false - replicas: 1 - port: 6379 - storage: 1Gi - -mongo: - create: false - replicas: 1 - port: 27017 - storage: 1Gi \ No newline at end of file diff --git a/helm/values.prod.yaml b/helm/values.prod.yaml new file mode 100644 index 0000000..64978c5 --- /dev/null +++ b/helm/values.prod.yaml @@ -0,0 +1,48 @@ +replicaCount: 1 + +image: + repository: gcr.io/crane-cloud-274413/activity-logger + pullPolicy: Always + tag: ${{ DOCKER_IMAGE_TAG }} + +nameOverride: "activity-logger" + +nginxConf: + server { + listen 80; + server_name localhost; + location / { + proxy_pass http://localhost:8000/; + proxy_set_header Host "localhost"; + } + } + +port: 8000 + +service: + type: NodePort + port: 80 + +environment: + JWT_SALT: ${{ JWT_SALT }} + MONGO_URI: mongo:27017 + FASTAPI_ENV: production + REDIS_URL: redis://redis:6379 + +celery: + create: true + command: + - "poetry" + - "run" + - "celery" + - "-A" + - "main.celery" + - "worker" + - "--loglevel=info" + port: 5001 + +redis: + create: false + +mongo: + create: true \ No newline at end of file diff --git a/helm/values.staging.yaml b/helm/values.staging.yaml index 1375025..9dbf894 100644 --- a/helm/values.staging.yaml +++ b/helm/values.staging.yaml @@ -10,12 +10,19 @@ nameOverride: "activity-logger" nginxConf: server { listen 80; - + server_name localhost; location / { proxy_pass http://localhost:8000/; + proxy_set_header Host "localhost"; } } +port: 8000 + +service: + type: NodePort + port: 80 + environment: JWT_SALT: ${{ JWT_SALT }} MONGO_URI: ${{ MONGO_URI }} @@ -35,7 +42,7 @@ celery: port: 5001 redis: - create: true + create: false mongo: create: true \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index d5b41ee..98df503 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,6 +4,9 @@ version = "0.1.0" description = "Logging application" authors = ["khalifan-kfan "] readme = "README.md" +packages = [ + { include = "app" }, +] [tool.poetry.dependencies] python = "^3.10"