diff --git a/.deploy/k8s/k8s-manifest.dev.yaml b/.deploy/k8s/k8s-manifest.dev.yaml new file mode 100644 index 000000000..f7416b2ec --- /dev/null +++ b/.deploy/k8s/k8s-manifest.dev.yaml @@ -0,0 +1,110 @@ +--- +kind: Service +apiVersion: v1 +metadata: + name: ever-teams-dev-lb + annotations: + service.beta.kubernetes.io/do-loadbalancer-name: 'demo.ever.team' + service.beta.kubernetes.io/do-loadbalancer-protocol: 'http2' + service.beta.kubernetes.io/do-loadbalancer-http2-ports: '443' + # Replace with your Certificate Id. You can get a list of Ids with 'doctl compute certificate list' + service.beta.kubernetes.io/do-loadbalancer-certificate-id: '0c4085c5-9692-4320-86f3-34f52b775a88' + service.beta.kubernetes.io/do-loadbalancer-size-slug: 'lb-small' + service.beta.kubernetes.io/do-loadbalancer-hostname: 'demo.ever.team' +spec: + type: LoadBalancer + selector: + app: ever-teams-dev-webapp + ports: + - name: http + protocol: TCP + port: 443 + targetPort: 3000 + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ever-teams-dev-webapp +spec: + replicas: 1 + selector: + matchLabels: + app: ever-teams-dev-webapp + template: + metadata: + labels: + app: ever-teams-dev-webapp + spec: + containers: + - name: ever-teams-dev-webapp + image: registry.digitalocean.com/ever/ever-teams-webapp-dev:latest + env: + - name: DEMO + value: 'true' + - name: NEXT_PUBLIC_SENTRY_DNS + value: '$NEXT_PUBLIC_SENTRY_DNS' + - name: SENTRY_DSN + value: '$SENTRY_DSN' + - name: NEXT_PUBLIC_JITSU_BROWSER_WRITE_KEY + value: '$NEXT_PUBLIC_JITSU_BROWSER_WRITE_KEY' + - name: NEXT_PUBLIC_JITSU_BROWSER_URL + value: '$NEXT_PUBLIC_JITSU_BROWSER_URL' + - name: SENTRY_AUTH_TOKEN + value: '$SENTRY_AUTH_TOKEN' + - name: NEXT_PUBLIC_CHATWOOT_API_KEY + value: '$NEXT_PUBLIC_CHATWOOT_API_KEY' + - name: NEXT_PUBLIC_SENTRY_DEBUG + value: '$NEXT_PUBLIC_SENTRY_DEBUG' + - name: SENTRY_PROJECT + value: '$SENTRY_PROJECT' + - name: SENTRY_ORG + value: '$SENTRY_ORG' + - name: SMTP_FROM_ADDRESS + value: '$SMTP_FROM_ADDRESS' + - name: JITSU_SERVER_WRITE_KEY + value: '$JITSU_SERVER_WRITE_KEY' + - name: JITSU_SERVER_URL + value: '$JITSU_SERVER_URL' + - name: NEXT_PUBLIC_COOKIE_DOMAINS + value: '$NEXT_PUBLIC_COOKIE_DOMAINS' + - name: NEXT_PUBLIC_BOARD_FIREBASE_CONFIG + value: '$NEXT_PUBLIC_BOARD_FIREBASE_CONFIG' + - name: NEXT_PUBLIC_BOARD_BACKEND_POST_URL + value: '$NEXT_PUBLIC_BOARD_BACKEND_POST_URL' + - name: NEXT_PUBLIC_BOARD_APP_DOMAIN + value: '$NEXT_PUBLIC_BOARD_APP_DOMAIN' + - name: MEET_JWT_APP_SECRET + value: '$MEET_JWT_APP_SECRET' + - name: MEET_JWT_APP_ID + value: '$MEET_JWT_APP_ID' + - name: NEXT_PUBLIC_MEET_DOMAIN + value: '$NEXT_PUBLIC_MEET_DOMAIN' + - name: GAUZY_API_SERVER_URL + value: '$GAUZY_API_SERVER_URL' + - name: NEXT_PUBLIC_GAUZY_API_SERVER_URL + value: '$NEXT_PUBLIC_GAUZY_API_SERVER_URL' + - name: MAILCHIMP_LIST_ID + value: '$MAILCHIMP_LIST_ID' + - name: MAILCHIMP_API_KEY + value: '$MAILCHIMP_API_KEY' + - name: POSTMARK_SERVER_API_TOKEN + value: '$POSTMARK_SERVER_API_TOKEN' + - name: NEXT_PUBLIC_GA_MEASUREMENT_ID + value: '$NEXT_PUBLIC_GA_MEASUREMENT_ID' + - name: SMTP_HOST + value: '$SMTP_HOST' + - name: SMTP_SECURE + value: '$SMTP_SECURE' + - name: SMTP_USERNAME + value: '$SMTP_USERNAME' + - name: SMTP_PASSWORD + value: '$SMTP_PASSWORD' + - name: CAPTCHA_SECRET_KEY + value: '$CAPTCHA_SECRET_KEY' + - name: NEXT_PUBLIC_CAPTCHA_SITE_KEY + value: '$NEXT_PUBLIC_CAPTCHA_SITE_KEY' + + ports: + - containerPort: 3000 + protocol: TCP diff --git a/.deploy/k8s/k8s-manifest.prod.yaml b/.deploy/k8s/k8s-manifest.prod.yaml new file mode 100644 index 000000000..1b81fffe9 --- /dev/null +++ b/.deploy/k8s/k8s-manifest.prod.yaml @@ -0,0 +1,110 @@ +--- +kind: Service +apiVersion: v1 +metadata: + name: ever-teams-prod-lb + annotations: + service.beta.kubernetes.io/do-loadbalancer-name: 'app.ever.team' + service.beta.kubernetes.io/do-loadbalancer-protocol: 'http2' + service.beta.kubernetes.io/do-loadbalancer-http2-ports: '443' + # Replace with your Certificate Id. You can get a list of Ids with 'doctl compute certificate list' + service.beta.kubernetes.io/do-loadbalancer-certificate-id: '0c4085c5-9692-4320-86f3-34f52b775a88' + service.beta.kubernetes.io/do-loadbalancer-size-slug: 'lb-small' + service.beta.kubernetes.io/do-loadbalancer-hostname: 'app.ever.team' +spec: + type: LoadBalancer + selector: + app: ever-teams-prod-webapp + ports: + - name: http + protocol: TCP + port: 443 + targetPort: 3000 + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ever-teams-prod-webapp +spec: + replicas: 1 + selector: + matchLabels: + app: ever-teams-prod-webapp + template: + metadata: + labels: + app: ever-teams-prod-webapp + spec: + containers: + - name: ever-teams-prod-webapp + image: registry.digitalocean.com/ever/ever-teams-webapp-prod:latest + env: + - name: DEMO + value: 'true' + - name: NEXT_PUBLIC_SENTRY_DNS + value: '$NEXT_PUBLIC_SENTRY_DNS' + - name: SENTRY_DSN + value: '$SENTRY_DSN' + - name: NEXT_PUBLIC_JITSU_BROWSER_WRITE_KEY + value: '$NEXT_PUBLIC_JITSU_BROWSER_WRITE_KEY' + - name: NEXT_PUBLIC_JITSU_BROWSER_URL + value: '$NEXT_PUBLIC_JITSU_BROWSER_URL' + - name: SENTRY_AUTH_TOKEN + value: '$SENTRY_AUTH_TOKEN' + - name: NEXT_PUBLIC_CHATWOOT_API_KEY + value: '$NEXT_PUBLIC_CHATWOOT_API_KEY' + - name: NEXT_PUBLIC_SENTRY_DEBUG + value: '$NEXT_PUBLIC_SENTRY_DEBUG' + - name: SENTRY_PROJECT + value: '$SENTRY_PROJECT' + - name: SENTRY_ORG + value: '$SENTRY_ORG' + - name: SMTP_FROM_ADDRESS + value: '$SMTP_FROM_ADDRESS' + - name: JITSU_SERVER_WRITE_KEY + value: '$JITSU_SERVER_WRITE_KEY' + - name: JITSU_SERVER_URL + value: '$JITSU_SERVER_URL' + - name: NEXT_PUBLIC_COOKIE_DOMAINS + value: '$NEXT_PUBLIC_COOKIE_DOMAINS' + - name: NEXT_PUBLIC_BOARD_FIREBASE_CONFIG + value: '$NEXT_PUBLIC_BOARD_FIREBASE_CONFIG' + - name: NEXT_PUBLIC_BOARD_BACKEND_POST_URL + value: '$NEXT_PUBLIC_BOARD_BACKEND_POST_URL' + - name: NEXT_PUBLIC_BOARD_APP_DOMAIN + value: '$NEXT_PUBLIC_BOARD_APP_DOMAIN' + - name: MEET_JWT_APP_SECRET + value: '$MEET_JWT_APP_SECRET' + - name: MEET_JWT_APP_ID + value: '$MEET_JWT_APP_ID' + - name: NEXT_PUBLIC_MEET_DOMAIN + value: '$NEXT_PUBLIC_MEET_DOMAIN' + - name: GAUZY_API_SERVER_URL + value: '$GAUZY_API_SERVER_URL' + - name: NEXT_PUBLIC_GAUZY_API_SERVER_URL + value: '$NEXT_PUBLIC_GAUZY_API_SERVER_URL' + - name: MAILCHIMP_LIST_ID + value: '$MAILCHIMP_LIST_ID' + - name: MAILCHIMP_API_KEY + value: '$MAILCHIMP_API_KEY' + - name: POSTMARK_SERVER_API_TOKEN + value: '$POSTMARK_SERVER_API_TOKEN' + - name: NEXT_PUBLIC_GA_MEASUREMENT_ID + value: '$NEXT_PUBLIC_GA_MEASUREMENT_ID' + - name: SMTP_HOST + value: '$SMTP_HOST' + - name: SMTP_SECURE + value: '$SMTP_SECURE' + - name: SMTP_USERNAME + value: '$SMTP_USERNAME' + - name: SMTP_PASSWORD + value: '$SMTP_PASSWORD' + - name: CAPTCHA_SECRET_KEY + value: '$CAPTCHA_SECRET_KEY' + - name: NEXT_PUBLIC_CAPTCHA_SITE_KEY + value: '$NEXT_PUBLIC_CAPTCHA_SITE_KEY' + + ports: + - containerPort: 3000 + protocol: TCP diff --git a/.github/workflows/deploy-do-dev.yml b/.github/workflows/deploy-do-dev.yml new file mode 100644 index 000000000..018805ecd --- /dev/null +++ b/.github/workflows/deploy-do-dev.yml @@ -0,0 +1,73 @@ +name: Deploy to DigitalOcean Dev + +on: + workflow_run: + workflows: ['Build and Publish Docker Images Dev'] + branches: [develop] + types: + - completed + +jobs: + deploy-demo: + runs-on: ubuntu-latest + + environment: dev + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install doctl + uses: digitalocean/action-doctl@v2 + with: + token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }} + + - name: Log in to DigitalOcean Container Registry with short-lived credentials + run: doctl registry login --expiry-seconds 600 + + - name: Save DigitalOcean kubeconfig with short-lived credentials + run: doctl kubernetes cluster kubeconfig save --expiry-seconds 600 k8s-gauzy + + - name: Apply k8s manifests changes in DigitalOcean k8s cluster (if any) + run: | + envsubst < $GITHUB_WORKSPACE/.deploy/k8s/k8s-manifest.dev.yaml | kubectl --context do-sfo2-k8s-gauzy apply -f - + env: + # below we are using GitHub secrets for both frontend and backend + CLOUD_PROVIDER: 'DO' + NEXT_PUBLIC_SENTRY_DNS: '${{ secrets.NEXT_PUBLIC_SENTRY_DNS }}' + SENTRY_DSN: '${{ secrets.SENTRY_DSN }}' + NEXT_PUBLIC_JITSU_BROWSER_WRITE_KEY: '${{ secrets.NEXT_PUBLIC_JITSU_BROWSER_WRITE_KEY }}' + NEXT_PUBLIC_JITSU_BROWSER_URL: '${{ secrets.NEXT_PUBLIC_JITSU_BROWSER_URL }}' + SENTRY_AUTH_TOKEN: '${{ secrets.SENTRY_AUTH_TOKEN }}' + NEXT_PUBLIC_CHATWOOT_API_KEY: '${{ secrets.NEXT_PUBLIC_CHATWOOT_API_KEY }}' + NEXT_PUBLIC_SENTRY_DEBUG: '${{ secrets.NEXT_PUBLIC_SENTRY_DEBUG }}' + SENTRY_PROJECT: '${{ secrets.SENTRY_PROJECT }}' + SENTRY_ORG: '${{ secrets.SENTRY_ORG }}' + SMTP_FROM_ADDRESS: '${{ secrets.SMTP_FROM_ADDRESS }}' + JITSU_SERVER_WRITE_KEY: '${{ secrets.JITSU_SERVER_WRITE_KEY }}' + JITSU_SERVER_URL: '${{ secrets.JITSU_SERVER_URL }}' + NEXT_PUBLIC_COOKIE_DOMAINS: '${{ secrets.NEXT_PUBLIC_COOKIE_DOMAINS }}' + NEXT_PUBLIC_BOARD_FIREBASE_CONFIG: '${{ secrets.NEXT_PUBLIC_BOARD_FIREBASE_CONFIG }}' + NEXT_PUBLIC_BOARD_BACKEND_POST_URL: '${{ secrets.NEXT_PUBLIC_BOARD_BACKEND_POST_URL }}' + NEXT_PUBLIC_BOARD_APP_DOMAIN: '${{ secrets.NEXT_PUBLIC_BOARD_APP_DOMAIN }}' + MEET_JWT_APP_SECRET: '${{ secrets.MEET_JWT_APP_SECRET }}' + MEET_JWT_APP_ID: '${{ secrets.MEET_JWT_APP_ID }}' + NEXT_PUBLIC_MEET_DOMAIN: '${{ secrets.NEXT_PUBLIC_MEET_DOMAIN }}' + GAUZY_API_SERVER_URL: '${{ secrets.GAUZY_API_SERVER_URL }}' + NEXT_PUBLIC_GAUZY_API_SERVER_URL: '${{ secrets.NEXT_PUBLIC_GAUZY_API_SERVER_URL }}' + MAILCHIMP_LIST_ID: '${{ secrets.MAILCHIMP_LIST_ID }}' + MAILCHIMP_API_KEY: '${{ secrets.MAILCHIMP_API_KEY }}' + POSTMARK_SERVER_API_TOKEN: '${{ secrets.POSTMARK_SERVER_API_TOKEN }}' + NEXT_PUBLIC_GA_MEASUREMENT_ID: '${{ secrets.NEXT_PUBLIC_GA_MEASUREMENT_ID }}' + SMTP_HOST: '${{ secrets.SMTP_HOST }}' + SMTP_SECURE: '${{ secrets.SMTP_SECURE }}' + SMTP_USERNAME: '${{ secrets.SMTP_USERNAME }}' + SMTP_PASSWORD: '${{ secrets.SMTP_PASSWORD }}' + CAPTCHA_SECRET_KEY: '${{ secrets.CAPTCHA_SECRET_KEY }}' + NEXT_PUBLIC_CAPTCHA_SITE_KEY: '${{ secrets.NEXT_PUBLIC_CAPTCHA_SITE_KEY }}' + + # we need this step because for now we just use :latest tag + # note: for production we will use different strategy later + - name: Restart Pods to pick up :latest tag version + run: | + kubectl --context do-sfo2-k8s-gauzy rollout restart deployment/ever-teams-dev-webapp diff --git a/.github/workflows/deploy-do-prod.yml b/.github/workflows/deploy-do-prod.yml new file mode 100644 index 000000000..f84988474 --- /dev/null +++ b/.github/workflows/deploy-do-prod.yml @@ -0,0 +1,73 @@ +name: Deploy to DigitalOcean Prod + +on: + workflow_run: + workflows: ['Build and Publish Docker Images Prod'] + branches: [main] + types: + - completed + +jobs: + deploy-demo: + runs-on: ubuntu-latest + + environment: prod + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install doctl + uses: digitalocean/action-doctl@v2 + with: + token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }} + + - name: Log in to DigitalOcean Container Registry with short-lived credentials + run: doctl registry login --expiry-seconds 600 + + - name: Save DigitalOcean kubeconfig with short-lived credentials + run: doctl kubernetes cluster kubeconfig save --expiry-seconds 600 k8s-gauzy + + - name: Apply k8s manifests changes in DigitalOcean k8s cluster (if any) + run: | + envsubst < $GITHUB_WORKSPACE/.deploy/k8s/k8s-manifest.prod.yaml | kubectl --context do-sfo2-k8s-gauzy apply -f - + env: + # below we are using GitHub secrets for both frontend and backend + CLOUD_PROVIDER: 'DO' + NEXT_PUBLIC_SENTRY_DNS: '${{ secrets.NEXT_PUBLIC_SENTRY_DNS }}' + SENTRY_DSN: '${{ secrets.SENTRY_DSN }}' + NEXT_PUBLIC_JITSU_BROWSER_WRITE_KEY: '${{ secrets.NEXT_PUBLIC_JITSU_BROWSER_WRITE_KEY }}' + NEXT_PUBLIC_JITSU_BROWSER_URL: '${{ secrets.NEXT_PUBLIC_JITSU_BROWSER_URL }}' + SENTRY_AUTH_TOKEN: '${{ secrets.SENTRY_AUTH_TOKEN }}' + NEXT_PUBLIC_CHATWOOT_API_KEY: '${{ secrets.NEXT_PUBLIC_CHATWOOT_API_KEY }}' + NEXT_PUBLIC_SENTRY_DEBUG: '${{ secrets.NEXT_PUBLIC_SENTRY_DEBUG }}' + SENTRY_PROJECT: '${{ secrets.SENTRY_PROJECT }}' + SENTRY_ORG: '${{ secrets.SENTRY_ORG }}' + SMTP_FROM_ADDRESS: '${{ secrets.SMTP_FROM_ADDRESS }}' + JITSU_SERVER_WRITE_KEY: '${{ secrets.JITSU_SERVER_WRITE_KEY }}' + JITSU_SERVER_URL: '${{ secrets.JITSU_SERVER_URL }}' + NEXT_PUBLIC_COOKIE_DOMAINS: '${{ secrets.NEXT_PUBLIC_COOKIE_DOMAINS }}' + NEXT_PUBLIC_BOARD_FIREBASE_CONFIG: '${{ secrets.NEXT_PUBLIC_BOARD_FIREBASE_CONFIG }}' + NEXT_PUBLIC_BOARD_BACKEND_POST_URL: '${{ secrets.NEXT_PUBLIC_BOARD_BACKEND_POST_URL }}' + NEXT_PUBLIC_BOARD_APP_DOMAIN: '${{ secrets.NEXT_PUBLIC_BOARD_APP_DOMAIN }}' + MEET_JWT_APP_SECRET: '${{ secrets.MEET_JWT_APP_SECRET }}' + MEET_JWT_APP_ID: '${{ secrets.MEET_JWT_APP_ID }}' + NEXT_PUBLIC_MEET_DOMAIN: '${{ secrets.NEXT_PUBLIC_MEET_DOMAIN }}' + GAUZY_API_SERVER_URL: '${{ secrets.GAUZY_API_SERVER_URL }}' + NEXT_PUBLIC_GAUZY_API_SERVER_URL: '${{ secrets.NEXT_PUBLIC_GAUZY_API_SERVER_URL }}' + MAILCHIMP_LIST_ID: '${{ secrets.MAILCHIMP_LIST_ID }}' + MAILCHIMP_API_KEY: '${{ secrets.MAILCHIMP_API_KEY }}' + POSTMARK_SERVER_API_TOKEN: '${{ secrets.POSTMARK_SERVER_API_TOKEN }}' + NEXT_PUBLIC_GA_MEASUREMENT_ID: '${{ secrets.NEXT_PUBLIC_GA_MEASUREMENT_ID }}' + SMTP_HOST: '${{ secrets.SMTP_HOST }}' + SMTP_SECURE: '${{ secrets.SMTP_SECURE }}' + SMTP_USERNAME: '${{ secrets.SMTP_USERNAME }}' + SMTP_PASSWORD: '${{ secrets.SMTP_PASSWORD }}' + CAPTCHA_SECRET_KEY: '${{ secrets.CAPTCHA_SECRET_KEY }}' + NEXT_PUBLIC_CAPTCHA_SITE_KEY: '${{ secrets.NEXT_PUBLIC_CAPTCHA_SITE_KEY }}' + + # we need this step because for now we just use :latest tag + # note: for production we will use different strategy later + - name: Restart Pods to pick up :latest tag version + run: | + kubectl --context do-sfo2-k8s-gauzy rollout restart deployment/ever-teams-prod-webapp diff --git a/.github/workflows/docker-build-publish-dev.yml b/.github/workflows/docker-build-publish-dev.yml new file mode 100644 index 000000000..a62864c77 --- /dev/null +++ b/.github/workflows/docker-build-publish-dev.yml @@ -0,0 +1,82 @@ +name: Build and Publish Docker Images Dev + +on: + push: + branches: [develop] + +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + ever-teams-webapp: + runs-on: buildjet-8vcpu-ubuntu-2204 + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build and push + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + load: true + tags: | + ghcr.io/ever-co/ever-teams-webapp-dev:latest + everco/ever-teams-webapp-dev:latest + registry.digitalocean.com/ever/ever-teams-webapp-dev:latest + ${{ secrets.CW_DOCKER_REGISTRY }}/ever-co/ever-teams-webapp-dev:latest + cache-from: type=registry,ref=everco/ever-teams-webapp-dev:latest + cache-to: type=inline + build-args: | + NODE_ENV=development + + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Push to Docker Hub Registry + run: | + docker push everco/ever-teams-webapp-dev:latest + + - name: Install doctl + uses: digitalocean/action-doctl@v2 + with: + token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }} + + - name: Log in to DigitalOcean Container Registry with short-lived credentials + run: doctl registry login --expiry-seconds 3600 + + - name: Push to DigitalOcean Registry + run: | + docker push registry.digitalocean.com/ever/ever-teams-webapp-dev:latest + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GH_TOKEN }} + + - name: Push to Github Registry + run: | + docker push ghcr.io/ever-co/ever-teams-webapp-dev:latest + + - name: Login to CW Container Registry + uses: docker/login-action@v2 + with: + registry: ${{ secrets.CW_DOCKER_REGISTRY }} + username: ${{ secrets.CW_DOCKER_USER }} + password: ${{ secrets.CW_DOCKER_USER_PASSWORD }} + + - name: Push to CW Registry + run: | + docker push ${{ secrets.CW_DOCKER_REGISTRY }}/ever-co/ever-teams-webapp-dev:latest diff --git a/.github/workflows/docker-build-publish.yml b/.github/workflows/docker-build-publish-prod.yml similarity index 97% rename from .github/workflows/docker-build-publish.yml rename to .github/workflows/docker-build-publish-prod.yml index 9888f0b7f..6addc3242 100644 --- a/.github/workflows/docker-build-publish.yml +++ b/.github/workflows/docker-build-publish-prod.yml @@ -34,6 +34,8 @@ jobs: ${{ secrets.CW_DOCKER_REGISTRY }}/ever-co/ever-teams-webapp:latest cache-from: type=registry,ref=everco/ever-teams-webapp:latest cache-to: type=inline + build-args: | + NODE_ENV=production - name: Login to DockerHub uses: docker/login-action@v2