mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-21 13:40:31 -06:00
chore: remove kamal configs
This commit is contained in:
129
.github/workflows/kamal-deploy.yml
vendored
129
.github/workflows/kamal-deploy.yml
vendored
@@ -1,129 +0,0 @@
|
||||
name: Kamal Deploy
|
||||
concurrency:
|
||||
group: deploy-to-kamal
|
||||
cancel-in-progress: false
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
#push:
|
||||
# branches:
|
||||
# - main
|
||||
|
||||
jobs:
|
||||
Deploy:
|
||||
runs-on: ubuntu-latest
|
||||
environment: production
|
||||
env:
|
||||
DOCKER_BUILDKIT: 1
|
||||
IS_FORMBRICKS_CLOUD: ${{ vars.IS_FORMBRICKS_CLOUD }}
|
||||
WEBAPP_URL: ${{ vars.WEBAPP_URL }}
|
||||
MIGRATE_DATABASE_URL: ${{ secrets.MIGRATE_DATABASE_URL }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }}
|
||||
ENCRYPTION_KEY: ${{ secrets.ENCRYPTION_KEY }}
|
||||
SHORT_URL_BASE: ${{ vars.SHORT_URL_BASE }}
|
||||
MAIL_FROM: ${{ secrets.MAIL_FROM }}
|
||||
SMTP_HOST: ${{ secrets.SMTP_HOST }}
|
||||
SMTP_PORT: ${{ secrets.SMTP_PORT }}
|
||||
SMTP_USER: ${{ secrets.SMTP_USER }}
|
||||
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
|
||||
PRIVACY_URL: ${{ vars.PRIVACY_URL }}
|
||||
TERMS_URL: ${{ vars.TERMS_URL }}
|
||||
IMPRINT_URL: ${{ vars.IMPRINT_URL }}
|
||||
GITHUB_ID: ${{ secrets.FB_GITHUB_ID }}
|
||||
GITHUB_SECRET: ${{ secrets.FB_GITHUB_SECRET }}
|
||||
GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
|
||||
GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
|
||||
AZUREAD_CLIENT_ID: ${{ secrets.AZUREAD_CLIENT_ID }}
|
||||
AZUREAD_CLIENT_SECRET: ${{ secrets.AZUREAD_CLIENT_SECRET }}
|
||||
AZUREAD_TENANT_ID: ${{ secrets.AZUREAD_TENANT_ID }}
|
||||
OIDC_CLIENT_ID: ${{ secrets.OIDC_CLIENT_ID }}
|
||||
OIDC_CLIENT_SECRET: ${{ secrets.OIDC_CLIENT_SECRET }}
|
||||
OIDC_ISSUER: ${{ secrets.OIDC_ISSUER }}
|
||||
OIDC_DISPLAY_NAME: ${{ secrets.OIDC_DISPLAY_NAME }}
|
||||
OIDC_SIGNING_ALGORITHM: ${{ secrets.OIDC_SIGNING_ALGORITHM }}
|
||||
CRON_SECRET: ${{ secrets.CRON_SECRET }}
|
||||
ASSET_PREFIX_URL: ${{ vars.ASSET_PREFIX_URL }}
|
||||
NOTION_OAUTH_CLIENT_ID: ${{ secrets.NOTION_OAUTH_CLIENT_ID }}
|
||||
NOTION_OAUTH_CLIENT_SECRET: ${{ secrets.NOTION_OAUTH_CLIENT_SECRET }}
|
||||
SLACK_CLIENT_ID: ${{ secrets.SLACK_CLIENT_ID }}
|
||||
SLACK_CLIENT_SECRET: ${{ secrets.SLACK_CLIENT_SECRET }}
|
||||
STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
|
||||
STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }}
|
||||
GOOGLE_SHEETS_CLIENT_ID: ${{ secrets.GOOGLE_SHEETS_CLIENT_ID }}
|
||||
GOOGLE_SHEETS_CLIENT_SECRET: ${{ secrets.GOOGLE_SHEETS_CLIENT_SECRET }}
|
||||
GOOGLE_SHEETS_REDIRECT_URL: ${{ secrets.GOOGLE_SHEETS_REDIRECT_URL }}
|
||||
AIRTABLE_CLIENT_ID: ${{ secrets.AIRTABLE_CLIENT_ID }}
|
||||
ENTERPRISE_LICENSE_KEY: ${{ secrets.ENTERPRISE_LICENSE_KEY }}
|
||||
DEFAULT_ORGANIZATION_ID: ${{ vars.DEFAULT_ORGANIZATION_ID }}
|
||||
CUSTOMER_IO_API_KEY: ${{ secrets.CUSTOMER_IO_API_KEY }}
|
||||
CUSTOMER_IO_SITE_ID: ${{ secrets.CUSTOMER_IO_SITE_ID }}
|
||||
NEXT_PUBLIC_POSTHOG_API_KEY: ${{ vars.NEXT_PUBLIC_POSTHOG_API_KEY }}
|
||||
NEXT_PUBLIC_POSTHOG_API_HOST: ${{ vars.NEXT_PUBLIC_POSTHOG_API_HOST }}
|
||||
NEXT_PUBLIC_FORMBRICKS_API_HOST: ${{ vars.NEXT_PUBLIC_FORMBRICKS_API_HOST }}
|
||||
NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID: ${{ vars.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID }}
|
||||
NEXT_PUBLIC_FORMBRICKS_ONBOARDING_SURVEY_ID: ${{ vars.NEXT_PUBLIC_FORMBRICKS_ONBOARDING_SURVEY_ID }}
|
||||
NEXT_PUBLIC_SENTRY_DSN: ${{ vars.NEXT_PUBLIC_SENTRY_DSN }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
NODE_ENV: production
|
||||
CLOUDFLARE_EMAIL: ${{ secrets.CLOUDFLARE_EMAIL }}
|
||||
CLOUDFLARE_DNS_API_TOKEN: ${{ secrets.CLOUDFLARE_DNS_API_TOKEN }}
|
||||
S3_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }}
|
||||
S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }}
|
||||
S3_REGION: ${{ vars.S3_REGION }}
|
||||
S3_BUCKET_NAME: ${{ vars.S3_BUCKET_NAME }}
|
||||
OPENTELEMETRY_LISTENER_URL: ${{ vars.OPENTELEMETRY_LISTENER_URL }}
|
||||
RATE_LIMITING_DISABLED: ${{ vars.RATE_LIMITING_DISABLED }}
|
||||
KAMAL_REGISTRY_PASSWORD: ${{ secrets.KAMAL_REGISTRY_PASSWORD }}
|
||||
DB_HOST: ${{ secrets.DB_HOST }}
|
||||
DB_USER: ${{ secrets.DB_USER }}
|
||||
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
|
||||
DB_NAME: ${{ secrets.DB_NAME }}
|
||||
REDIS_URL: ${{ secrets.REDIS_URL }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3.3.0
|
||||
bundler-cache: true
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
gem install kamal
|
||||
|
||||
- uses: webfactory/ssh-agent@v0.9.0
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Create builder
|
||||
run: docker buildx create --use --name formbricks-gh-actions-builder
|
||||
if: steps.buildx.outputs.should_create_builder == 'true'
|
||||
|
||||
- name: Push env variables to Kamal
|
||||
run: |
|
||||
kamal() { command kamal "$@" -c kamal/deploy.yml; }
|
||||
kamal env push
|
||||
|
||||
- name: Run deploy command
|
||||
run: |
|
||||
kamal() { command kamal "$@" -c kamal/deploy.yml; }
|
||||
set +e
|
||||
DEPLOY_OUTPUT=$(kamal deploy 2>&1)
|
||||
DEPLOY_EXIT_CODE=$?
|
||||
echo "$DEPLOY_OUTPUT"
|
||||
if [[ "$DEPLOY_OUTPUT" == *"container not unhealthy (healthy)"* ]]; then
|
||||
echo "Deployment reported healthy container. Considering as success."
|
||||
kamal lock release
|
||||
exit 0
|
||||
else
|
||||
exit $DEPLOY_EXIT_CODE
|
||||
fi
|
||||
shell: bash
|
||||
126
.github/workflows/kamal-setup.yml
vendored
126
.github/workflows/kamal-setup.yml
vendored
@@ -1,126 +0,0 @@
|
||||
name: Kamal Setup
|
||||
concurrency:
|
||||
group: setup-kamal
|
||||
cancel-in-progress: false
|
||||
|
||||
on:
|
||||
workflow_dispatch: # Only to be triggered when accessories are updated
|
||||
|
||||
jobs:
|
||||
Setup:
|
||||
runs-on: ubuntu-latest
|
||||
environment: production
|
||||
env:
|
||||
DOCKER_BUILDKIT: 1
|
||||
IS_FORMBRICKS_CLOUD: ${{ vars.IS_FORMBRICKS_CLOUD }}
|
||||
WEBAPP_URL: ${{ vars.WEBAPP_URL }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
MIGRATE_DATABASE_URL: ${{ secrets.MIGRATE_DATABASE_URL }}
|
||||
NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }}
|
||||
ENCRYPTION_KEY: ${{ secrets.ENCRYPTION_KEY }}
|
||||
SHORT_URL_BASE: ${{ vars.SHORT_URL_BASE }}
|
||||
MAIL_FROM: ${{ secrets.MAIL_FROM }}
|
||||
SMTP_HOST: ${{ secrets.SMTP_HOST }}
|
||||
SMTP_PORT: ${{ secrets.SMTP_PORT }}
|
||||
SMTP_USER: ${{ secrets.SMTP_USER }}
|
||||
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
|
||||
PRIVACY_URL: ${{ vars.PRIVACY_URL }}
|
||||
TERMS_URL: ${{ vars.TERMS_URL }}
|
||||
IMPRINT_URL: ${{ vars.IMPRINT_URL }}
|
||||
GITHUB_ID: ${{ secrets.FB_GITHUB_ID }}
|
||||
GITHUB_SECRET: ${{ secrets.FB_GITHUB_SECRET }}
|
||||
GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
|
||||
GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
|
||||
AZUREAD_CLIENT_ID: ${{ secrets.AZUREAD_CLIENT_ID }}
|
||||
AZUREAD_CLIENT_SECRET: ${{ secrets.AZUREAD_CLIENT_SECRET }}
|
||||
AZUREAD_TENANT_ID: ${{ secrets.AZUREAD_TENANT_ID }}
|
||||
OIDC_CLIENT_ID: ${{ secrets.OIDC_CLIENT_ID }}
|
||||
OIDC_CLIENT_SECRET: ${{ secrets.OIDC_CLIENT_SECRET }}
|
||||
OIDC_ISSUER: ${{ secrets.OIDC_ISSUER }}
|
||||
OIDC_DISPLAY_NAME: ${{ secrets.OIDC_DISPLAY_NAME }}
|
||||
OIDC_SIGNING_ALGORITHM: ${{ secrets.OIDC_SIGNING_ALGORITHM }}
|
||||
CRON_SECRET: ${{ secrets.CRON_SECRET }}
|
||||
ASSET_PREFIX_URL: ${{ vars.ASSET_PREFIX_URL }}
|
||||
NOTION_OAUTH_CLIENT_ID: ${{ secrets.NOTION_OAUTH_CLIENT_ID }}
|
||||
NOTION_OAUTH_CLIENT_SECRET: ${{ secrets.NOTION_OAUTH_CLIENT_SECRET }}
|
||||
SLACK_CLIENT_ID: ${{ secrets.SLACK_CLIENT_ID }}
|
||||
SLACK_CLIENT_SECRET: ${{ secrets.SLACK_CLIENT_SECRET }}
|
||||
STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
|
||||
STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }}
|
||||
GOOGLE_SHEETS_CLIENT_ID: ${{ secrets.GOOGLE_SHEETS_CLIENT_ID }}
|
||||
GOOGLE_SHEETS_CLIENT_SECRET: ${{ secrets.GOOGLE_SHEETS_CLIENT_SECRET }}
|
||||
GOOGLE_SHEETS_REDIRECT_URL: ${{ secrets.GOOGLE_SHEETS_REDIRECT_URL }}
|
||||
AIRTABLE_CLIENT_ID: ${{ secrets.AIRTABLE_CLIENT_ID }}
|
||||
ENTERPRISE_LICENSE_KEY: ${{ secrets.ENTERPRISE_LICENSE_KEY }}
|
||||
DEFAULT_ORGANIZATION_ID: ${{ vars.DEFAULT_ORGANIZATION_ID }}
|
||||
CUSTOMER_IO_API_KEY: ${{ secrets.CUSTOMER_IO_API_KEY }}
|
||||
CUSTOMER_IO_SITE_ID: ${{ secrets.CUSTOMER_IO_SITE_ID }}
|
||||
NEXT_PUBLIC_POSTHOG_API_KEY: ${{ vars.NEXT_PUBLIC_POSTHOG_API_KEY }}
|
||||
NEXT_PUBLIC_POSTHOG_API_HOST: ${{ vars.NEXT_PUBLIC_POSTHOG_API_HOST }}
|
||||
NEXT_PUBLIC_FORMBRICKS_API_HOST: ${{ vars.NEXT_PUBLIC_FORMBRICKS_API_HOST }}
|
||||
NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID: ${{ vars.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID }}
|
||||
NEXT_PUBLIC_FORMBRICKS_ONBOARDING_SURVEY_ID: ${{ vars.NEXT_PUBLIC_FORMBRICKS_ONBOARDING_SURVEY_ID }}
|
||||
NEXT_PUBLIC_SENTRY_DSN: ${{ vars.NEXT_PUBLIC_SENTRY_DSN }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
NODE_ENV: production
|
||||
CLOUDFLARE_EMAIL: ${{ secrets.CLOUDFLARE_EMAIL }}
|
||||
CLOUDFLARE_DNS_API_TOKEN: ${{ secrets.CLOUDFLARE_DNS_API_TOKEN }}
|
||||
S3_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }}
|
||||
S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }}
|
||||
S3_REGION: ${{ vars.S3_REGION }}
|
||||
S3_BUCKET_NAME: ${{ vars.S3_BUCKET_NAME }}
|
||||
OPENTELEMETRY_LISTENER_URL: ${{ vars.OPENTELEMETRY_LISTENER_URL }}
|
||||
RATE_LIMITING_DISABLED: ${{ vars.RATE_LIMITING_DISABLED }}
|
||||
KAMAL_REGISTRY_PASSWORD: ${{ secrets.KAMAL_REGISTRY_PASSWORD }}
|
||||
DB_HOST: ${{ secrets.DB_HOST }}
|
||||
DB_USER: ${{ secrets.DB_USER }}
|
||||
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
|
||||
DB_NAME: ${{ secrets.DB_NAME }}
|
||||
REDIS_URL: ${{ secrets.REDIS_URL }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3.3.0
|
||||
bundler-cache: true
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
gem install kamal
|
||||
|
||||
- uses: webfactory/ssh-agent@v0.9.0
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Create builder
|
||||
run: docker buildx create --use --name formbricks-gh-actions-builder
|
||||
if: steps.buildx.outputs.should_create_builder == 'true'
|
||||
|
||||
- name: Push env variables to Kamal
|
||||
run: |
|
||||
kamal() { command kamal "$@" -c kamal/deploy.yml; }
|
||||
kamal env push
|
||||
|
||||
- name: Run setup command
|
||||
run: |
|
||||
kamal() { command kamal "$@" -c kamal/deploy.yml; }
|
||||
set +e
|
||||
DEPLOY_OUTPUT=$(kamal setup 2>&1)
|
||||
DEPLOY_EXIT_CODE=$?
|
||||
echo "$DEPLOY_OUTPUT"
|
||||
if [[ "$DEPLOY_OUTPUT" == *"container not unhealthy (healthy)"* ]]; then
|
||||
echo "Deployment reported healthy container. Considering as success."
|
||||
kamal lock release
|
||||
exit 0
|
||||
else
|
||||
exit $DEPLOY_EXIT_CODE
|
||||
fi
|
||||
shell: bash
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# A sample post-deploy hook
|
||||
#
|
||||
# These environment variables are available:
|
||||
# KAMAL_RECORDED_AT
|
||||
# KAMAL_PERFORMER
|
||||
# KAMAL_VERSION
|
||||
# KAMAL_HOSTS
|
||||
# KAMAL_ROLE (if set)
|
||||
# KAMAL_DESTINATION (if set)
|
||||
# KAMAL_RUNTIME
|
||||
|
||||
echo "$KAMAL_PERFORMER deployed $KAMAL_VERSION to $KAMAL_DESTINATION in $KAMAL_RUNTIME seconds"
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Rebooted Traefik on $KAMAL_HOSTS"
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# A sample pre-build hook
|
||||
#
|
||||
# Checks:
|
||||
# 1. We have a clean checkout
|
||||
# 2. A remote is configured
|
||||
# 3. The branch has been pushed to the remote
|
||||
# 4. The version we are deploying matches the remote
|
||||
#
|
||||
# These environment variables are available:
|
||||
# KAMAL_RECORDED_AT
|
||||
# KAMAL_PERFORMER
|
||||
# KAMAL_VERSION
|
||||
# KAMAL_HOSTS
|
||||
# KAMAL_ROLE (if set)
|
||||
# KAMAL_DESTINATION (if set)
|
||||
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo "Git checkout is not clean, aborting..." >&2
|
||||
git status --porcelain >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
first_remote=$(git remote)
|
||||
|
||||
if [ -z "$first_remote" ]; then
|
||||
echo "No git remote set, aborting..." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
current_branch=$(git branch --show-current)
|
||||
|
||||
if [ -z "$current_branch" ]; then
|
||||
echo "Not on a git branch, aborting..." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
remote_head=$(git ls-remote $first_remote --tags $current_branch | cut -f1)
|
||||
|
||||
if [ -z "$remote_head" ]; then
|
||||
echo "Branch not pushed to remote, aborting..." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$KAMAL_VERSION" != "$remote_head" ]; then
|
||||
echo "Version ($KAMAL_VERSION) does not match remote HEAD ($remote_head), aborting..." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -1,47 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# A sample pre-connect check
|
||||
#
|
||||
# Warms DNS before connecting to hosts in parallel
|
||||
#
|
||||
# These environment variables are available:
|
||||
# KAMAL_RECORDED_AT
|
||||
# KAMAL_PERFORMER
|
||||
# KAMAL_VERSION
|
||||
# KAMAL_HOSTS
|
||||
# KAMAL_ROLE (if set)
|
||||
# KAMAL_DESTINATION (if set)
|
||||
# KAMAL_RUNTIME
|
||||
|
||||
hosts = ENV["KAMAL_HOSTS"].split(",")
|
||||
results = nil
|
||||
max = 3
|
||||
|
||||
elapsed = Benchmark.realtime do
|
||||
results = hosts.map do |host|
|
||||
Thread.new do
|
||||
tries = 1
|
||||
|
||||
begin
|
||||
Socket.getaddrinfo(host, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)
|
||||
rescue SocketError
|
||||
if tries < max
|
||||
puts "Retrying DNS warmup: #{host}"
|
||||
tries += 1
|
||||
sleep rand
|
||||
retry
|
||||
else
|
||||
puts "DNS warmup failed: #{host}"
|
||||
host
|
||||
end
|
||||
end
|
||||
|
||||
tries
|
||||
end
|
||||
end.map(&:value)
|
||||
end
|
||||
|
||||
retries = results.sum - hosts.size
|
||||
nopes = results.count { |r| r == max }
|
||||
|
||||
puts "Prewarmed %d DNS lookups in %.2f sec: %d retries, %d failures" % [ hosts.size, elapsed, retries, nopes ]
|
||||
@@ -1,109 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# A sample pre-deploy hook
|
||||
#
|
||||
# Checks the Github status of the build, waiting for a pending build to complete for up to 720 seconds.
|
||||
#
|
||||
# Fails unless the combined status is "success"
|
||||
#
|
||||
# These environment variables are available:
|
||||
# KAMAL_RECORDED_AT
|
||||
# KAMAL_PERFORMER
|
||||
# KAMAL_VERSION
|
||||
# KAMAL_HOSTS
|
||||
# KAMAL_COMMAND
|
||||
# KAMAL_SUBCOMMAND
|
||||
# KAMAL_ROLE (if set)
|
||||
# KAMAL_DESTINATION (if set)
|
||||
|
||||
# Only check the build status for production deployments
|
||||
if ENV["KAMAL_COMMAND"] == "rollback" || ENV["KAMAL_DESTINATION"] != "production"
|
||||
exit 0
|
||||
end
|
||||
|
||||
require "bundler/inline"
|
||||
|
||||
# true = install gems so this is fast on repeat invocations
|
||||
gemfile(true, quiet: true) do
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "octokit"
|
||||
gem "faraday-retry"
|
||||
end
|
||||
|
||||
MAX_ATTEMPTS = 72
|
||||
ATTEMPTS_GAP = 10
|
||||
|
||||
def exit_with_error(message)
|
||||
$stderr.puts message
|
||||
exit 1
|
||||
end
|
||||
|
||||
class GithubStatusChecks
|
||||
attr_reader :remote_url, :git_sha, :github_client, :combined_status
|
||||
|
||||
def initialize
|
||||
@remote_url = `git config --get remote.origin.url`.strip.delete_prefix("https://github.com/")
|
||||
@git_sha = `git rev-parse HEAD`.strip
|
||||
@github_client = Octokit::Client.new(access_token: ENV["GITHUB_TOKEN"])
|
||||
refresh!
|
||||
end
|
||||
|
||||
def refresh!
|
||||
@combined_status = github_client.combined_status(remote_url, git_sha)
|
||||
end
|
||||
|
||||
def state
|
||||
combined_status[:state]
|
||||
end
|
||||
|
||||
def first_status_url
|
||||
first_status = combined_status[:statuses].find { |status| status[:state] == state }
|
||||
first_status && first_status[:target_url]
|
||||
end
|
||||
|
||||
def complete_count
|
||||
combined_status[:statuses].count { |status| status[:state] != "pending"}
|
||||
end
|
||||
|
||||
def total_count
|
||||
combined_status[:statuses].count
|
||||
end
|
||||
|
||||
def current_status
|
||||
if total_count > 0
|
||||
"Completed #{complete_count}/#{total_count} checks, see #{first_status_url} ..."
|
||||
else
|
||||
"Build not started..."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
$stdout.sync = true
|
||||
|
||||
puts "Checking build status..."
|
||||
attempts = 0
|
||||
checks = GithubStatusChecks.new
|
||||
|
||||
begin
|
||||
loop do
|
||||
case checks.state
|
||||
when "success"
|
||||
puts "Checks passed, see #{checks.first_status_url}"
|
||||
exit 0
|
||||
when "failure"
|
||||
exit_with_error "Checks failed, see #{checks.first_status_url}"
|
||||
when "pending"
|
||||
attempts += 1
|
||||
end
|
||||
|
||||
exit_with_error "Checks are still pending, gave up after #{MAX_ATTEMPTS * ATTEMPTS_GAP} seconds" if attempts == MAX_ATTEMPTS
|
||||
|
||||
puts checks.current_status
|
||||
sleep(ATTEMPTS_GAP)
|
||||
checks.refresh!
|
||||
end
|
||||
rescue Octokit::NotFound
|
||||
exit_with_error "Build status could not be found"
|
||||
end
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Rebooting Traefik on $KAMAL_HOSTS..."
|
||||
147
kamal/README.md
147
kamal/README.md
@@ -1,147 +0,0 @@
|
||||
# Kamal Setup
|
||||
|
||||
1. Initiate a Linux instance & Get it's
|
||||
|
||||
- Public IP address
|
||||
- SSH credentials
|
||||
|
||||
2. Edit the IP address & SSH config in Kamal `deploy.yml` file.
|
||||
3. Test you SSH status with:
|
||||
|
||||
```sh
|
||||
kamal lock status
|
||||
```
|
||||
|
||||
4. If the above returns a non-zero error code, run the below:
|
||||
|
||||
```sh
|
||||
eval `ssh-agent -s`
|
||||
ssh-add <path-to-your-key>.pem
|
||||
```
|
||||
|
||||
5. Now test the SSH status again:
|
||||
|
||||
```sh
|
||||
kamal lock status
|
||||
```
|
||||
|
||||
This should now run successfully & exit with 0.
|
||||
|
||||
6. Generate a Classic Personal Access Token for `container:write` & `container:read` for your Image Registry (DockerHub, GHCR, etc.) & add it to your environment variables (.env file). Also update the Registry details in the `deploy.yml`.
|
||||
|
||||
7. If your SSH user is a non-root user, run the below command to add the user to the docker group:
|
||||
|
||||
```sh
|
||||
sudo usermod -aG docker ${USER}
|
||||
```
|
||||
|
||||
> Note: The above needs to be ran on the Cloud VM. There is an open Issue on Kamal for the same [here](https://github.com/basecamp/kamal/issues/405)
|
||||
|
||||
> Run the below for SSL config the first time
|
||||
|
||||
```sh
|
||||
sudo mkdir -p /letsencrypt && sudo touch /letsencrypt/acme.json && sudo chmod 600 /letsencrypt/acme.json
|
||||
```
|
||||
|
||||
> Run this command to create the private bridge network used by kamal to reference containers on one instance
|
||||
|
||||
```sh
|
||||
docker network create -d bridge private
|
||||
```
|
||||
|
||||
8. Make sure you have docker buildx locally on your machine where you run the kamal CLI from!
|
||||
|
||||
9. Voila! You are all set to deploy your application to the cloud with Kamal! 🚀
|
||||
|
||||
```sh
|
||||
kamal setup -c kamal/deploy.yml
|
||||
```
|
||||
|
||||
This will setup the cloud VM with all the necessary tools & dependencies to run your application.
|
||||
|
||||
> Make sure to run `kamal env push` before a `kamal deploy` to push the latest environment variables to the cloud VM.
|
||||
|
||||
### Debugging for Kamal
|
||||
|
||||
- If you run into an error such as:
|
||||
|
||||
```sh
|
||||
failed to solve: cannot copy to non-directory:
|
||||
```
|
||||
|
||||
Then simply run `pnpm clean` & try again.
|
||||
|
||||
- Make sure your Database accepts connection from the cloud VM. You can do this by adding the VM's IP address to the `Allowed Hosts` in your Database settings.
|
||||
|
||||
- If you get an error such as:
|
||||
|
||||
```sh
|
||||
Lock failed: failed to acquire lock: lockfile already exists
|
||||
```
|
||||
|
||||
Then simply run `kamal lock release -c kamal/deploy.yml` & try again.
|
||||
|
||||
- If you run into:
|
||||
|
||||
```sh
|
||||
No config found
|
||||
```
|
||||
|
||||
Then simply add the following at the end of the command: `-c kamal/deploy.yml`
|
||||
|
||||
For further details, refer to the [Kamal Documentation](https://kamal-deploy.org/docs/configuration) or reach out to us on our [Discord](https://formbricks.com/discord)
|
||||
|
||||
# Rollback to a Previous Version
|
||||
|
||||
```sh
|
||||
kamal rollback [git_commit_hash_to_rollback_to] -c kamal/deploy.yml
|
||||
```
|
||||
|
||||
## View Formbricks Server logs with Kamal
|
||||
|
||||
```sh
|
||||
kamal app logs -c kamal/deploy.yml
|
||||
```
|
||||
|
||||
# Configure Memory Metrics on AWS using CW Agent
|
||||
|
||||
1. Install the CloudWatch Agent on the EC2 instance
|
||||
|
||||
```sh
|
||||
wget https://amazoncloudwatch-agent.s3.amazonaws.com/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
|
||||
sudo dpkg -i -E ./amazon-cloudwatch-agent.deb
|
||||
```
|
||||
|
||||
2. Attach the IAM role of `CloudWatchFullAccessv2` to the EC2 instance
|
||||
|
||||
3. Edit the CloudWatch Agent config file
|
||||
|
||||
```sh
|
||||
sudo nano /opt/aws/amazon-cloudwatch-agent/bin/config.json
|
||||
```
|
||||
|
||||
4. Add the below config to the `config.json` file
|
||||
|
||||
```json
|
||||
{
|
||||
"metrics": {
|
||||
"metrics_collected": {
|
||||
"mem": {
|
||||
"measurement": ["mem_used_percent"],
|
||||
"metrics_collection_interval": 60
|
||||
}
|
||||
},
|
||||
"append_dimensions": {
|
||||
"InstanceId": "${aws:InstanceId}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
5. Fetch the config & start the CloudWatch Agent
|
||||
|
||||
```sh
|
||||
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json -s
|
||||
```
|
||||
|
||||
6. Now go to Cloudwatch > Metrics > All Metrics > Custom Namespaces > CWAgent > InstanceId > {InstanceId} > Tick the Checkbox next to it > Graph above will be updated
|
||||
154
kamal/deploy.yml
154
kamal/deploy.yml
@@ -1,154 +0,0 @@
|
||||
# Name of your application. Used to uniquely configure containers.
|
||||
service: formbricks-kamal
|
||||
|
||||
# Name of the container image.
|
||||
image: formbricks/formbricks-cloud
|
||||
|
||||
# Deploy to these servers.
|
||||
servers:
|
||||
web: # Use a named role, so it can be used as entrypoint by Traefik
|
||||
hosts:
|
||||
- 18.196.187.144
|
||||
- 18.196.172.27
|
||||
- 35.157.124.188
|
||||
- 18.199.207.103
|
||||
- ec2-18-194-217-29.eu-central-1.compute.amazonaws.com
|
||||
- ec2-3-64-56-61.eu-central-1.compute.amazonaws.com
|
||||
- ec2-3-122-60-81.eu-central-1.compute.amazonaws.com
|
||||
labels:
|
||||
traefik.http.routers.formbricks-kamal.entrypoints: web
|
||||
options:
|
||||
network: "private"
|
||||
|
||||
# Credentials for your image host.
|
||||
registry:
|
||||
# Specify the registry server, if you're not using Docker Hub
|
||||
server: ghcr.io
|
||||
username: mattinannt
|
||||
# Always use an access token rather than real password when possible.
|
||||
password:
|
||||
- KAMAL_REGISTRY_PASSWORD
|
||||
|
||||
# Inject ENV variables into containers (secrets come from .env).
|
||||
# Remember to run `kamal env push` after making changes!
|
||||
env:
|
||||
clear:
|
||||
REDIS_HTTP_URL: http://formbricks-kamal-webdis:7379
|
||||
secret:
|
||||
- IS_FORMBRICKS_CLOUD
|
||||
- WEBAPP_URL
|
||||
- DATABASE_URL
|
||||
- MIGRATE_DATABASE_URL
|
||||
- NEXTAUTH_SECRET
|
||||
- ENCRYPTION_KEY
|
||||
- SHORT_URL_BASE
|
||||
- MAIL_FROM
|
||||
- SMTP_HOST
|
||||
- SMTP_PORT
|
||||
- SMTP_USER
|
||||
- SMTP_PASSWORD
|
||||
- PRIVACY_URL
|
||||
- TERMS_URL
|
||||
- IMPRINT_URL
|
||||
- GITHUB_ID
|
||||
- GITHUB_SECRET
|
||||
- GOOGLE_CLIENT_ID
|
||||
- GOOGLE_CLIENT_SECRET
|
||||
- AZUREAD_CLIENT_ID
|
||||
- AZUREAD_CLIENT_SECRET
|
||||
- AZUREAD_TENANT_ID
|
||||
- OIDC_CLIENT_ID
|
||||
- OIDC_CLIENT_SECRET
|
||||
- OIDC_ISSUER
|
||||
- OIDC_DISPLAY_NAME
|
||||
- OIDC_SIGNING_ALGORITHM
|
||||
- CRON_SECRET
|
||||
- ASSET_PREFIX_URL
|
||||
- NOTION_OAUTH_CLIENT_ID
|
||||
- NOTION_OAUTH_CLIENT_SECRET
|
||||
- SLACK_CLIENT_ID
|
||||
- SLACK_CLIENT_SECRET
|
||||
- STRIPE_SECRET_KEY
|
||||
- STRIPE_WEBHOOK_SECRET
|
||||
- GOOGLE_SHEETS_CLIENT_ID
|
||||
- GOOGLE_SHEETS_CLIENT_SECRET
|
||||
- GOOGLE_SHEETS_REDIRECT_URL
|
||||
- AIRTABLE_CLIENT_ID
|
||||
- ENTERPRISE_LICENSE_KEY
|
||||
- DEFAULT_ORGANIZATION_ID
|
||||
- CUSTOMER_IO_API_KEY
|
||||
- CUSTOMER_IO_SITE_ID
|
||||
- NEXT_PUBLIC_POSTHOG_API_KEY
|
||||
- NEXT_PUBLIC_POSTHOG_API_HOST
|
||||
- NEXT_PUBLIC_FORMBRICKS_API_HOST
|
||||
- NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID
|
||||
- NEXT_PUBLIC_FORMBRICKS_ONBOARDING_SURVEY_ID
|
||||
- OPENTELEMETRY_LISTENER_URL
|
||||
- NEXT_PUBLIC_SENTRY_DSN
|
||||
- CLOUDFLARE_EMAIL
|
||||
- CLOUDFLARE_DNS_API_TOKEN
|
||||
- S3_ACCESS_KEY
|
||||
- S3_SECRET_KEY
|
||||
- S3_REGION
|
||||
- S3_BUCKET_NAME
|
||||
- RATE_LIMITING_DISABLED
|
||||
- DB_HOST
|
||||
- DB_USER
|
||||
- DB_PASSWORD
|
||||
- DB_NAME
|
||||
- SENTRY_AUTH_TOKEN
|
||||
- REDIS_URL
|
||||
|
||||
# Use a different ssh user than root
|
||||
ssh:
|
||||
user: ubuntu
|
||||
|
||||
# Configure builder setup.
|
||||
builder:
|
||||
context: .
|
||||
dockerfile: ./apps/web/Dockerfile
|
||||
args:
|
||||
- NEXT_PUBLIC_POSTHOG_API_KEY
|
||||
- NEXT_PUBLIC_POSTHOG_API_HOST
|
||||
- NEXT_PUBLIC_FORMBRICKS_API_HOST
|
||||
- NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID
|
||||
- NEXT_PUBLIC_FORMBRICKS_ONBOARDING_SURVEY_ID
|
||||
- NEXT_PUBLIC_SENTRY_DSN
|
||||
- ASSET_PREFIX_URL
|
||||
- SENTRY_AUTH_TOKEN
|
||||
multiarch: false
|
||||
cache:
|
||||
type: registry
|
||||
options: mode=max,image-manifest=true,oci-mediatypes=true
|
||||
|
||||
traefik:
|
||||
args:
|
||||
entryPoints.web.address: ":80"
|
||||
options:
|
||||
network: "private"
|
||||
|
||||
# Use accessory services (secrets come from .env).
|
||||
accessories:
|
||||
webdis:
|
||||
image: nicolas/webdis:0.1.22
|
||||
roles:
|
||||
- web
|
||||
env:
|
||||
secret:
|
||||
- REDIS_URL
|
||||
cmd: >
|
||||
/bin/sh -c '
|
||||
REDIS_HOST=$(echo $REDIS_URL | awk -F "[:/]" "{print \$4}") &&
|
||||
wget -O /usr/local/bin/webdis.json https://github.com/nicolasff/webdis/raw/0.1.22/webdis.json &&
|
||||
sed -i "s/\"redis_host\":.*/\"redis_host\": \"$REDIS_HOST\",/" /usr/local/bin/webdis.json &&
|
||||
sed -i "s/\"logfile\":.*/\"logfile\": \"\/dev\/stderr\"/" /usr/local/bin/webdis.json &&
|
||||
/usr/local/bin/webdis /usr/local/bin/webdis.json'
|
||||
port: 7379
|
||||
options:
|
||||
network: "private"
|
||||
|
||||
healthcheck:
|
||||
path: /health
|
||||
port: 3000
|
||||
max_attempts: 15
|
||||
interval: 20s
|
||||
Reference in New Issue
Block a user