Module: Mergify::RSpec::Utils

Defined in:
lib/mergify/rspec/utils.rb

Overview

Utility methods shared across the rspec-mergify gem.

Defined Under Namespace

Classes: InvalidRepositoryFullNameError

Constant Summary collapse

SUPPORTED_CIS =
{
  'GITHUB_ACTIONS' => :github_actions,
  'CIRCLECI' => :circleci,
  'JENKINS_URL' => :jenkins,
  'BUILDKITE' => :buildkite,
  '_RSPEC_MERGIFY_TEST' => :rspec_mergify_suite
}.freeze
TRUTHY_STRINGS =
%w[y yes t true on 1].freeze
FALSY_STRINGS =
%w[n no f false off 0].freeze

Class Method Summary collapse

Class Method Details

.ci_providerObject

Evaluates whether a CI environment variable should be considered enabled. rubocop:disable Metrics/MethodLength



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/mergify/rspec/utils.rb', line 49

def ci_provider
  SUPPORTED_CIS.each do |envvar, name|
    next unless ENV.key?(envvar)

    enabled =
      begin
        strtobool(ENV.fetch(envvar, ''))
      rescue ArgumentError
        !ENV.fetch(envvar, '').strip.empty?
      end

    return name if enabled
  end
  nil
end

.env_truthy?(key) ⇒ Boolean

Returns true when the named environment variable holds a truthy value.

Returns:

  • (Boolean)


37
38
39
# File 'lib/mergify/rspec/utils.rb', line 37

def env_truthy?(key)
  TRUTHY_STRINGS.include?(ENV.fetch(key, '').downcase)
end

.get_attributes(mapping) ⇒ Object

Build an attribute hash from a mapping of { attr_name => [cast_method_symbol, env_var_name_or_callable] }. Attributes whose env var is unset or whose callable returns nil are omitted.



103
104
105
106
107
108
109
110
111
112
# File 'lib/mergify/rspec/utils.rb', line 103

def get_attributes(mapping)
  mapping.each_with_object({}) do |(attr, (cast, env_or_callable)), result|
    value = env_or_callable.respond_to?(:call) ? env_or_callable.call : ENV.fetch(env_or_callable, nil)

    next if value.nil?
    next if value.respond_to?(:empty?) && value.empty?

    result[attr] = value.public_send(cast)
  end
end

.git(*args) ⇒ Object

Run a git subcommand via Open3. Returns stripped stdout on success, nil on failure.



93
94
95
96
97
98
# File 'lib/mergify/rspec/utils.rb', line 93

def git(*args)
  stdout, status = Open3.capture2('git', *args, err: File::NULL)
  status.success? ? stdout.strip : nil
rescue StandardError
  nil
end

.in_ci?Boolean

Returns true when the suite is running inside CI or when RSPEC_MERGIFY_ENABLE is set to a truthy value.

Returns:

  • (Boolean)


43
44
45
# File 'lib/mergify/rspec/utils.rb', line 43

def in_ci?
  env_truthy?('CI') || env_truthy?('RSPEC_MERGIFY_ENABLE')
end

.repository_nameObject

Detect the repository name using CI environment variables or a git remote fallback. rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/mergify/rspec/utils.rb', line 117

def repository_name
  provider = ci_provider

  case provider
  when :jenkins
    url = ENV.fetch('GIT_URL', nil)
    return repository_name_from_url(url) if url
  when :github_actions
    return ENV.fetch('GITHUB_REPOSITORY', nil)
  when :circleci
    url = ENV.fetch('CIRCLE_REPOSITORY_URL', nil)
    return repository_name_from_url(url) if url
  when :buildkite
    url = ENV.fetch('BUILDKITE_REPO', nil)
    return repository_name_from_url(url) if url
  when :rspec_mergify_suite
    return 'Mergifyio/rspec-mergify'
  end

  url = git('config', '--get', 'remote.origin.url')
  repository_name_from_url(url) if url
end

.repository_name_from_url(url) ⇒ Object

Parse a git remote URL (SSH or HTTPS) into “owner/repo” form. Returns nil when the URL cannot be recognised.



68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/mergify/rspec/utils.rb', line 68

def repository_name_from_url(url)
  # SSH: git@github.com:owner/repo.git
  if (m = url.match(%r{\Agit@[\w.-]+:(?<full_name>[\w.-]+/[\w.-]+?)(?:\.git)?/?$}))
    return m[:full_name]
  end

  # HTTPS/HTTP with optional host (and optional port)
  if (m = url.match(%r{\A(?:https?://[\w.-]+(?::\d+)?/)?(?<full_name>[\w.-]+/[\w.-]+)/?\z}))
    return m[:full_name]
  end

  nil
end

.split_full_repo_name(full_repo_name) ⇒ Object

Split “owner/repo” into [owner, repo]. Raises InvalidRepositoryFullNameError when the format is wrong.



84
85
86
87
88
89
# File 'lib/mergify/rspec/utils.rb', line 84

def split_full_repo_name(full_repo_name)
  parts = full_repo_name.split('/')
  return parts if parts.size == 2

  raise InvalidRepositoryFullNameError, "Invalid repository name: #{full_repo_name}"
end

.strtobool(string) ⇒ Object

Convert a string to a boolean. Truthy: y yes t true on 1 Falsy: n no f false off 0 Raises ArgumentError for anything else.

Raises:

  • (ArgumentError)


29
30
31
32
33
34
# File 'lib/mergify/rspec/utils.rb', line 29

def strtobool(string)
  return true  if TRUTHY_STRINGS.include?(string.downcase)
  return false if FALSY_STRINGS.include?(string.downcase)

  raise ArgumentError, "Could not convert '#{string}' to boolean"
end