Maintenance: Use precompiled native gems for common platforms.
Approved-by: Martin Gruner <mg@zammad.com> Co-authored-by: Martin Gruner <mg@zammad.com>
This commit is contained in:
90
.gitlab/check_native_gem_platforms.rb
Executable file
90
.gitlab/check_native_gem_platforms.rb
Executable file
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env ruby
|
||||
# Copyright (C) 2012-2026 Zammad Foundation, https://zammad-foundation.org/
|
||||
|
||||
# Ensures that all precompiled gems in Gemfile.lock are available for every platform
|
||||
# Zammad is built for (packager.io, Docker, CI, development machines), so that none of them
|
||||
# falls back to compiling its native extension from source.
|
||||
#
|
||||
# .gitlab/check_native_gem_platforms.rb [path/to/Gemfile.lock]
|
||||
|
||||
require 'bundler'
|
||||
|
||||
class CheckNativeGemPlatforms
|
||||
|
||||
# `ruby` is the fallback for all unlisted platforms. Bundler silently drops it when a new gem
|
||||
# is added to the Gemfile, which would break installations on those platforms.
|
||||
REQUIRED_PLATFORMS = %w[ruby x86_64-linux-gnu aarch64-linux-gnu x86_64-darwin arm64-darwin].freeze
|
||||
|
||||
# An update can leave only the source variant of a gem in the lockfile, e.g. when its precompiled
|
||||
# gems are not published yet. Listing the gems keeps them checked even then.
|
||||
PRECOMPILED_GEMS = %w[ffi google-protobuf nokogiri pg sass-embedded].freeze
|
||||
|
||||
def self.run(lockfile_path)
|
||||
new(lockfile_path).run
|
||||
end
|
||||
|
||||
def initialize(lockfile_path)
|
||||
@lockfile = Bundler::LockfileParser.new(File.read(lockfile_path))
|
||||
@errors = []
|
||||
end
|
||||
|
||||
def run
|
||||
puts 'Checking native gem platforms in Gemfile.lock…'
|
||||
|
||||
check_required_platforms
|
||||
check_precompiled_gems
|
||||
|
||||
if @errors.any?
|
||||
puts(@errors.map { |error| " #{error}" })
|
||||
exit 1
|
||||
end
|
||||
|
||||
puts " #{@lockfile.platforms.size} platforms present, #{precompiled_gems.size} precompiled gems (#{precompiled_gems.keys.sort.join(', ')}) available for all #{binary_platforms.size} binary platforms."
|
||||
puts 'done.'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_required_platforms
|
||||
platforms = @lockfile.platforms.map(&:to_s)
|
||||
|
||||
(REQUIRED_PLATFORMS - platforms).each do |platform|
|
||||
@errors << "Platform '#{platform}' is missing, restore it with: bundle lock --add-platform #{platform}"
|
||||
end
|
||||
end
|
||||
|
||||
def check_precompiled_gems
|
||||
precompiled_gems.each do |name, variants|
|
||||
# This script runs without ActiveSupport, so Array#exclude? is not available.
|
||||
@errors << "#{name} is a precompiled gem, add it to PRECOMPILED_GEMS in #{__FILE__}." if !PRECOMPILED_GEMS.include?(name) # rubocop:disable Rails/NegateInclude
|
||||
|
||||
binary_platforms.each do |platform|
|
||||
next if variants.any? { |spec| binary?(spec) && Gem::Platform.new(spec.platform) === platform } # rubocop:disable Style/CaseEquality
|
||||
|
||||
@errors << "#{name} #{variants.first.version} has no precompiled gem for #{platform}#{' and would need a Rust toolchain' if rust?(variants)}."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# A gem counts as precompiled if it is listed, or ships at least one platform variant. Rust-based
|
||||
# gems count even without either, their source variant is recognizable by its rb_sys dependency.
|
||||
def precompiled_gems
|
||||
@precompiled_gems ||= @lockfile.specs.group_by(&:name).select do |name, variants|
|
||||
PRECOMPILED_GEMS.include?(name) || variants.any? { |spec| binary?(spec) } || rust?(variants)
|
||||
end
|
||||
end
|
||||
|
||||
def rust?(variants)
|
||||
variants.any? { |spec| !binary?(spec) && spec.dependencies.any? { |dependency| dependency.name == 'rb_sys' } }
|
||||
end
|
||||
|
||||
def binary?(spec)
|
||||
spec.platform != Gem::Platform::RUBY
|
||||
end
|
||||
|
||||
def binary_platforms
|
||||
@binary_platforms ||= @lockfile.platforms.reject { |platform| platform == Gem::Platform::RUBY }
|
||||
end
|
||||
end
|
||||
|
||||
CheckNativeGemPlatforms.run(ARGV[0] || File.expand_path('../Gemfile.lock', __dir__))
|
||||
@@ -63,6 +63,8 @@
|
||||
- echo "bundler-audit security check…"
|
||||
- gem exec bundle-audit update
|
||||
- gem exec bundle-audit
|
||||
- echo "Native gem platforms check…"
|
||||
- .gitlab/check_native_gem_platforms.rb
|
||||
- echo "Brakeman security check…"
|
||||
- bin/brakeman -o /dev/stdout -o tmp/brakeman-report.html
|
||||
- echo "Checking if yard can generate documentation…"
|
||||
|
||||
@@ -18,7 +18,7 @@ WORKDIR /opt/zammad
|
||||
RUN apt-get update -qq && \
|
||||
apt-get install -y postgresql-common && \
|
||||
/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y && \
|
||||
apt-get install -y --no-install-recommends libjemalloc2 curl libimlib2 libpq5 nginx gnupg postgresql-client && \
|
||||
apt-get install -y --no-install-recommends libjemalloc2 curl libimlib2 nginx gnupg postgresql-client && \
|
||||
apt-get remove -y --purge exim4-base exim4-config bsd-mailx && \
|
||||
apt-get autoremove -y --purge && \
|
||||
rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
||||
@@ -48,7 +48,7 @@ SHELL ["/bin/bash", "-o", "errexit", "-o", "pipefail", "-c"]
|
||||
|
||||
# Install packages needed to build gems and node modules
|
||||
RUN apt-get update -qq && \
|
||||
apt-get install --no-install-recommends -y build-essential git libimlib2-dev libpq-dev libyaml-dev && \
|
||||
apt-get install --no-install-recommends -y build-essential git libimlib2-dev libssl-dev libyaml-dev && \
|
||||
rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
||||
|
||||
# Install application gems
|
||||
|
||||
40
Gemfile.lock
40
Gemfile.lock
@@ -304,6 +304,10 @@ GEM
|
||||
faraday-net_http (3.4.4)
|
||||
net-http (~> 0.5)
|
||||
ffi (1.17.4)
|
||||
ffi (1.17.4-aarch64-linux-gnu)
|
||||
ffi (1.17.4-arm64-darwin)
|
||||
ffi (1.17.4-x86_64-darwin)
|
||||
ffi (1.17.4-x86_64-linux-gnu)
|
||||
ffi-compiler (1.4.2)
|
||||
ffi (>= 1.15.5)
|
||||
rake
|
||||
@@ -318,6 +322,18 @@ GEM
|
||||
google-protobuf (4.36.1)
|
||||
bigdecimal
|
||||
rake (~> 13.3)
|
||||
google-protobuf (4.36.1-aarch64-linux-gnu)
|
||||
bigdecimal
|
||||
rake (~> 13.3)
|
||||
google-protobuf (4.36.1-arm64-darwin)
|
||||
bigdecimal
|
||||
rake (~> 13.3)
|
||||
google-protobuf (4.36.1-x86_64-darwin)
|
||||
bigdecimal
|
||||
rake (~> 13.3)
|
||||
google-protobuf (4.36.1-x86_64-linux-gnu)
|
||||
bigdecimal
|
||||
rake (~> 13.3)
|
||||
graphql (2.6.10)
|
||||
base64
|
||||
fiber-storage
|
||||
@@ -446,6 +462,14 @@ GEM
|
||||
nokogiri (1.19.4)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.19.4-aarch64-linux-gnu)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.19.4-arm64-darwin)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.19.4-x86_64-darwin)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.19.4-x86_64-linux-gnu)
|
||||
racc (~> 1.4)
|
||||
nori (2.9.1)
|
||||
bigdecimal
|
||||
stringio
|
||||
@@ -542,6 +566,10 @@ GEM
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
pg (1.6.3)
|
||||
pg (1.6.3-aarch64-linux)
|
||||
pg (1.6.3-arm64-darwin)
|
||||
pg (1.6.3-x86_64-darwin)
|
||||
pg (1.6.3-x86_64-linux)
|
||||
playwright-ruby-client (1.63.0)
|
||||
base64
|
||||
concurrent-ruby (>= 1.1.6)
|
||||
@@ -756,6 +784,14 @@ GEM
|
||||
sass-embedded (1.104.1)
|
||||
google-protobuf (~> 4.31)
|
||||
rake (>= 13)
|
||||
sass-embedded (1.104.1-aarch64-linux-gnu)
|
||||
google-protobuf (~> 4.31)
|
||||
sass-embedded (1.104.1-arm64-darwin)
|
||||
google-protobuf (~> 4.31)
|
||||
sass-embedded (1.104.1-x86_64-darwin)
|
||||
google-protobuf (~> 4.31)
|
||||
sass-embedded (1.104.1-x86_64-linux-gnu)
|
||||
google-protobuf (~> 4.31)
|
||||
securerandom (0.4.1)
|
||||
selenium-webdriver (4.49.0)
|
||||
base64 (~> 0.2)
|
||||
@@ -892,7 +928,11 @@ GEM
|
||||
multipart-post (~> 2.0)
|
||||
|
||||
PLATFORMS
|
||||
aarch64-linux-gnu
|
||||
arm64-darwin
|
||||
ruby
|
||||
x86_64-darwin
|
||||
x86_64-linux-gnu
|
||||
|
||||
DEPENDENCIES
|
||||
PoParser
|
||||
|
||||
Reference in New Issue
Block a user