From eb3673c00e07f91b58cf0947cfa17f9717fd8f30 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Mon, 13 Jul 2026 10:11:22 +0000 Subject: [PATCH 01/10] chore(devcontainer): simpler setup w/o docker compose --- .devcontainer/.env.example | 22 ++-- .devcontainer/Dockerfile | 38 +----- .devcontainer/VERSION | 2 +- .devcontainer/devcontainer-lock.json | 16 +-- .devcontainer/devcontainer.json | 32 ++++- .devcontainer/docker-compose.yml | 51 ------- .../features/tools/devcontainer-feature.json | 13 ++ .devcontainer/features/tools/install.sh | 61 +++++++++ .devcontainer/run | 23 ++-- .devcontainer/setup | 2 +- .github/workflows/build_images.yml | 24 ++-- .github/workflows/e2e_tests.yml | 124 +++++++++++++----- .gitignore | 1 + .mise.toml | 2 +- CONTRIBUTING.md | 2 +- 15 files changed, 244 insertions(+), 169 deletions(-) delete mode 100644 .devcontainer/docker-compose.yml create mode 100644 .devcontainer/features/tools/devcontainer-feature.json create mode 100755 .devcontainer/features/tools/install.sh diff --git a/.devcontainer/.env.example b/.devcontainer/.env.example index 873527bf3..2060b8bae 100644 --- a/.devcontainer/.env.example +++ b/.devcontainer/.env.example @@ -1,22 +1,20 @@ # Devcontainer configuration -RUBY_VERSION="3.4.9" + +RUBY_VERSION=3.4.9 # E2E testing -SENTRY_DSN="http://user:pass@sentry.localhost/project/42" -# SENTRY_DSN_JS="http://user:pass@sentry-js.localhost/project/43" -SENTRY_DSN_JS="" +SENTRY_DSN=http://user:pass@sentry.localhost/project/42 +# SENTRY_DSN_JS=http://user:pass@sentry-js.localhost/project/43 +SENTRY_DSN_JS= 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" +SENTRY_E2E_RAILS_APP_URL=http://localhost:4000 +SENTRY_E2E_SVELTE_APP_URL=http://localhost:4001 # ActiveJob queue adapter under test: async | inline | sidekiq | resque | delayed_job -SENTRY_E2E_ACTIVE_JOB_ADAPTER="async" - -# Redis for the sidekiq/resque adapters (the Compose service is named "redis") -REDIS_URL="redis://redis:6379" +SENTRY_E2E_ACTIVE_JOB_ADAPTER=async -# Faster builds with compose -COMPOSE_BAKE=true +# Redis for the sidekiq/resque adapters +REDIS_URL=redis://localhost:6379 diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 0ba375621..04d068021 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -35,14 +35,14 @@ RUN userdel -r ubuntu 2>/dev/null || true \ && groupadd --gid 1000 sentry \ && useradd --uid 1000 --gid sentry --shell /bin/bash --create-home sentry -WORKDIR /workspace/sentry +WORKDIR /workspaces/sentry-ruby -RUN chown -R sentry:sentry /workspace/sentry +RUN chown -R sentry:sentry /workspaces/sentry-ruby ENV LANG=C.UTF-8 \ BUNDLE_JOBS=4 \ BUNDLE_RETRY=3 \ - REDIS_HOST=redis \ + REDIS_HOST=localhost \ PATH=/home/sentry/.local/share/mise/shims:/home/sentry/.local/bin:$PATH USER sentry @@ -52,32 +52,6 @@ USER sentry # directory content when a volume is first attached). RUN mkdir -p /home/sentry/bundle -RUN curl https://mise.run | sh \ - && echo 'eval "$(/home/sentry/.local/bin/mise activate bash)"' >> /home/sentry/.bashrc \ - && echo 'eval "$(/home/sentry/.local/bin/mise activate zsh)"' >> /home/sentry/.zshenv - -# Pre-install Ruby at build time so the container starts immediately without -# downloading it at runtime. Switching Ruby versions requires a rebuild. -ARG RUBY_VERSION=latest - -# Java is always installed (required for JRuby). It is listed in .mise.toml so -# it is available for all users regardless of which Ruby flavour they use. -RUN echo "📦 Pre-installing java@temurin-21..." && \ - /home/sentry/.local/bin/mise install "java@temurin-21" && \ - /home/sentry/.local/bin/mise use --global "java@temurin-21" - -RUN echo "📦 Pre-installing ruby@${RUBY_VERSION} (precompiled)..." && \ - MISE_RUBY_COMPILE=0 /home/sentry/.local/bin/mise install "ruby@${RUBY_VERSION}" && \ - /home/sentry/.local/bin/mise use --global "ruby@${RUBY_VERSION}" - -# Node.js is always needed for the svelte-mini e2e app. -RUN echo "📦 Pre-installing node@lts..." && \ - /home/sentry/.local/bin/mise install "node@lts" && \ - /home/sentry/.local/bin/mise use --global "node@lts" - -# Install headless Chromium via Playwright (includes all system dependencies). -# Symlink the binary into ~/.local/bin which is already on PATH. -RUN /home/sentry/.local/share/mise/shims/npx playwright install chromium --with-deps -# Playwright lays out the binary under chrome-linux/ on arm64 and chrome-linux64/ -# on x86_64 (since Playwright 1.57), so the glob has to match both. -RUN bash -c 'ln -sf /home/sentry/.cache/ms-playwright/chromium-*/chrome-linux*/chrome /home/sentry/.local/bin/chromium' +# mise and the toolchain (Java, Ruby, Node, Chromium) are installed by the local +# `./features/tools` dev container feature, which runs after this Dockerfile — +# see devcontainer.json. diff --git a/.devcontainer/VERSION b/.devcontainer/VERSION index 9084fa2f7..227cea215 100644 --- a/.devcontainer/VERSION +++ b/.devcontainer/VERSION @@ -1 +1 @@ -1.1.0 +2.0.0 diff --git a/.devcontainer/devcontainer-lock.json b/.devcontainer/devcontainer-lock.json index 81236b5bc..06b03ee0e 100644 --- a/.devcontainer/devcontainer-lock.json +++ b/.devcontainer/devcontainer-lock.json @@ -1,25 +1,15 @@ { "features": { - "ghcr.io/devcontainers-extra/features/npm-packages:latest": { - "version": "1.0.1", - "resolved": "ghcr.io/devcontainers-extra/features/npm-packages@sha256:0851cc312204f4044f22230986134026409565f9e632d8ab2b8c639e81cedd7c", - "integrity": "sha256:0851cc312204f4044f22230986134026409565f9e632d8ab2b8c639e81cedd7c" - }, "ghcr.io/devcontainers/features/git:latest": { - "version": "1.3.5", - "resolved": "ghcr.io/devcontainers/features/git@sha256:27905dc196c01f77d6ba8709cb82eeaf330b3b108772e2f02d1cd0d826de1251", - "integrity": "sha256:27905dc196c01f77d6ba8709cb82eeaf330b3b108772e2f02d1cd0d826de1251" + "version": "1.3.8", + "resolved": "ghcr.io/devcontainers/features/git@sha256:fd75977de13a9979000e0e78baf949adb0ca71d2398995fa22e0a36d7e7e7fe2", + "integrity": "sha256:fd75977de13a9979000e0e78baf949adb0ca71d2398995fa22e0a36d7e7e7fe2" }, "ghcr.io/devcontainers/features/github-cli:latest": { "version": "1.1.0", "resolved": "ghcr.io/devcontainers/features/github-cli@sha256:d22f50b70ed75339b4eed1ba9ecde3a1791f90e88d37936517e3bace0bbad671", "integrity": "sha256:d22f50b70ed75339b4eed1ba9ecde3a1791f90e88d37936517e3bace0bbad671" }, - "ghcr.io/devcontainers/features/node:latest": { - "version": "2.0.0", - "resolved": "ghcr.io/devcontainers/features/node@sha256:fedd4c11f7adfb64283b578dddc7da906728daa25fa293351c9d913231acf12f", - "integrity": "sha256:fedd4c11f7adfb64283b578dddc7da906728daa25fa293351c9d913231acf12f" - }, "ghcr.io/nils-geistmann/devcontainers-features/zsh:latest": { "version": "0.0.8", "resolved": "ghcr.io/nils-geistmann/devcontainers-features/zsh@sha256:fd57a61a5187480b5e73f8041be5b67005be48f06503736df6cfdd8d0f38f3c4", diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 287243c71..b36cfa980 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,8 +1,29 @@ { "name": "sentry-ruby", - "dockerComposeFile": "docker-compose.yml", - "service": "sentry-dev", - "workspaceFolder": "/workspace/sentry", + "build": { + "dockerfile": "Dockerfile", + "context": "..", + "args": { + "BASE_IMAGE": "${localEnv:BASE_IMAGE:ubuntu:24.04}" + } + }, + "runArgs": ["--init"], + "mounts": [ + "source=sentry-ruby-bundle,target=/home/sentry/bundle,type=volume" + ], + "forwardPorts": [4000, 4001, 6379], + "containerEnv": { + "BUNDLE_PATH": "/home/sentry/bundle", + "SENTRY_DSN": "http://user:pass@sentry.localhost/project/42", + "SENTRY_DSN_JS": "", + "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", + "SENTRY_E2E_ACTIVE_JOB_ADAPTER": "async", + "REDIS_URL": "redis://localhost:6379" + }, + "postCreateCommand": "mise trust /workspaces/sentry-ruby", "features": { "ghcr.io/devcontainers/features/git:latest": { "ppa": false, @@ -10,8 +31,9 @@ }, "ghcr.io/devcontainers/features/github-cli:latest": {}, "ghcr.io/nils-geistmann/devcontainers-features/zsh:latest": {}, - "ghcr.io/devcontainers/features/node:latest": {}, - "ghcr.io/devcontainers-extra/features/npm-packages:latest": {}, + "./features/tools": { + "rubyVersion": "${localEnv:RUBY_VERSION:4.0}" + }, "ghcr.io/rocker-org/devcontainer-features/apt-packages:latest": { "packages": "inotify-tools,tzdata" } diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml deleted file mode 100644 index e9831a9f9..000000000 --- a/.devcontainer/docker-compose.yml +++ /dev/null @@ -1,51 +0,0 @@ -services: - sentry-build: &sentry-build - image: ${DOCKER_IMAGE:-sentry-ruby-devcontainer}:${DOCKER_TAG:-latest} - build: - context: .. - dockerfile: .devcontainer/Dockerfile - args: - BASE_IMAGE: ${BASE_IMAGE:-ubuntu:24.04} - RUBY_VERSION: ${RUBY_VERSION:-latest} - volumes: - - ..:/workspace/sentry:cached - working_dir: /workspace/sentry - env_file: [".env"] - - sentry-dev: - <<: *sentry-build - entrypoint: [".devcontainer/run"] - depends_on: - - redis - - sentry-test: - <<: *sentry-build - profiles: ["e2e"] - entrypoint: [".devcontainer/run"] - command: ["mise", "run", "e2e:serve"] - environment: - BUNDLE_PATH: /home/sentry/bundle - depends_on: - redis: - condition: service_healthy - volumes: - - ..:/workspace/sentry:cached - - bundle-gems:/home/sentry/bundle - ports: - - "${SENTRY_E2E_RAILS_APP_PORT}:4000" - - "${SENTRY_E2E_SVELTE_APP_PORT}:4001" - - redis: - image: redis:latest - environment: - - ALLOW_EMPTY_PASSWORD=yes - ports: - - "6379:6379" - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 2s - timeout: 3s - retries: 10 - -volumes: - bundle-gems: diff --git a/.devcontainer/features/tools/devcontainer-feature.json b/.devcontainer/features/tools/devcontainer-feature.json new file mode 100644 index 000000000..90de5a01b --- /dev/null +++ b/.devcontainer/features/tools/devcontainer-feature.json @@ -0,0 +1,13 @@ +{ + "name": "sentry-ruby toolchain", + "id": "tools", + "version": "1.0.0", + "description": "Installs mise and pre-installs the sentry-ruby toolchain (Java, Ruby, Node) via mise plus headless Chromium via Playwright, baked into the image so the container starts without downloading anything.", + "options": { + "rubyVersion": { + "type": "string", + "default": "4.0", + "description": "Ruby version to pre-install and set as the global default (latest 4.0.x by default). Switching versions requires an image rebuild." + } + } +} diff --git a/.devcontainer/features/tools/install.sh b/.devcontainer/features/tools/install.sh new file mode 100755 index 000000000..b6d5e2d2a --- /dev/null +++ b/.devcontainer/features/tools/install.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# +# Installs mise system-wide and pre-installs the sentry-ruby toolchain (Java, +# Ruby, Node) plus a headless Chromium, all baked into the image so the +# container starts without downloading anything at runtime. +# +set -euo pipefail + +RUBY_VERSION="${RUBYVERSION:-latest}" +USERNAME="${_REMOTE_USER:-sentry}" +USER_HOME="${_REMOTE_USER_HOME:-/home/${USERNAME}}" + +# Install mise system-wide via the official installer. This downloads a prebuilt +# binary from mise's CDN rather than the GitHub API, avoiding the API rate +# limits the gh-release-based community feature hits on shared CI runners. +echo "📦 Installing mise..." +export MISE_INSTALL_PATH=/usr/local/bin/mise +curl https://mise.run | sh +MISE_BIN=/usr/local/bin/mise +"$MISE_BIN" --version + +# Activate mise for the remote user's interactive shells. +echo "eval \"\$(${MISE_BIN} activate bash)\"" >> "${USER_HOME}/.bashrc" +echo "eval \"\$(${MISE_BIN} activate zsh)\"" >> "${USER_HOME}/.zshenv" +chown "${USERNAME}:${USERNAME}" "${USER_HOME}/.bashrc" "${USER_HOME}/.zshenv" + +# Run a command as the remote user with a sane PATH so mise writes tools into +# the user's own data dir (~/.local/share/mise) rather than root's. +as_user() { + sudo -u "${USERNAME}" -H env "PATH=${USER_HOME}/.local/bin:/usr/local/bin:/usr/bin:/bin" "$@" +} + +# ~/.local/bin is on PATH but nothing creates it now that mise is installed +# system-wide; ensure it exists for the Chromium symlink below. +as_user mkdir -p "${USER_HOME}/.local/bin" + +# Java is always installed (required for JRuby) and listed in .mise.toml so it +# is available regardless of which Ruby flavour is used. +echo "📦 Pre-installing java@temurin-21..." +as_user "$MISE_BIN" install "java@temurin-21" +as_user "$MISE_BIN" use --global "java@temurin-21" + +# Pre-install Ruby (precompiled) so the container starts immediately. +echo "📦 Pre-installing ruby@${RUBY_VERSION} (precompiled)..." +as_user env MISE_RUBY_COMPILE=0 "$MISE_BIN" install "ruby@${RUBY_VERSION}" +as_user "$MISE_BIN" use --global "ruby@${RUBY_VERSION}" + +# Node.js is always needed for the svelte-mini e2e app. +echo "📦 Pre-installing node@lts..." +as_user "$MISE_BIN" install "node@lts" +as_user "$MISE_BIN" use --global "node@lts" + +# Install headless Chromium via Playwright (includes all system dependencies) +# and symlink the binary into ~/.local/bin which is already on PATH. +echo "📦 Installing headless Chromium via Playwright..." +as_user "${USER_HOME}/.local/share/mise/shims/npx" playwright install chromium --with-deps +# Playwright lays out the binary under chrome-linux/ on arm64 and chrome-linux64/ +# on x86_64 (since Playwright 1.57), so the glob has to match both. +as_user bash -c "ln -sf ${USER_HOME}/.cache/ms-playwright/chromium-*/chrome-linux*/chrome ${USER_HOME}/.local/bin/chromium" + +echo "✅ Toolchain pre-install completed!" diff --git a/.devcontainer/run b/.devcontainer/run index caf752a83..e958b5356 100755 --- a/.devcontainer/run +++ b/.devcontainer/run @@ -1,24 +1,27 @@ #!/bin/bash # -# Container entrypoint. Ruby and other toolchains are pre-installed in the -# image; this script only handles per-run setup (ownership, mise activation) -# and hands off to whatever docker-compose passes as `command`. +# E2E container command wrapper. Ruby and other toolchains are pre-installed +# in the image; this script only handles per-run setup (ownership, mise +# activation) and hands off to the requested CI command. # set -euo pipefail -cd /workspace/sentry +cd /workspaces/sentry-ruby # In CI the workspace is checked out by the runner user (e.g. UID 1001) and # then bind-mounted into the container where we run as sentry (UID 1000). # Fix ownership once here so bundler, git, etc. can write freely. -sudo chown -R sentry:sentry /workspace/sentry 2>/dev/null || true -MISE_BIN="/home/sentry/.local/bin/mise" +sudo chown -R sentry:sentry /workspaces/sentry-ruby 2>/dev/null || true + +# mise is installed system-wide by the tools dev container feature, so it lives +# on PATH (typically /usr/local/bin/mise). +MISE_BIN="$(command -v mise || true)" # Git also refuses to operate in directories owned by a different user. -git config --global --add safe.directory /workspace/sentry 2>/dev/null || true +git config --global --add safe.directory /workspaces/sentry-ruby 2>/dev/null || true -if [[ ! -x "$MISE_BIN" ]]; then - echo "❌ mise not found at $MISE_BIN (it should be installed by the Dockerfile)" +if [[ -z "$MISE_BIN" || ! -x "$MISE_BIN" ]]; then + echo "❌ mise not found on PATH (it should be installed by the tools dev container feature)" exit 1 fi @@ -26,7 +29,7 @@ fi eval "$("$MISE_BIN" activate bash)" # Trust the workspace config so mise will use it without prompting. -"$MISE_BIN" trust /workspace/sentry >/dev/null +"$MISE_BIN" trust /workspaces/sentry-ruby >/dev/null if [[ $# -eq 0 ]]; then exec sleep infinity diff --git a/.devcontainer/setup b/.devcontainer/setup index 408f7d8de..c608e0da6 100755 --- a/.devcontainer/setup +++ b/.devcontainer/setup @@ -25,7 +25,7 @@ class SetupScript only_npm: false, with_foreman: false } - @workspace_root = '/workspace/sentry' + @workspace_root = '/workspaces/sentry-ruby' end def run(args) diff --git a/.github/workflows/build_images.yml b/.github/workflows/build_images.yml index ffc4bd624..1611496ef 100644 --- a/.github/workflows/build_images.yml +++ b/.github/workflows/build_images.yml @@ -55,15 +55,19 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 + # Build with the dev container CLI (not a plain `docker build`) so the dev + # container features — mise and the local `tools` feature that bakes the + # Ruby/Node/Java/Chromium toolchain — are applied to the pushed image. + # BASE_IMAGE and RUBY_VERSION are consumed via ${localEnv:...} in + # devcontainer.json, so they are passed as env vars to the CLI here. - name: Build and push devcontainer image - uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 + uses: devcontainers/ci@513af61f4de4f75d37e4438f184ba4358f0fc1ca # v0.3.1900000450 + env: + BASE_IMAGE: ${{ matrix.base_image }} + RUBY_VERSION: ${{ matrix.ruby_version }} with: - context: . - file: .devcontainer/Dockerfile - push: true - tags: | - ghcr.io/getsentry/sentry-ruby-devcontainer-${{ matrix.flavor }}:${{ steps.version.outputs.version }} - ${{ github.ref == 'refs/heads/master' && format('ghcr.io/getsentry/sentry-ruby-devcontainer-{0}:latest', matrix.flavor) || '' }} - build-args: | - BASE_IMAGE=${{ matrix.base_image }} - RUBY_VERSION=${{ matrix.ruby_version }} + subFolder: . + configFile: .devcontainer/devcontainer.json + imageName: ghcr.io/getsentry/sentry-ruby-devcontainer-${{ matrix.flavor }} + imageTag: ${{ github.ref == 'refs/heads/master' && format('{0},latest', steps.version.outputs.version) || steps.version.outputs.version }} + push: always diff --git a/.github/workflows/e2e_tests.yml b/.github/workflows/e2e_tests.yml index 018db5c5c..2ca45c582 100644 --- a/.github/workflows/e2e_tests.yml +++ b/.github/workflows/e2e_tests.yml @@ -48,10 +48,8 @@ jobs: run: | cd .devcontainer cp .env.example .env - echo "RUBY_VERSION=${{ matrix.ruby.version }}" >> .env - echo "DOCKER_IMAGE=ghcr.io/getsentry/sentry-ruby-devcontainer-${{ matrix.ruby.flavor }}" >> .env - echo "DOCKER_TAG=${{ steps.devcontainer-version.outputs.version }}" >> .env echo "SENTRY_E2E_ACTIVE_JOB_ADAPTER=${{ matrix.adapter }}" >> .env + echo "REDIS_URL=redis://redis:6379" >> .env - name: Log in to GHCR uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 @@ -63,6 +61,37 @@ jobs: - name: Pull test container image run: docker pull ghcr.io/getsentry/sentry-ruby-devcontainer-${{ matrix.ruby.flavor }}:${{ steps.devcontainer-version.outputs.version }} + - name: Prepare docker resources + run: | + network="sentry-ruby-e2e-${{ github.run_id }}-${{ matrix.ruby.flavor }}-${{ matrix.adapter }}" + bundle_volume="sentry-ruby-e2e-bundle-${{ github.run_id }}-${{ matrix.ruby.flavor }}-${{ matrix.adapter }}" + redis_container="sentry-ruby-e2e-redis-${{ github.run_id }}-${{ matrix.ruby.flavor }}-${{ matrix.adapter }}" + test_container="sentry-ruby-e2e-test-${{ github.run_id }}-${{ matrix.ruby.flavor }}-${{ matrix.adapter }}" + + echo "E2E_NETWORK=${network}" >> "$GITHUB_ENV" + echo "E2E_BUNDLE_VOLUME=${bundle_volume}" >> "$GITHUB_ENV" + echo "E2E_REDIS_CONTAINER=${redis_container}" >> "$GITHUB_ENV" + echo "E2E_TEST_CONTAINER=${test_container}" >> "$GITHUB_ENV" + + docker network create "${network}" + docker volume create "${bundle_volume}" + + docker run -d \ + --name "${redis_container}" \ + --network "${network}" \ + --network-alias redis \ + redis:latest + + for _ in $(seq 1 30); do + if docker exec "${redis_container}" redis-cli ping | grep -q PONG; then + exit 0 + fi + sleep 1 + done + + echo "Redis failed to become ready" >&2 + exit 1 + - name: Restore node_modules cache uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: @@ -73,49 +102,80 @@ jobs: - name: Set up test container run: | - docker compose \ - --file .devcontainer/docker-compose.yml \ + docker run --rm \ + --network "${E2E_NETWORK}" \ --env-file .devcontainer/.env \ - --profile e2e \ - run --rm sentry-test \ - .devcontainer/setup --only .,spec/apps/rails-mini + --env BUNDLE_PATH=/home/sentry/bundle \ + --env MISE_RUBY_VERSION=${{ matrix.ruby.version }} \ + --volume "${PWD}:/workspaces/sentry-ruby" \ + --volume "${E2E_BUNDLE_VOLUME}:/home/sentry/bundle" \ + "ghcr.io/getsentry/sentry-ruby-devcontainer-${{ matrix.ruby.flavor }}:${{ steps.devcontainer-version.outputs.version }}" \ + .devcontainer/run .devcontainer/setup --only .,spec/apps/rails-mini - name: Start test services run: | - docker compose \ - --file .devcontainer/docker-compose.yml \ + docker run -d \ + --name "${E2E_TEST_CONTAINER}" \ + --network "${E2E_NETWORK}" \ + --publish 4000:4000 \ + --publish 4001:4001 \ --env-file .devcontainer/.env \ - --profile e2e \ - up -d --no-build sentry-test - + --env BUNDLE_PATH=/home/sentry/bundle \ + --env MISE_RUBY_VERSION=${{ matrix.ruby.version }} \ + --volume "${PWD}:/workspaces/sentry-ruby" \ + --volume "${E2E_BUNDLE_VOLUME}:/home/sentry/bundle" \ + "ghcr.io/getsentry/sentry-ruby-devcontainer-${{ matrix.ruby.flavor }}:${{ steps.devcontainer-version.outputs.version }}" \ + .devcontainer/run mise run e2e:serve + + # Poll from the runner host, not a container action: the apps' ports are + # published to the host (`--publish`), so `localhost` here reaches them, + # whereas a Docker container action's `localhost` is its own container. - name: "Wait for rails-mini app to be ready" - uses: nev7n/wait_for_response@8bfc0523300e46e24e1b42d6783680aa921ee6cc # v1.2.0 - with: - url: 'http://localhost:4000/health' - responseCode: 200 - timeout: 90000 - interval: 500 + run: | + for _ in $(seq 1 180); do + if curl -sf http://localhost:4000/health >/dev/null; then + echo "rails-mini is ready" + exit 0 + fi + sleep 1 + done + echo "❌ rails-mini did not become ready in time" >&2 + docker logs "${E2E_TEST_CONTAINER}" 2>&1 | tail -n 200 || true + exit 1 - name: "Wait for svelte-mini app to be ready" - uses: nev7n/wait_for_response@8bfc0523300e46e24e1b42d6783680aa921ee6cc # v1.2.0 - with: - url: 'http://localhost:4001/health' - responseCode: 200 - timeout: 90000 - interval: 500 + run: | + for _ in $(seq 1 180); do + if curl -sf http://localhost:4001/health >/dev/null; then + echo "svelte-mini is ready" + exit 0 + fi + sleep 1 + done + echo "❌ svelte-mini did not become ready in time" >&2 + docker logs "${E2E_TEST_CONTAINER}" 2>&1 | tail -n 200 || true + exit 1 - name: Run e2e tests via sentry-test run: | - docker compose \ - --file .devcontainer/docker-compose.yml \ - --env-file .devcontainer/.env \ - --profile e2e \ - exec sentry-test \ - bundle exec rake + docker exec "${E2E_TEST_CONTAINER}" bundle exec rake + + - name: Dump service logs + if: failure() + run: | + echo "===== docker ps -a =====" + docker ps -a + echo "===== test container logs =====" + docker logs "${E2E_TEST_CONTAINER}" 2>&1 || true + echo "===== redis container logs =====" + docker logs "${E2E_REDIS_CONTAINER}" 2>&1 || true - name: Stop e2e services if: always() - run: docker compose --file .devcontainer/docker-compose.yml --profile e2e down + run: | + docker rm -f "${E2E_TEST_CONTAINER}" "${E2E_REDIS_CONTAINER}" 2>/dev/null || true + docker network rm "${E2E_NETWORK}" 2>/dev/null || true + docker volume rm "${E2E_BUNDLE_VOLUME}" 2>/dev/null || true - name: Upload test artifacts if: failure() diff --git a/.gitignore b/.gitignore index 6457c76c3..302e83806 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ node_modules mise.toml .devcontainer/.env + vendor/gems sentry-rails/Gemfile-*.lock diff --git a/.mise.toml b/.mise.toml index 6744ccf6f..0fe2980d3 100644 --- a/.mise.toml +++ b/.mise.toml @@ -2,7 +2,7 @@ ruby.compile = false [tools] -ruby = "latest" +ruby = "4.0" node = "lts" java = "temurin-21" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 92e2fcbd2..e4474e2ef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,7 +32,7 @@ The devcontainer is configured with `.devcontainer/.env` file, that you need to cp .devcontainer/.env.example .devcontainer/.env ``` -This file defines which specific image and Ruby version will be used to run the code. Edit it whenever you need to use a different image or Ruby version. +This file defines runtime settings for local e2e apps and devcontainer workflows. ## Contribute To Individual Gems From e3f875b383f45f22319ff4f7613eb99db4ee024a Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Tue, 14 Jul 2026 10:45:50 +0200 Subject: [PATCH 02/10] refactor(devcontainer): rename run to ci-run as now only CI needs it --- .devcontainer/ci-run | 12 +++++++++++ .devcontainer/run | 38 --------------------------------- .github/workflows/e2e_tests.yml | 4 ++-- 3 files changed, 14 insertions(+), 40 deletions(-) create mode 100755 .devcontainer/ci-run delete mode 100755 .devcontainer/run diff --git a/.devcontainer/ci-run b/.devcontainer/ci-run new file mode 100755 index 000000000..e9fd92b46 --- /dev/null +++ b/.devcontainer/ci-run @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -euo pipefail + +readonly WORKSPACE=/workspaces/sentry-ruby + +sudo chown -R sentry:sentry "$WORKSPACE" + +cd "$WORKSPACE" +mise trust "$WORKSPACE" >/dev/null + +exec "$@" diff --git a/.devcontainer/run b/.devcontainer/run deleted file mode 100755 index e958b5356..000000000 --- a/.devcontainer/run +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -# -# E2E container command wrapper. Ruby and other toolchains are pre-installed -# in the image; this script only handles per-run setup (ownership, mise -# activation) and hands off to the requested CI command. -# -set -euo pipefail - -cd /workspaces/sentry-ruby - -# In CI the workspace is checked out by the runner user (e.g. UID 1001) and -# then bind-mounted into the container where we run as sentry (UID 1000). -# Fix ownership once here so bundler, git, etc. can write freely. -sudo chown -R sentry:sentry /workspaces/sentry-ruby 2>/dev/null || true - -# mise is installed system-wide by the tools dev container feature, so it lives -# on PATH (typically /usr/local/bin/mise). -MISE_BIN="$(command -v mise || true)" - -# Git also refuses to operate in directories owned by a different user. -git config --global --add safe.directory /workspaces/sentry-ruby 2>/dev/null || true - -if [[ -z "$MISE_BIN" || ! -x "$MISE_BIN" ]]; then - echo "❌ mise not found on PATH (it should be installed by the tools dev container feature)" - exit 1 -fi - -# Activate mise for this shell so PATH/shims are resolved correctly. -eval "$("$MISE_BIN" activate bash)" - -# Trust the workspace config so mise will use it without prompting. -"$MISE_BIN" trust /workspaces/sentry-ruby >/dev/null - -if [[ $# -eq 0 ]]; then - exec sleep infinity -else - exec "$@" -fi diff --git a/.github/workflows/e2e_tests.yml b/.github/workflows/e2e_tests.yml index 2ca45c582..baaf36646 100644 --- a/.github/workflows/e2e_tests.yml +++ b/.github/workflows/e2e_tests.yml @@ -110,7 +110,7 @@ jobs: --volume "${PWD}:/workspaces/sentry-ruby" \ --volume "${E2E_BUNDLE_VOLUME}:/home/sentry/bundle" \ "ghcr.io/getsentry/sentry-ruby-devcontainer-${{ matrix.ruby.flavor }}:${{ steps.devcontainer-version.outputs.version }}" \ - .devcontainer/run .devcontainer/setup --only .,spec/apps/rails-mini + .devcontainer/ci-run .devcontainer/setup --only .,spec/apps/rails-mini - name: Start test services run: | @@ -125,7 +125,7 @@ jobs: --volume "${PWD}:/workspaces/sentry-ruby" \ --volume "${E2E_BUNDLE_VOLUME}:/home/sentry/bundle" \ "ghcr.io/getsentry/sentry-ruby-devcontainer-${{ matrix.ruby.flavor }}:${{ steps.devcontainer-version.outputs.version }}" \ - .devcontainer/run mise run e2e:serve + .devcontainer/ci-run mise run e2e:serve # Poll from the runner host, not a container action: the apps' ports are # published to the host (`--publish`), so `localhost` here reaches them, From 14c25167c626209a1eb0e8ecc041e5e2c6564a49 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Tue, 14 Jul 2026 08:49:59 +0000 Subject: [PATCH 03/10] chore(devcontainer): for e2e install playwright in headless only --- .devcontainer/VERSION | 2 +- .devcontainer/features/tools/install.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.devcontainer/VERSION b/.devcontainer/VERSION index 227cea215..38f77a65b 100644 --- a/.devcontainer/VERSION +++ b/.devcontainer/VERSION @@ -1 +1 @@ -2.0.0 +2.0.1 diff --git a/.devcontainer/features/tools/install.sh b/.devcontainer/features/tools/install.sh index b6d5e2d2a..69f06daf7 100755 --- a/.devcontainer/features/tools/install.sh +++ b/.devcontainer/features/tools/install.sh @@ -53,7 +53,7 @@ as_user "$MISE_BIN" use --global "node@lts" # Install headless Chromium via Playwright (includes all system dependencies) # and symlink the binary into ~/.local/bin which is already on PATH. echo "📦 Installing headless Chromium via Playwright..." -as_user "${USER_HOME}/.local/share/mise/shims/npx" playwright install chromium --with-deps +as_user "${USER_HOME}/.local/share/mise/shims/npx" playwright install chromium --with-deps --only-shell # Playwright lays out the binary under chrome-linux/ on arm64 and chrome-linux64/ # on x86_64 (since Playwright 1.57), so the glob has to match both. as_user bash -c "ln -sf ${USER_HOME}/.cache/ms-playwright/chromium-*/chrome-linux*/chrome ${USER_HOME}/.local/bin/chromium" From 29f6efb50141d15a280f985d9e8f2ba89b389189 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Tue, 14 Jul 2026 12:28:51 +0200 Subject: [PATCH 04/10] refactor(devcontainer): drop dep on playwright We don't use it after all and using it just to get chromium headless was an overkill. --- .devcontainer/Dockerfile | 6 +-- .../features/tools/devcontainer-feature.json | 10 +++- .devcontainer/features/tools/install.sh | 52 +++++++------------ .github/workflows/build_images.yml | 4 +- spec/spec_helper.rb | 5 +- 5 files changed, 35 insertions(+), 42 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 04d068021..590f51c29 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -52,6 +52,6 @@ USER sentry # directory content when a volume is first attached). RUN mkdir -p /home/sentry/bundle -# mise and the toolchain (Java, Ruby, Node, Chromium) are installed by the local -# `./features/tools` dev container feature, which runs after this Dockerfile — -# see devcontainer.json. +# Chromium, ChromeDriver, mise, and the toolchain (Java, Ruby, Node) are +# installed by the local `./features/tools` dev container feature, which runs +# after this Dockerfile — see devcontainer.json. diff --git a/.devcontainer/features/tools/devcontainer-feature.json b/.devcontainer/features/tools/devcontainer-feature.json index 90de5a01b..5e3777d61 100644 --- a/.devcontainer/features/tools/devcontainer-feature.json +++ b/.devcontainer/features/tools/devcontainer-feature.json @@ -2,12 +2,18 @@ "name": "sentry-ruby toolchain", "id": "tools", "version": "1.0.0", - "description": "Installs mise and pre-installs the sentry-ruby toolchain (Java, Ruby, Node) via mise plus headless Chromium via Playwright, baked into the image so the container starts without downloading anything.", + "description": "Installs Chromium, ChromeDriver, mise, and the sentry-ruby toolchain (Java, Ruby, Node).", + "installsAfter": [ + "ghcr.io/devcontainers/features/git", + "ghcr.io/devcontainers/features/github-cli", + "ghcr.io/nils-geistmann/devcontainers-features/zsh", + "ghcr.io/rocker-org/devcontainer-features/apt-packages" + ], "options": { "rubyVersion": { "type": "string", "default": "4.0", - "description": "Ruby version to pre-install and set as the global default (latest 4.0.x by default). Switching versions requires an image rebuild." + "description": "Ruby version to pre-install (latest 4.0.x by default). Switching versions requires an image rebuild." } } } diff --git a/.devcontainer/features/tools/install.sh b/.devcontainer/features/tools/install.sh index 69f06daf7..798d71c63 100755 --- a/.devcontainer/features/tools/install.sh +++ b/.devcontainer/features/tools/install.sh @@ -1,8 +1,6 @@ #!/usr/bin/env bash # -# Installs mise system-wide and pre-installs the sentry-ruby toolchain (Java, -# Ruby, Node) plus a headless Chromium, all baked into the image so the -# container starts without downloading anything at runtime. +# Installs mise, the sentry-ruby toolchain, and Chromium with ChromeDriver. # set -euo pipefail @@ -10,6 +8,19 @@ RUBY_VERSION="${RUBYVERSION:-latest}" USERNAME="${_REMOTE_USER:-sentry}" USER_HOME="${_REMOTE_USER_HOME:-/home/${USERNAME}}" +echo "📦 Installing Chromium and ChromeDriver..." +echo "deb http://deb.debian.org/debian sid main" > /etc/apt/sources.list.d/debian.list +wget -qO- https://ftp-master.debian.org/keys/archive-key-12.asc \ + | gpg --dearmor > /etc/apt/trusted.gpg.d/debian-archive-keyring.gpg +wget -qO- https://ftp-master.debian.org/keys/archive-key-12-security.asc \ + | gpg --dearmor > /etc/apt/trusted.gpg.d/debian-archive-security-keyring.gpg +for directory in bin lib lib32 lib64 libo32 libx32 sbin; do + dpkg-divert --package base-files --no-rename --remove "/${directory}" +done +apt-get update +apt-get install -y --no-install-recommends chromium chromium-driver +rm -rf /var/lib/apt/lists/* /var/cache/apt/* /etc/apt/sources.list.d/debian.list + # Install mise system-wide via the official installer. This downloads a prebuilt # binary from mise's CDN rather than the GitHub API, avoiding the API rate # limits the gh-release-based community feature hits on shared CI runners. @@ -24,38 +35,15 @@ echo "eval \"\$(${MISE_BIN} activate bash)\"" >> "${USER_HOME}/.bashrc" echo "eval \"\$(${MISE_BIN} activate zsh)\"" >> "${USER_HOME}/.zshenv" chown "${USERNAME}:${USERNAME}" "${USER_HOME}/.bashrc" "${USER_HOME}/.zshenv" -# Run a command as the remote user with a sane PATH so mise writes tools into -# the user's own data dir (~/.local/share/mise) rather than root's. +# Feature installers run as root, but the toolchain belongs to the remote user. as_user() { sudo -u "${USERNAME}" -H env "PATH=${USER_HOME}/.local/bin:/usr/local/bin:/usr/bin:/bin" "$@" } -# ~/.local/bin is on PATH but nothing creates it now that mise is installed -# system-wide; ensure it exists for the Chromium symlink below. -as_user mkdir -p "${USER_HOME}/.local/bin" - -# Java is always installed (required for JRuby) and listed in .mise.toml so it -# is available regardless of which Ruby flavour is used. -echo "📦 Pre-installing java@temurin-21..." -as_user "$MISE_BIN" install "java@temurin-21" -as_user "$MISE_BIN" use --global "java@temurin-21" - -# Pre-install Ruby (precompiled) so the container starts immediately. -echo "📦 Pre-installing ruby@${RUBY_VERSION} (precompiled)..." -as_user env MISE_RUBY_COMPILE=0 "$MISE_BIN" install "ruby@${RUBY_VERSION}" -as_user "$MISE_BIN" use --global "ruby@${RUBY_VERSION}" - -# Node.js is always needed for the svelte-mini e2e app. -echo "📦 Pre-installing node@lts..." -as_user "$MISE_BIN" install "node@lts" -as_user "$MISE_BIN" use --global "node@lts" - -# Install headless Chromium via Playwright (includes all system dependencies) -# and symlink the binary into ~/.local/bin which is already on PATH. -echo "📦 Installing headless Chromium via Playwright..." -as_user "${USER_HOME}/.local/share/mise/shims/npx" playwright install chromium --with-deps --only-shell -# Playwright lays out the binary under chrome-linux/ on arm64 and chrome-linux64/ -# on x86_64 (since Playwright 1.57), so the glob has to match both. -as_user bash -c "ln -sf ${USER_HOME}/.cache/ms-playwright/chromium-*/chrome-linux*/chrome ${USER_HOME}/.local/bin/chromium" +echo "📦 Pre-installing toolchain..." +as_user env MISE_RUBY_COMPILE=0 "$MISE_BIN" install \ + "java@temurin-21" \ + "ruby@${RUBY_VERSION}" \ + "node@lts" echo "✅ Toolchain pre-install completed!" diff --git a/.github/workflows/build_images.yml b/.github/workflows/build_images.yml index 1611496ef..dee8fb2f2 100644 --- a/.github/workflows/build_images.yml +++ b/.github/workflows/build_images.yml @@ -56,8 +56,8 @@ jobs: uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 # Build with the dev container CLI (not a plain `docker build`) so the dev - # container features — mise and the local `tools` feature that bakes the - # Ruby/Node/Java/Chromium toolchain — are applied to the pushed image. + # container features — including the local `tools` feature that bakes the + # Ruby/Node/Java toolchain and browser — are applied to the pushed image. # BASE_IMAGE and RUBY_VERSION are consumed via ${localEnv:...} in # devcontainer.json, so they are passed as env vars to the CLI here. - name: Build and push devcontainer image diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0124a6e67..64e314ec4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -31,13 +31,12 @@ options.add_argument("--disable-gpu") options.add_argument("--temp-profile") - # Use custom chromium binary if available - chromium_path = "/home/sentry/.local/bin/chromium" + chromium_path = ENV.fetch("SENTRY_E2E_CHROME", "/usr/bin/chromium") options.binary = chromium_path if File.exist?(chromium_path) # Use a local chromedriver if provided, bypassing Selenium Manager's # download (which only ships an x86 driver and fails on arm64). - chromedriver_path = ENV["SENTRY_E2E_CHROMEDRIVER"] || "/home/sentry/.local/bin/chromedriver" + chromedriver_path = ENV.fetch("SENTRY_E2E_CHROMEDRIVER", "/usr/bin/chromedriver") service = File.exist?(chromedriver_path) ? Selenium::WebDriver::Service.chrome(path: chromedriver_path) : nil Capybara::Selenium::Driver.new(app, browser: :chrome, options: options, service: service) From cae76e84f6cdf5a3911586fb0402cd0495daaddd Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Tue, 14 Jul 2026 12:29:42 +0200 Subject: [PATCH 05/10] chore(devcontainer): bump version --- .devcontainer/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/VERSION b/.devcontainer/VERSION index 38f77a65b..7ec1d6db4 100644 --- a/.devcontainer/VERSION +++ b/.devcontainer/VERSION @@ -1 +1 @@ -2.0.1 +2.1.0 From f3569ab15915409bb77e683c65f96a9f686f362a Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Tue, 14 Jul 2026 14:24:52 +0200 Subject: [PATCH 06/10] chore(devcontainer): bump version --- .devcontainer/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/VERSION b/.devcontainer/VERSION index 7ec1d6db4..ccbccc3dc 100644 --- a/.devcontainer/VERSION +++ b/.devcontainer/VERSION @@ -1 +1 @@ -2.1.0 +2.2.0 From 888df4e0c50733c18f2172fb9eed9de4023bdff2 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Tue, 14 Jul 2026 13:00:24 +0000 Subject: [PATCH 07/10] refactor(devcontainer): use "latest" for the ruby version --- .devcontainer/features/tools/devcontainer-feature.json | 6 +++--- .mise.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.devcontainer/features/tools/devcontainer-feature.json b/.devcontainer/features/tools/devcontainer-feature.json index 5e3777d61..fbf63f2a2 100644 --- a/.devcontainer/features/tools/devcontainer-feature.json +++ b/.devcontainer/features/tools/devcontainer-feature.json @@ -2,7 +2,7 @@ "name": "sentry-ruby toolchain", "id": "tools", "version": "1.0.0", - "description": "Installs Chromium, ChromeDriver, mise, and the sentry-ruby toolchain (Java, Ruby, Node).", + "description": "Installs development dependencies required by the Ruby SDK to run all tests", "installsAfter": [ "ghcr.io/devcontainers/features/git", "ghcr.io/devcontainers/features/github-cli", @@ -12,8 +12,8 @@ "options": { "rubyVersion": { "type": "string", - "default": "4.0", - "description": "Ruby version to pre-install (latest 4.0.x by default). Switching versions requires an image rebuild." + "default": "latest", + "description": "Ruby version to pre-install. Switching versions requires an image rebuild." } } } diff --git a/.mise.toml b/.mise.toml index 0fe2980d3..6744ccf6f 100644 --- a/.mise.toml +++ b/.mise.toml @@ -2,7 +2,7 @@ ruby.compile = false [tools] -ruby = "4.0" +ruby = "latest" node = "lts" java = "temurin-21" From 2a2c4991add2307a147c3a0615780f81000bfa94 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Tue, 14 Jul 2026 15:02:59 +0200 Subject: [PATCH 08/10] chore(devcontainer): bump version --- .devcontainer/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/VERSION b/.devcontainer/VERSION index ccbccc3dc..c043eea77 100644 --- a/.devcontainer/VERSION +++ b/.devcontainer/VERSION @@ -1 +1 @@ -2.2.0 +2.2.1 From ba77ed1ee604c3ef880d96a15c9a760b2802b914 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Tue, 14 Jul 2026 16:08:33 +0200 Subject: [PATCH 09/10] refactor(devcontainer): add redis-server as a dev/test/ci dep --- .devcontainer/devcontainer.json | 3 ++- .github/workflows/e2e_tests.yml | 29 +---------------------------- .mise.toml | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b36cfa980..3d65485fd 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -24,6 +24,7 @@ "REDIS_URL": "redis://localhost:6379" }, "postCreateCommand": "mise trust /workspaces/sentry-ruby", + "postStartCommand": "mise run services:redis", "features": { "ghcr.io/devcontainers/features/git:latest": { "ppa": false, @@ -35,7 +36,7 @@ "rubyVersion": "${localEnv:RUBY_VERSION:4.0}" }, "ghcr.io/rocker-org/devcontainer-features/apt-packages:latest": { - "packages": "inotify-tools,tzdata" + "packages": "inotify-tools,tzdata,redis-server" } }, "customizations": { diff --git a/.github/workflows/e2e_tests.yml b/.github/workflows/e2e_tests.yml index baaf36646..548389581 100644 --- a/.github/workflows/e2e_tests.yml +++ b/.github/workflows/e2e_tests.yml @@ -49,7 +49,6 @@ jobs: cd .devcontainer cp .env.example .env echo "SENTRY_E2E_ACTIVE_JOB_ADAPTER=${{ matrix.adapter }}" >> .env - echo "REDIS_URL=redis://redis:6379" >> .env - name: Log in to GHCR uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 @@ -63,35 +62,14 @@ jobs: - name: Prepare docker resources run: | - network="sentry-ruby-e2e-${{ github.run_id }}-${{ matrix.ruby.flavor }}-${{ matrix.adapter }}" bundle_volume="sentry-ruby-e2e-bundle-${{ github.run_id }}-${{ matrix.ruby.flavor }}-${{ matrix.adapter }}" - redis_container="sentry-ruby-e2e-redis-${{ github.run_id }}-${{ matrix.ruby.flavor }}-${{ matrix.adapter }}" test_container="sentry-ruby-e2e-test-${{ github.run_id }}-${{ matrix.ruby.flavor }}-${{ matrix.adapter }}" - echo "E2E_NETWORK=${network}" >> "$GITHUB_ENV" echo "E2E_BUNDLE_VOLUME=${bundle_volume}" >> "$GITHUB_ENV" - echo "E2E_REDIS_CONTAINER=${redis_container}" >> "$GITHUB_ENV" echo "E2E_TEST_CONTAINER=${test_container}" >> "$GITHUB_ENV" - docker network create "${network}" docker volume create "${bundle_volume}" - docker run -d \ - --name "${redis_container}" \ - --network "${network}" \ - --network-alias redis \ - redis:latest - - for _ in $(seq 1 30); do - if docker exec "${redis_container}" redis-cli ping | grep -q PONG; then - exit 0 - fi - sleep 1 - done - - echo "Redis failed to become ready" >&2 - exit 1 - - name: Restore node_modules cache uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: @@ -103,7 +81,6 @@ jobs: - name: Set up test container run: | docker run --rm \ - --network "${E2E_NETWORK}" \ --env-file .devcontainer/.env \ --env BUNDLE_PATH=/home/sentry/bundle \ --env MISE_RUBY_VERSION=${{ matrix.ruby.version }} \ @@ -116,7 +93,6 @@ jobs: run: | docker run -d \ --name "${E2E_TEST_CONTAINER}" \ - --network "${E2E_NETWORK}" \ --publish 4000:4000 \ --publish 4001:4001 \ --env-file .devcontainer/.env \ @@ -167,14 +143,11 @@ jobs: docker ps -a echo "===== test container logs =====" docker logs "${E2E_TEST_CONTAINER}" 2>&1 || true - echo "===== redis container logs =====" - docker logs "${E2E_REDIS_CONTAINER}" 2>&1 || true - name: Stop e2e services if: always() run: | - docker rm -f "${E2E_TEST_CONTAINER}" "${E2E_REDIS_CONTAINER}" 2>/dev/null || true - docker network rm "${E2E_NETWORK}" 2>/dev/null || true + docker rm -f "${E2E_TEST_CONTAINER}" 2>/dev/null || true docker volume rm "${E2E_BUNDLE_VOLUME}" 2>/dev/null || true - name: Upload test artifacts diff --git a/.mise.toml b/.mise.toml index 6744ccf6f..da978f252 100644 --- a/.mise.toml +++ b/.mise.toml @@ -24,8 +24,22 @@ run = [ "bundle exec rubocop -a" ] +[tasks."services:redis"] +description = "Start a local Redis server for specs and e2e apps; waits until ready, no-op if already running" +run = """ +redis-cli ping >/dev/null 2>&1 && exit 0 +redis-server --daemonize yes --save '' --dir /tmp --pidfile /tmp/redis.pid +for _ in $(seq 1 30); do + redis-cli ping >/dev/null 2>&1 && exit 0 + sleep 0.2 +done +echo 'redis did not become ready' >&2 +exit 1 +""" + [tasks."e2e:rails"] description = "Start the rails-mini e2e app" +depends = ["services:redis"] run = "cd spec/apps/rails-mini && bundle exec ruby app.rb" [tasks."e2e:svelte"] @@ -34,6 +48,7 @@ run = "cd spec/apps/svelte-mini && npm run dev" [tasks."e2e:worker"] description = "Start the rails-mini ActiveJob worker (sidekiq/resque/delayed_job; idles for async/inline)" +depends = ["services:redis"] run = "cd spec/apps/rails-mini && bundle exec ruby worker.rb" [tasks."e2e:serve"] From 8f2388e1aeb7fe6316d4c8880d7bf842467bc603 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Tue, 14 Jul 2026 16:08:51 +0200 Subject: [PATCH 10/10] chore(devcontainer): bump version --- .devcontainer/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/VERSION b/.devcontainer/VERSION index c043eea77..276cbf9e2 100644 --- a/.devcontainer/VERSION +++ b/.devcontainer/VERSION @@ -1 +1 @@ -2.2.1 +2.3.0