From 406f82b8d7db13944c1ca60f0e7eaaf3e45915f3 Mon Sep 17 00:00:00 2001 From: Prabhu Subramanian Date: Fri, 10 Jan 2025 15:26:11 +0000 Subject: [PATCH] Ruby 2.5 support Signed-off-by: Prabhu Subramanian --- .github/workflows/build-base-images.yml | 77 +++++++++++++++++++ ci/base-images/README.md | 16 +++- ci/base-images/cdxgen/Dockerfile.ruby25 | 28 +++++++ .../cdxgen/debian/Dockerfile.ruby33 | 1 + .../cdxgen/debian/Dockerfile.ruby34 | 1 + ci/base-images/sle/Dockerfile.ruby25 | 37 +++++++++ lib/helpers/envcontext.js | 18 +++++ lib/stages/pregen/pregen.js | 12 ++- types/lib/helpers/envcontext.d.ts.map | 2 +- types/lib/stages/pregen/pregen.d.ts.map | 2 +- 10 files changed, 184 insertions(+), 10 deletions(-) create mode 100644 ci/base-images/cdxgen/Dockerfile.ruby25 create mode 100644 ci/base-images/sle/Dockerfile.ruby25 diff --git a/.github/workflows/build-base-images.yml b/.github/workflows/build-base-images.yml index aeec370d2..28c45623f 100644 --- a/.github/workflows/build-base-images.yml +++ b/.github/workflows/build-base-images.yml @@ -222,6 +222,83 @@ jobs: tags: ghcr.io/cyclonedx/cdxgen-debian-dotnet6:v11 labels: ${{ steps.meta-cdxgen-debian-dotnet6.outputs.labels }} + sle-ruby25-image: + if: github.repository == 'CycloneDX/cdxgen' + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta-sle-ruby25 + uses: docker/metadata-action@v5 + with: + images: | + ghcr.io/cyclonedx/sle-ruby25 + + - name: Build and push Docker images + uses: docker/build-push-action@v5 + with: + context: . + file: ci/base-images/sle/Dockerfile.ruby25 + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta-sle-ruby25.outputs.tags }} + labels: ${{ steps.meta-sle-ruby25.outputs.labels }} + + cdxgen-sle-ruby25-image: + if: github.repository == 'CycloneDX/cdxgen' + runs-on: ubuntu-latest + needs: sle-ruby25-image + permissions: + packages: write + steps: + - uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta-cdxgen-sle-ruby25 + uses: docker/metadata-action@v5 + with: + images: | + ghcr.io/cyclonedx/cdxgen-ruby25 + + - name: Build and push Docker images + uses: docker/build-push-action@v5 + if: github.ref == 'refs/heads/master' + with: + context: . + file: ci/base-images/cdxgen/Dockerfile.ruby25 + platforms: linux/amd64,linux/arm64 + push: true + tags: ghcr.io/cyclonedx/cdxgen-ruby25:v11 + labels: ${{ steps.meta-cdxgen-sle-ruby25.outputs.labels }} + debian-ruby33-image: if: github.repository == 'CycloneDX/cdxgen' runs-on: ubuntu-latest diff --git a/ci/base-images/README.md b/ci/base-images/README.md index 8b64bb67c..dcc07aad5 100644 --- a/ci/base-images/README.md +++ b/ci/base-images/README.md @@ -146,24 +146,32 @@ docker run --rm -e CDXGEN_DEBUG_MODE=debug -v /tmp:/tmp -v $(pwd):/app:rw -t ghc Use the custom image `ghcr.io/cyclonedx/cdxgen-ruby34:v11`. -Ruby 3.3.6 +Ruby 3.3.6 (debian version) ```shell docker run --rm -e CDXGEN_DEBUG_MODE=debug -v /tmp:/tmp -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen-ruby33:v11 -r /app -o /app/bom.json -t ruby ``` -Ruby 3.4.1 +Ruby 3.4.1 (debian version) ```shell docker run --rm -e CDXGEN_DEBUG_MODE=debug -v /tmp:/tmp -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen-ruby34:v11 -r /app -o /app/bom.json -t ruby ``` +Ruby 2.5.0 (SLE version) + +Use the custom image `ghcr.io/cyclonedx/cdxgen-ruby25:v11`. + +```shell +docker run --rm -e CDXGEN_DEBUG_MODE=debug -v /tmp:/tmp -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen-ruby25:v11 -r /app -o /app/bom.json -t ruby +``` + Pass any Ruby version with the type argument to make cdxgen automatically install the appropriate version using `rbenv` prior to BOM generation. -Example: Pass `-t ruby2.5.0` to install Ruby 2.5.0 +Example: Pass `-t ruby3.3.1` to install Ruby 3.3.1 ```shell -docker run --rm -e CDXGEN_DEBUG_MODE=debug -v /tmp:/tmp -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen-ruby34:v11 -r /app -o /app/bom.json -t ruby2.5.0 +docker run --rm -e CDXGEN_DEBUG_MODE=debug -v /tmp:/tmp -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen-ruby34:v11 -r /app -o /app/bom.json -t ruby3.3.1 ``` ## Troubleshooting diff --git a/ci/base-images/cdxgen/Dockerfile.ruby25 b/ci/base-images/cdxgen/Dockerfile.ruby25 new file mode 100644 index 000000000..0b53aec3a --- /dev/null +++ b/ci/base-images/cdxgen/Dockerfile.ruby25 @@ -0,0 +1,28 @@ +FROM ghcr.io/cyclonedx/sle-ruby25:master + +LABEL maintainer="CycloneDX" \ + org.opencontainers.image.authors="Team AppThreat " \ + org.opencontainers.image.source="https://github.com/CycloneDX/cdxgen" \ + org.opencontainers.image.url="https://github.com/CycloneDX/cdxgen" \ + org.opencontainers.image.version="rolling" \ + org.opencontainers.image.vendor="AppThreat" \ + org.opencontainers.image.licenses="Apache-2.0" \ + org.opencontainers.image.title="cdxgen" \ + org.opencontainers.image.description="Rolling image with cdxgen SBOM generator for Ruby 2.5 apps" \ + org.opencontainers.docker.cmd="docker run --rm -v /tmp:/tmp -p 9090:9090 -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen-ruby25:v11 -r /app --server" + +ENV CDXGEN_IN_CONTAINER=true \ + NODE_COMPILE_CACHE="/opt/cdxgen-node-cache" \ + CDXGEN_GEM_HOME="/tmp/gems" \ + PYTHONPATH=/opt/pypi +ENV PATH=${PATH}:/usr/local/bin:/opt/pypi/bin: + +COPY . /opt/cdxgen + +RUN cd /opt/cdxgen && corepack enable && corepack pnpm install --prod --package-import-method copy && corepack pnpm cache delete \ + && mkdir -p /opt/cdxgen-node-cache \ + && node /opt/cdxgen/bin/cdxgen.js --help \ + && rm -rf ${CDXGEN_GEM_HOME} && mkdir -p ${CDXGEN_GEM_HOME} \ + && chmod a-w -R /opt + +ENTRYPOINT ["node", "/opt/cdxgen/bin/cdxgen.js"] diff --git a/ci/base-images/cdxgen/debian/Dockerfile.ruby33 b/ci/base-images/cdxgen/debian/Dockerfile.ruby33 index 880581ba5..5f299f559 100644 --- a/ci/base-images/cdxgen/debian/Dockerfile.ruby33 +++ b/ci/base-images/cdxgen/debian/Dockerfile.ruby33 @@ -22,6 +22,7 @@ COPY . /opt/cdxgen RUN cd /opt/cdxgen && corepack enable && corepack pnpm install --prod --package-import-method copy && corepack pnpm cache delete \ && mkdir -p /opt/cdxgen-node-cache \ && node /opt/cdxgen/bin/cdxgen.js --help \ + && rm -rf ${CDXGEN_GEM_HOME} && mkdir -p ${CDXGEN_GEM_HOME} \ && chmod a-w -R /opt ENTRYPOINT ["node", "/opt/cdxgen/bin/cdxgen.js"] diff --git a/ci/base-images/cdxgen/debian/Dockerfile.ruby34 b/ci/base-images/cdxgen/debian/Dockerfile.ruby34 index 3d5367c25..33ed87400 100644 --- a/ci/base-images/cdxgen/debian/Dockerfile.ruby34 +++ b/ci/base-images/cdxgen/debian/Dockerfile.ruby34 @@ -22,6 +22,7 @@ COPY . /opt/cdxgen RUN cd /opt/cdxgen && corepack enable && corepack pnpm install --prod --package-import-method copy && corepack pnpm cache delete \ && mkdir -p /opt/cdxgen-node-cache \ && node /opt/cdxgen/bin/cdxgen.js --help \ + && rm -rf ${CDXGEN_GEM_HOME} && mkdir -p ${CDXGEN_GEM_HOME} \ && chmod a-w -R /opt ENTRYPOINT ["node", "/opt/cdxgen/bin/cdxgen.js"] diff --git a/ci/base-images/sle/Dockerfile.ruby25 b/ci/base-images/sle/Dockerfile.ruby25 new file mode 100644 index 000000000..97c16018e --- /dev/null +++ b/ci/base-images/sle/Dockerfile.ruby25 @@ -0,0 +1,37 @@ +FROM registry.suse.com/bci/ruby:2.5 + +ENV LC_ALL=en_US.UTF-8 \ + LANG=en_US.UTF-8 \ + LANGUAGE=en_US.UTF-8 \ + JAVA_OPTIONS="-Dhttps.protocols=TLSv1.1,TLSv1.2" + +ENV PATH=${PATH}:/usr/local/bin:/root/.local/bin:/root/.rbenv/bin: + +RUN set -e; \ + ARCH_NAME="$(rpm --eval '%{_arch}')"; \ + url=; \ + case "${ARCH_NAME##*-}" in \ + 'x86_64') \ + OS_ARCH_SUFFIX=''; \ + GOBIN_VERSION='amd64'; \ + ;; \ + 'aarch64') \ + OS_ARCH_SUFFIX='-aarch64'; \ + GOBIN_VERSION='arm64'; \ + ;; \ + *) echo >&2 "error: unsupported architecture: '$ARCH_NAME'"; exit 1 ;; \ + esac \ + && zypper refresh && zypper --non-interactive update && zypper --non-interactive install -l --no-recommends git-core java-21-openjdk-devel nodejs20 npm20 python311 python311-pip wget zip unzip make gawk \ + && npm install -g corepack \ + && gem install bundler -v 2.3.27 \ + && gem install rubygems-update -v 3.3.27 \ + && bundle config git.allow_insecure true \ + && git clone https://github.com/rbenv/rbenv.git --depth=1 ~/.rbenv \ + && echo 'export PATH="/root/.rbenv/bin:$PATH"' >> ~/.bashrc \ + && echo 'eval "$(/root/.rbenv/bin/rbenv init - bash)"' >> ~/.bashrc \ + && source ~/.bashrc \ + && mkdir -p "$(rbenv root)/plugins" \ + && git clone https://github.com/rbenv/ruby-build.git --depth=1 "$(rbenv root)/plugins/ruby-build" \ + && zypper clean -a + +CMD /bin/bash diff --git a/lib/helpers/envcontext.js b/lib/helpers/envcontext.js index 2d22a2f86..3e2dd3ef3 100644 --- a/lib/helpers/envcontext.js +++ b/lib/helpers/envcontext.js @@ -906,6 +906,7 @@ export function performBundleInstall( process.env.BUNDLE_INSTALL_ARGS.split(" "), ); } + const gemFileLock = join(basePath, "Gemfile.lock"); console.log( `Invoking ${bundleCommand} ${installArgs.join(" ")} from ${basePath} with GEM_HOME ${cdxgenGemHome}. Please wait ...`, ); @@ -981,6 +982,23 @@ export function performBundleInstall( } return result.status === 0; } + if (result?.stderr?.includes("requires rubygems version")) { + console.log( + "This project requires a specific version of RubyGems. To do this, the existing version must be uninstalled followed by installing the required version. `sudo gem uninstall rubygems-update -v ` and then `sudo gem install rubygems-update -v `.", + ); + if (existsSync(gemFileLock)) { + console.log("Run `bundle install` command to troubleshoot the build."); + } else { + console.log( + "Try building this project directly and set the environment variable CDXGEN_GEM_HOME with the gems directory. Look for any Dockerfile or CI workflow files for information regarding the exact version of Ruby, RubyGems, Bundler needed to build this project.", + ); + } + if (process.env?.CDXGEN_IN_CONTAINER === "true") { + console.log( + "TIP: Create your own container image by using an existing Ruby base image from here: https://github.com/CycloneDX/cdxgen/tree/master/ci/base-images/debian", + ); + } + } if ( !pythonWarningShown && (result?.stderr?.includes("Failed to build gem native extension") || diff --git a/lib/stages/pregen/pregen.js b/lib/stages/pregen/pregen.js index e59dae9dd..bcdb56e06 100644 --- a/lib/stages/pregen/pregen.js +++ b/lib/stages/pregen/pregen.js @@ -476,7 +476,7 @@ export function prepareRubyEnv(filePath, options) { rubyVersionNeeded, filePath, ); - let bundleTool; + let bundleTool = "bundle"; if (status) { if (fullToolBinDir) { if (!process.env?.PATH?.includes(`versions/${rubyVersionNeeded}`)) { @@ -514,9 +514,13 @@ export function prepareRubyEnv(filePath, options) { return; } } - if (bundleTool && existsSync(bundleTool)) { + if (bundleTool && (bundleTool === "bundle" || existsSync(bundleTool))) { if (DEBUG_MODE) { - console.log(`bundle command is now available at ${bundleTool}`); + if (bundleTool === "bundle") { + console.log("cdxgen will use the default bundle command."); + } else { + console.log(`bundle command is available at ${bundleTool}`); + } } // Invoke bundle install for (const agemf of gemFiles) { @@ -535,7 +539,7 @@ export function prepareRubyEnv(filePath, options) { } else { // Just attempt bundle install console.log( - "Attempting bundle install with the default Ruby installation. This is more likely to fail ...", + "Attempting bundle install with the default Ruby installation.", ); for (const agemf of gemFiles) { performBundleInstall( diff --git a/types/lib/helpers/envcontext.d.ts.map b/types/lib/helpers/envcontext.d.ts.map index 87539f0fc..d58e4298e 100644 --- a/types/lib/helpers/envcontext.d.ts.map +++ b/types/lib/helpers/envcontext.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"envcontext.d.ts","sourceRoot":"","sources":["../../../lib/helpers/envcontext.js"],"names":[],"mappings":"AAsCA;;;;;;GAMG;AACH,wCALW,MAAM,OACN,MAAM,OAMhB;AAED;;;;;GAKG;AACH,kCAJW,MAAM,OAMhB;AAED;;;;;;GAMG;AACH,gDAJW,MAAM,OAMhB;AAED;;;;;GAKG;AACH,mCAJW,MAAM,MAsBhB;AAED;;;;;GAKG;AACH,+BAJW,MAAM,SAgChB;AAED;;;;;;;GAOG;AACH,oCALW,MAAM,oBAOhB;AAED;;;;;GAKG;AACH,qCAHW,MAAM;;;;;;;;;EAsBhB;AAED;;;;;GAKG;AACH,uCAHW,MAAM;;;;;EAgBhB;AAED;;;;;GAKG;AACH,uCAHW,MAAM;;;;;EAgBhB;AAED;;;;;GAKG;AACH,qCAHW,MAAM;;;;;EAkBhB;AAED;;;;;GAKG;AACH,oCAHW,MAAM;;;;;EAehB;AAED;;;;;GAKG;AACH,qCAHW,MAAM;;;;;EAehB;AAED;;;;;GAKG;AACH,mCAHW,MAAM;;;;EAahB;AAED;;;;;GAKG;AACH,sCAHW,MAAM;;;;EAahB;AAED;;;;;GAKG;AACH,qCAHW,MAAM;;;;EAahB;AAED;;;;;;GAMG;AACH,+DAEC;AAED;;;;;;;;;IAmCC;AAwCD;;GAEG;AACH,6CAeC;AAED;;GAEG;AACH,0CAUC;AAED;;;;;;;GAOG;AACH,mFAqBC;AAED;;;;;;;GAOG;AACH,+EAyFC;AAED;;;;;;GAMG;AACH,8DAuBC;AAED;;;;;;GAMG;AACH,iEAmCC;AASD;;;;GAIG;AACH,4CAiBC;AAED,yDAIC;AAED;;;;;;GAMG;AACH,sGAsCC;AAED;;;;;GAKG;AACH;;;EA+DC;AAED;;;;;GAKG;AACH,mFA6DC;AAED;;;;;;;;;GASG;AACH,+GAFa,OAAO,CA+HnB;AA99BD,8BAAwD"} \ No newline at end of file +{"version":3,"file":"envcontext.d.ts","sourceRoot":"","sources":["../../../lib/helpers/envcontext.js"],"names":[],"mappings":"AAsCA;;;;;;GAMG;AACH,wCALW,MAAM,OACN,MAAM,OAMhB;AAED;;;;;GAKG;AACH,kCAJW,MAAM,OAMhB;AAED;;;;;;GAMG;AACH,gDAJW,MAAM,OAMhB;AAED;;;;;GAKG;AACH,mCAJW,MAAM,MAsBhB;AAED;;;;;GAKG;AACH,+BAJW,MAAM,SAgChB;AAED;;;;;;;GAOG;AACH,oCALW,MAAM,oBAOhB;AAED;;;;;GAKG;AACH,qCAHW,MAAM;;;;;;;;;EAsBhB;AAED;;;;;GAKG;AACH,uCAHW,MAAM;;;;;EAgBhB;AAED;;;;;GAKG;AACH,uCAHW,MAAM;;;;;EAgBhB;AAED;;;;;GAKG;AACH,qCAHW,MAAM;;;;;EAkBhB;AAED;;;;;GAKG;AACH,oCAHW,MAAM;;;;;EAehB;AAED;;;;;GAKG;AACH,qCAHW,MAAM;;;;;EAehB;AAED;;;;;GAKG;AACH,mCAHW,MAAM;;;;EAahB;AAED;;;;;GAKG;AACH,sCAHW,MAAM;;;;EAahB;AAED;;;;;GAKG;AACH,qCAHW,MAAM;;;;EAahB;AAED;;;;;;GAMG;AACH,+DAEC;AAED;;;;;;;;;IAmCC;AAwCD;;GAEG;AACH,6CAeC;AAED;;GAEG;AACH,0CAUC;AAED;;;;;;;GAOG;AACH,mFAqBC;AAED;;;;;;;GAOG;AACH,+EAyFC;AAED;;;;;;GAMG;AACH,8DAuBC;AAED;;;;;;GAMG;AACH,iEAmCC;AASD;;;;GAIG;AACH,4CAiBC;AAED,yDAIC;AAED;;;;;;GAMG;AACH,sGAsCC;AAED;;;;;GAKG;AACH;;;EA+DC;AAED;;;;;GAKG;AACH,mFA6DC;AAED;;;;;;;;;GASG;AACH,+GAFa,OAAO,CAiJnB;AAh/BD,8BAAwD"} \ No newline at end of file diff --git a/types/lib/stages/pregen/pregen.d.ts.map b/types/lib/stages/pregen/pregen.d.ts.map index 47e3c9c00..9fcbdbbc3 100644 --- a/types/lib/stages/pregen/pregen.d.ts.map +++ b/types/lib/stages/pregen/pregen.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"pregen.d.ts","sourceRoot":"","sources":["../../../../lib/stages/pregen/pregen.js"],"names":[],"mappings":"AA4BA;;;;;GAKG;AACH,iEAkBC;AAED;;;;GAIG;AACH,iEASC;AAED;;;;;GAKG;AACH,wEAqCC;AAED;;;;;GAKG;AACH,qEAyDC;AAED;;;;;;;;GAQG;AACH,uEAmBC;AAED;;;;;GAKG;AACH,0EAqCC;AAED;;;;;GAKG;AACH,sEA6EC;AAED;;;;;GAKG;AACH,qEA0MC"} \ No newline at end of file +{"version":3,"file":"pregen.d.ts","sourceRoot":"","sources":["../../../../lib/stages/pregen/pregen.js"],"names":[],"mappings":"AA4BA;;;;;GAKG;AACH,iEAkBC;AAED;;;;GAIG;AACH,iEASC;AAED;;;;;GAKG;AACH,wEAqCC;AAED;;;;;GAKG;AACH,qEAyDC;AAED;;;;;;;;GAQG;AACH,uEAmBC;AAED;;;;;GAKG;AACH,0EAqCC;AAED;;;;;GAKG;AACH,sEA6EC;AAED;;;;;GAKG;AACH,qEA8MC"} \ No newline at end of file