Skip to content

Improved devcontainer setup with e2e test mini infra #2672

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

Merged
merged 13 commits into from
Aug 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions .devcontainer/.env.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
IMAGE=bitnami/ruby
# Official Ruby images
IMAGE="ruby:3.4.5-slim-bookworm"
VERSION="3.4.5"

# Adjust as needed
TAG=3.4
# IMAGE="jruby:latest"

# IMAGE=jruby
# TAG=latest
# E2E testing
SENTRY_DSN="http://user:[email protected]/project/42"
SENTRY_DSN_JS="http://user:[email protected]/project/43"

SENTRY_E2E_RAILS_APP_PORT=4000
SENTRY_E2E_SVELTE_APP_PORT=4001

SENTRY_E2E_RAILS_APP_URL="http://localhost:4000"
SENTRY_E2E_SVELTE_APP_URL="http://localhost:4001"

# Faster builds with compose
COMPOSE_BAKE=true
34 changes: 16 additions & 18 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
ARG IMAGE="bitnami/ruby"
ARG TAG="latest"
ARG IMAGE="ruby"

FROM ${IMAGE}:${TAG}
FROM ${IMAGE} AS build

USER root
RUN apt-get update && apt-get install -y \
RUN apt-get update && apt-get install -y --no-install-recommends \
sudo \
gnupg \
git \
curl \
wget \
zsh \
vim \
build-essential \
sudo \
pkg-config \
libssl-dev \
libreadline-dev \
zlib1g-dev \
Expand All @@ -22,31 +19,32 @@ RUN apt-get update && apt-get install -y \
libncurses5-dev \
libffi-dev \
libgdbm-dev \
sqlite3 \
nodejs \
npm \
chromium \
chromium-driver \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

RUN groupadd --gid 1000 sentry \
&& useradd --uid 1000 --gid sentry --shell /bin/zsh --create-home sentry

# Add sentry to sudoers with NOPASSWD option
RUN echo "sentry ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/sentry \
&& chmod 0440 /etc/sudoers.d/sentry

RUN groupadd --gid 1000 sentry \
&& useradd --uid 1000 --gid sentry --shell /bin/bash --create-home sentry

WORKDIR /workspace/sentry

RUN chown -R sentry:sentry /workspace/sentry
RUN mkdir /workspace/gems && chown -R sentry:sentry /workspace/gems

ARG TAG=latest
ARG GEM_HOME="/workspace/gems/${TAG}"
ARG VERSION
ARG GEM_HOME="/workspace/sentry/vendor/gems/${VERSION}"

ENV LANG=C.UTF-8 \
BUNDLE_JOBS=4 \
BUNDLE_RETRY=3 \
GEM_HOME=/workspace/gems/${TAG} \
GEM_HOME=/workspace/sentry/vendor/gems/${VERSION} \
PATH=$PATH:${GEM_HOME}/bin \
REDIS_HOST=redis

USER sentry

CMD ["ruby", "--version"]
23 changes: 16 additions & 7 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
{
"name": "sentry-ruby",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"service": "sentry-dev",
"workspaceFolder": "/workspace/sentry",
"features": {
"ghcr.io/devcontainers/features/github-cli": {},
"ghcr.io/nils-geistmann/devcontainers-features/zsh": {},
"ghcr.io/devcontainers-extra/features/npm-packages": {},
"ghcr.io/rocker-org/devcontainer-features/apt-packages": {
"packages": "inotify-tools"
}
},
"customizations": {
"vscode": {
"extensions": [
"sleistner.vscode-fileutils",
"Shopify.ruby-lsp"
],
"settings": {}
},
"rubyLsp.rubyVersionManager": {
"identifier": "none"
"editor.formatOnSaveMode": "modifications",
"editor.formatOnSave": true,
"rubyLsp.rubyVersionManager": {
"identifier": "auto"
},
"rubyLsp.formatter": "auto"
}
},
"remoteUser": "sentry",
"postCreateCommand": "ruby --version"
"remoteUser": "sentry"
}
27 changes: 20 additions & 7 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
services:
app:
sentry-build: &sentry-build
image: ${DOCKER_IMAGE:-sentry-ruby-devcontainer}:${DOCKER_TAG:-latest}
build:
context: .
dockerfile: Dockerfile
context: ..
dockerfile: .devcontainer/Dockerfile
args:
IMAGE: ${IMAGE}
TAG: ${TAG}
VERSION: ${VERSION}
volumes:
- ..:/workspace/sentry:cached
command: sleep infinity
environment:
- REDIS_URL=${REDIS_URL:-redis://redis:6379/0}
working_dir: /workspace/sentry
env_file: [".env"]

sentry-dev:
<<: *sentry-build
entrypoint: ".devcontainer/run --service dev"
command: "sleep infinity"
depends_on:
- redis

sentry-test:
<<: *sentry-build
entrypoint: ".devcontainer/run --service test"
command: ["foreman", "start"]
ports:
- "${SENTRY_E2E_RAILS_APP_PORT}:4000"
- "${SENTRY_E2E_SVELTE_APP_PORT}:4001"

redis:
image: redis:latest
environment:
Expand Down
92 changes: 92 additions & 0 deletions .devcontainer/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/bin/bash

set -e

cd /workspace/sentry

sudo mkdir -p vendor/gems
sudo chown -R sentry:sentry vendor/gems

git config --global --add safe.directory /workspace/sentry
git config --global --add safe.directory /workspace/sentry/vendor/gems/*

sudo chown -R sentry:sentry .

run_service_setup() {
local service="$1"

echo "🚀 Running setup for service: $service"

case "$service" in
"dev")
if ! .devcontainer/setup --with-foreman --only-bundle; then
echo "❌ Setup failed for service: $service"
exit 1
fi
;;
"test")
if ! .devcontainer/setup --with-foreman --only .,spec/apps/rails-mini; then
echo "❌ Setup failed for service: $service"
exit 1
fi
;;
*)
echo "❌ Unknown service: $service"
echo "Available services: dev, test"
exit 1
;;
esac

echo "✅ Setup completed for service: $service"
}

# Function to start services in background
start_services_if_needed() {
# Check if we're running tests (bundle exec rake)
if [[ "$*" == *"bundle exec rake"* ]]; then
echo "🚀 Starting e2e services in background for test execution..."

# Start foreman in background
foreman start &
FOREMAN_PID=$!

# Wait for services to be ready
echo "⏳ Waiting for services to start..."
for i in {1..30}; do
if curl -f http://localhost:4000/health >/dev/null 2>&1 && \
curl -f http://localhost:4001/health >/dev/null 2>&1; then
echo "✅ Services are ready!"
break
fi

if [ $i -eq 30 ]; then
echo "❌ Services failed to start within timeout"
kill $FOREMAN_PID 2>/dev/null || true
exit 1
fi

sleep 2
done

# Set up cleanup trap
trap "echo '🧹 Stopping services...'; kill $FOREMAN_PID 2>/dev/null || true; wait $FOREMAN_PID 2>/dev/null || true" EXIT
fi
}

# Parse arguments
if [ "$1" = "--service" ] && [ -n "$2" ]; then
service="$2"
shift 2

run_service_setup "$service"

if [ $# -gt 0 ]; then
start_services_if_needed "$@"
exec "$@"
else
exec bash
fi
else
start_services_if_needed "$@"
exec "$@"
fi
Loading
Loading