diff --git a/.editorconfig b/.editorconfig index 6ab7b6cbb..4be6792be 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,14 +1,13 @@ # http://editorconfig.org - root = true [*] -end_of_line = lf charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true -indent_style = space +end_of_line = lf indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true [*.{diff,md}] trim_trailing_whitespace = false diff --git a/.github/workflows/codeforafrica-deploy-dev-app.yml b/.github/workflows/codeforafrica-deploy-dev-app.yml index 819212eb9..2f760fcdf 100644 --- a/.github/workflows/codeforafrica-deploy-dev-app.yml +++ b/.github/workflows/codeforafrica-deploy-dev-app.yml @@ -5,7 +5,7 @@ on: branches: [main] paths: - "apps/codeforafrica/**" - - "codeforafrica.Dockerfile" + - "Dockerfile" - ".github/workflows/codeforafrica-deploy-dev-app.yml" concurrency: @@ -67,7 +67,7 @@ jobs: cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new context: . - file: ./codeforafrica.Dockerfile + target: codeforafrica-runner push: true tags: "${{ env.IMAGE_NAME }}:${{ github.sha }}" diff --git a/.github/workflows/codeforafrica-deploy-prod.yml b/.github/workflows/codeforafrica-deploy-prod.yml index a5b8fb3a7..84f6c1816 100644 --- a/.github/workflows/codeforafrica-deploy-prod.yml +++ b/.github/workflows/codeforafrica-deploy-prod.yml @@ -88,7 +88,7 @@ jobs: cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new context: . - file: ./codeforafrica.Dockerfile + target: codeforafrica-runner push: true tags: "${{ env.IMAGE_NAME }}:${{ steps.version-check.outputs.version }}" diff --git a/.github/workflows/codeforafrica-deploy-review-app.yml b/.github/workflows/codeforafrica-deploy-review-app.yml index 13ebaea89..6076dfa3c 100644 --- a/.github/workflows/codeforafrica-deploy-review-app.yml +++ b/.github/workflows/codeforafrica-deploy-review-app.yml @@ -4,7 +4,7 @@ on: pull_request: paths: - "apps/codeforafrica/**" - - "codeforafrica.Dockerfile" + - "Dockerfile" - ".github/workflows/codeforafrica-deploy-review-app.yml" # By default, a workflow only runs when a pull_request event's activity # type is opened, synchronize, or reopened. We need at least closed to @@ -66,7 +66,7 @@ jobs: cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new context: . - file: ./codeforafrica.Dockerfile + target: codeforafrica-runner push: true tags: "${{ env.IMAGE_NAME }}:${{ github.sha }}" diff --git a/Dockerfile b/Dockerfile index 55263a788..41e5aa852 100644 --- a/Dockerfile +++ b/Dockerfile @@ -115,6 +115,120 @@ RUN set -ex \ EXPOSE ${PORT} +# ============================================================================ +# Code for Africa +# ============================================================================ + +# +# codeforafrica-desp: image with all codeforafrica dependencies +# ------------------------------------------------------------- + +FROM base-deps as codeforafrica-deps + +# TODO(kilemensi): Figure out why this is needed +COPY packages/commons-ui-testing-library/package.json ./packages/commons-ui-testing-library/package.json + +COPY apps/codeforafrica/package.json ./apps/codeforafrica/package.json + +RUN pnpm --filter "./apps/codeforafrica/" install --offline --frozen-lockfile + +# +# codeforafrica-builder: image that uses deps to build shippable output +# --------------------------------------------------------------------- + +FROM base-builder as codeforafrica-builder + +ARG NEXT_TELEMETRY_DISABLED \ + # Next.js / Payload (build time) + PORT \ + # Next.js (runtime) + NEXT_PUBLIC_APP_NAME="Code for Africa" \ + NEXT_PUBLIC_APP_URL=http://localhost:3000 \ + NEXT_PUBLIC_SENTRY_DSN="" \ + # Payload (runtime) + MONGODB_URL \ + PAYLOAD_SECRET \ + # Sentry (build time) + SENTRY_AUTH_TOKEN \ + SENTRY_ENVIRONMENT \ + SENTRY_ORG="" \ + SENTRY_PROJECT="" + +COPY --from=codeforafrica-deps /workspace/node_modules ./node_modules + +# TODO(kilemensi): Investigate why we need @commons-ui sources. +COPY packages ./packages + +COPY --from=codeforafrica-deps /workspace/packages/commons-ui-core/node_modules ./packages/commons-ui-core/node_modules +COPY --from=codeforafrica-deps /workspace/packages/commons-ui-next/node_modules ./packages/commons-ui-next/node_modules +COPY --from=codeforafrica-deps /workspace/packages/commons-ui-testing-library/node_modules ./packages/commons-ui-testing-library/node_modules +COPY --from=codeforafrica-deps /workspace/packages/eslint-config-commons-ui/node_modules ./packages/eslint-config-commons-ui/node_modules +COPY --from=codeforafrica-deps /workspace/apps/codeforafrica/node_modules ./apps/codeforafrica/node_modules + +COPY apps/codeforafrica ./apps/codeforafrica/ + +RUN pnpm --filter "./apps/codeforafrica/" build-next + +ARG PAYLOAD_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} + +RUN pnpm --filter "./apps/codeforafrica/" build-payload + +# +# codeforafrica-runner: final deployable image +# -------------------------------------------- + +FROM base-runner as codeforafrica-runner + +# TODO(koech): Standadise naming of Mongo DB URL. Our options: +# - MONGODB_URL (codeforafrica) +# - MONGO_URL (charterafrica) +ARG MONGODB_URL \ + NEXT_PUBLIC_APP_LOGO_URL \ + PAYLOAD_CONFIG_PATH="dist/payload.config.js" \ + PAYLOAD_PUBLIC_APP_URL + +ENV MONGODB_URL=${MONGODB_URL} \ + # TODO(koech): Standadise naming of GA MEASUREMENT ID. Our options: + # - GA_MEASUREMENT_ID (charterafrica, codeforafrica) + # - GOOGLE_ANALYTICS (pesayetu, vpnmanager) + # This is only needed at runtime + NEXT_PUBLIC_APP_LOGO_URL=${NEXT_PUBLIC_APP_LOGO_URL} \ + PAYLOAD_PUBLIC_APP_URL=${PAYLOAD_PUBLIC_APP_URL} \ + PAYLOAD_CONFIG_PATH=${PAYLOAD_CONFIG_PATH} \ + PAYLOAD_SECRET=${PAYLOAD_SECRET} + +RUN set -ex \ + # Create nextjs cache dir w/ correct permissions + && mkdir -p ./apps/codeforafrica//.next \ + && chown nextjs:nodejs ./apps/codeforafrica/.next + +# PNPM +# symlink some dependencies +COPY --from=codeforafrica-builder --chown=nextjs:nodejs /workspace/node_modules ./node_modules + +# Since we can't use output: "standalone", copy all app's dependencies +COPY --from=codeforafrica-builder --chown=nextjs:nodejs /workspace/apps/codeforafrica/node_modules ./apps/codeforafrica/node_modules + +# Next.js +# Public assets +COPY --from=codeforafrica-builder --chown=nextjs:nodejs /workspace/apps/codeforafrica/public ./apps/codeforafrica/public + +# Since we can't use output: "standalone", copy the whole app's .next folder +# TODO(kilemensi): Figure out which files in .next folder are not needed +COPY --from=codeforafrica-builder --chown=nextjs:nodejs /workspace/apps/codeforafrica/.next ./apps/codeforafrica/.next + +# Payload +COPY --from=codeforafrica-builder /workspace/apps/codeforafrica/dist ./apps/codeforafrica/dist +COPY --from=codeforafrica-builder /workspace/apps/codeforafrica/build ./apps/codeforafrica/build + +# Since we can't use output: "standalone", switch to specific app's folder +WORKDIR /workspace/apps/codeforafrica + +USER nextjs + +# Custom server to run Payload and Next.js in the same app +CMD ["node", "dist/server.js"] + # ============================================================================ # PesaYetu # ============================================================================ diff --git a/apps/codeforafrica/next.config.js b/apps/codeforafrica/next.config.js index c3a5a867a..db92419f2 100644 --- a/apps/codeforafrica/next.config.js +++ b/apps/codeforafrica/next.config.js @@ -1,12 +1,5 @@ -const path = require("path"); - const { withSentryConfig } = require("@sentry/nextjs"); -const PROJECT_ROOT = process.env.PROJECT_ROOT?.trim(); -const outputFileTracingRoot = PROJECT_ROOT - ? path.resolve(__dirname, PROJECT_ROOT) - : undefined; - const nextConfig = { images: { domains: process.env.NEXT_PUBLIC_IMAGE_DOMAINS?.split(",") @@ -16,16 +9,12 @@ const nextConfig = { process.env.NEXT_PUBLIC_IMAGE_UNOPTIMIZED?.trim()?.toLowerCase() === "true", }, - experimental: { - outputFileTracingRoot, - }, modularizeImports: { // NOTE: only transform @mui/material and not any of sub-modules e.g. @mui/material/styles. "@mui/material^": { transform: "@mui/material/{{member}}", }, }, - output: "standalone", pageExtensions: ["page.js"], reactStrictMode: true, transpilePackages: ["@commons-ui/core", "@commons-ui/next"], diff --git a/apps/codeforafrica/turbo.json b/apps/codeforafrica/turbo.json index e40a53bb8..c0ced17a2 100644 --- a/apps/codeforafrica/turbo.json +++ b/apps/codeforafrica/turbo.json @@ -21,7 +21,6 @@ "PAYLOAD_PUBLIC_APP_URL", "PAYLOAD_PUBLIC_DEFAULT_LOCALE", "PAYLOAD_PUBLIC_LOCALES", - "PROJECT_ROOT", "SENTRY_AUTH_TOKEN", "SENTRY_ORG", "SENTRY_PROJECT" diff --git a/codeforafrica.Dockerfile b/codeforafrica.Dockerfile deleted file mode 100644 index 2076be28b..000000000 --- a/codeforafrica.Dockerfile +++ /dev/null @@ -1,81 +0,0 @@ -FROM node:20.14-alpine as node-alpine - -RUN apk update \ - && apk upgrade - - -FROM node-alpine as base - -RUN apk add --no-cache libc6-compat - -ARG PNPM_VERSION=9.1.4 - -RUN corepack enable && corepack prepare pnpm@${PNPM_VERSION} --activate - -WORKDIR /workspace - -COPY pnpm-lock.yaml . - -RUN pnpm fetch - -FROM base as builder - - -WORKDIR /workspace - -COPY *.yaml *.json ./ -COPY packages ./packages -COPY apps/codeforafrica ./apps/codeforafrica - -# Use virtual store: https://pnpm.io/cli/fetch#usage-scenario -RUN pnpm install --recursive --offline --frozen-lockfile - -ARG PORT=3000 \ - MONGODB_URL \ - PAYLOAD_SECRET \ - NEXT_PUBLIC_APP_URL=http://localhost:3000 \ - NEXT_PUBLIC_SENTRY_DSN="" \ - # Sentry config for source maps upload (needed at build time only) - SENTRY_AUTH_TOKEN="" \ - SENTRY_ENVIRONMENT="" \ - SENTRY_ORG="" \ - SENTRY_PROJECT="" - -RUN pnpm build-next --filter=codeforafrica - -ARG PAYLOAD_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} - -RUN pnpm build-payload --filter=codeforafrica - -FROM builder as runner - -RUN rm -rf /var/cache/apk/* - -ARG NEXT_PUBLIC_APP_NAME \ - NEXT_PUBLIC_APP_URL \ - NEXT_PUBLIC_GA_MEASUREMENT_ID \ - NEXT_PUBLIC_SEO_DISABLED \ - PAYLOAD_CONFIG_PATH="dist/payload.config.js" \ - PAYLOAD_PUBLIC_APP_URL \ - NEXT_PUBLIC_APP_LOGO_URL \ - NEXT_PUBLIC_SENTRY_DSN \ - PORT \ - SENTRY_ENV - -ENV NODE_ENV=production \ - PAYLOAD_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} \ - PORT=${PORT} \ - PAYLOAD_CONFIG_PATH=${PAYLOAD_CONFIG_PATH} \ - PAYLOAD_SECRET=${PAYLOAD_SECRET} \ - MONGODB_URL=${MONGODB_URL} \ - NEXT_PUBLIC_APP_LOGO_URL=${NEXT_PUBLIC_APP_LOGO_URL} \ - NEXT_PUBLIC_APP_NAME=${NEXT_PUBLIC_APP_NAME} \ - NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} \ - NEXT_PUBLIC_SENTRY_DSN=${NEXT_PUBLIC_SENTRY_DSN} \ - SENTRY_ENVIRONMENT=${SENTRY_ENVIRONMENT} - -WORKDIR /workspace/apps/codeforafrica - -EXPOSE ${PORT} - -CMD [ "node", "dist/server.js" ] diff --git a/docker-compose.yml b/docker-compose.yml index 139564295..5d8a7a862 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,7 +33,7 @@ services: condition: service_healthy build: context: . - dockerfile: codeforafrica.Dockerfile + target: codeforafrica-runner args: - MONGO_URL=mongodb://${MONGO_INITDB_ROOT_USERNAME:-root}:${MONGO_INITDB_ROOT_PASSWORD:-rootpassword}@host.docker.internal:${MONGODB_PORT:-27017}/codeforafrica?authSource=admin&directConnection=true - PAYLOAD_SECRET