diff --git a/Dockerfile b/Dockerfile index 5cff15dc5..388c5a4ef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,9 +5,11 @@ WORKDIR /app ENV NEXT_PUBLIC_API_BASE_URL=http://NEXT_PUBLIC_API_BASE_URL_PLACEHOLDER RUN yarn global add turbo +RUN apk add tree COPY . . -RUN turbo prune --scope=app --docker +RUN turbo prune --scope=app --scope=plane-deploy --docker +CMD tree -I node_modules/ # Add lockfile and package.json's of isolated subworkspace FROM node:18-alpine AS installer @@ -21,14 +23,14 @@ COPY --from=builder /app/out/json/ . COPY --from=builder /app/out/yarn.lock ./yarn.lock RUN yarn install -# Build the project +# # Build the project COPY --from=builder /app/out/full/ . COPY turbo.json turbo.json COPY replace-env-vars.sh /usr/local/bin/ USER root RUN chmod +x /usr/local/bin/replace-env-vars.sh -RUN yarn turbo run build --filter=app +RUN yarn turbo run build ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \ BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL @@ -96,11 +98,16 @@ RUN adduser --system --uid 1001 captain COPY --from=installer /app/apps/app/next.config.js . COPY --from=installer /app/apps/app/package.json . +COPY --from=installer /app/apps/space/next.config.js . +COPY --from=installer /app/apps/space/package.json . COPY --from=installer --chown=captain:plane /app/apps/app/.next/standalone ./ COPY --from=installer --chown=captain:plane /app/apps/app/.next/static ./apps/app/.next/static +COPY --from=installer --chown=captain:plane /app/apps/space/.next/standalone ./ +COPY --from=installer --chown=captain:plane /app/apps/space/.next ./apps/space/.next + ENV NEXT_TELEMETRY_DISABLED 1 # RUN rm /etc/nginx/conf.d/default.conf diff --git a/apps/app/Dockerfile.web b/apps/app/Dockerfile.web index e0b5f29c1..2b28e1fd1 100644 --- a/apps/app/Dockerfile.web +++ b/apps/app/Dockerfile.web @@ -33,8 +33,8 @@ RUN yarn turbo run build --filter=app ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \ BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL - -RUN /usr/local/bin/replace-env-vars.sh http://NEXT_PUBLIC_WEBAPP_URL_PLACEHOLDER ${NEXT_PUBLIC_API_BASE_URL} +ENV NEXT_PUBLIC_DEPLOY_URL=${NEXT_PUBLIC_DEPLOY_URL} +RUN /usr/local/bin/replace-env-vars.sh http://NEXT_PUBLIC_WEBAPP_URL_PLACEHOLDER ${NEXT_PUBLIC_API_BASE_URL} app FROM node:18-alpine AS runner WORKDIR /app diff --git a/apps/app/components/tiptap/bubble-menu/index.tsx b/apps/app/components/tiptap/bubble-menu/index.tsx index 259b5ecea..e68900782 100644 --- a/apps/app/components/tiptap/bubble-menu/index.tsx +++ b/apps/app/components/tiptap/bubble-menu/index.tsx @@ -15,36 +15,36 @@ export interface BubbleMenuItem { type EditorBubbleMenuProps = Omit; -export const EditorBubbleMenu: FC = (props) => { +export const EditorBubbleMenu: FC = (props: any) => { const items: BubbleMenuItem[] = [ { name: "bold", - isActive: () => props.editor.isActive("bold"), - command: () => props.editor.chain().focus().toggleBold().run(), + isActive: () => props.editor?.isActive("bold"), + command: () => props.editor?.chain().focus().toggleBold().run(), icon: BoldIcon, }, { name: "italic", - isActive: () => props.editor.isActive("italic"), - command: () => props.editor.chain().focus().toggleItalic().run(), + isActive: () => props.editor?.isActive("italic"), + command: () => props.editor?.chain().focus().toggleItalic().run(), icon: ItalicIcon, }, { name: "underline", - isActive: () => props.editor.isActive("underline"), - command: () => props.editor.chain().focus().toggleUnderline().run(), + isActive: () => props.editor?.isActive("underline"), + command: () => props.editor?.chain().focus().toggleUnderline().run(), icon: UnderlineIcon, }, { name: "strike", - isActive: () => props.editor.isActive("strike"), - command: () => props.editor.chain().focus().toggleStrike().run(), + isActive: () => props.editor?.isActive("strike"), + command: () => props.editor?.chain().focus().toggleStrike().run(), icon: StrikethroughIcon, }, { name: "code", - isActive: () => props.editor.isActive("code"), - command: () => props.editor.chain().focus().toggleCode().run(), + isActive: () => props.editor?.isActive("code"), + command: () => props.editor?.chain().focus().toggleCode().run(), icon: CodeIcon, }, ]; @@ -78,7 +78,7 @@ export const EditorBubbleMenu: FC = (props) => { className="flex w-fit divide-x divide-custom-border-300 rounded border border-custom-border-300 bg-custom-background-100 shadow-xl" > { setIsNodeSelectorOpen(!isNodeSelectorOpen); @@ -86,7 +86,7 @@ export const EditorBubbleMenu: FC = (props) => { }} /> { setIsLinkSelectorOpen(!isLinkSelectorOpen); diff --git a/apps/space/Dockerfile.space b/apps/space/Dockerfile.space new file mode 100644 index 000000000..0240ddbf7 --- /dev/null +++ b/apps/space/Dockerfile.space @@ -0,0 +1,70 @@ +FROM node:18-alpine AS builder +RUN apk add --no-cache libc6-compat +# Set working directory +WORKDIR /app +ENV NEXT_PUBLIC_API_BASE_URL=http://NEXT_PUBLIC_API_BASE_URL_PLACEHOLDER + +RUN yarn global add turbo +COPY . . + +RUN turbo prune --scope=space --docker + +# Add lockfile and package.json's of isolated subworkspace +FROM node:18-alpine AS installer + +RUN apk add --no-cache libc6-compat +WORKDIR /app +ARG NEXT_PUBLIC_API_BASE_URL=http://localhost:8000 + +# First install the dependencies (as they change less often) +COPY .gitignore .gitignore +COPY --from=builder /app/out/json/ . +COPY --from=builder /app/out/yarn.lock ./yarn.lock +RUN yarn install --network-timeout 500000 + +# Build the project +COPY --from=builder /app/out/full/ . +COPY turbo.json turbo.json +COPY replace-env-vars.sh /usr/local/bin/ +USER root +RUN chmod +x /usr/local/bin/replace-env-vars.sh + +RUN yarn turbo run build --filter=space + +ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \ + BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL + +RUN /usr/local/bin/replace-env-vars.sh http://NEXT_PUBLIC_WEBAPP_URL_PLACEHOLDER ${NEXT_PUBLIC_API_BASE_URL} space + +FROM node:18-alpine AS runner +WORKDIR /app + +# Don't run production as root +RUN addgroup --system --gid 1001 plane +RUN adduser --system --uid 1001 captain +USER captain + +COPY --from=installer /app/apps/space/next.config.js . +COPY --from=installer /app/apps/space/package.json . + +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=installer --chown=captain:plane /app/apps/space/.next/standalone ./ + +COPY --from=installer --chown=captain:plane /app/apps/space/.next ./apps/space/.next + +ARG NEXT_PUBLIC_API_BASE_URL=http://localhost:8000 +ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \ + BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL + +USER root +COPY replace-env-vars.sh /usr/local/bin/ +COPY start.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/replace-env-vars.sh +RUN chmod +x /usr/local/bin/start.sh + +USER captain + +ENV NEXT_TELEMETRY_DISABLED 1 + +EXPOSE 3000 diff --git a/apps/space/next.config.js b/apps/space/next.config.js index 398eb0400..0dd1894bb 100644 --- a/apps/space/next.config.js +++ b/apps/space/next.config.js @@ -1,9 +1,14 @@ /** @type {import('next').NextConfig} */ +const path = require('path') const nextConfig = { + reactStrictMode: false, + swcMinify: true, experimental: { + outputFileTracingRoot: path.join(__dirname, "../../"), appDir: true, }, + output: 'standalone' }; module.exports = nextConfig; diff --git a/apps/space/package.json b/apps/space/package.json index dd7a3058c..e37dfa54a 100644 --- a/apps/space/package.json +++ b/apps/space/package.json @@ -1,11 +1,11 @@ { - "name": "plane-deploy", + "name": "space", "version": "0.0.1", "private": true, "scripts": { - "dev": "next dev", + "dev": "next dev -p 4000", "build": "next build", - "start": "next start", + "start": "next start -p 4000", "lint": "next lint" }, "dependencies": { diff --git a/docker-compose-hub.yml b/docker-compose-hub.yml index c0466e09c..84ff8b833 100644 --- a/docker-compose-hub.yml +++ b/docker-compose-hub.yml @@ -38,11 +38,12 @@ services: container_name: planefrontend image: makeplane/plane-frontend:latest restart: always - command: /usr/local/bin/start.sh + command: /usr/local/bin/start.sh apps/app/server.js app env_file: - .env environment: NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL} + NEXT_PUBLIC_DEPLOY_URL: ${NEXT_PUBLIC_DEPLOY_URL} NEXT_PUBLIC_GOOGLE_CLIENTID: "0" NEXT_PUBLIC_GITHUB_APP_NAME: "0" NEXT_PUBLIC_GITHUB_ID: "0" @@ -54,6 +55,20 @@ services: depends_on: - plane-api - plane-worker + + plane-deploy: + container_name: planedeploy + image: makeplane/plane-space:latest + restart: always + command: node apps/space/server.js space + env_file: + - .env + environment: + NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL} + depends_on: + - plane-api + - plane-worker + - plane-web plane-api: container_name: planebackend diff --git a/docker-compose.yml b/docker-compose.yml index be8b96258..d1ffca809 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -41,12 +41,14 @@ services: dockerfile: ./apps/app/Dockerfile.web args: NEXT_PUBLIC_API_BASE_URL: http://localhost:8000 + NEXT_PUBLIC_DEPLOY_URL: http://localhost/spaces restart: always - command: /usr/local/bin/start.sh + command: /usr/local/bin/start.sh apps/app/server.js app env_file: - .env environment: NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL} + NEXT_PUBLIC_DEPLOY_URL: ${NEXT_PUBLIC_DEPLOY_URL} NEXT_PUBLIC_GOOGLE_CLIENTID: "0" NEXT_PUBLIC_GITHUB_APP_NAME: "0" NEXT_PUBLIC_GITHUB_ID: "0" @@ -58,6 +60,23 @@ services: depends_on: - plane-api - plane-worker + plane-deploy: + container_name: planedeploy + build: + context: . + dockerfile: ./apps/space/Dockerfile.space space + args: + NEXT_PUBLIC_API_BASE_URL: http://localhost:8000 + restart: always + command: /usr/local/bin/start.sh apps/space/server.js space + env_file: + - .env + environment: + NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL} + depends_on: + - plane-api + - plane-worker + - plane-web plane-api: container_name: planebackend diff --git a/nginx/nginx-single-docker-image.conf b/nginx/nginx-single-docker-image.conf index 8d927a1b2..b9f50d664 100644 --- a/nginx/nginx-single-docker-image.conf +++ b/nginx/nginx-single-docker-image.conf @@ -18,6 +18,11 @@ server { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } + location /space/ { + proxy_pass http://localhost:4000/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; diff --git a/nginx/nginx.conf.template b/nginx/nginx.conf.template index 206c94b51..796c9e10d 100644 --- a/nginx/nginx.conf.template +++ b/nginx/nginx.conf.template @@ -15,6 +15,10 @@ server { proxy_pass http://planefrontend:3000/; } + location /spaces/ { + proxy_pass http://planedeploy:3000/; + } + location /api/ { proxy_pass http://planebackend:8000/api/; } diff --git a/replace-env-vars.sh b/replace-env-vars.sh index 56c6d2025..afdc1492e 100644 --- a/replace-env-vars.sh +++ b/replace-env-vars.sh @@ -1,6 +1,7 @@ #!/bin/sh FROM=$1 TO=$2 +DIRECTORY=$3 if [ "${FROM}" = "${TO}" ]; then echo "Nothing to replace, the value is already set to ${TO}." @@ -11,4 +12,4 @@ fi # Only perform action if $FROM and $TO are different. echo "Replacing all statically built instances of $FROM with this string $TO ." -grep -R -la "${FROM}" apps/app/.next | xargs -I{} sed -i "s|$FROM|$TO|g" "{}" +grep -R -la "${FROM}" apps/$DIRECTORY/.next | xargs -I{} sed -i "s|$FROM|$TO|g" "{}" diff --git a/setup.sh b/setup.sh index a5a8e9b6a..235e1a977 100755 --- a/setup.sh +++ b/setup.sh @@ -1,5 +1,5 @@ #!/bin/bash -# cp ./.env.example ./.env +cp ./.env.example ./.env # Export for tr error in mac export LC_ALL=C diff --git a/start.sh b/start.sh index 173e333a4..dcb97db6d 100644 --- a/start.sh +++ b/start.sh @@ -3,7 +3,7 @@ set -x # Replace the statically built BUILT_NEXT_PUBLIC_API_BASE_URL with run-time NEXT_PUBLIC_API_BASE_URL # NOTE: if these values are the same, this will be skipped. -/usr/local/bin/replace-env-vars.sh "$BUILT_NEXT_PUBLIC_API_BASE_URL" "$NEXT_PUBLIC_API_BASE_URL" +/usr/local/bin/replace-env-vars.sh "$BUILT_NEXT_PUBLIC_API_BASE_URL" "$NEXT_PUBLIC_API_BASE_URL" $2 echo "Starting Plane Frontend.." -node apps/app/server.js \ No newline at end of file +node $1