diff --git a/.github/actions/build-ruby-layer/action.yml b/.github/actions/build-ruby-layer/action.yml index 0fc7f4597f..2d0eaa3853 100644 --- a/.github/actions/build-ruby-layer/action.yml +++ b/.github/actions/build-ruby-layer/action.yml @@ -12,17 +12,20 @@ outputs: runs: using: composite steps: - - name: Build Ruby layer - shell: bash - working-directory: ruby/src - run: ./build.sh - - name: Save Ruby OpenTelemetry SDK version id: version shell: bash working-directory: ruby/src run: | - unzip -q build/opentelemetry-ruby-layer.zip - export GEM_PATH=$PWD/ruby/gems/3.3.0/ - SDK_VERSION=$(ruby -e 'require "opentelemetry-sdk"; puts OpenTelemetry::SDK::VERSION') + SDK_VERSION=$(sed -n 's/^ opentelemetry-sdk (\([^)]*\))$/\1/p' otel/layer/Gemfile.lock) echo "component-version=$SDK_VERSION" >> "$GITHUB_OUTPUT" + + - name: Set up QEMU + uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0 + with: + platforms: arm64 + + - name: Build Ruby layer + shell: bash + working-directory: ruby/src + run: ./build.sh diff --git a/.github/workflows/ci-ruby.yml b/.github/workflows/ci-ruby.yml index 07789afbd6..fda37f53b3 100644 --- a/.github/workflows/ci-ruby.yml +++ b/.github/workflows/ci-ruby.yml @@ -5,12 +5,14 @@ on: paths: - 'ruby/**' - '.github/workflows/ci-ruby.yml' + - '.github/actions/build-ruby-layer/**' branches: - main pull_request: paths: - 'ruby/**' - '.github/workflows/ci-ruby.yml' + - '.github/actions/build-ruby-layer/**' branches: - main @@ -25,6 +27,4 @@ jobs: with: persist-credentials: false - name: Build Ruby layer - shell: bash - working-directory: ruby/src - run: ./build.sh + uses: $/.github/actions/build-ruby-layer diff --git a/.github/workflows/release-layer-ruby.yml b/.github/workflows/release-layer-ruby.yml index f0e5680e45..d6e16b58c4 100644 --- a/.github/workflows/release-layer-ruby.yml +++ b/.github/workflows/release-layer-ruby.yml @@ -111,7 +111,7 @@ jobs: artifact-name: opentelemetry-ruby-layer.zip layer-name: opentelemetry-ruby component-version: ${{ needs.build-layer.outputs.component-version }} - runtimes: ruby3.3 ruby3.4 + runtimes: ruby3.3 ruby3.4 ruby4.0 release-group: prod aws_region: ${{ matrix.aws_region }} secrets: diff --git a/integration-tests/tests/layer.test.ts b/integration-tests/tests/layer.test.ts index a962a7f55a..c7c2492fe4 100644 --- a/integration-tests/tests/layer.test.ts +++ b/integration-tests/tests/layer.test.ts @@ -24,6 +24,7 @@ describe(`${language} Lambda layer`, () => { }), ); expect(response.StatusCode).toBe(200); + expect(response.FunctionError).toBeUndefined(); const payload = JSON.parse(new TextDecoder().decode(response.Payload)); const body = JSON.parse(payload.body); diff --git a/ruby/src/otel/Dockerfile b/ruby/src/otel/Dockerfile index d6e1a993dc..9a0d88432b 100644 --- a/ruby/src/otel/Dockerfile +++ b/ruby/src/otel/Dockerfile @@ -1,60 +1,48 @@ -FROM ubuntu:26.04@sha256:f144425ff09be612d6d9ad965196e9cdc23dae1f42110a8a11a3e9a8198759f7 +# Builds one layer with gems for each Ruby version on both x86_64 and arm64. -RUN mkdir /build +FROM --platform=linux/amd64 public.ecr.aws/sam/build-ruby3.3:1.168.0@sha256:3d8db205275c9d1d67f06fda990e1f1856d052d56321d4b9b14b7cb56d115133 AS ruby3.3-amd64 +COPY layer/Gemfile layer/Gemfile.lock install-gems.sh /build/ +RUN /build/install-gems.sh -COPY . /build +FROM --platform=linux/arm64 public.ecr.aws/sam/build-ruby3.3:1.168.0@sha256:3d8db205275c9d1d67f06fda990e1f1856d052d56321d4b9b14b7cb56d115133 AS ruby3.3-arm64 +COPY layer/Gemfile layer/Gemfile.lock install-gems.sh /build/ +RUN /build/install-gems.sh -RUN apt-get update && apt-get install -y git curl libssl-dev libreadline-dev zlib1g-dev autoconf bison build-essential libyaml-dev libreadline-dev libncurses5-dev libffi-dev libgdbm-dev zip +FROM --platform=linux/amd64 public.ecr.aws/sam/build-ruby3.4:1.168.0@sha256:7a2d4e8330b46f1b6a80fa16780da0c44c5e38be3ef27390f29fae75f95bd48d AS ruby3.4-amd64 +COPY layer/Gemfile layer/Gemfile.lock install-gems.sh /build/ +RUN /build/install-gems.sh -RUN git clone https://github.com/rbenv/rbenv.git ~/.rbenv \ - && git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build \ - && git clone https://github.com/rbenv/rbenv-default-gems.git ~/.rbenv/plugins/rbenv-default-gems \ - && echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.profile \ - && echo 'eval "$(rbenv init -)"' >> ~/.profile \ - && echo 'eval "$(rbenv init -)"' >> ~/.bashrc \ - && echo 'bundler' > ~/.rbenv/default-gems +FROM --platform=linux/arm64 public.ecr.aws/sam/build-ruby3.4:1.168.0@sha256:7a2d4e8330b46f1b6a80fa16780da0c44c5e38be3ef27390f29fae75f95bd48d AS ruby3.4-arm64 +COPY layer/Gemfile layer/Gemfile.lock install-gems.sh /build/ +RUN /build/install-gems.sh -RUN echo 'alias be="bundle exec"' >> ~/.bashrc -RUN echo 'alias be="bundle exec"' >> ~/.profile +FROM --platform=linux/amd64 public.ecr.aws/sam/build-ruby4.0:1.168.0@sha256:e55cb4e278819c87c158abc25d593d465fc89d3c4992da710092b1a2e60ada86 AS ruby4.0-amd64 +COPY layer/Gemfile layer/Gemfile.lock install-gems.sh /build/ +RUN /build/install-gems.sh -# install rubies to build our gem against Gemfile -RUN . ~/.profile \ - && cd /root/.rbenv/plugins/ruby-build && git pull && cd - \ - && rbenv install 3.3.0 \ - && rbenv install 3.4.0 +FROM --platform=linux/arm64 public.ecr.aws/sam/build-ruby4.0:1.168.0@sha256:e55cb4e278819c87c158abc25d593d465fc89d3c4992da710092b1a2e60ada86 AS ruby4.0-arm64 +COPY layer/Gemfile layer/Gemfile.lock install-gems.sh /build/ +RUN /build/install-gems.sh -WORKDIR /build/layer - -RUN . ~/.profile && rbenv local 3.3.0 && bundle install -RUN . ~/.profile && rbenv local 3.4.0 && bundle install - -WORKDIR /root/.rbenv/versions/3.3.0/lib/ruby/gems/ -RUN zip -r gems-3.3.0.zip 3.3.0/ - -WORKDIR /root/.rbenv/versions/3.4.0/lib/ruby/gems/ - -# rbenv install 3.4.0 get 3.4.0+1/, so need to change back to 3.4.0+1 -RUN mv 3.4.0+1/ 3.4.0/ -RUN set -e && \ - dir=$(find /root/.rbenv/versions/3.4.0/lib/ruby/gems/ -type d -name '3.4.0+1' | head -n 1) && \ - target=$(echo "$dir" | sed 's/3\.4\.0+1/3.4.0/') && \ - mv "$dir" "$target" -RUN zip -r gems-3.4.0.zip 3.4.0/ - -# copy gems to /build/ruby/gems for zipping -RUN mkdir /build/ruby && mkdir /build/ruby/gems -WORKDIR /build/ruby/gems -RUN cp /root/.rbenv/versions/3.3.0/lib/ruby/gems/gems-3.3.0.zip . && unzip gems-3.3.0.zip && rm gems-3.3.0.zip -RUN cp /root/.rbenv/versions/3.4.0/lib/ruby/gems/gems-3.4.0.zip . && unzip gems-3.4.0.zip && rm gems-3.4.0.zip -RUN ls -al /build/ruby/gems - -# rm gem cache -RUN rm /root/.rbenv/versions/3.3.0/lib/ruby/gems/3.3.0/cache/* \ - && rm /root/.rbenv/versions/3.4.0/lib/ruby/gems/3.4.0/cache/* - -# zip all the gems +FROM public.ecr.aws/sam/build-ruby3.3:1.168.0@sha256:3d8db205275c9d1d67f06fda990e1f1856d052d56321d4b9b14b7cb56d115133 WORKDIR /build -RUN cp layer/otel-handler . && cp layer/wrapper.rb . -RUN zip -r opentelemetry-ruby-layer.zip ruby/ otel-handler wrapper.rb - -CMD cp /build/opentelemetry-ruby-layer.zip /out/opentelemetry-ruby-layer.zip +COPY --from=ruby3.3-amd64 /gems/ruby/ amd64/ +COPY --from=ruby3.4-amd64 /gems/ruby/ amd64/ +COPY --from=ruby4.0-amd64 /gems/ruby/ amd64/ +COPY --from=ruby3.3-arm64 /gems/ruby/ arm64/ +COPY --from=ruby3.4-arm64 /gems/ruby/ arm64/ +COPY --from=ruby4.0-arm64 /gems/ruby/ arm64/ + +RUN if diff -rq amd64 arm64 2>&1 | grep -v '^Only in '; then \ + echo "ERROR: amd64 and arm64 gem trees clash on the paths above" >&2; exit 1; \ + fi + +RUN mkdir -p ruby/gems \ + && cp -a amd64/. ruby/gems/ \ + && cp -a arm64/. ruby/gems/ + +COPY layer/otel-handler ./ +COPY layer/wrapper.rb ./ +RUN zip -qr opentelemetry-ruby-layer.zip ruby/ otel-handler wrapper.rb + +CMD ["cp", "/build/opentelemetry-ruby-layer.zip", "/out/opentelemetry-ruby-layer.zip"] diff --git a/ruby/src/otel/install-gems.sh b/ruby/src/otel/install-gems.sh new file mode 100755 index 0000000000..761449cee7 --- /dev/null +++ b/ruby/src/otel/install-gems.sh @@ -0,0 +1,14 @@ +#!/bin/sh +set -eu + +# Keep compiled extensions only under extensions/-linux/, not in the +# arch-agnostic gems//lib/, so amd64 and arm64 trees can be merged. +echo "install_extension_in_lib: false" > ~/.gemrc + +cd /build +BUNDLE_PATH=/gems BUNDLE_FROZEN=true BUNDLE_VERSION=system \ + bundle install --jobs "$(nproc)" + +cd /gems/ruby/*/ +rm -rf cache doc build_info bin plugins gems/*/ext +find extensions \( -name mkmf.log -o -name gem_make.out \) -delete