diff --git a/.github/workflows/docker-ci b/.github/workflows/docker-ci new file mode 100755 index 00000000000000..4d4c932b12cbee --- /dev/null +++ b/.github/workflows/docker-ci @@ -0,0 +1,391 @@ +--- +name: Docker CI + +on: + push: + branches: + - main + + pull_request: + branches: + - main + types: [opened, synchronize, reopened] + + pull_request_target: + branches: + - main + types: [opened, synchronize, reopened] + + workflow_dispatch: + + +jobs: +# # FIRST JOB ####################################################################### +# builds a test image and push to GHCR which will subequently be pulled by integration-test +# and trivy scan jobs for their respective actions + build-test-image: + name: Build Image for Testing + runs-on: ubuntu-latest + permissions: + contents: write + packages: write + + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to ghcr.io registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Extract metadata for the Docker image + id: docker_meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + tags: | + ${{ github.run_id }} + + - name: Build and Push to GHCR + uses: docker/build-push-action@v5 + with: + file: infra/docker/web/Dockerfile + push: true + tags: ${{ steps.docker_meta.outputs.tags }} + cache-to: | + type=gha,scope=main-base,mode=max + cache-from: | + type=gha,scope=main-base + platforms: linux/amd64 + + + # # # # # NEXT JOB ####################################################################### +# builds and runs unit test specified in the repo by targeting unit-test layer of multistage docker build +# however uses the cache from test image to increase speed + unit-test: + name: unit test in docker + needs: [build-test-image] + runs-on: ubuntu-latest + permissions: + packages: read + contents: read + + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to ghcr.io registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Build and unit-test + uses: docker/build-push-action@v5 + with: + file: infra/docker/web/Dockerfile + target: unit-test + push: false + cache-to: | + type=gha,scope=main-test,mode=max + cache-from: | + type=gha,scope=main-base + type=gha,scope=main-test + platforms: linux/amd64 + + + # # # # # NEXT JOB ####################################################################### + # pulls test image from GHCR and run integration test in docker compose testing ability of the built app + # to succesfully connect to postgres db + integration-test: + name: Integration test in Compose + needs: [build-test-image] + runs-on: ubuntu-latest + permissions: + packages: read + contents: read + + steps: + - name: checkout + uses: actions/checkout@v4 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to ghcr.io registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Downcase repo name + run: | + echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV} + + - name: Test healthcheck in Docker Compose + run: | + export TESTING_IMAGE=ghcr.io/${REPO}:"$GITHUB_RUN_ID" + echo Testing image: "$TESTING_IMAGE" + + docker compose -f ./infra/docker/web/integration-test/compose.yml up -d calcom + + echo "Waiting for the server to be healthy..." + sleep 60s + + curl --fail http://localhost:3000 || exit 1 + + +# # # # # NEXT JOB ####################################################################### +# pulls test image from GHCR and run a trivy vulnerability scan for high and crtical CVEs (non-blocking) +# and uploads the sarif result to github security tab + scan-image: + name: Scan Image with Trivy + needs: [build-test-image] + runs-on: ubuntu-latest + + permissions: + contents: read + packages: read + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + + steps: + - name: checkout + uses: actions/checkout@v4 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to ghcr.io registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Downcase repo name + run: | + echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV} + + + - name: Run Trivy for HIGH,CRITICAL CVEs and report (non-blocking) + uses: aquasecurity/trivy-action@0.20.0 + with: + image-ref: ghcr.io/${{env.REPO}}:${{ github.run_id }} + format: sarif # table, json, sarif + exit-code: 0 # 1 or 0. 0 means don't fail the job if issues are found + ignore-unfixed: true # Ignore unpatched/unfixed vulnerabilities + vuln-type: 'os,library' + severity: 'HIGH,CRITICAL' # UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL + timeout: 10m0s + output: 'trivy-results.sarif' + env: + TRIVY_USERNAME: ${{ github.repository_owner }} + TRIVY_PASSWORD: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v3 + if: always() + with: + sarif_file: 'trivy-results.sarif' + +# NEXT JOB ####################################################################### +# generates changelog.MD or add to an existing one and create releases using conventional commits. +# creates prelease when a pull request is made to main branch if a succesful test image +# was built, with succesful unit and integration test. +# creates a release when a merge is made to the main branch +# and adds either the prelease or released version to github output +# to be used by final image published to docker hub + changelog: + name: automated changelog using conventional commit + needs: [build-test-image, unit-test, integration-test, scan-image] + runs-on: ubuntu-latest + outputs: + TAG: ${{ steps.docker_tag.outputs.TAG }} + permissions: + contents: write + + + steps: + - name: check out the repository with all releases + uses: actions/checkout@v4 + with: + # fetch-depth: 0 + persist-credentials: 'false' + ref: ${{github.event.repository.default_branch}} + + + + - name: conventional Changelog Action + id: changelog + uses: TriPSs/conventional-changelog-action@v5.1.0 + with: + github-token: ${{ secrets.RELEASE_MAIN }} + version-file: "./apps/web/package.json" + git-branch: ${{github.event.repository.default_branch}} + preset: "conventionalcommits" + input-file: "./apps/web/CHANGELOG.md" + output-file: "./apps/web/CHANGELOG.md" + tag-prefix: "v" + pre-release: "${{github.event_name == 'pull_request'}} || ${{github.event_name == 'pull_request_target'}}" + pre-release-identifier: "alpha" + skip-on-empty: 'false' + # release-count: 20 + skip-git-pull: true + + - name: Create Release + uses: actions/create-release@v1 + if: ${{ steps.changelog.outputs.skipped == 'false' }} + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_MAIN }} + with: + tag_name: ${{ steps.changelog.outputs.tag }} + release_name: ${{ steps.changelog.outputs.tag }} + body: ${{ steps.changelog.outputs.clean_changelog }} + + - name: export tag for final build + id: docker_tag + run: | + echo "TAG=${{ steps.changelog.outputs.tag }}" >> $GITHUB_OUTPUT + + +# NEXT JOB ####################################################################### +# builds the final image and adds latest tag and image:V*.*.* semantic versioning tag to merge request +# and image:v*.*.*-alpha.* tag to pull requests made to main branch before pushing to dockerhub + build-final-image: + name: Build Final Image + needs: [unit-test, integration-test, scan-image,changelog] + runs-on: ubuntu-latest + + permissions: + contents: write + packages: write + pull-requests: write # needed to create and update comments in PRs + + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to ghcr.io registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker Metadata for Final Image Build + id: docker_meta + uses: docker/metadata-action@v5 + with: + images: ${{ secrets.DOCKERHUB_USERNAME }}/cal.com + flavor: | + latest=false + tags: | + type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }} + type=raw,value=${{needs.changelog.outputs.TAG}} + + - name: Docker Build and Push to Docker Hub + uses: docker/build-push-action@v5 + with: + file: infra/docker/web/Dockerfile + push: true + tags: | + ${{ steps.docker_meta.outputs.tags }} , + labels: ${{ steps.docker_meta.outputs.labels }} + cache-from: | + type=gha,scope=main-base + platforms: linux/amd64 + + + +# NEXT JOB ####################################################################### +#update docker compose image tag + + update-compose: + name: Tag kubernetes manifest and update compose + needs: [unit-test, integration-test, scan-image,changelog,build-final-image] + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + + + - name: Checkout repository + uses: actions/checkout@v4 + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + with: + persist-credentials: false + fetch-depth: 0 + ref: ${{ github.ref }} + + - name: Update compose manifest + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + run: | + yq --inplace ".services.calcom.image = \"${{ secrets.DOCKERHUB_USERNAME }}/calcom:${{ needs.changelog.outputs.TAG }}\"" infra/docker/web/docker-compose.yaml + + - name: Configure git + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + run: | + git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + + - name: Commit changes + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + run: | + git add . + git commit -m "Release ${{ needs.changelog.outputs.TAG }} [skip ci]" + + - name: Push changes + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.RELEASE_MAIN }} + branch: ${{ github.ref }} + + + + + + \ No newline at end of file diff --git a/apps/web/config/build-env.config.js b/apps/web/config/build-env.config.js new file mode 100644 index 00000000000000..123dfb876a11ca --- /dev/null +++ b/apps/web/config/build-env.config.js @@ -0,0 +1,19 @@ +const { z } = require("zod"); +const {getValidatedBuildEnv} = require("./getValidatedBuildEnv"); + + +const schema = { + NEXT_BUILD_ENV_OUTPUT: z + .enum(['standalone', 'classic'], { + description: + 'For standalone mode: https://nextjs.org/docs/pages/api-reference/next-config-js/output', + }) + .default('classic') +}; + + +const buildEnvSchema = z.object(schema); +const buildEnv = getValidatedBuildEnv(buildEnvSchema); + + +module.exports = { buildEnvSchema, buildEnv }; diff --git a/apps/web/config/getValidatedBuildEnv.js b/apps/web/config/getValidatedBuildEnv.js new file mode 100644 index 00000000000000..2562dd97b3551c --- /dev/null +++ b/apps/web/config/getValidatedBuildEnv.js @@ -0,0 +1,20 @@ +/** + * Return a validated / transformed environment object from a zodSchema + * + * Validated build envs are shown in the console by default. In case of error it will + * exit/die with an error indicating missing requirements + * +*/ +const getValidatedBuildEnv = (zodSchema, options = {}) => { + const { env = process.env, displayConsole = true } = options ?? {}; + const parsedEnv = zodSchema.safeParse(env); + if (parsedEnv.success) { + if (displayConsole) { + console.log('Build env(s)', parsedEnv); + } + return parsedEnv.data; + } + console.error(parsedEnv); +}; + +module.exports = { getValidatedBuildEnv }; \ No newline at end of file diff --git a/apps/web/next.config.js b/apps/web/next.config.js index 0b5a9395bf76e0..e43bb7fc468ad7 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -13,6 +13,19 @@ const { orgUserTypeEmbedRoutePath, } = require("./pagesAndRewritePaths"); +const { buildEnv } = require ("./config/build-env.config"); + +const path = require ('node:path') ; +const url = require ('node:url'); + + + +const workspaceRoot = path.resolve( + path.dirname(url.fileURLToPath(require('url').pathToFileURL(__filename).toString())), + '..', + '..' +); + if (!process.env.NEXTAUTH_SECRET) throw new Error("Please set NEXTAUTH_SECRET"); if (!process.env.CALENDSO_ENCRYPTION_KEY) throw new Error("Please set CALENDSO_ENCRYPTION_KEY"); const isOrganizationsEnabled = @@ -172,8 +185,22 @@ const matcherConfigUserTypeEmbedRoute = { /** @type {import("next").NextConfig} */ const nextConfig = { - output: "standalone", + + + ...(buildEnv.NEXT_BUILD_ENV_OUTPUT === 'standalone' + ? { output: 'standalone', outputFileTracing: true } + : {}), + + swcMinify: true, + + + experimental: { + + ...(buildEnv.NEXT_BUILD_ENV_OUTPUT === 'standalone' + ? { outputFileTracingRoot: workspaceRoot } + : {}), + // externalize server-side node_modules with size > 1mb, to improve dev mode performance/RAM usage serverComponentsExternalPackages: ["next-i18next"], optimizePackageImports: ["@calcom/ui"], diff --git a/apps/web/package.json b/apps/web/package.json index 93ba8016c392f4..8ee51391ae4b08 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -19,11 +19,16 @@ "lint:fix": "eslint . --ext .ts,.js,.tsx,.jsx --fix", "lint:report": "eslint . --format json --output-file ../../lint-results/web.json", "check-changed-files": "ts-node scripts/ts-check-changed-files.ts", + + "docker-start-web": "prisma migrate deploy --schema /app/packages/prisma/schema.prisma && node /app/apps/web/server.js", + + "translate-locales": "ts-node scripts/check-missing-translations.ts" + }, "engines": { - "node": "18", - "yarn": "3.4.1" + "node": "18" + }, "dependencies": { "@boxyhq/saml-jackson": "1.18.6", diff --git a/infra/docker/web/.dockerignore b/infra/docker/web/.dockerignore new file mode 100644 index 00000000000000..6e100ccdb9088e --- /dev/null +++ b/infra/docker/web/.dockerignore @@ -0,0 +1,5 @@ +.git +.github +.env.example +node_modules +**/node_modules \ No newline at end of file diff --git a/infra/docker/web/.env.example b/infra/docker/web/.env.example new file mode 100644 index 00000000000000..effbab25a84e97 --- /dev/null +++ b/infra/docker/web/.env.example @@ -0,0 +1,64 @@ +# Set this value to 'agree' to accept our license: +# LICENSE: https://github.com/calendso/calendso/blob/main/LICENSE +# +# Summary of terms: +# - The codebase has to stay open source, whether it was modified or not +# - You can not repackage or sell the codebase +# - Acquire a commercial license to remove these terms by emailing: license@cal.com +NEXT_PUBLIC_LICENSE_CONSENT= +LICENSE= + +# BASE_URL and NEXT_PUBLIC_APP_URL are both deprecated. Both are replaced with one variable, NEXT_PUBLIC_WEBAPP_URL +# BASE_URL=http://localhost:3000 +# NEXT_PUBLIC_APP_URL=http://localhost:3000 + +NEXT_PUBLIC_WEBAPP_URL=http://localhost:3000 +NEXT_PUBLIC_API_V2_URL=http://localhost:5555/api/v2 + + +# Configure NEXTAUTH_URL manually if needed, otherwise it will resolve to {NEXT_PUBLIC_WEBAPP_URL}/api/auth +# NEXTAUTH_URL=http://localhost:3000/api/auth + +# It is highly recommended that the NEXTAUTH_SECRET must be overridden and very unique +# Use `openssl rand -base64 32` to generate a key +NEXTAUTH_SECRET=secret + +# Encryption key that will be used to encrypt CalDAV credentials, choose a random string, for example with `dd if=/dev/urandom bs=1K count=1 | md5sum` +CALENDSO_ENCRYPTION_KEY=secret + +# Deprecation note: JWT_SECRET is no longer used +# JWT_SECRET=secret + +POSTGRES_USER=unicorn_user +POSTGRES_PASSWORD=magical_password +POSTGRES_DB=calendso +DATABASE_HOST=database:5432 +DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${DATABASE_HOST}/${POSTGRES_DB} +DATABASE_DIRECT_URL=${DATABASE_URL} +GOOGLE_API_CREDENTIALS={} + +# Set this to '1' if you don't want Cal to collect anonymous usage +CALCOM_TELEMETRY_DISABLED= + +# Used for the Office 365 / Outlook.com Calendar integration +MS_GRAPH_CLIENT_ID= +MS_GRAPH_CLIENT_SECRET= + +# Used for the Zoom integration +ZOOM_CLIENT_ID= +ZOOM_CLIENT_SECRET= + +# E-mail settings +# Configures the global From: header whilst sending emails. +EMAIL_FROM=notifications@example.com + +# Configure SMTP settings (@see https://nodemailer.com/smtp/). +EMAIL_SERVER_HOST=smtp.example.com +EMAIL_SERVER_PORT=587 +EMAIL_SERVER_USER=email_user +EMAIL_SERVER_PASSWORD=email_password + +NODE_ENV=production + +# HOSTNAME=example.com +# NEXTJS_PORT='' diff --git a/infra/docker/web/Dockerfile b/infra/docker/web/Dockerfile new file mode 100644 index 00000000000000..8195038bc3380f --- /dev/null +++ b/infra/docker/web/Dockerfile @@ -0,0 +1,100 @@ +FROM node:18-slim as base + +RUN set -eux; \ + apt-get update -qq && \ + apt-get install -y build-essential openssl pkg-config python-is-python3 jq git && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists /var/cache/apt/archives + +############################################# +FROM base as builder + +WORKDIR /app + +# Disables some well-known postinstall scripts +ENV PRISMA_SKIP_POSTINSTALL_GENERATE=true \ + HUSKY=0 + +ENV NEXT_BUILD_ENV_OUTPUT=standalone + +ENV NEXT_PUBLIC_WEBAPP_URL=http://localhost:3000 \ + NEXT_PUBLIC_API_V2_URL=http://localhost:5555/api/v2 \ + NEXTAUTH_URL=${NEXT_PUBLIC_WEBAPP_URL}/api/auth \ + NEXTAUTH_SECRET=auth_secret \ + CALENDSO_ENCRYPTION_KEY=encyrption_secret \ + NEXT_PUBLIC_LICENSE_CONSENT=$NEXT_PUBLIC_LICENSE_CONSENT_PLACEHOLDER \ + CALCOM_TELEMETRY_DISABLED=$CALCOM_TELEMETRY_DISABLED_PLACEHOLDER \ + MAX_OLD_SPACE_SIZE=4096 + +ENV NODE_ENV=production \ + NODE_OPTIONS=--max-old-space-size=${MAX_OLD_SPACE_SIZE} + +COPY --link . . + +# align turbo with package.json version +RUN TURBO_VERSION=$(cat package.json | jq '.dependencies["turbo"]' -r) npm i -g turbo@${TURBO_VERSION} + +RUN yarn config set httpTimeout 1200000 && \ + turbo prune --scope=@calcom/web --docker && \ + yarn && \ + turbo run build --filter=@calcom/web... && \ + rm -rf node_modules/.cache .yarn/cache apps/web/.next/cache + + +############################################# +FROM base as unit-test + +WORKDIR /app + +COPY --from=builder /app/. ./ + +RUN yarn test + + +############################################# +FROM node:18-slim as runner + +# Install packages needed for deployment +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y openssl jq curl bash && \ + rm -rf /var/lib/apt/lists /var/cache/apt/archives + +WORKDIR /app + +# chown to node default user/group +COPY --from=builder --chown=node:node /app/apps/web/next.config.js \ + /app/apps/web/next-i18next.config.js \ + /app/apps/web/package.json \ + ./ + +# automatically leverage outputfiletracing to reduce image size +COPY --from=builder --chown=node:node /app/apps/web/.next/standalone ./ +COPY --from=builder --chown=node:node /app/apps/web/.next/static ./apps/web/.next/static +COPY --from=builder --chown=node:node /app/apps/web/public ./apps/web/public + +# # prisma schema to be loaded at runtime with dependency +RUN PRISMA_CLIENT_VERSION=$(cat packages/prisma/package.json | jq '.dependencies["@prisma/client"]' -r) npm i -g @prisma/client@${PRISMA_CLIENT_VERSION} && \ + PRISMA_VERSION=$(cat packages/prisma/package.json | jq '.dependencies["prisma"]' -r) npm i -g prisma@${PRISMA_VERSION} + +COPY --from=builder --chown=node:node /app/packages/prisma /app/packages/prisma + +# entrypoint scripts +COPY --chown=node:node infra/docker/web/scripts ./ +RUN ["chmod", "+x", "./replace-placeholder.sh"] + +USER node + +ENTRYPOINT ["/bin/bash", "./replace-placeholder.sh"] + + +# enables standalone access to api route endpoints by changing the inline "localhost" +# in server.js to "0.0.0.0" +ENV HOSTNAME=0.0.0.0 +ENV PORT=${NEXTJS_PORT:-3000} +EXPOSE ${PORT} + +CMD ["yarn", "workspace", "@calcom/web", "docker-start-web"] + + + + diff --git a/infra/docker/web/docker-compose.yaml b/infra/docker/web/docker-compose.yaml new file mode 100644 index 00000000000000..ab02b3ed53500f --- /dev/null +++ b/infra/docker/web/docker-compose.yaml @@ -0,0 +1,25 @@ +version: '3' + +volumes: + database-data: + +services: + database: + image: postgres + volumes: + - database-data:/var/lib/postgresql/data/ + env_file: .env + healthcheck: + test: [ "CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + interval: 10s + retries: 10 + + + calcom: + image: calcom/cal.com + ports: + - 3000:3000 + env_file: .env + depends_on: + database: + condition: service_healthy \ No newline at end of file diff --git a/infra/docker/web/integration-test/compose.yml b/infra/docker/web/integration-test/compose.yml new file mode 100644 index 00000000000000..6646e44a68080f --- /dev/null +++ b/infra/docker/web/integration-test/compose.yml @@ -0,0 +1,30 @@ +volumes: + database-data: + +services: + database: + image: postgres + volumes: + - database-data:/var/lib/postgresql/data/ + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + + + + calcom: + image: "${TESTING_IMAGE}" + ports: + - 3000:3000 + environment: + - DATABASE_URL=postgresql://postgres:postgres@database:5432/calcom + - DATABASE_DIRECT_URL=postgresql://postgres:postgres@database:5432/calcom + depends_on: + - database + + + + + + + diff --git a/infra/docker/web/scripts/placeholder.yml b/infra/docker/web/scripts/placeholder.yml new file mode 100644 index 00000000000000..a5a742d559ea39 --- /dev/null +++ b/infra/docker/web/scripts/placeholder.yml @@ -0,0 +1,6 @@ +NEXT_PUBLIC_WEBAPP_URL : http://localhost:3000 +NEXT_PUBLIC_API_V2_URL: http://localhost:5555/api/v2 +NEXTAUTH_SECRET : auth_secret +CALENDSO_ENCRYPTION_KEY : encyrption_secret +NEXT_PUBLIC_LICENSE_CONSENT: NEXT_PUBLIC_LICENSE_CONSENT_PLACEHOLDER +CALCOM_TELEMETRY_DISABLED : CALCOM_TELEMETRY_DISABLED_PLACEHOLDER diff --git a/infra/docker/web/scripts/replace-placeholder.sh b/infra/docker/web/scripts/replace-placeholder.sh new file mode 100644 index 00000000000000..4d037952ff91fa --- /dev/null +++ b/infra/docker/web/scripts/replace-placeholder.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# # no verbose +set +x + +# Define the path to the YAML file +YAML_FILE="placeholder.yml" +# Define the path to the .next folder +NEXT_FOLDER="apps/web/.next" + +function apply_path { + # Check if the YAML file exists + if [ ! -f "$YAML_FILE" ]; then + echo "Error: YAML file $YAML_FILE not found." + exit 1 + fi + # Parse the YAML file and extract keys and values of variables + while IFS=':' read -r key value; do + # Remove leading and trailing whitespace from the key and value + config_key=$(echo "$key" | sed 's/^[ \t]*//;s/[ \t]*$//') + config_value=$(echo "$value" | sed 's/^[ \t]*//;s/[ \t]*$//') + + + # Iterate over all environment variables + while IFS='=' read -r docker_key docker_value; do + # Check if docker_key matches config_key + if [ "$docker_key" == "$config_key" ]; then + + if [ -n "$docker_value" ]; then + # Replace the value in the .next folder with the value from Docker runtime + + find $NEXT_FOLDER \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s#$config_value#$docker_value#g" + echo "Replaced value of $config_value with $docker_value in .next folder" + fi + break # Stop iterating once the key is found + fi + done < <(env) + +done < "$YAML_FILE" +} + +apply_path +echo "Starting Nextjs" +exec "$@" \ No newline at end of file diff --git a/packages/config/eslint-preset.js b/packages/config/eslint-preset.js index 60aa49f6bba56d..f165d7d04fbcd0 100644 --- a/packages/config/eslint-preset.js +++ b/packages/config/eslint-preset.js @@ -43,6 +43,10 @@ module.exports = { }, ], "prefer-template": "error", + "prettier/prettier": [ 'warn', { + endOfLine: 'auto', + }, + ], }, overrides: [ {