From 1ef9f0b6970bba887cc110ac46abf8c586479d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bedr=CC=8Cich=20Schindler?= Date: Fri, 27 Mar 2026 15:40:33 +0100 Subject: [PATCH 1/9] Introduce `devcontainer` service container based development environment (#705) All development is now done inside the container named `devcontainer` which contains all necessary tools and dependencies. The devcontainer orchestrates other service containers behind the scenes via Docker-from-Docker. Other containers are implementation details and should not be accessed directly. This is breaking change commit for development environment, so it is required to remove all the env files and start with fresh one. There are two supported ways to access the development environment. Recommended way is to use Development Containers with an IDE. The alternative is to use Docker Compose directly. Local development is officially no more supported. What more, documentation of contribution and CLAUDE.md was updated to match with the changes. --- .devcontainer/devcontainer.json | 23 ++ .env.dist | 51 ++++- .env.playwright.dist | 9 - .gitignore | 4 +- CLAUDE.md | 17 +- docker-compose.base.yml | 91 ++++++++ docker-compose.yml | 43 ---- docker-compose.yml.dist | 42 ++++ docker/build-docker-images.sh | 21 ++ docker/react_ui_devcontainer/Dockerfile | 128 +++++++++++ .../files/home/developer/shell-init.sh | 9 + .../files/usr/local/bin/claude | 3 + .../files/usr/local/bin/copilot | 3 + .../files/usr/local/bin/docker-entrypoint | 10 + .../files/usr/local/bin/mkdocs | 3 + .../files/usr/local/bin/node | 3 + .../files/usr/local/bin/npm | 7 + .../files/usr/local/bin/npx | 3 + .../files/usr/local/bin/opencode | 3 + .../Dockerfile.dist | 4 + package.json | 1 - setup.sh | 104 +++++++++ src/docs/contribute/general-guidelines.md | 200 ++++++++++++++---- src/docs/contribute/testing-guidelines.md | 56 +---- tests/playwright/env/parseDotEnvFile.ts | 2 +- 25 files changed, 671 insertions(+), 169 deletions(-) create mode 100644 .devcontainer/devcontainer.json delete mode 100644 .env.playwright.dist create mode 100644 docker-compose.base.yml delete mode 100644 docker-compose.yml create mode 100644 docker-compose.yml.dist create mode 100644 docker/build-docker-images.sh create mode 100644 docker/react_ui_devcontainer/Dockerfile create mode 100644 docker/react_ui_devcontainer/files/home/developer/shell-init.sh create mode 100644 docker/react_ui_devcontainer/files/usr/local/bin/claude create mode 100644 docker/react_ui_devcontainer/files/usr/local/bin/copilot create mode 100644 docker/react_ui_devcontainer/files/usr/local/bin/docker-entrypoint create mode 100644 docker/react_ui_devcontainer/files/usr/local/bin/mkdocs create mode 100644 docker/react_ui_devcontainer/files/usr/local/bin/node create mode 100644 docker/react_ui_devcontainer/files/usr/local/bin/npm create mode 100644 docker/react_ui_devcontainer/files/usr/local/bin/npx create mode 100644 docker/react_ui_devcontainer/files/usr/local/bin/opencode create mode 100644 docker/react_ui_devcontainer_local/Dockerfile.dist create mode 100755 setup.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..776e3df25 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,23 @@ +{ + "name": "React UI (${localWorkspaceFolderBasename})", + "initializeCommand": "sh ./setup.sh", + "dockerComposeFile": [ + "../docker-compose.yml", + ], + "service": "devcontainer", + "shutdownAction": "stopCompose", + "workspaceFolder": "/workspace", + "forwardPorts": [ + "docs:8000" + ], + "portsAttributes": { + "docs:8000": { + "label": "Docs server", + "protocol": "http", + "onAutoForward": "openBrowser" + } + }, + "otherPortsAttributes": { + "onAutoForward": "ignore" + } +} diff --git a/.env.dist b/.env.dist index d60e62cef..f410ad558 100644 --- a/.env.dist +++ b/.env.dist @@ -1,13 +1,52 @@ -############################### -# Docker compose configuration # -############################### +################################ +# Docker Compose configuration # +################################ -# Host system port where the live documentation is to be made accessible -COMPOSE_START_PORT=8000 +# Docker compose project name must match directory name of the project to allow devcontainer to communicate with other containers +COMPOSE_PROJECT_NAME=react-ui -# Host system port where Playwright Component Testing report is to be made accessible +# Docker compose ports for Docs server instances +COMPOSE_START_DOCS_SERVER_PORT=8000 + +# Docker compose ports for Playwright Component Testing report server COMPOSE_PLAYWRIGHT_REPORT_PORT=9323 +# Flag whether to start JavaScript files watcher at container start +COMPOSE_START_JS_FILES_WATCHER_AT_START=true + +# Flag whether to start docs server at container start +COMPOSE_START_DOCS_SERVER_AT_START=true + # Ownership of the files created in the container +# ⚠️ [Linux] This needs to be set to the output of `id --user` +# ⚠️ [MacOS] This needs to be set to 1000 COMPOSE_UID=1000 +# ⚠️ [Linux] This needs to be set to the output of `id --group` +# ⚠️ [MacOS] This needs to be set to 1000 COMPOSE_GID=1000 + +############################# +# Devcontainer configuration # +############################# + +# IDEs automatically mount the host's SSH agent socket into the container +# Visual Studio Code does this by default, it can be disabled by setting the following variable to true. +# JetBrains IDEs do not mount this by default, but they can be configured to do so. +BLOCK_SSH_AUTH_SOCK=false + +# Select your preferred editor and visual (vim, nano) +EDITOR=vim +VISUAL=vim + +# Select your preferred shell (/bin/bash, /bin/fish, /bin/zsh) +SHELL=/bin/bash + +########################### +# Playwright configuration # +########################### + +# Number of workers to use to run Playwright tests +PW_WORKERS=1 + +# Port used by Playwright Component Testing to serve the test files +PW_CT_PORT=3100 diff --git a/.env.playwright.dist b/.env.playwright.dist deleted file mode 100644 index 41bd68e69..000000000 --- a/.env.playwright.dist +++ /dev/null @@ -1,9 +0,0 @@ -########################### -# Playwright configuration # -########################### - -# Number of workers to use to run Playwright tests -PW_WORKERS=1 - -# Port used by Playwright Component Testing to serve the test files -PW_CT_PORT=3100 diff --git a/.gitignore b/.gitignore index 2b0232bac..e2ab471d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ /coverage +/docker-compose.yml +/docker/react_ui_devcontainer_local +!/docker/react_ui_devcontainer_local/Dockerfile.dist /dist /node_modules /playwright-report/ @@ -6,6 +9,5 @@ /src/docs/_assets/generated/* /tests/playwright/.temp/ .env -.env.playwright statistics.html !.gitkeep diff --git a/CLAUDE.md b/CLAUDE.md index ebcbc7f3f..443df34ae 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,17 +4,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Commands -All `npm` commands must be run inside Docker containers. Use `node_shell` for most tasks, `playwright` for visual tests. +All commands below are meant to be run directly inside the Docker container `devcontainer`. +If project is started using Development Containers, run it without starting the Docker. -```bash -# Enter node_shell container -docker compose run --rm node_shell - -# Enter playwright container (for visual tests) -docker compose run --rm --service-ports playwright -``` - -**Within `node_shell`:** ```bash npm run lint # All linters (ESLint + Stylelint + Markdownlint) @@ -23,11 +15,6 @@ npm run stylelint # SCSS linting npm run test:jest # All Jest unit tests npm run test:jest:ts -- # Single TypeScript test file npm run test:jest:js -- # Single JavaScript test file -``` - -**Within `playwright`:** - -```bash npm run test:playwright-ct:all # All component tests npm run test:playwright-ct:all-with-update # Update snapshots npm run test:playwright-ct:all -- -- src/components/Button # Tests for one component diff --git a/docker-compose.base.yml b/docker-compose.base.yml new file mode 100644 index 000000000..cb59f6c75 --- /dev/null +++ b/docker-compose.base.yml @@ -0,0 +1,91 @@ +services: + # This service is responsible for providing the main development environment for developers + devcontainer: + hostname: ${COMPOSE_PROJECT_NAME:-react-ui}_devcontainer + build: + context: docker/react_ui_devcontainer/ + dockerfile: Dockerfile + # Start dependent services before starting the `devcontainer` service to ensure that the necessary environments + # and tools are available when the `devcontainer` starts. + depends_on: + node: + condition: service_started + playwright: + condition: service_started + docs: + condition: service_started + user: ${COMPOSE_UID}:${COMPOSE_GID} + # Keep the container running indefinitely to allow developers to attach to it and use it as their development environment + command: sleep infinity + # Injects environment variables from the `.env` file into the `devcontainer` service, + # making them accessible within the container's environment. + env_file: + - .env + environment: + # This must be set correctly for the `devcontainer` to be able to access the host's Docker daemon, + # enabling Docker-from-Docker capabilities (e.g., running Docker commands from within the `devcontainer`). + COMPOSE_PROJECT_NAME: ${COMPOSE_PROJECT_NAME:-react-ui} + init: true + volumes: + - .:/workspace:z + # The following volume is used to allow the `devcontainer` to access the host's Docker daemon, + # enabling Docker-from-Docker capabilities (e.g., running Docker commands from within the `devcontainer`). + - /var/run/docker.sock:/var/run/docker.sock + # The following named volumes persist data (e.g. terminal history, AI tools data, etc.) across container restarts. + # Using separate named volumes (instead of a single volume with subpaths) allows Docker to automatically + # seed the volume with data from the image on first use. + - terminal-history:/home/developer/.terminal_history + - claude-config:/home/developer/.config/claude + - claude-share:/home/developer/.local/share/claude + - claude-state:/home/developer/.local/state/claude + - copilot:/home/developer/.copilot + - copilot-config:/home/developer/.config/copilot + - opencode-config:/home/developer/.config/opencode + - opencode-share:/home/developer/.local/share/opencode + - opencode-state:/home/developer/.local/state/opencode + + # This service provides Node environment and NPM + node: + build: docker/node + user: ${COMPOSE_UID}:${COMPOSE_GID} + command: sh -c 'if [ "$$COMPOSE_START_JS_FILES_WATCHER_AT_START" = "true" ]; then npm ci && npm start; else sleep infinity; fi' + env_file: + - .env + volumes: + - .:/workspace:z + + # This service provides Playwright environment and tools for browser automation and testing + playwright: + build: docker/playwright + user: ${COMPOSE_UID}:${COMPOSE_GID} + command: sleep infinity + env_file: + - .env + ports: + - ${COMPOSE_PLAYWRIGHT_REPORT_PORT}:9323 + volumes: + - .:/workspace:z + + # This provides server for documentation + docs: + build: docker/mkdocs + user: ${COMPOSE_UID}:${COMPOSE_GID} + entrypoint: sh -c 'if [ "$$COMPOSE_START_DOCS_SERVER_AT_START" = "true" ]; then mkdocs serve; else sleep infinity; fi' + env_file: + - .env + ports: + - ${COMPOSE_START_DOCS_SERVER_PORT}:8000 + volumes: + - .:/workspace:ro + +volumes: + # The following volumes are used to persist data (e.g. terminal history, AI tools data, etc.) across container restarts + terminal-history: + claude-config: + claude-share: + claude-state: + copilot: + copilot-config: + opencode-config: + opencode-share: + opencode-state: diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 6896b094f..000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,43 +0,0 @@ -services: - # Base services - do not run directly - mkdocs: - build: docker/mkdocs - user: ${COMPOSE_UID-1000}:${COMPOSE_GID-1000} - volumes: - - .:/workspace:z - node: - build: docker/node - user: ${COMPOSE_UID-1000}:${COMPOSE_GID-1000} - volumes: - - .:/workspace:z - - # Dev services - mkdocs_dev_server: - extends: mkdocs - entrypoint: mkdocs serve - ports: - - ${COMPOSE_START_PORT-8000}:8000 - node_dev_server: - extends: node - entrypoint: npm start - node_shell: - extends: node - entrypoint: bash - - # For running Playwright tests - playwright: - build: docker/playwright - entrypoint: bash - user: ${COMPOSE_UID-1000}:${COMPOSE_GID-1000} - ports: - - ${COMPOSE_PLAYWRIGHT_REPORT_PORT-9323}:9323 - volumes: - - .:/workspace:z - - # Build services - mkdocs_build_site: - extends: mkdocs - entrypoint: mkdocs build - node_build_site: - extends: node - entrypoint: npm run build diff --git a/docker-compose.yml.dist b/docker-compose.yml.dist new file mode 100644 index 000000000..3cd78e1f7 --- /dev/null +++ b/docker-compose.yml.dist @@ -0,0 +1,42 @@ +services: + # This service is responsible for providing the main development environment for developers + devcontainer: + extends: + file: docker-compose.base.yml + service: devcontainer + # Use `build` when you want to customize the devcontainer using `docker/react_ui_devcontainer_local/Dockerfile` + # build: + # context: ./docker/react_ui_devcontainer_local/ + # dockerfile: Dockerfile + # Use `image` when you want to use the default devcontainer + image: react-ui_devcontainer + + # This service provides Node environment and NPM + node: + extends: + file: docker-compose.base.yml + service: node + + # This service provides Playwright environment and tools for browser automation and testing + playwright: + extends: + file: docker-compose.base.yml + service: playwright + + # This provides server for documentation + docs: + extends: + file: docker-compose.base.yml + service: docs + +volumes: + # The following volumes are used to persist data (e.g. terminal history, AI tools data, etc.) across container restarts + terminal-history: + claude-config: + claude-share: + claude-state: + copilot: + copilot-config: + opencode-config: + opencode-share: + opencode-state: diff --git a/docker/build-docker-images.sh b/docker/build-docker-images.sh new file mode 100644 index 000000000..cb49e0d01 --- /dev/null +++ b/docker/build-docker-images.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +set -e +trap 'echo "Failed to build Docker images"; exit 1' ERR + +cd "$(dirname "$0")" + +echo "Building Docker images..." + +PROJECT_NAME=$(grep -E '^COMPOSE_PROJECT_NAME=' ../.env | cut -d '=' -f 2-) +PROJECT_DEVCONTAINER_IMAGE="${PROJECT_NAME}_devcontainer" + +echo "Building Docker image $PROJECT_DEVCONTAINER_IMAGE..." +docker build -t "$PROJECT_DEVCONTAINER_IMAGE" -f ./react_ui_devcontainer/Dockerfile ./react_ui_devcontainer/ + +cd .. + +echo "Building project Docker images using docker-compose..." +docker compose build + +echo "All Docker images built successfully!" diff --git a/docker/react_ui_devcontainer/Dockerfile b/docker/react_ui_devcontainer/Dockerfile new file mode 100644 index 000000000..1e703af9b --- /dev/null +++ b/docker/react_ui_devcontainer/Dockerfile @@ -0,0 +1,128 @@ +FROM debian:bookworm AS react-ui-devcontainer + +# Build arguments for user configuration +# Those can be changed using fixuid's remapping feature when running the container +ARG USERNAME=developer +ARG USER_UID=1000 +ARG USER_GID=1000 +ARG HOME="/home/${USERNAME}" + +# Default shell and editor settings, overridable via .env +ENV EDITOR="vim" +ENV VISUAL="vim" +ENV SHELL="/bin/bash" +ENV CLAUDE_CONFIG_DIR="${HOME}/.config/claude" +ENV OPENCODE_CONFIG="${HOME}/.config/opencode/opencode.json" +ENV OPENCODE_CONFIG_DIR="${HOME}/.config/opencode" + +# Install sudo, editors (vim, nano), SSH client, Git, shells (zsh, fish) and common utilities +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + sudo \ + ca-certificates \ + curl \ + gnupg \ + vim \ + nano \ + openssh-client \ + git \ + fish \ + zsh && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Create the user +RUN addgroup --gid $USER_GID $USERNAME && \ + adduser --uid $USER_UID --ingroup $USERNAME --home $HOME -shell $SHELL --disabled-password --gecos "" $USERNAME && \ + echo "$USERNAME ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME && \ + chmod 0440 /etc/sudoers.d/$USERNAME + +# Install fixuid to allow remapping the `developer` user to the host UID/GID when running in a container +RUN USER=$USERNAME && \ + GROUP=$USERNAME && \ + ARCH=$(dpkg --print-architecture) && \ + curl -SsL https://github.com/boxboat/fixuid/releases/download/v0.6.0/fixuid-0.6.0-linux-${ARCH}.tar.gz | tar -C /usr/local/bin -xzf - && \ + chown root:root /usr/local/bin/fixuid && \ + chmod 4755 /usr/local/bin/fixuid && \ + mkdir -p /etc/fixuid && \ + printf "user: $USER\ngroup: $GROUP\npaths: [$HOME]" > /etc/fixuid/config.yml + +# Install Docker CLI and Compose plugin to enable Docker-from-Docker +RUN install -m 0755 -d /etc/apt/keyrings && \ + curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --batch --yes --dearmor -o /etc/apt/keyrings/docker.gpg && \ + chmod a+r /etc/apt/keyrings/docker.gpg && \ + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \ + https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \ + > /etc/apt/sources.list.d/docker.list && \ + apt-get update && \ + apt-get install -y --no-install-recommends docker-ce-cli docker-compose-plugin && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +# Switch to the `developer` user for all user-level installations +USER $USERNAME:$USERNAME + +# Install Oh My Zsh +RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" + +# Persist terminal history across container restarts via a Docker volume +# mounted at $HOME/.terminal_history in docker-compose.base.yml +RUN mkdir -p "$HOME/.terminal_history" && \ + touch "$HOME/.terminal_history/bash_history" && \ + touch "$HOME/.terminal_history/zsh_history" && \ + touch "$HOME/.terminal_history/fish_history" && \ + SNIPPET_BASH="export PROMPT_COMMAND='history -a' && export HISTFILE=$HOME/.terminal_history/bash_history" && \ + echo "$SNIPPET_BASH" >> "$HOME/.bashrc" && \ + SNIPPET_ZSH="export PROMPT_COMMAND='history -a' && export HISTFILE=$HOME/.terminal_history/zsh_history" && \ + echo "$SNIPPET_ZSH" >> "$HOME/.zshrc" && \ + mkdir -p "$HOME/.local/share/fish" && \ + touch "$HOME/.terminal_history/fish_history" && \ + ln -sf "$HOME/.terminal_history/fish_history" "$HOME/.local/share/fish/fish_history" + +# Install Claude Code CLI +RUN mkdir -p "$HOME/.config/claude" && \ + curl -fsSL https://claude.ai/install.sh | bash + +# Install Open Code CLI +RUN curl -fsSL https://opencode.ai/install | bash -s -- --no-modify-path + +# Install Github Copilot CLI +# Note: Copilot CLI does not support XDG configuration, see: +# * +# * +RUN curl -fsSL https://gh.io/copilot-install | PREFIX="$HOME/.local" bash + +# Wrapper scripts for AI coding assistants ensure they are available in PATH +# and handle necessary environment variable setup +COPY --chmod=+x files/usr/local/bin/copilot /usr/local/bin/copilot +COPY --chmod=+x files/usr/local/bin/claude /usr/local/bin/claude +COPY --chmod=+x files/usr/local/bin/opencode /usr/local/bin/opencode +COPY --chmod=+x files/usr/local/bin/docker-entrypoint /usr/local/bin/docker-entrypoint +COPY --chmod=+x files/home/$USERNAME/shell-init.sh ${HOME}/shell-init.sh + +# Wrapper scripts that execute commands inside the appropriate Docker containers. +# These scripts use Docker-from-Docker to run the commands in the context of the +# respective Docker containers, allowing container agnostic development workflows. +COPY --chmod=+x files/usr/local/bin/node /usr/local/bin/node +COPY --chmod=+x files/usr/local/bin/npm /usr/local/bin/npm +COPY --chmod=+x files/usr/local/bin/npx /usr/local/bin/npx +COPY --chmod=+x files/usr/local/bin/mkdocs /usr/local/bin/mkdocs + +# Ensure /usr/local/bin takes precedence over VS Code injected paths +# and run profile script on every shell startup to apply .env configuration +RUN mkdir -p $HOME/.config/fish && \ + echo 'export PATH="/usr/local/bin:$PATH"' >> $HOME/.bashrc && \ + echo 'export PATH="/usr/local/bin:$PATH"' >> $HOME/.zshrc && \ + echo 'set -gx PATH /usr/local/bin $PATH' >> $HOME/.config/fish/config.fish && \ + echo '$HOME/shell-init.sh' >> $HOME/.bashrc && \ + echo '$HOME/shell-init.sh' >> $HOME/.zshrc && \ + echo '$HOME/shell-init.sh' >> $HOME/.config/fish/config.fish + +# Set the default working directory when starting a container from this image +WORKDIR /workspace + +# Set the default command to run when starting a container from this image +# The fixuid command will adjust the `developer` user's UID and GID to match +# the host user's UID and GID when running in a container, ensuring that +# any files created by the `developer` user inside the container have +# the correct ownership on the host system. +ENTRYPOINT ["docker-entrypoint"] diff --git a/docker/react_ui_devcontainer/files/home/developer/shell-init.sh b/docker/react_ui_devcontainer/files/home/developer/shell-init.sh new file mode 100644 index 000000000..3e704e44a --- /dev/null +++ b/docker/react_ui_devcontainer/files/home/developer/shell-init.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# Block SSH agent forwarding if the environment variable `BLOCK_SSH_AUTH_SOCK` is set to "true" +if [ "$BLOCK_SSH_AUTH_SOCK" = "true" ]; then + # Disable SSH agent forwarding for the current shell session + export SSH_AUTH_SOCK=/dev/null + # Remove any existing SSH agent socket files created by VS Code + find /tmp -maxdepth 1 -name 'vscode-ssh-auth-*.sock' -delete 2>/dev/null +fi diff --git a/docker/react_ui_devcontainer/files/usr/local/bin/claude b/docker/react_ui_devcontainer/files/usr/local/bin/claude new file mode 100644 index 000000000..de603a311 --- /dev/null +++ b/docker/react_ui_devcontainer/files/usr/local/bin/claude @@ -0,0 +1,3 @@ +#!/bin/sh + +/home/developer/.local/bin/claude "$@" diff --git a/docker/react_ui_devcontainer/files/usr/local/bin/copilot b/docker/react_ui_devcontainer/files/usr/local/bin/copilot new file mode 100644 index 000000000..4df0dff87 --- /dev/null +++ b/docker/react_ui_devcontainer/files/usr/local/bin/copilot @@ -0,0 +1,3 @@ +#!/bin/sh + +/home/developer/.local/bin/copilot --config-dir "/home/developer/.config/copilot" "$@" diff --git a/docker/react_ui_devcontainer/files/usr/local/bin/docker-entrypoint b/docker/react_ui_devcontainer/files/usr/local/bin/docker-entrypoint new file mode 100644 index 000000000..661ebd04f --- /dev/null +++ b/docker/react_ui_devcontainer/files/usr/local/bin/docker-entrypoint @@ -0,0 +1,10 @@ +#!/bin/sh + +# Ensure the developer user owns their home directory and all files within it +sudo chown -R developer:developer /home/developer + +# Remap the developer user's UID/GID to match the host user +eval "$(fixuid -q)" + +# Execute the command passed to the container (e.g. via `command` in docker-compose) +exec "$@" diff --git a/docker/react_ui_devcontainer/files/usr/local/bin/mkdocs b/docker/react_ui_devcontainer/files/usr/local/bin/mkdocs new file mode 100644 index 000000000..20789ea83 --- /dev/null +++ b/docker/react_ui_devcontainer/files/usr/local/bin/mkdocs @@ -0,0 +1,3 @@ +#!/bin/sh + +sudo docker compose -p "$COMPOSE_PROJECT_NAME" exec docs mkdocs "$@" diff --git a/docker/react_ui_devcontainer/files/usr/local/bin/node b/docker/react_ui_devcontainer/files/usr/local/bin/node new file mode 100644 index 000000000..60e2db562 --- /dev/null +++ b/docker/react_ui_devcontainer/files/usr/local/bin/node @@ -0,0 +1,3 @@ +#!/bin/sh + +sudo docker compose -p "$COMPOSE_PROJECT_NAME" exec node node "$@" diff --git a/docker/react_ui_devcontainer/files/usr/local/bin/npm b/docker/react_ui_devcontainer/files/usr/local/bin/npm new file mode 100644 index 000000000..931941c1d --- /dev/null +++ b/docker/react_ui_devcontainer/files/usr/local/bin/npm @@ -0,0 +1,7 @@ +#!/bin/sh + +if [ "$1" = "run" ] && echo "$2" | grep -q '^test:playwright'; then + sudo docker compose -p "$COMPOSE_PROJECT_NAME" exec playwright npm "$@" +else + sudo docker compose -p "$COMPOSE_PROJECT_NAME" exec node npm "$@" +fi diff --git a/docker/react_ui_devcontainer/files/usr/local/bin/npx b/docker/react_ui_devcontainer/files/usr/local/bin/npx new file mode 100644 index 000000000..b4c97acc5 --- /dev/null +++ b/docker/react_ui_devcontainer/files/usr/local/bin/npx @@ -0,0 +1,3 @@ +#!/bin/sh + +sudo docker compose -p "$COMPOSE_PROJECT_NAME" exec node npx "$@" diff --git a/docker/react_ui_devcontainer/files/usr/local/bin/opencode b/docker/react_ui_devcontainer/files/usr/local/bin/opencode new file mode 100644 index 000000000..17c2198ee --- /dev/null +++ b/docker/react_ui_devcontainer/files/usr/local/bin/opencode @@ -0,0 +1,3 @@ +#!/bin/sh + +/home/developer/.opencode/bin/opencode "$@" diff --git a/docker/react_ui_devcontainer_local/Dockerfile.dist b/docker/react_ui_devcontainer_local/Dockerfile.dist new file mode 100644 index 000000000..cc6c1d498 --- /dev/null +++ b/docker/react_ui_devcontainer_local/Dockerfile.dist @@ -0,0 +1,4 @@ +# react-ui_devcontainer might differ based on Docker compose project name +FROM react-ui_devcontainer as react-ui_devcontainer_local + +# Your additional setup for the local development can go here diff --git a/package.json b/package.json index 4a3cb3758..781a0d165 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "lint": "npm run eslint && npm run markdownlint && npm run stylelint", "markdownlint": "markdownlint-cli2 \"README.md\" \"src/**/*.md\"", "postbuild": "npm run copy", - "postinstall": "cp -n .env.dist .env && cp -n .env.playwright.dist .env.playwright || true", "precopy": "rm -rf dist && mkdir dist", "prepublishOnly": "npm run build", "start": "webpack --watch --mode=development", diff --git a/setup.sh b/setup.sh new file mode 100755 index 000000000..a8acc4451 --- /dev/null +++ b/setup.sh @@ -0,0 +1,104 @@ +#!/bin/sh + +DEFAULT_PROJECT_NAME="react-ui" +DEFAULT_USER_ID=1000 +DEFAULT_GROUP_ID=1000 + +set -e +trap 'echo "Failed to setup project"; exit 1' ERR + +# Function to handle sed command with cross-platform compatibility +sed_cmd() { + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "$@" + else + sed -i "$@" + fi +} + +cd "$(dirname "$0")" + +echo "Setting up project..." + +# Create and configure .env file if it doesn't exist +if [ ! -f .env ]; then + echo "Creating .env file..." + cp .env.dist .env.temp + + echo "Configuring .env file..." + + PROJECT_PATH=$(pwd) + PROJECT_NAME=$(basename "$PROJECT_PATH") + + if [[ "$OSTYPE" == "darwin"* ]]; then + # MacOS + USER_ID=$DEFAULT_USER_ID + GROUP_ID=$DEFAULT_GROUP_ID + else + # Linux + USER_ID=$(id -u) + GROUP_ID=$(id -g) + fi + + sed_cmd "s|^COMPOSE_PROJECT_NAME=.*|COMPOSE_PROJECT_NAME=$PROJECT_NAME|" .env.temp + sed_cmd "s|^COMPOSE_UID=.*|COMPOSE_UID=$USER_ID|" .env.temp + sed_cmd "s|^COMPOSE_GID=.*|COMPOSE_GID=$GROUP_ID|" .env.temp + + LOCAL_SHELL= + if [ -n "$SHELL" ]; then + sed_cmd "s|^SHELL=.*|SHELL=$SHELL|" .env.temp + LOCAL_SHELL=$SHELL + fi + + LOCAL_EDITOR= + if [ -n "$EDITOR" ]; then + sed_cmd "s|^EDITOR=.*|EDITOR=$EDITOR|" .env.temp + LOCAL_EDITOR=$EDITOR + fi + + LOCAL_VISUAL= + if [ -n "$VISUAL" ]; then + sed_cmd "s|^VISUAL=.*|VISUAL=$VISUAL|" .env.temp + LOCAL_VISUAL=$VISUAL + fi + + cp .env.temp .env + rm .env.temp + + echo "Configured .env file with the following values:" + echo "Project name: $PROJECT_NAME" + echo "Project path: $PROJECT_PATH" + echo "User ID: $USER_ID" + echo "Group ID: $GROUP_ID" + + if [ -n "$LOCAL_SHELL" ]; then + echo "Shell: $LOCAL_SHELL" + fi + if [ -n "$LOCAL_EDITOR" ]; then + echo "Editor: $LOCAL_EDITOR" + fi + if [ -n "$LOCAL_VISUAL" ]; then + echo "Visual: $LOCAL_VISUAL" + fi +else + echo ".env file already exists, skipping creation." +fi + +# Create docker-compose.yml if it doesn't exist +if [ ! -f docker-compose.yml ]; then + echo "Creating and configuring docker-compose.yml file..." + cp docker-compose.yml.dist docker-compose.yml + + DEFAULT_PROJECT_DEVCONTAINER_IMAGE="${DEFAULT_PROJECT_NAME}_devcontainer" + PROJECT_NAME=$(grep -E '^COMPOSE_PROJECT_NAME=' .env | cut -d '=' -f 2-) + PROJECT_DEVCONTAINER_IMAGE="${PROJECT_NAME}_devcontainer" + + sed_cmd "s|image: $DEFAULT_PROJECT_DEVCONTAINER_IMAGE|image: $PROJECT_DEVCONTAINER_IMAGE|" docker-compose.yml +else + echo "docker-compose.yml file already exists, skipping creation." +fi + +# Build Docker images +sh ./docker/build-docker-images.sh + +echo "Project setup completed successfully!" diff --git a/src/docs/contribute/general-guidelines.md b/src/docs/contribute/general-guidelines.md index 74aa840ac..726201166 100644 --- a/src/docs/contribute/general-guidelines.md +++ b/src/docs/contribute/general-guidelines.md @@ -2,99 +2,205 @@ In the first place, thank you for your interest in contributing! 🙏 -## Development +## Development Environment -Working on the site requires: +### Overview -* [Docker] -* [Docker Compose] +All development is done inside the container named `devcontainer` which +contains all necessary tools and dependencies. All commands in the documentation +are container-agnostic and are meant to be run directly inside the `devcontainer`. -This allows running the documentation site which serves as a development platform. +The `devcontainer` orchestrates other service containers behind the scenes via +Docker-from-Docker. Other containers are implementation details and should not +be accessed directly. -### Configure Docker Compose +There are two supported ways to access the development environment. Recommended +way is to use [Development Containers] with an IDE, which provides a more +seamless experience. The alternative is to use Docker Compose directly. -Review the default env variable values in the `docker-compose.yml` file. -The defaults should work for most systems, but can be changed if needed. -To change them, edit the `.env` file as needed. +### Requirements -### Use Docker Compose +* [Docker] +* [Docker Compose] +* [Development Containers] (strongly recommended) -#### Node shell +### Setup -All npm commands such as `npm ci`, `npm test`, `npm run eslint` and others you -need to run them within the `node_shell` Docker container. +#### Automatic setup -To log into the container, run: +Run the setup script to automatically create and configure all necessary files +and build Docker images: ```bash -docker compose run --rm node_shell +sh setup.sh ``` -If you want to run single command, run: +[Development Containers] run this script automatically if the project has not +been set up prior to opening it. -```bash -docker compose run --rm node_shell -c 'npm ' -``` +#### Manual setup -#### Run the Dev Server +If you prefer to set up the project manually: -1. **Within `node_shell`:** Install dependencies: +1. Create `.env` file and configure it: ```bash - npm ci + cp .env.dist .env ``` -2. **On host:** Run development server: +2. Create `docker-compose.yml` and configure it: ```bash - docker compose up node_dev_server mkdocs_dev_server + cp docker-compose.yml.dist docker-compose.yml ``` -#### Build the Project - -1. **On host:** Make sure the dev server is not running: +3. Build Docker images: ```bash - docker compose down + sh docker/build-docker-images.sh ``` -2. **Within `node_shell`:** Install dependencies: +#### Environment + +The `.env` file configures services (ports, UID/GID, source mapping), +the `devcontainer` shell, editor and SSH agent forwarding, as well as application +settings. See `.env.dist` for available options. + +### Accessing the Development Environment + +#### Using Development Containers + +Open the project in an IDE that supports [Development Containers] (e.g. +[Visual Studio Code][vscode-devcontainers], [JetBrains IDEs][jetbrains-devcontainers]). +The IDE will automatically setup the environment using the configuration in +`.devcontainer/devcontainer.json`. + +#### Using Docker Compose + +1. Start the `devcontainer` in the background: ```bash - npm ci + docker compose up -d ``` -3. **On host:** Build JS: +2. Open a shell inside the `devcontainer`: ```bash - docker compose run --rm node_build_site + docker compose exec devcontainer bash ``` -4. **On host:** Build mkDocs: +3. To stop the environment: ```bash - docker compose run --rm mkdocs_build_site + docker compose down ``` -#### Playwright +### Customization -npm commands such as `test:playwright-ct:all` and `test:playwright-ct:all-with-update` -need to be run them within the `playwright` Docker container. +To customize the `devcontainer`, create a +`docker/react_ui_devcontainer_local/Dockerfile` that extends the base image: -To log into the container, run: +```Dockerfile +FROM react-ui_devcontainer as react-ui_devcontainer_local +# Add your customizations here +``` + +Then ensure `docker-compose.yml` has the `build` directive for the `devcontainer` +service: + +```yml +devcontainer: + extends: + file: docker-compose.base.yml + service: devcontainer + build: + context: ./docker/react_ui_devcontainer_local/ + dockerfile: Dockerfile +``` + +Rebuild the images after making changes: ```bash -docker compose run --rm --service-ports playwright +sh docker/build-docker-images.sh ``` -If you want to run single command, run: +If you need to persist additional data across container restarts, see how it is +done in `docker-compose.base.yml`. You will need to add a volume mapping to the +`devcontainer` service and add a corresponding named volume definition. + +### What the `devcontainer` Contains + +The `devcontainer` is built in the following layers: + +#### Base Layer (`react-ui_devcontainer`) + +General-purpose development layer. Makes the environment container-agnostic +by wrapping commands to run in the appropriate service containers. + + +* **OS:** Debian Bookworm +* **Shells:** Bash, Zsh (with Oh My Zsh), Fish +* **Editors:** Vim, Nano +* **Tools:** Git, SSH client, Docker CLI (Docker-from-Docker) +* **AI coding assistants:** Claude Code, GitHub Copilot CLI, Open Code + +#### Local Layer (`react-ui_devcontainer_local`) + +Optional layer that allows individual developers to customize the environment. +See [Customization](#customization) for details. + +### Service Containers + +The `devcontainer` depends on the following service containers defined in +`docker-compose.base.yml`: + +| Container | Purpose | +|--------------|--------------------------------------------------| +| `node` | Runs Node.js commands (`npm`, `node`) | +| `playwright` | Runs Playwright and Lighthouse tests | +| `docs` | Serves documentation via MkDocs | + +All service containers mount the workspace at `/workspace` so that file changes +are shared. + +## Installing Dependencies + +Run it on initial setup or when dependencies have changed: ```bash -docker compose run --rm --service-ports playwright -c 'npm run test:playwright-ct:*' +npm ci ``` -Argument `--service-ports` is used to expose the ports of the container to the host -to serve the test report. +## Building + +To build the JavaScript code: + +```bash +npm run build +``` + +To build the documentation: + +```bash +mkdocs build +``` + +## Running + +> See `.env` whether both the application and documentation server are not configured +> to auto-start on container startup. If they are, you can skip the following steps. + +To start building JavaScript files in watch mode: + +```bash +npm run start +``` + +To start the documentation server: + +```bash +mkdocs serve +``` ## Testing @@ -161,7 +267,7 @@ pull request from the changelog. The best way for development of React UI is to link `react-ui` into your application with `npm link` so you can see it in action. -1. In React UI repository, run `npm link` +1. In React UI repository **on your host machine**, run `npm link` 2. In your application, run `npm link @react-ui-org/react-ui` To prevent [Invalid Hook Call Warning][react-invalid-hook] when React UI is @@ -202,8 +308,12 @@ the documentation platform. Do see their respective documentation for details. -[Docker]: https://www.docker.com +[apple-silicon-issue]: https://racom-jira.atlassian.net/browse/WECL-312 +[Development Containers]: https://containers.dev/ +[Docker]: https://docs.docker.com/get-started/ [Docker Compose]: https://docs.docker.com/compose/ +[jetbrains-devcontainers]: https://www.jetbrains.com/help/idea/start-dev-container-inside-ide.html#dev_container_context_menu +[vscode-devcontainers]: https://code.visualstudio.com/docs/devcontainers/tutorial [react-invalid-hook]: https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react [mkdocs-material]: https://squidfunk.github.io/mkdocs-material/ [Docoff]: https://github.com/react-ui-org/docoff diff --git a/src/docs/contribute/testing-guidelines.md b/src/docs/contribute/testing-guidelines.md index 2ff90ccbd..ab50a214e 100644 --- a/src/docs/contribute/testing-guidelines.md +++ b/src/docs/contribute/testing-guidelines.md @@ -3,9 +3,9 @@ Tools used to test the application: * **ESLint** (static code analysis of JS files) -* **Markdownlint** (static analysis of MD files) * **Stylelint** (static code analysis of CSS files) -* **Jest** (unit testing) +* **Markdownlint** (static code analysis of Markdown files) +* **Jest** (unit tests) * **Playwright** (visual and functional component testing) Generally, `npm test` and `npm run test:playwright-ct:all` should be run within @@ -13,17 +13,13 @@ their designated Docker containers before pushing changes to the repository. ## Tools -### Linters (ESlint, Markdownlint, Stylelint) - -**On host:** - -[Open][gh-gg-node-shell] `node_shell` Docker container: +Except Playwright, you can run all tests with a single command: ```bash -docker compose run --rm node_shell +npm run test ``` -**Within `node_shell`:** +### Linters (ESLint, Markdownlint, Stylelint) Run linters either all together: @@ -39,52 +35,18 @@ npm run ### Jest -**On host:** - -[Open][gh-gg-node-shell] `node_shell` Docker container: - ```bash -docker compose run --rm node_shell -``` - -**Within `node_shell`:** - -Run Jest tests: - -```bash -npm run test:jest +npm run jest ``` ### Playwright -Playwright tests must be run in a Docker container to ensure a uniform -environment. Otherwise, snapshots would differ between operating systems. - -This is the reason why you need to run Playwright tests separately -from other tools. - -#### Configuration +#### Configuration -Test parameters can be tweaked by creating and tweaking `.env.playwright` file: - -```bash -cp .env.playwright.dist .env.playwright -``` +Test parameters can be tweaked by creating and tweaking `.env` file. #### Running Tests -Playwright tests can be run using the following commands: - -**On host:** - -[Open][gh-gg-playwright] `playwright` Docker container: - -```bash -docker compose run --rm --service-ports playwright -``` - -**Within `playwright`:** - Run tests: ```bash @@ -116,6 +78,4 @@ Then open the displayed URL (typically `http://localhost:9323`) in your browser. Please note that the test report is only available if the tests were run prior to serving the report. -[gh-gg-node-shell]: ./general-guidelines.md#node-shell -[gh-gg-playwright]: ./general-guidelines.md#playwright [playwright-cli]: https://playwright.dev/docs/test-cli#reference diff --git a/tests/playwright/env/parseDotEnvFile.ts b/tests/playwright/env/parseDotEnvFile.ts index 02aa3a346..9f1ac73aa 100644 --- a/tests/playwright/env/parseDotEnvFile.ts +++ b/tests/playwright/env/parseDotEnvFile.ts @@ -1,6 +1,6 @@ import dotenv from 'dotenv'; -const PLAYWRIGHT_ENV_FILE = '.env.playwright'; +const PLAYWRIGHT_ENV_FILE = '.env'; /** * Load and parse Playwright environment file into an object. From dae197be57f212e913e8df8d0815e85e4741bd1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bed=C5=99ich=20Schindler?= Date: Fri, 27 Mar 2026 16:04:56 +0100 Subject: [PATCH 2/9] !fixup Introduce `devcontainer` service container based development environment (#705) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .devcontainer/devcontainer.json | 2 +- docker-compose.base.yml | 2 +- docker/react_ui_devcontainer/Dockerfile | 4 ++-- src/docs/contribute/testing-guidelines.md | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 776e3df25..61b61d945 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,7 +2,7 @@ "name": "React UI (${localWorkspaceFolderBasename})", "initializeCommand": "sh ./setup.sh", "dockerComposeFile": [ - "../docker-compose.yml", + "../docker-compose.yml" ], "service": "devcontainer", "shutdownAction": "stopCompose", diff --git a/docker-compose.base.yml b/docker-compose.base.yml index cb59f6c75..c48b9d7ba 100644 --- a/docker-compose.base.yml +++ b/docker-compose.base.yml @@ -76,7 +76,7 @@ services: ports: - ${COMPOSE_START_DOCS_SERVER_PORT}:8000 volumes: - - .:/workspace:ro + - .:/workspace:z volumes: # The following volumes are used to persist data (e.g. terminal history, AI tools data, etc.) across container restarts diff --git a/docker/react_ui_devcontainer/Dockerfile b/docker/react_ui_devcontainer/Dockerfile index 1e703af9b..068f156eb 100644 --- a/docker/react_ui_devcontainer/Dockerfile +++ b/docker/react_ui_devcontainer/Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Create the user RUN addgroup --gid $USER_GID $USERNAME && \ - adduser --uid $USER_UID --ingroup $USERNAME --home $HOME -shell $SHELL --disabled-password --gecos "" $USERNAME && \ + adduser --uid $USER_UID --ingroup $USERNAME --home $HOME --shell $SHELL --disabled-password --gecos "" $USERNAME && \ echo "$USERNAME ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME && \ chmod 0440 /etc/sudoers.d/$USERNAME @@ -85,7 +85,7 @@ RUN mkdir -p "$HOME/.config/claude" && \ # Install Open Code CLI RUN curl -fsSL https://opencode.ai/install | bash -s -- --no-modify-path -# Install Github Copilot CLI +# Install GitHub Copilot CLI # Note: Copilot CLI does not support XDG configuration, see: # * # * diff --git a/src/docs/contribute/testing-guidelines.md b/src/docs/contribute/testing-guidelines.md index ab50a214e..30aa046af 100644 --- a/src/docs/contribute/testing-guidelines.md +++ b/src/docs/contribute/testing-guidelines.md @@ -36,12 +36,12 @@ npm run ### Jest ```bash -npm run jest +npm run test:jest ``` ### Playwright -#### Configuration +#### Configuration Test parameters can be tweaked by creating and tweaking `.env` file. From cae210f63fbdb471dbf38aceaaa8c4f0d5983eee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bedr=CC=8Cich=20Schindler?= Date: Fri, 27 Mar 2026 16:09:18 +0100 Subject: [PATCH 3/9] fixup! !fixup Introduce `devcontainer` service container based development environment (#705) --- docker/build-docker-images.sh | 2 +- docker/react_ui_devcontainer_local/Dockerfile.dist | 2 +- setup.sh | 2 +- src/docs/contribute/general-guidelines.md | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docker/build-docker-images.sh b/docker/build-docker-images.sh index cb49e0d01..0030311d7 100644 --- a/docker/build-docker-images.sh +++ b/docker/build-docker-images.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash set -e trap 'echo "Failed to build Docker images"; exit 1' ERR diff --git a/docker/react_ui_devcontainer_local/Dockerfile.dist b/docker/react_ui_devcontainer_local/Dockerfile.dist index cc6c1d498..b61d6a879 100644 --- a/docker/react_ui_devcontainer_local/Dockerfile.dist +++ b/docker/react_ui_devcontainer_local/Dockerfile.dist @@ -1,4 +1,4 @@ -# react-ui_devcontainer might differ based on Docker compose project name +# Image name `react-ui_devcontainer` might differ based on Docker compose project name FROM react-ui_devcontainer as react-ui_devcontainer_local # Your additional setup for the local development can go here diff --git a/setup.sh b/setup.sh index a8acc4451..7678e1557 100755 --- a/setup.sh +++ b/setup.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash DEFAULT_PROJECT_NAME="react-ui" DEFAULT_USER_ID=1000 diff --git a/src/docs/contribute/general-guidelines.md b/src/docs/contribute/general-guidelines.md index 726201166..1f14b4149 100644 --- a/src/docs/contribute/general-guidelines.md +++ b/src/docs/contribute/general-guidelines.md @@ -101,6 +101,7 @@ To customize the `devcontainer`, create a `docker/react_ui_devcontainer_local/Dockerfile` that extends the base image: ```Dockerfile +# Image name `react-ui_devcontainer` might differ based on Docker compose project name FROM react-ui_devcontainer as react-ui_devcontainer_local # Add your customizations here ``` From 3195ad699056f9d713c757503ac54d86ddd4a2e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bedr=CC=8Cich=20Schindler?= Date: Fri, 27 Mar 2026 19:04:07 +0100 Subject: [PATCH 4/9] fixup! fixup! !fixup Introduce `devcontainer` service container based development environment (#705) --- .devcontainer/devcontainer.json | 2 +- src/docs/contribute/general-guidelines.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 61b61d945..3a1fa1795 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,6 @@ { "name": "React UI (${localWorkspaceFolderBasename})", - "initializeCommand": "sh ./setup.sh", + "initializeCommand": "bash ./setup.sh", "dockerComposeFile": [ "../docker-compose.yml" ], diff --git a/src/docs/contribute/general-guidelines.md b/src/docs/contribute/general-guidelines.md index 1f14b4149..3a243ba88 100644 --- a/src/docs/contribute/general-guidelines.md +++ b/src/docs/contribute/general-guidelines.md @@ -32,7 +32,7 @@ Run the setup script to automatically create and configure all necessary files and build Docker images: ```bash -sh setup.sh +bash setup.sh ``` [Development Containers] run this script automatically if the project has not @@ -57,7 +57,7 @@ If you prefer to set up the project manually: 3. Build Docker images: ```bash - sh docker/build-docker-images.sh + bash docker/build-docker-images.sh ``` #### Environment @@ -122,7 +122,7 @@ devcontainer: Rebuild the images after making changes: ```bash -sh docker/build-docker-images.sh +bash docker/build-docker-images.sh ``` If you need to persist additional data across container restarts, see how it is From 92e80ca8261ecab5268318081086264715173323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bedr=CC=8Cich=20Schindler?= Date: Fri, 27 Mar 2026 19:08:03 +0100 Subject: [PATCH 5/9] fixup! fixup! fixup! !fixup Introduce `devcontainer` service container based development environment (#705) --- src/docs/contribute/general-guidelines.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/docs/contribute/general-guidelines.md b/src/docs/contribute/general-guidelines.md index 3a243ba88..9dc76af92 100644 --- a/src/docs/contribute/general-guidelines.md +++ b/src/docs/contribute/general-guidelines.md @@ -138,7 +138,6 @@ The `devcontainer` is built in the following layers: General-purpose development layer. Makes the environment container-agnostic by wrapping commands to run in the appropriate service containers. - * **OS:** Debian Bookworm * **Shells:** Bash, Zsh (with Oh My Zsh), Fish * **Editors:** Vim, Nano @@ -309,7 +308,6 @@ the documentation platform. Do see their respective documentation for details. -[apple-silicon-issue]: https://racom-jira.atlassian.net/browse/WECL-312 [Development Containers]: https://containers.dev/ [Docker]: https://docs.docker.com/get-started/ [Docker Compose]: https://docs.docker.com/compose/ From 8cf087bd63927852c35685654ffad9cb6c9a1183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bedr=CC=8Cich=20Schindler?= Date: Fri, 27 Mar 2026 19:24:25 +0100 Subject: [PATCH 6/9] fixup! fixup! fixup! fixup! !fixup Introduce `devcontainer` service container based development environment (#705) --- CLAUDE.md | 3 ++- src/docs/contribute/testing-guidelines.md | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 443df34ae..65b606a1c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,7 +5,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Commands All commands below are meant to be run directly inside the Docker container `devcontainer`. -If project is started using Development Containers, run it without starting the Docker. +If you open the project in a Dev Container, you can run these commands without manually +starting Docker Compose on the host. ```bash diff --git a/src/docs/contribute/testing-guidelines.md b/src/docs/contribute/testing-guidelines.md index 30aa046af..33b235bb7 100644 --- a/src/docs/contribute/testing-guidelines.md +++ b/src/docs/contribute/testing-guidelines.md @@ -13,10 +13,10 @@ their designated Docker containers before pushing changes to the repository. ## Tools -Except Playwright, you can run all tests with a single command: +You can run all tests with a single command: ```bash -npm run test +npm run lint && npm test && npm run test:playwright-ct:all ``` ### Linters (ESLint, Markdownlint, Stylelint) From b0cee5fa4286a3ca1df53f8d2f7938c31a08598f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bedr=CC=8Cich=20Schindler?= Date: Fri, 27 Mar 2026 19:30:12 +0100 Subject: [PATCH 7/9] fixup! fixup! fixup! fixup! fixup! !fixup Introduce `devcontainer` service container based development environment (#705) --- docker/build-docker-images.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker/build-docker-images.sh b/docker/build-docker-images.sh index 0030311d7..03ad3368e 100644 --- a/docker/build-docker-images.sh +++ b/docker/build-docker-images.sh @@ -7,6 +7,11 @@ cd "$(dirname "$0")" echo "Building Docker images..." +if [ ! -f ../.env ]; then + echo "Error: .env file not found in the project root" + exit 1 +fi + PROJECT_NAME=$(grep -E '^COMPOSE_PROJECT_NAME=' ../.env | cut -d '=' -f 2-) PROJECT_DEVCONTAINER_IMAGE="${PROJECT_NAME}_devcontainer" From 58cd4e51bb630d3e95523602b08b8beaa6f90587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bedr=CC=8Cich=20Schindler?= Date: Fri, 27 Mar 2026 19:42:43 +0100 Subject: [PATCH 8/9] fixup! fixup! fixup! fixup! fixup! fixup! !fixup Introduce `devcontainer` service container based development environment (#705) --- docker/react_ui_devcontainer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/react_ui_devcontainer/Dockerfile b/docker/react_ui_devcontainer/Dockerfile index 068f156eb..a0765218d 100644 --- a/docker/react_ui_devcontainer/Dockerfile +++ b/docker/react_ui_devcontainer/Dockerfile @@ -62,7 +62,7 @@ RUN install -m 0755 -d /etc/apt/keyrings && \ USER $USERNAME:$USERNAME # Install Oh My Zsh -RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" +RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended # Persist terminal history across container restarts via a Docker volume # mounted at $HOME/.terminal_history in docker-compose.base.yml From 1bf514f869f8bd7775f2780b8c906be7ed1f4287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bedr=CC=8Cich=20Schindler?= Date: Fri, 27 Mar 2026 20:35:27 +0100 Subject: [PATCH 9/9] fixup! fixup! fixup! fixup! fixup! fixup! fixup! !fixup Introduce `devcontainer` service container based development environment (#705) --- setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index 7678e1557..e62a87db6 100755 --- a/setup.sh +++ b/setup.sh @@ -5,7 +5,7 @@ DEFAULT_USER_ID=1000 DEFAULT_GROUP_ID=1000 set -e -trap 'echo "Failed to setup project"; exit 1' ERR +trap 'echo "Failed to setup project"; rf -f .env.temp; exit 1' ERR # Function to handle sed command with cross-platform compatibility sed_cmd() {