ruby

package
v0.44.1 Latest Latest
Warning

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

Go to latest
Published: Jun 10, 2026 License: AGPL-3.0 Imports: 2 Imported by: 0

Documentation

Overview

Package ruby provides parsed, cached views of common Ruby/Rails project files in the build context (Gemfile, Gemfile.lock, .ruby-version, .tool-versions). Rules under the tally/ruby/* namespace consume the typed facts here instead of re-parsing the files themselves.

All entry points return nil when the file is unobservable or fails to parse: rules then degrade gracefully to Dockerfile-only mode.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseRubyVersionFile

func ParseRubyVersionFile(content []byte) string

ParseRubyVersionFile parses a `.ruby-version` file's content. The format accepted by chruby/rbenv/asdf is one of:

3.3.5
ruby-3.3.5

Optional surrounding whitespace and a trailing newline are tolerated. Returns "" when no version is found.

func ParseToolVersionsFile

func ParseToolVersionsFile(content []byte) string

ParseToolVersionsFile parses a `.tool-versions` (asdf format) file. Each non-blank line lists `<tool> <version> [version2 ...]`. We return the first version listed for the `ruby` tool, or "" if none is found.

Types

type ContextFileReader

type ContextFileReader interface {
	// FileExists reports whether path resolves to a regular file in the
	// build context.
	FileExists(path string) bool

	// ReadFile reads a regular file's content from the build context.
	ReadFile(path string) ([]byte, error)

	// IsIgnored reports whether the path is excluded by .dockerignore.
	// Implementations that don't model .dockerignore should return
	// (false, nil); a non-nil error reduces to "treat as ignored" so we
	// don't reason over inputs the build process cannot see.
	IsIgnored(path string) (bool, error)
}

ContextFileReader is the minimal subset of internal/context.BuildContext that the loader needs. Declared locally so the package does not import internal/facts or internal/context, keeping import direction clean.

type GemfileFacts

type GemfileFacts struct {
	// RubyConstraint holds the value passed to the top-level ruby "..."
	// directive, when present. Quotes are stripped.
	RubyConstraint string

	// Sources lists every URL passed to a top-level source "..." directive,
	// preserving Gemfile order.
	Sources []string

	// GitGems lists gem entries that pin to a git: or github: source. Order
	// matches first appearance.
	GitGems []string

	// HasDevGroup is true when the Gemfile contains a `group :development do`
	// block (multi-group declarations like `group :development, :test do`
	// also count).
	HasDevGroup bool

	// HasTestGroup is true when the Gemfile contains a `group :test do` block
	// (multi-group declarations like `group :development, :test do` also count).
	HasTestGroup bool
}

GemfileFacts is the typed projection of a Gemfile that complements LockfileFacts. All fields are zero-valued when the Gemfile is unobservable or fails to parse.

func ParseGemfile

func ParseGemfile(content []byte) *GemfileFacts

ParseGemfile parses Gemfile content into typed facts. Returns nil for empty input or input that yields no recognizable directives.

type LockfileFacts

type LockfileFacts struct {
	// BundledWith is the value of the BUNDLED WITH block (may be empty for
	// legacy Bundler 1.x lockfiles that do not include the block).
	BundledWith string

	// RubyVersion is the value of the RUBY VERSION block (may be empty).
	RubyVersion string

	// Platforms lists every entry in the PLATFORMS block.
	Platforms []string

	// Sources lists every remote: URL declared by GEM/GIT/PATH/PLUGIN SOURCE
	// blocks, in the order they appear.
	Sources []string

	// DirectDeps maps gem name to version constraint, from the DEPENDENCIES
	// block. The value preserves the constraint as written in the lockfile
	// (for example "~> 8.0", ">= 1.2.3", or empty when no constraint is
	// listed).
	DirectDeps map[string]string

	// Specs maps gem name to exact version, derived from each block's specs:
	// section. Platform-suffixed gem names like "nokogiri (1.13.6-x86_64-linux)"
	// are normalized to "nokogiri" -> "1.13.6".
	Specs map[string]string

	// HasGitGems is true when at least one GIT block is present.
	HasGitGems bool

	// HasPathGems is true when at least one PATH block is present.
	HasPathGems bool

	// NativeExtGems lists gems detected as native-extension gems via the
	// curated list. Order matches first appearance in the lockfile.
	NativeExtGems []string
}

LockfileFacts is the typed projection of Gemfile.lock that Ruby rules consume. All fields are zero-valued when Gemfile.lock is not observable or fails to parse.

func ParseLockfile

func ParseLockfile(content []byte) *LockfileFacts

ParseLockfile parses Gemfile.lock content into typed facts. Returns nil when the input is empty or when parsing fails for any reason. Partial input that looks plausibly like a lockfile is accepted; missing sections leave the corresponding fields zero-valued.

type RubyFacts

type RubyFacts struct {
	// Lockfile holds parsed Gemfile.lock data, or nil when no observable
	// lockfile is present.
	Lockfile *LockfileFacts

	// Gemfile holds parsed Gemfile data, or nil when no observable Gemfile is
	// present.
	Gemfile *GemfileFacts

	// RubyVersion is the project's resolved Ruby version, in priority order:
	//
	//  1. .ruby-version
	//  2. .tool-versions (the `ruby` line)
	//  3. Lockfile.RubyVersion (RUBY VERSION block)
	//
	// Empty when none of the sources yield a value.
	RubyVersion string

	// HasEncryptedCredentials reports whether the project ships any of the
	// canonical Rails encrypted-credentials files (config/credentials.yml.enc
	// or config/credentials/<env>.yml.enc for one of the standard envs).
	// Rules that need to know whether RAILS_MASTER_KEY is actually load-bearing
	// at build time (e.g. asset-precompile-without-dummy-key) consult this.
	HasEncryptedCredentials bool

	// EncryptedCredentialsPaths records the observed credentials files in the
	// build context. Order matches the probe order. Empty when no credentials
	// files are observable.
	EncryptedCredentialsPaths []string
}

RubyFacts bundles every observable Ruby project file the rule namespace cares about. Each pointer is nil when the underlying file is missing, unobservable, or malformed.

func Load

func Load(reader ContextFileReader) *RubyFacts

Load reads the four well-known Ruby project files from the build context and returns parsed RubyFacts. A nil reader yields a non-nil RubyFacts with every pointer field nil (rules can then call .Lockfile == nil etc. without special-casing). Read errors and .dockerignore-excluded paths are silently treated as "no signal" — the corresponding pointer is left nil.

Memoization is the caller's responsibility; for the standard rule pipeline it happens inside *facts.FileFacts via sync.Once.

Jump to

Keyboard shortcuts

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