Class: RailsAiBridge::Registry::DefaultGitRunner

Inherits:
Object
  • Object
show all
Includes:
GitRunner
Defined in:
lib/rails_ai_bridge/registry/skill_source_resolver.rb

Overview

Default implementation of GitRunner using Open3 to spawn git subprocesses.

This is the production implementation used for actual git operations. All git commands are wrapped in a Timeout::timeout block so a slow or unreachable remote cannot block the calling thread indefinitely.

Constant Summary collapse

ALLOWED_GIT_URL_PATTERN =
Note:

Skill-pack clones accept only https://, SCP-style git@host:path, and ssh:// remote URLs.

Clones a remote repository to a local directory path.

Returns:

  • (void)

Raises:

  • (ArgumentError)

    if the URL or destination is unsafe or not allowlisted

  • (RuntimeError)

    if git clone command fails, returns non-zero, or times out

%r{\A(?:https://|ssh://|git@[A-Za-z0-9._-]+:)}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(timeout: 30) ⇒ DefaultGitRunner

Returns a new instance of DefaultGitRunner.



64
65
66
# File 'lib/rails_ai_bridge/registry/skill_source_resolver.rb', line 64

def initialize(timeout: 30)
  @timeout = timeout
end

Instance Attribute Details

#timeoutObject (readonly)

Parameters:

  • timeout (Integer)

    seconds before a git operation is forcibly interrupted



62
63
64
# File 'lib/rails_ai_bridge/registry/skill_source_resolver.rb', line 62

def timeout
  @timeout
end

Instance Method Details

#checkout_ref(path, ref) ⇒ void

This method returns an undefined value.

Checks out a specific git ref inside a local repository directory.

Parameters:

  • path (String)

    path to the local repository

  • ref (String)

    branch, tag, or commit SHA to check out

Raises:

  • (ArgumentError)

    if ref starts with a dash (option injection guard)

  • (RuntimeError)

    if git checkout command fails, returns non-zero, or times out



129
130
131
132
133
134
135
136
137
# File 'lib/rails_ai_bridge/registry/skill_source_resolver.rb', line 129

def checkout_ref(path, ref)
  raise ArgumentError, "Invalid ref #{ref.inspect}: refs must not start with '-'" if ref.start_with?('-')

  with_timeout('git checkout') do
    # The ref is validated above before being passed to git.
    _stdout, stderr, status = Open3.capture3('git', 'checkout', ref, chdir: path) # nosemgrep: ruby.lang.security.dangerous-exec.dangerous-exec
    fail_with_sanitized_error!('git checkout', stderr) unless status.success?
  end
end

#clone_repo(url, dest) ⇒ Object

Raises:

  • (ArgumentError)


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/rails_ai_bridge/registry/skill_source_resolver.rb', line 79

def clone_repo(url, dest)
  url = url.to_s
  # Avoid interpolating +url+ into errors: userinfo may contain credentials.
  raise ArgumentError, "Invalid git URL: URLs must not start with '-'" if url.start_with?('-')
  raise ArgumentError, "Invalid destination: paths must not start with '-'" if dest.to_s.start_with?('-')
  unless url.match?(ALLOWED_GIT_URL_PATTERN)
    raise ArgumentError,
          'Invalid git URL: scheme is not allowlisted (use https://, git@host:path, or ssh://)'
  end

  with_timeout('git clone') do
    _stdout, stderr, status = Open3.capture3('git', 'clone', '--', url, dest)
    fail_with_sanitized_error!('git clone', stderr) unless status.success?
  end
end

#current_commit(path) ⇒ String

Returns the current HEAD commit SHA for the repository at path.

Parameters:

  • path (String)

    path to the local repository

Returns:

  • (String)

    40-character hex commit SHA

Raises:

  • (RuntimeError)

    if the git command fails or returns non-zero



113
114
115
116
117
118
119
120
# File 'lib/rails_ai_bridge/registry/skill_source_resolver.rb', line 113

def current_commit(path)
  with_timeout('git rev-parse') do
    stdout, stderr, status = Open3.capture3('git', 'rev-parse', 'HEAD', chdir: path) # nosemgrep: ruby.lang.security.dangerous-exec.dangerous-exec
    fail_with_sanitized_error!('git rev-parse', stderr) unless status.success?

    stdout.strip
  end
end

#pull_repo(path) ⇒ void

This method returns an undefined value.

Pulls latest changes inside a local repository directory.

Parameters:

  • path (String)

    path to the local repository

Raises:

  • (RuntimeError)

    if git pull command fails, returns non-zero, or times out



100
101
102
103
104
105
106
# File 'lib/rails_ai_bridge/registry/skill_source_resolver.rb', line 100

def pull_repo(path)
  with_timeout('git pull') do
    # Command is fully static; only the chdir option is a validated directory path.
    _stdout, stderr, status = Open3.capture3('git', 'pull', chdir: path) # nosemgrep: ruby.lang.security.dangerous-exec.dangerous-exec
    fail_with_sanitized_error!('git pull', stderr) unless status.success?
  end
end