From 8649522b5b7aac65a370780f9cc4e093a111edef Mon Sep 17 00:00:00 2001 From: Piyush Jain <122745947+d3vb0ox@users.noreply.github.com> Date: Mon, 24 Mar 2025 09:21:32 +0530 Subject: [PATCH] chore(actions): Update github actions to follow new release pattern (#5037) --- .github/workflows/deploy-formbricks-cloud.yml | 64 +++++++ .github/workflows/formbricks-deploy.yml | 31 ++++ .github/workflows/release-docker-github.yml | 13 +- .github/workflows/release-docker.yml | 59 ------- .github/workflows/release-helm-chart.yml | 15 +- infra/formbricks-cloud-helm/helmfile.yaml | 17 ++ .../formbricks-cloud-helm/values.yaml.gotmpl | 164 ++++++++++++++++++ infra/terraform/rds.tf | 9 + 8 files changed, 303 insertions(+), 69 deletions(-) create mode 100644 .github/workflows/deploy-formbricks-cloud.yml create mode 100644 .github/workflows/formbricks-deploy.yml delete mode 100644 .github/workflows/release-docker.yml create mode 100644 infra/formbricks-cloud-helm/helmfile.yaml create mode 100644 infra/formbricks-cloud-helm/values.yaml.gotmpl diff --git a/.github/workflows/deploy-formbricks-cloud.yml b/.github/workflows/deploy-formbricks-cloud.yml new file mode 100644 index 0000000000..bff5c196e3 --- /dev/null +++ b/.github/workflows/deploy-formbricks-cloud.yml @@ -0,0 +1,64 @@ +name: Formbricks Cloud Deployment + +on: + workflow_dispatch: + inputs: + VERSION: + description: 'The version of the Docker image to release' + required: true + type: string + REPOSITORY: + description: 'The repository to use for the Docker image' + required: false + type: string + default: 'ghcr.io/formbricks/formbricks' + workflow_call: + inputs: + VERSION: + description: 'The version of the Docker image to release' + required: true + type: string + REPOSITORY: + description: 'The repository to use for the Docker image' + required: false + type: string + default: 'ghcr.io/formbricks/formbricks' + +permissions: + id-token: write + contents: write + +jobs: + helmfile-deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_ASSUME_ROLE_ARN }} + aws-region: "eu-central-1" + + - name: Setup Cluster Access + run: | + aws eks update-kubeconfig --name formbricks-prod-eks --region eu-central-1 + env: + AWS_REGION: eu-central-1 + + - uses: helmfile/helmfile-action@v2 + env: + VERSION: ${{ inputs.VERSION }} + REPOSITORY: ${{ inputs.REPOSITORY }} + FORMBRICKS_S3_BUCKET: ${{ secrets.FORMBRICKS_S3_BUCKET }} + FORMBRICKS_INGRESS_CERT_ARN: ${{ secrets.FORMBRICKS_INGRESS_CERT_ARN }} + FORMBRICKS_ROLE_ARN: ${{ secrets.FORMBRICKS_ROLE_ARN }} + with: + helm-plugins: > + https://github.com/databus23/helm-diff, + https://github.com/jkroepke/helm-secrets + helmfile-args: apply + helmfile-auto-init: "false" + helmfile-workdirectory: infra/formbricks-cloud-helm + diff --git a/.github/workflows/formbricks-deploy.yml b/.github/workflows/formbricks-deploy.yml new file mode 100644 index 0000000000..fb2fdb206c --- /dev/null +++ b/.github/workflows/formbricks-deploy.yml @@ -0,0 +1,31 @@ +name: Build and Deploy Formbricks + +on: + workflow_dispatch: + push: + tags: + - "v*" + +jobs: + docker-build: + name: Build stable docker image + if: startsWith(github.ref, 'refs/tags/v') + uses: ./.github/workflows/release-docker-github.yml + + helm-chart-release: + name: Release Helm Chart + uses: ./.github/workflows/release-helm-chart.yml + needs: + - docker-build + with: + VERSION: ${{ needs.docker-build.outputs.VERSION }} + + deploy-formbricks-cloud: + name: Deploy Helm Chart + secrets: inherit + uses: ./.github/workflows/deploy-formbricks-cloud.yml + needs: + - docker-build + - helm-chart-release + with: + VERSION: ${{ needs.docker-build.outputs.VERSION }} diff --git a/.github/workflows/release-docker-github.yml b/.github/workflows/release-docker-github.yml index 837dcfe4b5..c09d66d553 100644 --- a/.github/workflows/release-docker-github.yml +++ b/.github/workflows/release-docker-github.yml @@ -6,10 +6,11 @@ name: Docker Release to Github # documentation. on: - workflow_dispatch: - push: - tags: - - "v*" + workflow_call: + outputs: + VERSION: + description: release version + value: ${{ jobs.build.outputs.VERSION }} env: # Use docker.io for Docker Hub if empty @@ -33,6 +34,9 @@ jobs: # with sigstore/fulcio when running outside of PRs. id-token: write + outputs: + VERSION: ${{ steps.extract_release_tag.outputs.VERSION }} + steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 @@ -48,6 +52,7 @@ jobs: TAG=${{ github.ref }} TAG=${TAG#refs/tags/v} echo "RELEASE_TAG=$TAG" >> $GITHUB_ENV + echo "VERSION=$TAG" >> $GITHUB_OUTPUT - name: Update package.json version run: | diff --git a/.github/workflows/release-docker.yml b/.github/workflows/release-docker.yml deleted file mode 100644 index d3367333ca..0000000000 --- a/.github/workflows/release-docker.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Release on Dockerhub - -on: - push: - tags: - - "v*" - -permissions: - contents: read - -jobs: - release-image-on-dockerhub: - name: Release on Dockerhub - permissions: - contents: read - runs-on: ubuntu-latest - env: - TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} - TURBO_TEAM: ${{ secrets.TURBO_TEAM }} - DATABASE_URL: "postgresql://postgres:postgres@localhost:5432/formbricks?schema=public" - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 - with: - egress-policy: audit - - - name: Checkout Repo - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 - - - name: Get Release Tag - id: extract_release_tag - run: | - TAG=${{ github.ref }} - TAG=${TAG#refs/tags/v} - echo "RELEASE_TAG=$TAG" >> $GITHUB_ENV - - - name: Update package.json version - run: | - sed -i "s/\"version\": \"0.0.0\"/\"version\": \"${{ env.RELEASE_TAG }}\"/" ./apps/web/package.json - cat ./apps/web/package.json | grep version - - - name: Log in to Docker Hub - uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0 - - - name: Build and push Docker image - uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # v4.2.1 - with: - context: . - file: ./apps/web/Dockerfile - push: true - tags: | - ${{ secrets.DOCKER_USERNAME }}/formbricks:${{ env.RELEASE_TAG }} - ${{ secrets.DOCKER_USERNAME }}/formbricks:latest diff --git a/.github/workflows/release-helm-chart.yml b/.github/workflows/release-helm-chart.yml index 85cfe16894..fbe39e160d 100644 --- a/.github/workflows/release-helm-chart.yml +++ b/.github/workflows/release-helm-chart.yml @@ -1,9 +1,12 @@ name: Publish Helm Chart on: - release: - types: - - published + workflow_call: + inputs: + VERSION: + description: 'The version of the Helm chart to release' + required: true + type: string permissions: contents: read @@ -39,8 +42,8 @@ jobs: - name: Update Chart.yaml with new version run: | - yq -i ".version = \"${VERSION#v}\"" helm-chart/Chart.yaml - yq -i ".appVersion = \"${VERSION}\"" helm-chart/Chart.yaml + yq -i ".version = \"${{ inputs.VERSION }}\"" helm-chart/Chart.yaml + yq -i ".appVersion = \"v${{ inputs.VERSION }}\"" helm-chart/Chart.yaml - name: Package Helm chart run: | @@ -48,4 +51,4 @@ jobs: - name: Push Helm chart to GitHub Container Registry run: | - helm push formbricks-${VERSION#v}.tgz oci://ghcr.io/formbricks/helm-charts + helm push formbricks-${{ inputs.VERSION }}.tgz oci://ghcr.io/formbricks/helm-charts diff --git a/infra/formbricks-cloud-helm/helmfile.yaml b/infra/formbricks-cloud-helm/helmfile.yaml new file mode 100644 index 0000000000..c986cf6ad2 --- /dev/null +++ b/infra/formbricks-cloud-helm/helmfile.yaml @@ -0,0 +1,17 @@ +repositories: + - name: helm-charts + url: ghcr.io/formbricks/helm-charts + oci: true + +releases: + - name: formbricks + namespace: formbricks + chart: helm-charts/formbricks + version: ^3.0.0 + values: + - values.yaml.gotmpl + set: + - name: deployment.image.tag + value: v{{ requiredEnv "VERSION" }} + - name: deployment.image.repository + value: {{ requiredEnv "REPOSITORY" }} diff --git a/infra/formbricks-cloud-helm/values.yaml.gotmpl b/infra/formbricks-cloud-helm/values.yaml.gotmpl new file mode 100644 index 0000000000..ec5e571ddf --- /dev/null +++ b/infra/formbricks-cloud-helm/values.yaml.gotmpl @@ -0,0 +1,164 @@ +cronJob: + enabled: true + jobs: + ping: + args: + - /bin/sh + - -c + - 'curl -X POST -H "content-type: application/json" -H "x-api-key: $CRON_SECRET" + "$WEBAPP_URL/api/cron/ping"' + env: + CRON_SECRET: + valueFrom: + secretKeyRef: + key: CRON_SECRET + name: formbricks-app-env + WEBAPP_URL: + valueFrom: + secretKeyRef: + key: WEBAPP_URL + name: formbricks-app-env + image: + imagePullPolicy: IfNotPresent + repository: curlimages/curl + tag: latest + schedule: 0 9 * * * + successfulJobsHistoryLimit: 0 + survey-status: + args: + - /bin/sh + - -c + - 'curl -X POST -H "content-type: application/json" -H "x-api-key: $CRON_SECRET" + "$WEBAPP_URL/api/cron/survey-status"' + env: + CRON_SECRET: + valueFrom: + secretKeyRef: + key: CRON_SECRET + name: formbricks-app-env + WEBAPP_URL: + valueFrom: + secretKeyRef: + key: WEBAPP_URL + name: formbricks-app-env + image: + imagePullPolicy: IfNotPresent + repository: curlimages/curl + tag: latest + schedule: 0 0 * * * + successfulJobsHistoryLimit: 0 + weekely-summary: + args: + - /bin/sh + - -c + - 'curl -X POST -H "content-type: application/json" -H "x-api-key: $CRON_SECRET" + "$WEBAPP_URL/api/cron/weekly-summary"' + env: + CRON_SECRET: + valueFrom: + secretKeyRef: + key: CRON_SECRET + name: formbricks-app-env + WEBAPP_URL: + valueFrom: + secretKeyRef: + key: WEBAPP_URL + name: formbricks-app-env + image: + imagePullPolicy: IfNotPresent + repository: curlimages/curl + tag: latest + schedule: 0 8 * * 1 + successfulJobsHistoryLimit: 0 + +## Deployment & Autoscaling +deployment: + env: + DOCKER_CRON_ENABLED: + value: "0" + RATE_LIMITING_DISABLED: + value: "1" + S3_BUCKET_NAME: + value: {{ requiredEnv "FORMBRICKS_S3_BUCKET" }} + envFrom: + app-env: + nameSuffix: app-env + type: secret + nodeSelector: + karpenter.sh/capacity-type: on-demand + reloadOnChange: true +autoscaling: + enabled: true + maxReplicas: 10 + minReplicas: 3 + metrics: + - resource: + name: cpu + target: + averageUtilization: 60 + type: Utilization + type: Resource + - resource: + name: memory + target: + averageUtilization: 60 + type: Utilization + type: Resource + +### Secrets +secret: + enabled: false +externalSecret: + enabled: true + files: + app-env: + dataFrom: + key: prod/formbricks/environment + app-secrets: + dataFrom: + key: prod/formbricks/secrets + refreshInterval: 1m + secretStore: + kind: ClusterSecretStore + name: aws-secrets-manager + +## Ingress +ingress: + annotations: + alb.ingress.kubernetes.io/certificate-arn: {{ requiredEnv "FORMBRICKS_INGRESS_CERT_ARN" }} + alb.ingress.kubernetes.io/group.name: formbricks + alb.ingress.kubernetes.io/healthcheck-path: /health + alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]' + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-2021-06 + alb.ingress.kubernetes.io/ssl-redirect: "443" + alb.ingress.kubernetes.io/target-type: ip + enabled: true + hosts: + - host: app.k8s.formbricks.com + paths: + - path: / + pathType: Prefix + serviceName: formbricks + - host: app.formbricks.com + paths: + - path: / + pathType: Prefix + serviceName: formbricks + ingressClassName: alb + +## RBAC +rbac: + enabled: true + serviceAccount: + annotations: + eks.amazonaws.com/role-arn: {{ requiredEnv "FORMBRICKS_ROLE_ARN" }} + additionalLabels: {} + enabled: true + name: formbricks + +## Dependencies +postgresql: + enabled: false +redis: + enabled: false diff --git a/infra/terraform/rds.tf b/infra/terraform/rds.tf index 0049018e7f..2455b737b0 100644 --- a/infra/terraform/rds.tf +++ b/infra/terraform/rds.tf @@ -23,6 +23,15 @@ module "rds-aurora" { master_username = "formbricks" master_password = random_password.postgres.result manage_master_user_password = false + create_db_cluster_parameter_group = true + db_cluster_parameter_group_family = data.aws_rds_engine_version.postgresql.parameter_group_family + db_cluster_parameter_group_parameters = [ + { + name = "shared_preload_libraries" + value = "pglogical" + apply_method = "pending-reboot" + } + ] vpc_id = module.vpc.vpc_id db_subnet_group_name = module.vpc.database_subnet_group_name