-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Devcontainer support and integrated with vscode for agile development and testing #1274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughA complete development container environment for the Crawl4AI project is introduced. This includes a custom Dockerfile, Docker Compose setup, environment variable configuration, and detailed documentation. The setup provisions Python, Node.js, Docker CLI, Redis, Playwright, and various development tools, along with VS Code integration, shell customizations, and workflow instructions. Changes
Sequence Diagram(s)sequenceDiagram
participant Dev as Developer
participant VSCode as VS Code/Cursor
participant DevContainer as Dev Container
participant Redis as Redis
participant API as Crawl4AI API Server
Dev->>VSCode: Open project in dev container
VSCode->>DevContainer: Launch devcontainer (Docker Compose)
DevContainer->>Redis: Connect on port 6379
DevContainer->>API: (Optional) Interact via exposed API port 11235
Dev->>DevContainer: Use shell, run tests, debug, develop
DevContainer->>Dev: Provide tooling, Python, Node, Playwright, Docker CLI
API->>Redis: Use Redis for caching/data
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (3)
.devcontainer/Dockerfile.dev (1)
134-153
: Repository GPG keys are added but not fingerprint-checkedBoth Docker & NodeSource keys are imported without validating the fingerprint. A malicious MITM could still inject a key.
Example hardening:
curl -fsSL https://download.docker.com/linux/debian/gpg \ | gpg --dearmor -o /etc/apt/keyrings/docker.gpg gpg --show-keys /etc/apt/keyrings/docker.gpg | grep '9DC8 5822 9FC7 DD38' || exit 1Same for NodeSource.
.devcontainer/devcontainer.json (1)
63-64
:python.languageServer
is deprecatedThe pylance extension now manages itself; the setting is ignored and will be removed in upcoming VS Code releases. You can drop it safely.
.devcontainer/README.md (1)
19-26
: Use proper heading syntax instead of emphasised textLines 19–26 trigger
MD036
because**Opción A: VS Code**
is used as a heading. Replace with### Opción A: VS Code
(and the same for “Opción B”) to silence markdown-lint and improve structure.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
.devcontainer/Dockerfile.dev
(1 hunks).devcontainer/README.md
(1 hunks).devcontainer/devcontainer.json
(1 hunks).devcontainer/docker-compose.yml
(1 hunks).env.dev
(1 hunks)
🧰 Additional context used
🪛 LanguageTool
.devcontainer/README.md
[misspelling] ~9-~9: Si es adjetivo o nombre, se escribe con tilde.
Context: ...estión de contenedores - Redis para cache y cola de tareas - API Server de Cr...
(DIACRITICS_VERB_N_ADJ)
[style] ~175-~175: Considere alternativas para este anglicismo (recomendable sobre todo en contextos más formales).
Context: ... ## 🚀 Tips Avanzados ### Ejecutar Crawl Local
python from crawl4ai import A...
(ES_SIMPLE_REPLACE_ANGLICISM_PREMIUM_CRAWL)
[misspelling] ~215-~215: Si es adjetivo o nombre, se escribe con tilde.
Context: ...s extensiones de VS Code se persisten - El cache de Playwright se mantiene entre sesione...
(DIACRITICS_VERB_N_ADJ)
🪛 markdownlint-cli2 (0.17.2)
.devcontainer/README.md
19-19: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
26-26: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
36-36: Bare URL used
(MD034, no-bare-urls)
37-37: Bare URL used
(MD034, no-bare-urls)
39-39: Bare URL used
(MD034, no-bare-urls)
111-111: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (1)
.devcontainer/docker-compose.yml (1)
25-29
:SYS_PTRACE
+seccomp:unconfined
give the container full debugging powersThat’s fine for local dev but worth highlighting: any code executed inside the container can ptrace the host-namespace processes once the Docker socket is also mounted.
If you publish this compose file, add an explicit comment or conditional flag so CI/remote users don’t inherit unnecessary privileges.
OPENAI_API_KEY=sk-mock-openai-key-for-development | ||
DEEPSEEK_API_KEY=mock-deepseek-api-key-for-development | ||
ANTHROPIC_API_KEY=mock-anthropic-api-key-for-development | ||
GROQ_API_KEY=mock-groq-api-key-for-development | ||
TOGETHER_API_KEY=mock-together-api-key-for-development | ||
MISTRAL_API_KEY=mock-mistral-api-key-for-development | ||
GEMINI_API_TOKEN=mock-gemini-api-token-for-development | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Treat credentials-like values as secrets – move them out of version control
Even though the keys and the JWT secret are mocked, keeping a real .env.dev
with populated values in the repo normalises checking secrets in. Accidental replacement with production keys is a common “paper-cut” incident.
Consider:
-OPENAI_API_KEY=sk-mock-openai-key-for-development
+# example only – real keys must be supplied via a local override
+OPENAI_API_KEY=
and add the file to .gitignore
, keeping a committed .env.dev.example
instead, then reference it through env_file:
in docker-compose.yml
.
This keeps the workflow unchanged while removing the latent risk.
Also applies to: 50-53
🏁 Script executed:
#!/bin/bash
echo "Listing .env files:"
find . -maxdepth 2 -type f -name ".env*"
echo
echo "Checking .gitignore for env patterns:"
grep -R ".env" -n .gitignore || true
echo
echo "Searching for .env.dev.example:"
find . -maxdepth 2 -type f -name ".env.dev.example"
echo
echo "Searching for env_file references in docker-compose files:"
grep -R "env_file" -n .
Length of output: 926
Move .env.dev
out of version control and use an example file
Your .env.dev
is currently committed—even though .gitignore
ignores only .env
, not .env.dev
. There’s also no .env.dev.example
to serve as a template. To prevent accidental check-ins of real keys:
• Rename .env.dev
→ .env.dev.example
, commit that with empty values
• Add .env.dev
to your .gitignore
• Update docker-compose.yml
to continue referencing env_file: .env.dev
Example diff:
--- a/.env.dev
+++ b/.env.dev.example
@@
-OPENAI_API_KEY=sk-mock-openai-key-for-development
-DEEPSEEK_API_KEY=mock-deepseek-api-key-for-development
-ANTHROPIC_API_KEY=mock-anthropic-api-key-for-development
-GROQ_API_KEY=mock-groq-api-key-for-development
-TOGETHER_API_KEY=mock-together-api-key-for-development
-MISTRAL_API_KEY=mock-mistral-api-key-for-development
-GEMINI_API_TOKEN=mock-gemini-api-token-for-development
+OPENAI_API_KEY=
+DEEPSEEK_API_KEY=
+ANTHROPIC_API_KEY=
+GROQ_API_KEY=
+TOGETHER_API_KEY=
+MISTRAL_API_KEY=
+GEMINI_API_TOKEN=
--- a/.gitignore
+++ b/.gitignore
@@ -124,6 +124,7 @@ test_env/
.llm.env
+.env.dev
No changes needed in docker-compose.yml
aside from ensuring it points to the untracked .env.dev
. This preserves your workflow while removing any latent secret-leak risk.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
OPENAI_API_KEY=sk-mock-openai-key-for-development | |
DEEPSEEK_API_KEY=mock-deepseek-api-key-for-development | |
ANTHROPIC_API_KEY=mock-anthropic-api-key-for-development | |
GROQ_API_KEY=mock-groq-api-key-for-development | |
TOGETHER_API_KEY=mock-together-api-key-for-development | |
MISTRAL_API_KEY=mock-mistral-api-key-for-development | |
GEMINI_API_TOKEN=mock-gemini-api-token-for-development | |
# Rename .env.dev → .env.dev.example with empty values | |
OPENAI_API_KEY= | |
DEEPSEEK_API_KEY= | |
ANTHROPIC_API_KEY= | |
GROQ_API_KEY= | |
TOGETHER_API_KEY= | |
MISTRAL_API_KEY= | |
GEMINI_API_TOKEN= |
OPENAI_API_KEY=sk-mock-openai-key-for-development | |
DEEPSEEK_API_KEY=mock-deepseek-api-key-for-development | |
ANTHROPIC_API_KEY=mock-anthropic-api-key-for-development | |
GROQ_API_KEY=mock-groq-api-key-for-development | |
TOGETHER_API_KEY=mock-together-api-key-for-development | |
MISTRAL_API_KEY=mock-mistral-api-key-for-development | |
GEMINI_API_TOKEN=mock-gemini-api-token-for-development | |
# .gitignore (add below .llm.env) | |
test_env/ | |
.llm.env | |
.env.dev |
🤖 Prompt for AI Agents
In the .env.dev file from lines 4 to 11, the issue is that this file with mock
API keys is currently committed to version control, which risks exposing
secrets. To fix this, rename .env.dev to .env.dev.example and replace all values
with empty strings to serve as a template. Then add .env.dev to your .gitignore
file to prevent it from being committed. Finally, ensure docker-compose.yml
still references .env.dev as the env_file so your workflow remains unchanged but
secrets are protected.
RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended \ | ||
&& echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc \ | ||
&& echo 'alias ll="ls -la"' >> ~/.zshrc \ | ||
&& echo 'alias gs="git status"' >> ~/.zshrc \ | ||
&& echo 'alias gp="git pull"' >> ~/.zshrc \ | ||
&& echo 'alias gc="git commit"' >> ~/.zshrc \ | ||
&& echo 'alias gco="git checkout"' >> ~/.zshrc \ | ||
&& echo 'alias dev="python -m crawl4ai.server"' >> ~/.zshrc \ | ||
&& echo 'alias test="pytest -v"' >> ~/.zshrc \ | ||
&& echo 'alias fmt="black . && ruff check . --fix"' >> ~/.zshrc \ | ||
&& echo 'alias crawl="crawl4ai-doctor && python -m crawl4ai.server"' >> ~/.zshrc \ | ||
&& echo 'alias redis-status="redis-cli ping"' >> ~/.zshrc | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curl | sh
without verification is a supply-chain risk
Executing remote scripts blindly (Oh-My-Zsh installer) means the image build will run whatever that URL serves at build time.
Safer pattern:
curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh \
| grep -q 'checksum-value' # verify expected content
or pin to a specific commit and GPG-verify.
🤖 Prompt for AI Agents
In .devcontainer/Dockerfile.dev around lines 114 to 126, the current RUN command
downloads and executes the Oh-My-Zsh install script directly via curl without
verifying its integrity, which is a supply-chain risk. To fix this, modify the
Dockerfile to first download the script to a temporary file, verify its checksum
or GPG signature against a known trusted value or pinned commit, and only then
execute it if verification passes. This ensures the script has not been tampered
with before running it during the image build.
RUN pip install --upgrade pip setuptools wheel \ | ||
&& pip install \ | ||
uv \ | ||
poetry \ | ||
black \ | ||
ruff \ | ||
mypy \ | ||
pytest \ | ||
pytest-cov \ | ||
pytest-asyncio \ | ||
pytest-xdist \ | ||
ipython \ | ||
ipdb \ | ||
rich \ | ||
httpx \ | ||
pydantic \ | ||
python-dotenv \ | ||
pre-commit \ | ||
commitizen \ | ||
python-semantic-release \ | ||
pylint \ | ||
bandit \ | ||
safety \ | ||
notebook \ | ||
jupyterlab \ | ||
mcp \ | ||
fastmcp | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Unpinned pip install
list breaks reproducibility
Everything is installed at “latest”. A dev-container is expected to be deterministic; tomorrow’s ruff
or pytest
release can brick everyone’s environment.
Pin at least major versions or, preferably, freeze the whole stack in requirements-dev.lock
and do:
- RUN pip install \
- uv \
- poetry \
- ...
+COPY requirements-dev.lock /tmp/
+RUN pip install -r /tmp/requirements-dev.lock
This also lets Dependabot/Safety give you meaningful reports.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In .devcontainer/Dockerfile.dev around lines 82 to 109, the pip install commands
install packages without version pins, which breaks reproducibility. To fix
this, create a requirements-dev.lock file that freezes all development
dependencies with exact versions, then modify the Dockerfile to install packages
using this lock file instead of listing packages individually. This ensures
deterministic builds and enables better vulnerability and update tracking.
environment: | ||
- REDIS_HOST=redis | ||
- REDIS_PORT=6379 | ||
- OPENAI_API_KEY=mock_openai_key | ||
- ANTHROPIC_API_KEY=mock_anthropic_key | ||
- GROQ_API_KEY=mock_groq_key | ||
- TOGETHER_API_KEY=mock_together_key | ||
- MISTRAL_API_KEY=mock_mistral_key | ||
- GEMINI_API_TOKEN=mock_gemini_token | ||
- DEEPSEEK_API_KEY=mock_deepseek_key | ||
- DEVELOPMENT=true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Duplicate env vars – prefer a central env_file
The API service re-lists every key already present in .env.dev
, diverging from the single-source-of-truth idea and creating drift risk.
- environment:
- - REDIS_HOST=redis
- - REDIS_PORT=6379
- - OPENAI_API_KEY=mock_openai_key
- ...
+ env_file:
+ - ../.env.dev
+ environment:
+ # only overrides that differ from .env.dev
+ - REDIS_HOST=redis
This keeps the config dry and future-proof.
🤖 Prompt for AI Agents
In .devcontainer/docker-compose.yml around lines 62 to 72, the environment
variables for the API service are duplicated instead of referencing the central
.env.dev file. To fix this, remove the explicit environment variable listings
under the API service and replace them with a reference to the env_file key
pointing to .env.dev. This ensures a single source of truth for environment
variables and prevents configuration drift.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (3)
.devcontainer/start-services.sh (1)
48-59
: Potential endless wait whenredis-cli
is absent.If
redis-cli
is not installed the loop keeps retrying until timeout,
printing “Redis no está disponible” although the service may be healthy.
Consider:
- Abort early when
redis-cli
is missing.- Or use
nc -z redis 6379
as a fallback check..devcontainer/setup.sh (2)
5-9
: Avoid unconditionalsudo
; fall back gracefully.
sudo
may not exist or be required (root container). Check first:- sudo chmod 666 /var/run/docker.sock + (command -v sudo >/dev/null 2>&1 && sudo chmod 666 /var/run/docker.sock) \ + || chmod 666 /var/run/docker.sock
79-82
: Consider usingpip install -e ".[dev,all]"
with a requirements lock.Pinned deps avoid “works-on-my-machine” syndrome and speed up rebuilds.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.devcontainer/setup.sh
(1 hunks).devcontainer/start-services.sh
(1 hunks).gitignore
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- .gitignore
🧰 Additional context used
🪛 Shellcheck (0.10.0)
.devcontainer/setup.sh
[warning] 78-78: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.
(SC2164)
🔇 Additional comments (1)
.devcontainer/start-services.sh (1)
16-23
: Verify sudo availability before use in.devcontainer/start-services.sh
I wasn’t able to locate
start-services.sh
to confirm, so please ensure you guard against missingsudo
(common in root-based devcontainers). For example:- if ! groups "$USER" | grep -q docker; then - sudo usermod -aG docker "$USER" + if ! groups "$USER" | grep -q docker; then + if command -v sudo >/dev/null 2>&1; then + sudo usermod -aG docker "$USER" + else + usermod -aG docker "$USER" + fiThis ensures the script won’t fail if
sudo
isn’t installed.
#!/bin/bash | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add strict‐mode guards (set -euo pipefail
).
Fail fast to avoid cascading errors and make debugging easier.
#!/bin/bash
+set -euo pipefail
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
#!/bin/bash | |
#!/bin/bash | |
set -euo pipefail |
🤖 Prompt for AI Agents
In .devcontainer/start-services.sh at lines 1 to 2, add the strict-mode guards
by inserting the line 'set -euo pipefail' immediately after the shebang line.
This will cause the script to exit on errors, unset variables, or failed pipes,
improving reliability and debugging.
cat > /tmp/test_crawl4ai.py << 'EOF' | ||
#!/usr/bin/env python3 | ||
""" | ||
Test rápido de Crawl4AI | ||
""" | ||
import asyncio | ||
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig | ||
|
||
async def test_basic_crawl(): | ||
print("🧪 Probando crawl básico...") | ||
try: | ||
browser_config = BrowserConfig(headless=True) | ||
crawler_config = CrawlerRunConfig(cache_mode="bypass") | ||
|
||
async with AsyncWebCrawler(config=browser_config) as crawler: | ||
result = await crawler.arun( | ||
url="https://httpbin.org/html", | ||
config=crawler_config | ||
) | ||
|
||
if result.success: | ||
print(f"✅ Crawl exitoso! Contenido: {len(result.markdown)} caracteres") | ||
return True | ||
else: | ||
print(f"❌ Crawl falló: {result.error}") | ||
return False | ||
except Exception as e: | ||
print(f"❌ Error: {e}") | ||
return False | ||
|
||
if __name__ == "__main__": | ||
success = asyncio.run(test_basic_crawl()) | ||
exit(0 if success else 1) | ||
EOF |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use sys.exit
rather than the interactive exit
helper.
exit()
comes from the site
module and isn’t guaranteed in non-interactive
scripts. Switch to sys.exit
for reliability.
@@
-import asyncio
+import sys, asyncio
@@
-if __name__ == "__main__":
- success = asyncio.run(test_basic_crawl())
- exit(0 if success else 1)
+if __name__ == "__main__":
+ success = asyncio.run(test_basic_crawl())
+ sys.exit(0 if success else 1)
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
cat > /tmp/test_crawl4ai.py << 'EOF' | |
#!/usr/bin/env python3 | |
""" | |
Test rápido de Crawl4AI | |
""" | |
import asyncio | |
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig | |
async def test_basic_crawl(): | |
print("🧪 Probando crawl básico...") | |
try: | |
browser_config = BrowserConfig(headless=True) | |
crawler_config = CrawlerRunConfig(cache_mode="bypass") | |
async with AsyncWebCrawler(config=browser_config) as crawler: | |
result = await crawler.arun( | |
url="https://httpbin.org/html", | |
config=crawler_config | |
) | |
if result.success: | |
print(f"✅ Crawl exitoso! Contenido: {len(result.markdown)} caracteres") | |
return True | |
else: | |
print(f"❌ Crawl falló: {result.error}") | |
return False | |
except Exception as e: | |
print(f"❌ Error: {e}") | |
return False | |
if __name__ == "__main__": | |
success = asyncio.run(test_basic_crawl()) | |
exit(0 if success else 1) | |
EOF | |
cat > /tmp/test_crawl4ai.py << 'EOF' | |
#!/usr/bin/env python3 | |
""" | |
Test rápido de Crawl4AI | |
""" | |
import sys, asyncio | |
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig | |
async def test_basic_crawl(): | |
print("🧪 Probando crawl básico...") | |
try: | |
browser_config = BrowserConfig(headless=True) | |
crawler_config = CrawlerRunConfig(cache_mode="bypass") | |
async with AsyncWebCrawler(config=browser_config) as crawler: | |
result = await crawler.arun( | |
url="https://httpbin.org/html", | |
config=crawler_config | |
) | |
if result.success: | |
print(f"✅ Crawl exitoso! Contenido: {len(result.markdown)} caracteres") | |
return True | |
else: | |
print(f"❌ Crawl falló: {result.error}") | |
return False | |
except Exception as e: | |
print(f"❌ Error: {e}") | |
return False | |
if __name__ == "__main__": | |
success = asyncio.run(test_basic_crawl()) | |
sys.exit(0 if success else 1) | |
EOF |
🤖 Prompt for AI Agents
In .devcontainer/start-services.sh around lines 76 to 109, the script uses the
interactive exit() helper to terminate the program, which is not reliable in
non-interactive scripts. Import the sys module at the top of the Python script
and replace exit(0 if success else 1) with sys.exit(0 if success else 1) to
ensure proper script termination.
#!/bin/bash | ||
|
||
echo "🔧 Configurando entorno de desarrollo Crawl4AI..." | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enable strict shell options.
Add set -euo pipefail
right after the shebang to surface failures early.
#!/bin/bash
+set -euo pipefail
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
#!/bin/bash | |
echo "🔧 Configurando entorno de desarrollo Crawl4AI..." | |
#!/bin/bash | |
set -euo pipefail | |
echo "🔧 Configurando entorno de desarrollo Crawl4AI..." |
🤖 Prompt for AI Agents
In .devcontainer/setup.sh at the beginning of the file (lines 1 to 4), add the
line `set -euo pipefail` immediately after the shebang (`#!/bin/bash`). This
will enable strict shell options to make the script exit on errors, undefined
variables, and failures in pipelines, helping to catch issues early during
execution.
cd /workspace | ||
pip install -e ".[all]" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Handle cd
failure (ShellCheck SC2164).
The hard-coded /workspace
path may be absent in some hosts (Codespaces uses /workspaces/<repo>
). Fail loudly or use $PWD
-relative path.
-cd /workspace
+cd /workspace || { echo "❌ /workspace not found"; exit 1; }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
cd /workspace | |
pip install -e ".[all]" | |
cd /workspace || { echo "❌ /workspace not found"; exit 1; } | |
pip install -e ".[all]" |
🧰 Tools
🪛 Shellcheck (0.10.0)
[warning] 78-78: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.
(SC2164)
🤖 Prompt for AI Agents
In .devcontainer/setup.sh around lines 78 to 80, the script changes directory to
a hard-coded /workspace path which may not exist on all hosts, causing silent
failures. Modify the script to check if /workspace exists before cd or use a
relative path based on $PWD to ensure the directory change succeeds or fail
loudly with an error message if the directory is missing.
Summary
Added Development Container support to streamline the development environment setup and ensure consistent development experience across different platforms. This implementation includes a complete dev container configuration with VS Code/Cursor integration, pre-configured tools, and automated service management.
List of files changed and why
How Has This Been Tested?
Verified building of the containers inside devcontainer and integrated with vscode in macOS 15.5
Checklist:
Implemented consistent formatting across all dev container files
Used standard Docker and dev container best practices
Followed project's Python code style
Reviewed all configuration files for security best practices
Verified environment variable handling
Checked for potential permission issues
Validated service dependencies and health checks
Added detailed comments in devcontainer.json for configuration sections
Documented Dockerfile.dev build stages and dependencies
Included explanatory comments in docker-compose.yml
Added comprehensive setup instructions in README.md
Created detailed .devcontainer/README.md
Added dev container setup instructions
Documented available development tools and commands
Included troubleshooting guide and best practices
Dev container configuration itself doesn't require unit tests

Environment setup has been validated through manual testing
Service health checks are in place
Development workflow has been verified
Future ideas
I would like to integrate this as a terraform template in coder.com for use as provisionable environment.
Summary by CodeRabbit
New Features
Documentation