From fc893574d39b91779d4418d2f894a63c8c558693 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 8 May 2026 10:28:44 +0000 Subject: [PATCH 1/3] WIP --- .devcontainer/Dockerfile | 19 +++++++++---------- .devcontainer/devcontainer.json | 4 ++-- .devcontainer/docker-compose.yml | 4 ---- .devcontainer/run | 2 ++ .devcontainer/setup | 6 +++--- .mise.toml | 2 ++ 6 files changed, 18 insertions(+), 19 deletions(-) create mode 100644 .mise.toml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index d083a7abc..827967897 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,6 +1,4 @@ -ARG IMAGE="ruby" - -FROM ${IMAGE} AS build +FROM ubuntu:24.04 RUN apt-get update && apt-get install -y --no-install-recommends \ sudo \ @@ -8,6 +6,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ git \ curl \ wget \ + ca-certificates \ build-essential \ pkg-config \ libssl-dev \ @@ -27,21 +26,21 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ RUN echo "sentry ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/sentry \ && chmod 0440 /etc/sudoers.d/sentry -RUN groupadd --gid 1000 sentry \ +RUN userdel -r ubuntu 2>/dev/null || true \ + && groupdel ubuntu 2>/dev/null || true \ + && 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 -ARG VERSION -ARG GEM_HOME="/workspace/sentry/vendor/gems/${VERSION}" - ENV LANG=C.UTF-8 \ BUNDLE_JOBS=4 \ BUNDLE_RETRY=3 \ - GEM_HOME=/workspace/sentry/vendor/gems/${VERSION} \ - PATH=$PATH:${GEM_HOME}/bin \ - REDIS_HOST=redis + REDIS_HOST=redis \ + PATH=/home/sentry/.local/bin:$PATH USER sentry + +RUN curl https://mise.run | sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f21983fb3..9c3b1249e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,7 +5,6 @@ "workspaceFolder": "/workspace/sentry", "features": { "ghcr.io/devcontainers/features/github-cli:latest": {}, - "ghcr.io/devcontainers-extra/features/mise:latest": {}, "ghcr.io/nils-geistmann/devcontainers-features/zsh:latest": {}, "ghcr.io/devcontainers/features/node:latest": {}, "ghcr.io/devcontainers-extra/features/npm-packages:latest": {}, @@ -27,5 +26,6 @@ "rubyLsp.formatter": "auto" } }, - "remoteUser": "sentry" + "remoteUser": "sentry", + "postCreateCommand": "mise trust && mise install ruby@latest" } diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index a85243cba..7a75d8cc2 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -4,9 +4,6 @@ services: build: context: .. dockerfile: .devcontainer/Dockerfile - args: - IMAGE: ${IMAGE} - VERSION: ${VERSION} volumes: - ..:/workspace/sentry:cached working_dir: /workspace/sentry @@ -15,7 +12,6 @@ services: sentry-dev: <<: *sentry-build entrypoint: ".devcontainer/run --service dev" - command: "sleep infinity" depends_on: - redis diff --git a/.devcontainer/run b/.devcontainer/run index 59661dace..fba77702a 100755 --- a/.devcontainer/run +++ b/.devcontainer/run @@ -2,6 +2,8 @@ set -e +eval "$(mise activate bash)" + cd /workspace/sentry sudo mkdir -p vendor/gems diff --git a/.devcontainer/setup b/.devcontainer/setup index 9789d999f..8ec21b831 100755 --- a/.devcontainer/setup +++ b/.devcontainer/setup @@ -140,18 +140,18 @@ class SetupScript puts "๐Ÿ“ฆ Updating RubyGems and Bundler..." if RUBY_VERSION >= "3.0" - unless system("sudo gem update --system --silent") + unless system("gem update --system --silent") puts "โŒ RubyGems update failed" exit 1 end else - unless system("sudo gem update --silent --system 3.4.22") + unless system("gem update --silent --system 3.4.22") puts "โŒ RubyGems update failed" exit 1 end # sentry-sidekiq does not bundle with Bundler 2.5.x that ships with RubyGems 3.4.22 - unless system("sudo gem install bundler -v 2.4.22") + unless system("gem install bundler -v 2.4.22") puts "โŒ Bundler installation failed" exit 1 end diff --git a/.mise.toml b/.mise.toml new file mode 100644 index 000000000..9963cc0f0 --- /dev/null +++ b/.mise.toml @@ -0,0 +1,2 @@ +[tools] +ruby = "4.0" From 20251602a1cd10f203f1554ddebab3ca5a6462ff Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 8 May 2026 10:58:02 +0000 Subject: [PATCH 2/3] WIP --- .devcontainer/Dockerfile | 5 +- .devcontainer/devcontainer-lock.json | 29 ++++++++ .devcontainer/devcontainer.json | 5 +- .devcontainer/docker-compose.yml | 4 +- .devcontainer/run | 107 ++++++++------------------- .devcontainer/setup | 20 +---- .mise.toml | 2 +- 7 files changed, 70 insertions(+), 102 deletions(-) create mode 100644 .devcontainer/devcontainer-lock.json diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 827967897..80d5e20ea 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:24.04 +FROM ubuntu:latest RUN apt-get update && apt-get install -y --no-install-recommends \ sudo \ @@ -43,4 +43,5 @@ ENV LANG=C.UTF-8 \ USER sentry -RUN curl https://mise.run | sh +RUN curl https://mise.run | sh \ + && echo 'eval "$(/home/sentry/.local/bin/mise activate zsh)"' >> /home/sentry/.zshenv diff --git a/.devcontainer/devcontainer-lock.json b/.devcontainer/devcontainer-lock.json new file mode 100644 index 000000000..1cf373bb3 --- /dev/null +++ b/.devcontainer/devcontainer-lock.json @@ -0,0 +1,29 @@ +{ + "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/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", + "integrity": "sha256:fd57a61a5187480b5e73f8041be5b67005be48f06503736df6cfdd8d0f38f3c4" + }, + "ghcr.io/rocker-org/devcontainer-features/apt-packages:latest": { + "version": "1.0.2", + "resolved": "ghcr.io/rocker-org/devcontainer-features/apt-packages@sha256:87a4d7750a596a5db034ba8508782f31aebdc2ffe955c66aaecb33d9de2ecdae", + "integrity": "sha256:87a4d7750a596a5db034ba8508782f31aebdc2ffe955c66aaecb33d9de2ecdae" + } + } +} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 9c3b1249e..4f89e2184 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -9,7 +9,7 @@ "ghcr.io/devcontainers/features/node:latest": {}, "ghcr.io/devcontainers-extra/features/npm-packages:latest": {}, "ghcr.io/rocker-org/devcontainer-features/apt-packages:latest": { - "packages": "inotify-tools" + "packages": "inotify-tools,tzdata" } }, "customizations": { @@ -26,6 +26,5 @@ "rubyLsp.formatter": "auto" } }, - "remoteUser": "sentry", - "postCreateCommand": "mise trust && mise install ruby@latest" + "remoteUser": "sentry" } diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 7a75d8cc2..50e01bbaf 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -11,13 +11,13 @@ services: sentry-dev: <<: *sentry-build - entrypoint: ".devcontainer/run --service dev" + entrypoint: [".devcontainer/run"] depends_on: - redis sentry-test: <<: *sentry-build - entrypoint: ".devcontainer/run --service test" + entrypoint: [".devcontainer/run"] command: ["foreman", "start"] ports: - "${SENTRY_E2E_RAILS_APP_PORT}:4000" diff --git a/.devcontainer/run b/.devcontainer/run index fba77702a..8acf88b0d 100755 --- a/.devcontainer/run +++ b/.devcontainer/run @@ -1,94 +1,47 @@ #!/bin/bash - -set -e - -eval "$(mise activate bash)" +# +# Container entrypoint. +# +# Order of operations: +# 1. Set up mise (the Ruby version manager) for this shell. +# 2. Ensure the desired Ruby is installed (precompiled, no source build). +# 3. Hand off to whatever docker-compose passes as `command`. +# +set -euo pipefail cd /workspace/sentry -sudo mkdir -p vendor/gems -sudo chown -R sentry:sentry vendor/gems - -# git config --global --replace-all safe.directory /workspace/sentry -# git config --global --replace-all safe.directory /workspace/sentry/vendor/gems/* - -sudo chown -R sentry:sentry . +# ---- 1. mise setup ----------------------------------------------------------- -run_service_setup() { - local service="$1" +MISE_BIN="/home/sentry/.local/bin/mise" - 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..." +if [[ ! -x "$MISE_BIN" ]]; then + echo "โŒ mise not found at $MISE_BIN (it should be installed by the Dockerfile)" + exit 1 +fi - # Start foreman in background - foreman start & - FOREMAN_PID=$! +# Activate mise for this shell so PATH/shims are resolved correctly. +eval "$("$MISE_BIN" activate bash)" - # 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 +# Trust the workspace config so mise will use it without prompting. +"$MISE_BIN" trust /workspace/sentry >/dev/null - if [ $i -eq 30 ]; then - echo "โŒ Services failed to start within timeout" - kill $FOREMAN_PID 2>/dev/null || true - exit 1 - fi +# ---- 2. Install Ruby (precompiled) ------------------------------------------- - sleep 2 - done +# Default to the latest Ruby unless the caller pins a specific version. +RUBY_VERSION="${RUBY_VERSION:-latest}" - # Set up cleanup trap - trap "echo '๐Ÿงน Stopping services...'; kill $FOREMAN_PID 2>/dev/null || true; wait $FOREMAN_PID 2>/dev/null || true" EXIT - fi -} +# Always pull a precompiled binary from jdx/ruby โ€” never build from source. +export MISE_RUBY_COMPILE=0 -# Parse arguments -if [ "$1" = "--service" ] && [ -n "$2" ]; then - service="$2" - shift 2 +echo "๐Ÿ“ฆ Installing ruby@${RUBY_VERSION} (precompiled)..." +"$MISE_BIN" install "ruby@${RUBY_VERSION}" +"$MISE_BIN" use --global "ruby@${RUBY_VERSION}" - run_service_setup "$service" +# ---- 3. Hand off ------------------------------------------------------------- - if [ $# -gt 0 ]; then - start_services_if_needed "$@" - exec "$@" - else - exec bash - fi +if [[ $# -eq 0 ]]; then + exec sleep infinity else - start_services_if_needed "$@" exec "$@" fi diff --git a/.devcontainer/setup b/.devcontainer/setup index 8ec21b831..521841f0d 100755 --- a/.devcontainer/setup +++ b/.devcontainer/setup @@ -35,7 +35,6 @@ class SetupScript if should_run_bundle? cleanup_ruby_lsp_directories - update_rubygems_and_bundler install_bundle_dependencies install_foreman_gem if @options[:with_foreman] end @@ -139,22 +138,9 @@ class SetupScript def update_rubygems_and_bundler puts "๐Ÿ“ฆ Updating RubyGems and Bundler..." - if RUBY_VERSION >= "3.0" - unless system("gem update --system --silent") - puts "โŒ RubyGems update failed" - exit 1 - end - else - unless system("gem update --silent --system 3.4.22") - puts "โŒ RubyGems update failed" - exit 1 - end - - # sentry-sidekiq does not bundle with Bundler 2.5.x that ships with RubyGems 3.4.22 - unless system("gem install bundler -v 2.4.22") - puts "โŒ Bundler installation failed" - exit 1 - end + unless system("gem update --system --silent") + puts "โŒ RubyGems update failed" + exit 1 end end diff --git a/.mise.toml b/.mise.toml index 9963cc0f0..eefa30b4c 100644 --- a/.mise.toml +++ b/.mise.toml @@ -1,2 +1,2 @@ [tools] -ruby = "4.0" +ruby = "latest" From 56b2c6ba3cfc67caf89795758844a0bc68466f22 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 8 May 2026 11:16:27 +0000 Subject: [PATCH 3/3] WIP --- .devcontainer/Dockerfile | 10 ++++++ .devcontainer/run | 11 ++++-- .github/workflows/build_images.yml | 54 ++++++++++-------------------- 3 files changed, 37 insertions(+), 38 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 80d5e20ea..e833250ed 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -45,3 +45,13 @@ USER sentry RUN curl https://mise.run | sh \ && echo 'eval "$(/home/sentry/.local/bin/mise activate zsh)"' >> /home/sentry/.zshenv + +# When RUBY_VERSION is provided at build time, pre-install that Ruby so the +# container starts immediately without downloading it at runtime. When it is +# empty (local dev builds) Ruby is installed lazily by the `run` entrypoint. +ARG RUBY_VERSION="" +RUN if [ -n "${RUBY_VERSION}" ]; then \ + 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}"; \ + fi diff --git a/.devcontainer/run b/.devcontainer/run index 8acf88b0d..9cac53c07 100755 --- a/.devcontainer/run +++ b/.devcontainer/run @@ -34,8 +34,15 @@ RUBY_VERSION="${RUBY_VERSION:-latest}" # Always pull a precompiled binary from jdx/ruby โ€” never build from source. export MISE_RUBY_COMPILE=0 -echo "๐Ÿ“ฆ Installing ruby@${RUBY_VERSION} (precompiled)..." -"$MISE_BIN" install "ruby@${RUBY_VERSION}" +# Skip installation when the version is already present in the image (e.g. CI +# images built with the RUBY_VERSION build arg in the Dockerfile). +if "$MISE_BIN" list ruby 2>/dev/null | grep -qF "${RUBY_VERSION}"; then + echo "โœ… ruby@${RUBY_VERSION} already installed, skipping download." +else + echo "๐Ÿ“ฆ Installing ruby@${RUBY_VERSION} (precompiled)..." + "$MISE_BIN" install "ruby@${RUBY_VERSION}" +fi + "$MISE_BIN" use --global "ruby@${RUBY_VERSION}" # ---- 3. Hand off ------------------------------------------------------------- diff --git a/.github/workflows/build_images.yml b/.github/workflows/build_images.yml index 0a07303ea..4d05c2f1e 100644 --- a/.github/workflows/build_images.yml +++ b/.github/workflows/build_images.yml @@ -9,11 +9,11 @@ on: - .github/workflows/build_images.yml # Uncomment if you want to test things out in a PR - # - # pull_request: - # paths: - # - .devcontainer/** - # - .github/workflows/build_images.yml + + pull_request: + paths: + - .devcontainer/** + - .github/workflows/build_images.yml permissions: contents: read @@ -24,45 +24,28 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby_image: - - ruby:2.7.8-slim-bullseye - - ruby:3.0.7-slim-bullseye - - ruby:3.1.7-slim-bookworm - - ruby:3.2.9-slim-trixie - - ruby:3.3.10-slim-trixie - - ruby:3.4.8-slim-trixie - - ruby:4.0.0-slim-trixie + ruby_version: + - "2.7.8" + - "3.0.7" + - "3.1.7" + - "3.2.9" + - "3.3.10" + - "3.4.8" + - "4.0.0" steps: - name: Check out current commit uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - name: Generate short image name and extract version + - name: Generate short image name id: image_name run: | - ruby_image="${{ matrix.ruby_image }}" - - # Extract full version for GEM_HOME (e.g., ruby:3.4.5-slim-bookworm -> 3.4.5) - if [[ "$ruby_image" == ruby:* ]]; then - full_version=$(echo "$ruby_image" | cut -d: -f2 | cut -d- -f1) - version=$(echo "$ruby_image" | cut -d: -f2 | cut -d. -f1,2) - short_name="sentry-ruby-devcontainer-${version}" - elif [[ "$ruby_image" == jruby:latest ]]; then - full_version="latest" - short_name="sentry-ruby-devcontainer-jruby-latest" - elif [[ "$ruby_image" == jruby:* ]]; then - full_version=$(echo "$ruby_image" | cut -d: -f2 | cut -d- -f1) - version=$(echo "$ruby_image" | cut -d: -f2 | cut -d. -f1,2) - short_name="sentry-ruby-devcontainer-jruby-${version}" - else - full_version="latest" - short_name="sentry-ruby-devcontainer-${ruby_image}" - fi + ruby_version="${{ matrix.ruby_version }}" + version=$(echo "$ruby_version" | cut -d. -f1,2) + short_name="sentry-ruby-devcontainer-${version}" echo "short_name=${short_name}" >> $GITHUB_OUTPUT - echo "full_version=${full_version}" >> $GITHUB_OUTPUT echo "Generated short image name: ${short_name}" - echo "Extracted full version: ${full_version}" - name: Build and push devcontainer image id: build @@ -73,8 +56,7 @@ jobs: ghcr: true publish_on_pr: true build_args: | - IMAGE=${{ matrix.ruby_image }} - VERSION=${{ steps.image_name.outputs.full_version }} + RUBY_VERSION=${{ matrix.ruby_version }} - name: Use outputs run: |