mirror of
https://github.com/lloeki/minimal-rack/
synced 2025-12-06 05:04:40 +01:00
Add minimal apps
This commit is contained in:
commit
6fda5da1d2
11 changed files with 629 additions and 0 deletions
2
.dockerignore
Normal file
2
.dockerignore
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
/log/
|
||||||
|
/tmp/
|
||||||
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
use_nix
|
||||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/log/
|
||||||
|
/tmp/
|
||||||
|
/vendor/
|
||||||
36
Dockerfile
Normal file
36
Dockerfile
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
ARG RUBY_VERSION
|
||||||
|
|
||||||
|
FROM ruby:${RUBY_VERSION}
|
||||||
|
|
||||||
|
# bash: for consistency
|
||||||
|
# tzdata: rails
|
||||||
|
# gcompat: nokogiri & al.
|
||||||
|
# Error loading shared library ld-linux-x86-64.so.2: No such file or directory
|
||||||
|
# Error loading shared library ld-linux-aarch64.so.1: No such file or directory
|
||||||
|
RUN if [ -f /etc/alpine-release ]; then apk add build-base bash tzdata && if ! grep -e '^3\.8' /etc/alpine-release; then apk add gcompat; fi; fi
|
||||||
|
|
||||||
|
RUN <<-SHELL
|
||||||
|
case ${RUBY_VERSION} in
|
||||||
|
2.1*|2.2*)
|
||||||
|
gem update --system '2.7.11'
|
||||||
|
gem install bundler -v '~> 1.17.3'
|
||||||
|
;;
|
||||||
|
2.3*|2.4*)
|
||||||
|
# rails 4.1 and 4.2 need bundler < 2.0
|
||||||
|
gem update --system '2.7.11'
|
||||||
|
gem install bundler -v '~> 1.17.3'
|
||||||
|
;;
|
||||||
|
2.5*)
|
||||||
|
gem update --system '3.3.27'
|
||||||
|
gem install bundler -v '~> 2.3.27'
|
||||||
|
;;
|
||||||
|
2.6*|2.7*)
|
||||||
|
gem update --system '3.4.22'
|
||||||
|
gem install bundler -v '~> 2.4.22'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
gem update --system
|
||||||
|
gem install bundler
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
SHELL
|
||||||
244
Rakefile
Normal file
244
Rakefile
Normal file
|
|
@ -0,0 +1,244 @@
|
||||||
|
def resolve_args(args)
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
compatibility = YAML.load(File.read('compatibility'))
|
||||||
|
a = args.to_a
|
||||||
|
|
||||||
|
filename = nil
|
||||||
|
ruby_image = nil
|
||||||
|
while (arg = a.shift)
|
||||||
|
candidate = File.basename(arg, '.rb')
|
||||||
|
|
||||||
|
if (c = compatibility[candidate.split(':')[0]])
|
||||||
|
kind = candidate.split(':')[0]
|
||||||
|
version = candidate.split(':')[1] # TODO: nil?
|
||||||
|
compatibility_match = c.select do |e|
|
||||||
|
# TODO: corner cases
|
||||||
|
# does not match on 3 if only ~> 3.2, e.g rails
|
||||||
|
# matches on 4 if ~> 4.0 and ~> 4.2 but will resolve to 4.2 but with 4.0 compat match (wrong ruby, wrong gem...)
|
||||||
|
Gem::Requirement.new(e['version']).satisfied_by?(Gem::Version.new(version))
|
||||||
|
end.tap do |m|
|
||||||
|
if m.empty?
|
||||||
|
raise ArgumentError, "unmatched requirement for #{kind}:#{version}"
|
||||||
|
elsif !m.one?
|
||||||
|
raise ArgumentError, "ambiguous version range for #{kind}:#{version}"
|
||||||
|
end
|
||||||
|
end.first
|
||||||
|
elsif candidate =~ /^(\d+\.\d+(?:\.\d+|))$/
|
||||||
|
ruby_version = $1
|
||||||
|
ruby_libc = 'gnu'
|
||||||
|
elsif candidate =~ /^(\d+\.\d+(?:\.\d+|))-alpine$/
|
||||||
|
ruby_version = $1
|
||||||
|
ruby_libc = 'musl'
|
||||||
|
elsif %w[x86_64 aarch64].include?(candidate)
|
||||||
|
ruby_cpu = candidate
|
||||||
|
elsif %w[musl alpine].include?(candidate)
|
||||||
|
ruby_libc = 'musl'
|
||||||
|
elsif %w[gnu debian].include?(candidate)
|
||||||
|
ruby_libc = 'gnu'
|
||||||
|
elsif %w[puma unicorn rainbows thin falcon webrick].include?(candidate)
|
||||||
|
server = candidate
|
||||||
|
else
|
||||||
|
raise ArgumentError, "unsupported arg: #{arg}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if server.nil?
|
||||||
|
server = 'thin'
|
||||||
|
end
|
||||||
|
|
||||||
|
if kind.nil?
|
||||||
|
if ruby_version.nil?
|
||||||
|
kind = compatibility.keys.first # TODO: pick a better one than .first
|
||||||
|
compatibility_match = compatibility[kind].first # TODO: pick a better one than .first
|
||||||
|
# TODO: get kind version (for serve), like having kind specified but versionless
|
||||||
|
else
|
||||||
|
match = compatibility.each_with_object([]) do |(k, c), m|
|
||||||
|
version_matches = c.select do |e|
|
||||||
|
Gem::Requirement.new(e['ruby']).satisfied_by?(Gem::Version.new(ruby_version))
|
||||||
|
end
|
||||||
|
|
||||||
|
m << [k, version_matches] if version_matches.any?
|
||||||
|
end.first # TODO: pick a better one than .first
|
||||||
|
|
||||||
|
if match.nil?
|
||||||
|
raise ArgumentError, "unmatched requirement for ruby:#{ruby_version}"
|
||||||
|
end
|
||||||
|
|
||||||
|
compatibility_match = match[1].first # TODO: pick a better one than .first
|
||||||
|
# TODO: get kind version (for serve), like having kind specified but versionless
|
||||||
|
kind = match[0]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if filename.nil?
|
||||||
|
filename = compatibility_match['main'] || kind + '.rb'
|
||||||
|
end
|
||||||
|
|
||||||
|
if ruby_version.nil?
|
||||||
|
match = %w[2.1 2.2 2.3 2.4 2.5 2.6 2.7 3.0 3.1 3.2 3.3].map { |v| Gem::Version.new(v) }.select do |v|
|
||||||
|
Gem::Requirement.new(compatibility_match['ruby']).satisfied_by?(v)
|
||||||
|
end.max
|
||||||
|
|
||||||
|
if match.nil?
|
||||||
|
raise ArgumentError, "unmatched requirement for ruby with #{kind}:#{version}"
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_version = match.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
if ruby_cpu.nil?
|
||||||
|
if RUBY_PLATFORM =~ /^(?:universal\.|)(x86_64|aarch64|arm64)/
|
||||||
|
ruby_cpu = $1.sub(/arm64(:?e|)/, 'aarch64')
|
||||||
|
else
|
||||||
|
raise ArgumentError, "unsupported platform: #{RUBY_PLATFORM}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_os = 'linux'
|
||||||
|
|
||||||
|
if ruby_libc.nil?
|
||||||
|
ruby_libc = 'gnu'
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_platform = "#{ruby_cpu}-#{ruby_os}-#{ruby_libc}"
|
||||||
|
|
||||||
|
if ruby_image.nil?
|
||||||
|
if ruby_libc == 'musl'
|
||||||
|
ruby_image = ruby_version + '-alpine'
|
||||||
|
else
|
||||||
|
ruby_image = ruby_version
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
{
|
||||||
|
version: version,
|
||||||
|
ruby_image: ruby_image,
|
||||||
|
ruby_version: ruby_version,
|
||||||
|
filename: filename,
|
||||||
|
server: server,
|
||||||
|
ruby_platform: ruby_platform,
|
||||||
|
}.tap { |r| p r }
|
||||||
|
end
|
||||||
|
|
||||||
|
def satisfied?(result, deps = [])
|
||||||
|
result_time = case result
|
||||||
|
when String
|
||||||
|
File.ctime(result).to_datetime
|
||||||
|
when Proc
|
||||||
|
result.call
|
||||||
|
else
|
||||||
|
raise ArgumentError, "invalid type: #{dep.class}"
|
||||||
|
end
|
||||||
|
|
||||||
|
return false if result_time.nil?
|
||||||
|
return true if deps.empty?
|
||||||
|
|
||||||
|
deps.map do |dep|
|
||||||
|
dep_time = case dep
|
||||||
|
when String
|
||||||
|
File.ctime(dep).to_datetime
|
||||||
|
when Proc
|
||||||
|
dep.call
|
||||||
|
else
|
||||||
|
raise ArgumentError, "invalid type: #{dep.class}"
|
||||||
|
end
|
||||||
|
|
||||||
|
result_time > dep_time
|
||||||
|
end.reduce(:&)
|
||||||
|
end
|
||||||
|
|
||||||
|
namespace :docker do
|
||||||
|
def image(env)
|
||||||
|
"sandbox/minimal:ruby-#{env[:ruby_image]}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def volume(env)
|
||||||
|
"sandbox-minimal-ruby-#{env[:ruby_image]}-#{env[:ruby_platform]}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def docker_platform(env)
|
||||||
|
env[:ruby_platform].split('-').take(2).reverse.join('/')
|
||||||
|
end
|
||||||
|
|
||||||
|
def image_time(image)
|
||||||
|
require 'time'
|
||||||
|
|
||||||
|
last_tag_time = `docker image inspect -f '{{ .Metadata.LastTagTime }}' '#{image}'`.chomp
|
||||||
|
|
||||||
|
if $?.to_i == 0
|
||||||
|
DateTime.strptime(last_tag_time, '%Y-%m-%d %H:%M:%S.%N %z')
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def volume_time(volume)
|
||||||
|
require 'time'
|
||||||
|
|
||||||
|
volume_creation_time = `docker volume inspect -f '{{ .CreatedAt }}' '#{volume}'`.chomp
|
||||||
|
|
||||||
|
if $?.to_i == 0
|
||||||
|
DateTime.strptime(volume_creation_time, '%Y-%m-%dT%H:%M:%S%z')
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
namespace :image do
|
||||||
|
task :build do |_task, args|
|
||||||
|
env = resolve_args(args)
|
||||||
|
|
||||||
|
deps = [
|
||||||
|
'Dockerfile'
|
||||||
|
]
|
||||||
|
|
||||||
|
next if satisfied?(-> { image_time(image(env)) }, deps)
|
||||||
|
|
||||||
|
sh "docker buildx build --platform #{docker_platform(env)} -f Dockerfile --build-arg RUBY_VERSION='#{env[:ruby_image]}' --tag '#{image(env)}' ."
|
||||||
|
end
|
||||||
|
|
||||||
|
task :clean do |_task, args|
|
||||||
|
env = resolve_args(args)
|
||||||
|
|
||||||
|
sh "docker image rm '#{image(env)}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
namespace :volume do
|
||||||
|
task :create do |_task, args|
|
||||||
|
env = resolve_args(args)
|
||||||
|
|
||||||
|
next if satisfied?(-> () { volume_time(volume(env))} )
|
||||||
|
|
||||||
|
sh "docker volume create #{volume(env)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
task :clean do |_task, args|
|
||||||
|
env = resolve_args(args)
|
||||||
|
|
||||||
|
sh "docker volume rm '#{volume(env)}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
task :build => :'docker:image:build'
|
||||||
|
task :volume => :'docker:volume:create'
|
||||||
|
|
||||||
|
task :ruby => [:build, :volume] do |_task, args|
|
||||||
|
env = resolve_args(args)
|
||||||
|
|
||||||
|
sh "docker run --rm -it --platform #{docker_platform(env)} -v '#{volume(env)}':'/usr/local/bundle' -v '#{Dir.pwd}':'#{Dir.pwd}' -w '#{Dir.pwd}' '#{image(env)}'"
|
||||||
|
end
|
||||||
|
|
||||||
|
task :shell => [:build, :volume] do |_task, args|
|
||||||
|
env = resolve_args(args)
|
||||||
|
|
||||||
|
sh "docker run --rm -it --platform #{docker_platform(env)} -v '#{volume(env)}':'/usr/local/bundle' -v '#{Dir.pwd}':'#{Dir.pwd}' -w '#{Dir.pwd}' '#{image(env)}' /bin/bash"
|
||||||
|
end
|
||||||
|
|
||||||
|
task :serve => [:build, :volume] do |_task, args|
|
||||||
|
env = resolve_args(args)
|
||||||
|
|
||||||
|
sh "docker run --rm -it --platform #{docker_platform(env)} -v '#{volume(env)}':'/usr/local/bundle' -v '#{Dir.pwd}':'#{Dir.pwd}' -w '#{Dir.pwd}' -p 3000:3000 '#{image(env)}' ruby '#{env[:filename]}' '#{env[:version]}' '#{env[:server]}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
83
compatibility
Normal file
83
compatibility
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
rack:
|
||||||
|
- version: '~> 1.3'
|
||||||
|
ruby: ['>= 1.8.7', '< 3.0']
|
||||||
|
- version: '~> 2.0'
|
||||||
|
ruby: '>= 2.3.0'
|
||||||
|
- version: '~> 3.0'
|
||||||
|
ruby: '>= 2.4.0'
|
||||||
|
gem:
|
||||||
|
rackup: '>= 0'
|
||||||
|
# thin: false
|
||||||
|
sinatra:
|
||||||
|
- version: '~> 1.0'
|
||||||
|
ruby: ['>= 1.8.7', '< 3.0']
|
||||||
|
gem:
|
||||||
|
rack: '< 2.0'
|
||||||
|
- version: '~> 2.0'
|
||||||
|
ruby: '>= 2.3.0'
|
||||||
|
- version: '~> 3.0'
|
||||||
|
ruby: '>= 2.6.0'
|
||||||
|
rails:
|
||||||
|
- version: '~> 3.2.0'
|
||||||
|
ruby: ['>= 1.8.7', '< 2.4']
|
||||||
|
gem:
|
||||||
|
bundler: '< 2.0'
|
||||||
|
- version: '~> 4.0.0'
|
||||||
|
ruby: ['>= 1.9.3', '< 2.3']
|
||||||
|
gem:
|
||||||
|
bundler: '< 2.0'
|
||||||
|
- version: '~> 4.1.0'
|
||||||
|
ruby: ['>= 1.9.3', '< 2.4']
|
||||||
|
gem:
|
||||||
|
bundler: '< 2.0'
|
||||||
|
- version: '~> 4.2.0'
|
||||||
|
ruby: ['>= 1.9.3', '< 2.5']
|
||||||
|
gem:
|
||||||
|
loofah: '~> 2.19.1' # solve Nokogiri::HTML4 exception
|
||||||
|
bundler: '< 2.0'
|
||||||
|
- version: '~> 5.0.0'
|
||||||
|
ruby: ['>= 2.2.2', '< 2.5']
|
||||||
|
gem:
|
||||||
|
loofah: '~> 2.19.1' # solve Nokogiri::HTML4 exception
|
||||||
|
- version: '~> 5.1.0'
|
||||||
|
ruby: ['>= 2.2.2', '< 2.6']
|
||||||
|
- version: '~> 5.2.0'
|
||||||
|
ruby: ['>= 2.2.2', '< 2.7']
|
||||||
|
- version: '~> 6.0.0'
|
||||||
|
# 2.7 excluded because stringio defaults to 3.0
|
||||||
|
ruby: ['>= 2.5', '< 2.7']
|
||||||
|
gem:
|
||||||
|
# superclass mismatch for class StringIO (TypeError)
|
||||||
|
stringio: '< 3.0'
|
||||||
|
- version: '~> 6.1.0'
|
||||||
|
# 3.3 has a bug: https://bugs.ruby-lang.org/issues/20085
|
||||||
|
ruby: ['>= 2.5', '< 3.3']
|
||||||
|
- version: '~> 7.0.0'
|
||||||
|
# 3.3 has a bug: https://bugs.ruby-lang.org/issues/20085
|
||||||
|
ruby: ['>= 2.7', '< 3.3']
|
||||||
|
- version: '~> 7.1.0'
|
||||||
|
# 3.3 has a bug: https://bugs.ruby-lang.org/issues/20085
|
||||||
|
ruby: ['>= 2.7', '< 3.3']
|
||||||
|
grape:
|
||||||
|
- version: ['~> 1.0', '< 1.3']
|
||||||
|
ruby: ['>= 2.0', '< 3.0']
|
||||||
|
gem:
|
||||||
|
activesupport: '< 7.0'
|
||||||
|
rack: '< 2.0'
|
||||||
|
- version: ['~> 1.3', '< 1.6']
|
||||||
|
ruby: ['>= 2.4', '< 3.0']
|
||||||
|
gem:
|
||||||
|
activesupport: '< 7.0'
|
||||||
|
rack: '< 3.0'
|
||||||
|
- version: ['~> 1.6', '< 1.8']
|
||||||
|
ruby: ['>= 2.5']
|
||||||
|
gem:
|
||||||
|
rackup: '>= 0'
|
||||||
|
- version: ['~> 1.8', '< 2.0']
|
||||||
|
ruby: ['>= 2.6']
|
||||||
|
gem:
|
||||||
|
rackup: '>= 0'
|
||||||
|
- version: '~> 2.0'
|
||||||
|
ruby: ['>= 2.6']
|
||||||
|
gem:
|
||||||
|
rackup: '>= 0'
|
||||||
73
grape.rb
Normal file
73
grape.rb
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
begin
|
||||||
|
require "bundler/inline"
|
||||||
|
rescue LoadError => e
|
||||||
|
$stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
|
||||||
|
raise e
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'yaml'
|
||||||
|
compatibility = YAML.load(File.read('compatibility'))
|
||||||
|
|
||||||
|
kind = File.basename(__FILE__, '.rb')
|
||||||
|
version = ARGV[0] || raise(ArgumentError, 'missing version')
|
||||||
|
match = compatibility[kind].select do |e|
|
||||||
|
Gem::Requirement.new(e['version']).satisfied_by?(Gem::Version.new(version))
|
||||||
|
end.tap do |m|
|
||||||
|
if m.empty?
|
||||||
|
raise ArgumentError, "unmatched requirement for #{kind}:#{version}"
|
||||||
|
elsif !m.one?
|
||||||
|
raise ArgumentError, "ambiguous version range for #{kind}:#{version}"
|
||||||
|
end
|
||||||
|
end.first
|
||||||
|
server = ARGV[1] || 'thin'
|
||||||
|
|
||||||
|
gemfile(true) do
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
ruby match['ruby']
|
||||||
|
|
||||||
|
gem 'grape', "~> #{version}.0"
|
||||||
|
gem server
|
||||||
|
|
||||||
|
match.fetch('gem', []).each do |name, requirement|
|
||||||
|
gem name, requirement
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'rack'
|
||||||
|
require 'grape'
|
||||||
|
|
||||||
|
class API < Grape::API
|
||||||
|
version 'v0', using: :header, vendor: 'hello'
|
||||||
|
format :json
|
||||||
|
prefix :hello
|
||||||
|
|
||||||
|
get :world do
|
||||||
|
{ hello: 'world' }
|
||||||
|
end
|
||||||
|
|
||||||
|
#resource :hello do
|
||||||
|
# route_param :id do
|
||||||
|
# get do
|
||||||
|
# { hello: 'world' }
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#end
|
||||||
|
|
||||||
|
# mount API::Sub
|
||||||
|
# mount API::V1 => '/v1'
|
||||||
|
end
|
||||||
|
|
||||||
|
App = Rack::Builder.new do
|
||||||
|
# precompile routes
|
||||||
|
API.compile!
|
||||||
|
|
||||||
|
run API
|
||||||
|
|
||||||
|
# sinatra:
|
||||||
|
# use Rack::Session::Cookie
|
||||||
|
# run Rack::Cascade.new [Web, API]
|
||||||
|
end
|
||||||
|
|
||||||
|
Rack::Server.new(app: App, Host: '0.0.0.0', Port: 3000).start
|
||||||
|
|
||||||
46
rack.rb
Normal file
46
rack.rb
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
begin
|
||||||
|
require "bundler/inline"
|
||||||
|
rescue LoadError => e
|
||||||
|
$stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
|
||||||
|
raise e
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'yaml'
|
||||||
|
compatibility = YAML.load(File.read('compatibility'))
|
||||||
|
|
||||||
|
kind = File.basename(__FILE__, '.rb')
|
||||||
|
version = ARGV[0] || raise(ArgumentError, 'missing version')
|
||||||
|
match = compatibility[kind].select do |e|
|
||||||
|
Gem::Requirement.new(e['version']).satisfied_by?(Gem::Version.new(version))
|
||||||
|
end.tap do |m|
|
||||||
|
if m.empty?
|
||||||
|
raise ArgumentError, "unmatched requirement for #{kind}:#{version}"
|
||||||
|
elsif !m.one?
|
||||||
|
raise ArgumentError, "ambiguous version range for #{kind}:#{version}"
|
||||||
|
end
|
||||||
|
end.first
|
||||||
|
server = ARGV[1] || 'thin'
|
||||||
|
|
||||||
|
gemfile(true) do
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
ruby match['ruby']
|
||||||
|
|
||||||
|
gem 'rack', "~> #{version}.0"
|
||||||
|
gem server
|
||||||
|
|
||||||
|
match.fetch('gem', []).each do |name, requirement|
|
||||||
|
gem name, requirement
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'rack'
|
||||||
|
require 'json'
|
||||||
|
|
||||||
|
App = Rack::Builder.new do
|
||||||
|
map "/hello/world" do
|
||||||
|
run -> (env) { [200, { 'content-type' => 'application/json' }, [JSON.dump({ hello: :world })]] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Rack::Server.new(app: App, Host: '0.0.0.0', Port: 3000).start
|
||||||
68
rails.rb
Normal file
68
rails.rb
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
begin
|
||||||
|
require "bundler/inline"
|
||||||
|
rescue LoadError => e
|
||||||
|
$stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
|
||||||
|
raise e
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'yaml'
|
||||||
|
compatibility = YAML.load(File.read('compatibility'))
|
||||||
|
|
||||||
|
kind = File.basename(__FILE__, '.rb')
|
||||||
|
version = ARGV[0] || raise(ArgumentError, 'missing version')
|
||||||
|
match = compatibility[kind].select do |e|
|
||||||
|
Gem::Requirement.new(e['version']).satisfied_by?(Gem::Version.new(version))
|
||||||
|
end.tap do |m|
|
||||||
|
if m.empty?
|
||||||
|
raise ArgumentError, "unmatched requirement for #{kind}:#{version}"
|
||||||
|
elsif !m.one?
|
||||||
|
raise ArgumentError, "ambiguous version range for #{kind}:#{version}"
|
||||||
|
end
|
||||||
|
end.first
|
||||||
|
server = ARGV[1] || 'thin'
|
||||||
|
|
||||||
|
gemfile(true) do
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
ruby match['ruby']
|
||||||
|
|
||||||
|
gem 'rails', "~> #{version}.0"
|
||||||
|
gem server
|
||||||
|
|
||||||
|
match.fetch('gem', []).each do |name, requirement|
|
||||||
|
gem name, requirement
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require "action_controller/railtie"
|
||||||
|
|
||||||
|
class App < Rails::Application
|
||||||
|
routes.append do
|
||||||
|
get "/hello/world" => "hello#world"
|
||||||
|
end
|
||||||
|
|
||||||
|
config.consider_all_requests_local = true # display errors
|
||||||
|
config.eager_load = true # load everything
|
||||||
|
|
||||||
|
if Gem::Requirement.new('< 4.0').satisfied_by?(Gem.loaded_specs['rails'].version)
|
||||||
|
config.secret_token = 'a4e6df27-2f39-41e4-83d2-3bc4d087c910'
|
||||||
|
else
|
||||||
|
config.secret_key_base = 'a4e6df27-2f39-41e4-83d2-3bc4d087c910'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if Gem::Requirement.new('< 5.0').satisfied_by?(Gem.loaded_specs['rails'].version)
|
||||||
|
action_controller_api_class = ActionController::Base
|
||||||
|
else
|
||||||
|
action_controller_api_class = ActionController::API
|
||||||
|
end
|
||||||
|
|
||||||
|
class HelloController < action_controller_api_class
|
||||||
|
def world
|
||||||
|
render json: {hello: :world}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
App.initialize!
|
||||||
|
|
||||||
|
Rack::Server.new(app: App, Host: '0.0.0.0', Port: 3000).start
|
||||||
25
shell.nix
Normal file
25
shell.nix
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
pkgs ? import <nixpkgs> {},
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
ruby = pkgs.ruby_3_2;
|
||||||
|
llvm = pkgs.llvmPackages_16;
|
||||||
|
gcc = pkgs.gcc13;
|
||||||
|
in llvm.stdenv.mkDerivation {
|
||||||
|
name = "sandbox-minimal.shell";
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
ruby
|
||||||
|
|
||||||
|
# for psych >= 5.1 pulled by rails 7.1
|
||||||
|
pkgs.libyaml.dev
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
shellHook = ''
|
||||||
|
export RUBY_VERSION="$(ruby -e 'puts RUBY_VERSION.gsub(/\d+$/, "0")')"
|
||||||
|
export GEM_HOME="$(pwd)/vendor/bundle/ruby/$RUBY_VERSION"
|
||||||
|
export BUNDLE_PATH="$(pwd)/vendor/bundle"
|
||||||
|
export PATH="$GEM_HOME/bin:$PATH"
|
||||||
|
'';
|
||||||
|
}
|
||||||
48
sinatra.rb
Normal file
48
sinatra.rb
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
begin
|
||||||
|
require "bundler/inline"
|
||||||
|
rescue LoadError => e
|
||||||
|
$stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
|
||||||
|
raise e
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'yaml'
|
||||||
|
compatibility = YAML.load(File.read('compatibility'))
|
||||||
|
|
||||||
|
kind = File.basename(__FILE__, '.rb')
|
||||||
|
version = ARGV[0] || raise(ArgumentError, 'missing version')
|
||||||
|
match = compatibility[kind].select do |e|
|
||||||
|
Gem::Requirement.new(e['version']).satisfied_by?(Gem::Version.new(version))
|
||||||
|
end.tap do |m|
|
||||||
|
if m.empty?
|
||||||
|
raise ArgumentError, "unmatched requirement for #{kind}:#{version}"
|
||||||
|
elsif !m.one?
|
||||||
|
raise ArgumentError, "ambiguous version range for #{kind}:#{version}"
|
||||||
|
end
|
||||||
|
end.first
|
||||||
|
server = ARGV[1] || 'thin'
|
||||||
|
|
||||||
|
gemfile(true) do
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
ruby match['ruby'] if match['ruby']
|
||||||
|
|
||||||
|
gem 'sinatra', "~> #{version}.0"
|
||||||
|
gem server
|
||||||
|
|
||||||
|
match.fetch('gem', []).each do |name, requirement|
|
||||||
|
gem name, requirement
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'sinatra/base'
|
||||||
|
require 'json'
|
||||||
|
|
||||||
|
class App < Sinatra::Base
|
||||||
|
get '/hello/world' do
|
||||||
|
status 200
|
||||||
|
content_type :json
|
||||||
|
body JSON.dump({ hello: :world })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Rack::Server.new(app: App, Host: '0.0.0.0', Port: 3000).start
|
||||||
Loading…
Add table
Add a link
Reference in a new issue