Skip to content

Commit

Permalink
wip: ruby provider
Browse files Browse the repository at this point in the history
  • Loading branch information
nbw committed Jan 30, 2025
1 parent d2168e0 commit 93e30e7
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 2 deletions.
6 changes: 4 additions & 2 deletions core/providers/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/railwayapp/railpack/core/providers/node"
"github.com/railwayapp/railpack/core/providers/php"
"github.com/railwayapp/railpack/core/providers/python"
"github.com/railwayapp/railpack/core/providers/ruby"
"github.com/railwayapp/railpack/core/providers/staticfile"
)

Expand All @@ -17,10 +18,11 @@ type Provider interface {

func GetLanguageProviders() []Provider {
return []Provider{
&php.PhpProvider{},
&golang.GoProvider{},
&node.NodeProvider{},
&php.PhpProvider{},
&python.PythonProvider{},
&golang.GoProvider{},
&ruby.RubyProvider{},
&staticfile.StaticfileProvider{},
}
}
Expand Down
95 changes: 95 additions & 0 deletions core/providers/ruby/ruby.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package ruby

import (
"fmt"
"strings"

"github.com/railwayapp/railpack/core/generate"
"github.com/railwayapp/railpack/core/plan"
)

const (
DEFAULT_RUBY_VERSION = "latest"
)

type RubyProvider struct{}

func (p *RubyProvider) Name() string {
return "ruby"
}

func (p *RubyProvider) Detect(ctx *generate.GenerateContext) (bool, error) {
hasRuby := ctx.App.HasMatch("Gemfile")

return hasRuby, nil
}

func (p *RubyProvider) Plan(ctx *generate.GenerateContext) error {
packages := p.packages(ctx)

_ = p.install(ctx, packages)

ctx.Start.Command = fmt.Sprintf("ruby %s", "app.rb")

return nil
}

func (p *RubyProvider) packages(ctx *generate.GenerateContext) *generate.MiseStepBuilder {
packages := ctx.GetMiseStepBuilder()

ruby := packages.Default("ruby", DEFAULT_RUBY_VERSION)

if envVersion, varName := ctx.Env.GetConfigVariable("RUBY_VERSION"); envVersion != "" {
packages.Version(ruby, envVersion, varName)
}

if version := p.gemfileRubyVersion(ctx); version != "" {
packages.Version(ruby, version, "Gemfile.lock")
}

return packages
}

func (p *RubyProvider) install(ctx *generate.GenerateContext, packages *generate.MiseStepBuilder) *generate.CommandStepBuilder {
install := ctx.NewCommandStep("install")
install.AddCommands([]plan.Command{
// make sure gem is updated
plan.NewExecCommand("gem update --system --no-document"),
// install bundler
plan.NewExecCommand("gem install -N bundler"),
plan.NewCopyCommand("Gemfile"),
plan.NewCopyCommand("Gemfile.lock"),
plan.NewExecCommand("bundle install"),
})

install.DependsOn = []string{packages.DisplayName}

return install
}

// scan for a Gemfile.lock and return the Ruby version
func (p *RubyProvider) gemfileRubyVersion(ctx *generate.GenerateContext) string {
if gemfileLock, err := ctx.App.ReadFile("Gemfile.lock"); err == nil {
foundRubyVersion := false
lines := strings.Split(string(gemfileLock), "\n")
for _, line := range lines {
// Look for the "RUBY VERSION" line
if strings.HasPrefix(line, "RUBY VERSION") {
foundRubyVersion = true
continue
}

// The Ruby version follows "RUBY VERSION"
if foundRubyVersion {
fields := strings.Fields(line)
if len(fields) >= 2 && fields[0] == "ruby" {
fmt.Println("Ruby Version:", fields[1])
return fields[1]
}
}
}
// packages.Version(ruby, string(versionFile), "Gemfile.lock")
}

return ""
}
55 changes: 55 additions & 0 deletions core/providers/ruby/ruby_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package ruby

import (
"testing"

testingUtils "github.com/railwayapp/railpack/core/testing"
"github.com/stretchr/testify/require"
)

func TestDetect(t *testing.T) {
tests := []struct {
name string
path string
want bool
}{
{
name: "sinatra",
path: "../../../examples/ruby-sinatra",
want: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := testingUtils.CreateGenerateContext(t, tt.path)
provider := RubyProvider{}
got, err := provider.Detect(ctx)
require.NoError(t, err)
require.Equal(t, tt.want, got)
})
}
}
func TestGemfileRubyVersion(t *testing.T) {
tests := []struct {
name string
path string
want string
}{
{
name: "sinatra",
path: "../../../examples/ruby-sinatra",
want: "3.2",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := testingUtils.CreateGenerateContext(t, tt.path)
provider := RubyProvider{}
version, err := provider.gemfileRubyVersion(ctx)

Check failure on line 50 in core/providers/ruby/ruby_test.go

View workflow job for this annotation

GitHub Actions / Check and Test

assignment mismatch: 2 variables but provider.gemfileRubyVersion returns 1 value (typecheck)
require.NoError(t, err)
require.Equal(t, tt.want, version)
})
}
}
2 changes: 2 additions & 0 deletions examples/ruby-sinatra/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

source 'https://rubygems.org'
14 changes: 14 additions & 0 deletions examples/ruby-sinatra/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
GEM
remote: https://rubygems.org/
specs:

PLATFORMS
arm64-darwin-21

DEPENDENCIES

RUBY VERSION
ruby 3.2

BUNDLED WITH
2.3.7
1 change: 1 addition & 0 deletions examples/ruby-sinatra/Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: ruby app.rb
5 changes: 5 additions & 0 deletions examples/ruby-sinatra/app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require 'sinatra'

get '/' do
'Hello world!'
end

0 comments on commit 93e30e7

Please sign in to comment.