diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..c0746bcb8 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,48 @@ +{ + "name": "Forem DEVcontainer", + "dockerComposeFile": "../docker-compose.yml", + "service": "devcontainer", + "runServices": ["postgres", "redis"], + "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", + "remoteEnv": { + "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}", + "GIT_EDITOR": "code --wait" + }, + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { + "version": "latest", + "enableNonRootDocker": "false", + "moby": "true" + }, + "ghcr.io/devcontainers/features/common-utils:2": { + "installZsh": "true", + "configureZshAsDefaultShell": "true" + } + }, + "portsAttributes": { + "3000": { + "onAutoForward": "notify" + }, + "3035": { + // This port is used by the Rails' webpack-dev-server. Users won't need to access it directly. + "onAutoForward": "silent" + } + }, + "updateContentCommand": "bin/setup", + "postCreateCommand": ".devcontainer/postCreateCommand-init.sh", + "postAttachCommand": ".devcontainer/postAttachCommand-init.sh", + "customizations": { + "vscode": { + // Extensions listed here will be installed unlike the one specificed in extensions.json + "extensions": [ + "Shopify.ruby-lsp", + "KoichiSasada.vscode-rdbg", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode" + ], + "settings": { + "terminal.integrated.defaultProfile.linux": "zsh" + } + } + } +} diff --git a/.devcontainer/postAttachCommand-init.sh b/.devcontainer/postAttachCommand-init.sh new file mode 100755 index 000000000..c0988b4c4 --- /dev/null +++ b/.devcontainer/postAttachCommand-init.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +if [ -n "$CODESPACE_NAME" ]; then + echo "Running updates" + + # Github Codespace prebuild caches the codebase. + # This means depending on the time the Codespace is created, + # it may not be on latest commit with latest dependency changes + # + # See https://github.com/orgs/community/discussions/58172 + + if git fetch origin "$(git rev-parse --abbrev-ref HEAD)" && git diff --quiet "HEAD..origin/$(git rev-parse --abbrev-ref HEAD)" ;then + echo "Branch is already up to date" + else + echo "Branch is not up to date, pulling latest code" + git pull origin "$(git rev-parse --abbrev-ref HEAD)" --no-rebase + echo "Updating dependencies" + bin/setup + fi +fi + +cat <> ~/.zshrc + +if [ ! -f .env ]; then + echo "Creating .env file" + cp .env_sample .env +fi + +if [ -n "$CODESPACE_NAME" ]; then + echo "Updating .env file with codespace specific values" + echo APP_DOMAIN="${CODESPACE_NAME}-3000.app.github.dev" >> .env + echo APP_PROTOCOL=https:// >> .env +fi diff --git a/.husky/pre-commit b/.husky/pre-commit index 2d6927b6f..5a182ef10 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,6 +1,4 @@ -#!/bin/sh -FILES=$(git diff --cached --name-only) -[ -z "$FILES" ] && exit 0 +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" -# Run lint-staged on all staged -echo "$FILES" | yarn lint-staged +yarn lint-staged diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 0dadc54ed..cb1c9be7f 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,13 +1,16 @@ { + // List of extensions which should be recommended for users of this workspace. + // Suggestions are welcome! "recommendations": [ - "nickytonline.dev-to-extension-pack", - "waderyan.nodejs-extension-pack", - "esbenp.prettier-vscode", - "donjayamanne.git-extension-pack", - "rebornix.ruby", - "ms-vsliveshare.vsliveshare-pack", "42crunch.vscode-openapi", + "donjayamanne.git-extension-pack", + "esbenp.prettier-vscode", + "firefox-devtools.vscode-firefox-d", + "ms-vsliveshare.vsliveshare-pack", "philosowaffle.openapi-designer", - "silvenon.mdx" + "sbenp.prettier-vscode", + "silvenon.mdx", + "waderyan.nodejs-extension-pack", + "koichisasada.vscode-rdbg" ] } diff --git a/Containerfile b/Containerfile index da53a1d5b..98d1b08c2 100644 --- a/Containerfile +++ b/Containerfile @@ -149,6 +149,8 @@ CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0", "-p", "3000"] ## Development FROM base AS development +ENV TMPDIR=/var/tmp + # Common dependencies # Using --mount to speed up build with caching, see https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/reference.md#run---mount RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ @@ -187,12 +189,14 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -yq --no-install-recommends \ nodejs -# Application dependencies +# Application dependencies, for Cypress, node-canvas RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ --mount=type=tmpfs,target=/var/log \ DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \ - imagemagick + build-essential \ + libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb \ + libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev # Configure bundler ENV LANG=C.UTF-8 \ diff --git a/bin/setup b/bin/setup index 96b520c24..83a4ec8f0 100755 --- a/bin/setup +++ b/bin/setup @@ -39,7 +39,4 @@ FileUtils.chdir APP_ROOT do puts "\n== Removing old logs and tempfiles ==" system! "bin/rails log:clear tmp:clear" - - puts "\n== Restarting application server ==" - system! "bin/rails restart" end diff --git a/bin/startup b/bin/startup index c7e84efbf..45fb83695 100755 --- a/bin/startup +++ b/bin/startup @@ -12,5 +12,7 @@ end chdir APP_ROOT do puts "== STARTING UP ==" - system! "foreman start -f Procfile.dev" + # Foreman .env load behavior is at odds with dotenv + # https://github.com/ddollar/foreman/issues/702#issuecomment-1227334155 + system! "foreman start -f Procfile.dev --env=/dev/null" end diff --git a/config/initializers/docker.rb b/config/initializers/docker.rb index 322346813..46e271d77 100644 --- a/config/initializers/docker.rb +++ b/config/initializers/docker.rb @@ -2,9 +2,8 @@ if Rails.env.development? && File.file?("/.dockerenv") # Using shell tools so we don't need to require Socket and IPAddr host_ip = `ip route|awk '/default/ { print $3 }'`.strip - logger = Logger.new($stdout) - logger.info "Allowing #{host_ip} for BetterErrors and Web Console" + # Need to allow the host IP for BetterErrors and Web Console if defined?(BetterErrors::Middleware) BetterErrors::Middleware.allow_ip!(host_ip) end diff --git a/docker-compose.yml b/docker-compose.yml index 1e0bf595f..f59a9fc62 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,15 +19,16 @@ x-backend: &backend stdin_open: true tty: true volumes: - - .:/app:cached + - ${LOCAL_WORKSPACE_FOLDER:-.}:/app:cached - bundle:/usr/local/bundle + - cypress:/root/.cache/Cypress - rails_cache:/app/tmp/cache - assets:/app/public/assets - node_modules:/app/node_modules - packs:/app/public/packs - packs-test:/app/public/packs-test - history:/usr/local/hist - - ./.dockerdev/.psqlrc:/root/.psqlrc:ro + - ${LOCAL_WORKSPACE_FOLDER:-.}/.dockerdev/.psqlrc:/root/.psqlrc:ro environment: &backend_environment <<: *env REDIS_URL: redis://redis:6379/ @@ -49,6 +50,32 @@ x-backend: &backend condition: service_healthy services: + devcontainer: + <<: *backend + environment: + MALLOC_ARENA_MAX: 2 + WEB_CONCURRENCY: ${WEB_CONCURRENCY:-1} + REDIS_URL: redis://redis:6379/ + DATABASE_URL: postgres://postgres:postgres@postgres:5432 + DATABASE_URL_TEST: postgres://postgres:postgres@postgres:5432 + volumes: + - ${LOCAL_WORKSPACE_FOLDER:-.}:/workspaces/forem:cached + - bundle:/usr/local/bundle + - cypress:/root/.cache/Cypress + - rails_cache:/workspaces/forem/tmp/cache + - assets:/workspaces/forem/public/assets + - node_modules:/workspaces/forem/node_modules + - packs:/workspaces/forem/public/packs + - packs-test:/workspaces/forem/public/packs-test + - history:/usr/local/hist + - ${LOCAL_WORKSPACE_FOLDER:-.}/.dockerdev/.psqlrc:/root/.psqlrc:ro + - /var/run/docker.sock:/var/run/docker-host.sock + command: sleep infinity + tmpfs: + - /workspaces/forem/tmp/pids + ports: + - '3000:3000' + rails: <<: *backend command: bundle exec rails @@ -71,7 +98,7 @@ services: postgres: image: postgres:13 volumes: - - ./.dockerdev/.psqlrc:/root/.psqlrc:ro + - ${LOCAL_WORKSPACE_FOLDER:-.}/.dockerdev/.psqlrc:/root/.psqlrc:ro - postgres:/var/lib/postgresql/data - history:/usr/local/hist environment: @@ -101,7 +128,7 @@ services: ports: - '3035:3035' volumes: - - .:/app:cached + - ${LOCAL_WORKSPACE_FOLDER:-.}:/app:cached - bundle:/usr/local/bundle - node_modules:/app/node_modules - packs:/app/public/packs @@ -113,6 +140,7 @@ services: volumes: bundle: + cypress: node_modules: history: rails_cache: