ruby

package
v0.18.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 26, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package ruby implements omnibump support for Ruby projects using Bundler.

Updates are performed via direct Gemfile.lock text editing — no Ruby or Bundler CLI is required at runtime. This matches the deployment model where omnibump runs in melange build sandboxes without guaranteed toolchain availability.

Manifest files

The package detects Ruby projects by the presence of Gemfile.lock in the target directory. Both Gemfile and Gemfile.lock are listed as manifest files, but only Gemfile.lock is parsed and modified.

Gemfile.lock parsing

The parser handles the three source section types found in Bundler lockfiles:

  • GEM — gems from a rubygems remote (e.g. rubygems.org)
  • GIT — gems from a git repository
  • PATH — gems from a local filesystem path

Within each section, spec lines (4-space indent) identify gems and their versions, while dependency constraint lines (6-space indent) are preserved but not modified during updates.

Update strategy

All updates are direct text replacements: the version in " gemname (oldversion)" is replaced with the new version. Dependency constraint lines are left untouched. Downgrade attempts are detected via semver comparison and skipped with a warning.

Limitations

  • No constraint validation: bumping a gem to a version that violates another gem's constraints will produce an inconsistent lockfile.
  • No checksum or integrity handling (Gemfile.lock has none, unlike go.sum).
  • AnalyzeRemote is not yet implemented.
Example
package main

import (
	"fmt"

	"github.com/chainguard-dev/omnibump/pkg/languages"
)

func main() {
	// Get the Ruby language from the registry.
	lang, err := languages.Get("ruby")
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println("Language:", lang.Name())
}
Output:
Language: ruby

Index

Examples

Constants

View Source
const (
	// LanguageRuby is the language identifier.
	LanguageRuby = "ruby"

	// ManifestGemfile is the Gemfile manifest filename.
	ManifestGemfile = "Gemfile"

	// ManifestGemfileLock is the Gemfile.lock manifest filename.
	ManifestGemfileLock = "Gemfile.lock"
)

Language and manifest constants.

Variables

View Source
var (
	// ErrGemfileLockNotFound is returned when Gemfile.lock is not found.
	ErrGemfileLockNotFound = errors.New("gemfile.lock not found")

	// ErrRemoteAnalysisNotImplemented is returned when remote analysis is not implemented.
	ErrRemoteAnalysisNotImplemented = errors.New("remote analysis not yet implemented")

	// ErrValidationFailed is returned when post-update validation detects a version mismatch.
	ErrValidationFailed = errors.New("validation failed")

	// ErrPackageNotFound is returned when a dependency is not found in the lockfile.
	ErrPackageNotFound = errors.New("package not found in Gemfile.lock")
)
View Source
var (
	// ErrInvalidGemfileLock is returned when the lockfile cannot be parsed.
	ErrInvalidGemfileLock = errors.New("invalid Gemfile.lock format")
)

Functions

func DoUpdate

func DoUpdate(ctx context.Context, packages map[string]*Package, gemfileLockPath string) error

DoUpdate performs the actual update of gem versions in a Gemfile.lock. It does direct text replacement — no Ruby/Bundler CLI needed.

Types

type Analyzer

type Analyzer struct{}

Analyzer implements the analyzer.Analyzer interface for Ruby projects.

func (*Analyzer) Analyze

func (a *Analyzer) Analyze(ctx context.Context, projectPath string) (*analyzer.AnalysisResult, error)

Analyze performs dependency analysis on a Ruby project.

func (*Analyzer) AnalyzeRemote

func (a *Analyzer) AnalyzeRemote(_ context.Context, _ map[string][]byte) (*analyzer.RemoteAnalysisResult, error)

AnalyzeRemote performs dependency analysis on remotely-fetched Ruby files. Not yet implemented for Ruby — returns error.

func (*Analyzer) RecommendStrategy

func (a *Analyzer) RecommendStrategy(_ context.Context, _ *analyzer.AnalysisResult, deps []analyzer.Dependency) (*analyzer.Strategy, error)

RecommendStrategy always recommends direct updates for Ruby dependencies. Ruby doesn't have a "property" abstraction like Maven.

type GemPackage

type GemPackage struct {
	Name         string
	Version      string
	Source       string
	Dependencies []string // Dependency constraints (e.g., "rack (~> 3.0)")
}

GemPackage represents a gem from Gemfile.lock.

func ParseGemfileLock

func ParseGemfileLock(r io.Reader) ([]GemPackage, error)

ParseGemfileLock parses a Gemfile.lock file and returns the list of gem packages. It handles GEM, GIT, PATH, PLATFORMS, and BUNDLED WITH sections.

type Package

type Package struct {
	Name    string
	Version string
	Index   int // For ordering updates
}

Package represents a target gem dependency to update.

type Ruby

type Ruby struct{}

Ruby implements the Language interface for Ruby projects.

func (*Ruby) Detect

func (r *Ruby) Detect(_ context.Context, dir string) (bool, error)

Detect checks if Ruby manifest files exist in the directory.

Example
package main

import (
	"context"
	"fmt"
	"os"
	"path/filepath"

	"github.com/chainguard-dev/omnibump/pkg/languages/ruby"
)

func main() {
	// Create a temporary directory with a Gemfile.lock to simulate a Ruby project.
	dir, err := os.MkdirTemp("", "ruby-example-*")
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	defer func() { _ = os.RemoveAll(dir) }()

	lockfile := filepath.Join(dir, "Gemfile.lock")
	content := "GEM\n  remote: https://rubygems.org/\n  specs:\n    rack (3.1.8)\n"
	if err := os.WriteFile(lockfile, []byte(content), 0o644); err != nil {
		fmt.Println("error:", err)
		return
	}

	r := &ruby.Ruby{}
	detected, err := r.Detect(context.Background(), dir)
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println("Detected:", detected)
}
Output:
Detected: true

func (*Ruby) GetManifestFiles

func (r *Ruby) GetManifestFiles() []string

GetManifestFiles returns Ruby manifest files.

Example
package main

import (
	"fmt"

	"github.com/chainguard-dev/omnibump/pkg/languages/ruby"
)

func main() {
	r := &ruby.Ruby{}
	files := r.GetManifestFiles()
	for _, f := range files {
		fmt.Println(f)
	}
}
Output:
Gemfile
Gemfile.lock

func (*Ruby) Name

func (r *Ruby) Name() string

Name returns the language identifier.

func (*Ruby) SupportsAnalysis

func (r *Ruby) SupportsAnalysis() bool

SupportsAnalysis returns true since Ruby has analysis capabilities.

func (*Ruby) Update

func (r *Ruby) Update(ctx context.Context, cfg *languages.UpdateConfig) error

Update performs dependency updates on a Ruby project.

func (*Ruby) Validate

func (r *Ruby) Validate(ctx context.Context, cfg *languages.UpdateConfig) error

Validate checks if the updates were applied successfully.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL