Class: GemXray::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/gemxray/config.rb

Constant Summary collapse

DEFAULT_CONFIG_PATH =
".gemxray.yml"
DEFAULT_SCAN_DIRS =
%w[app lib config db script bin exe spec test tasks].freeze
DEFAULTS =
{
  gemfile_path: "Gemfile",
  format: "terminal",
  only: nil,
  severity: "info",
  auto_fix: false,
  dry_run: false,
  ci: false,
  ci_fail_on: "warning",
  comment: false,
  bundle_install: false,
  whitelist: [],
  scan_dirs: [],
  overrides: {},
  redundant_depth: 2,
  github: {
    base_branch: "main",
    labels: %w[dependencies cleanup],
    reviewers: [],
    per_gem: false,
    bundle_install: true
  },
  license: {
    enabled: true,
    allowed: [],
    deny_unknown: false
  },
  archive: {
    enabled: true,
    github_token_env: "GITHUB_TOKEN"
  }
}.freeze
SEVERITY_ORDER =
{ danger: 0, warning: 1, info: 2 }.freeze
TEMPLATE =
<<~YAML.freeze
  version: 1

  ci: false
  ci_fail_on: warning

  whitelist:
    - bootsnap
    - tzinfo-data

  scan_dirs:
    - engines/billing/app
    - engines/billing/lib

  overrides:
    puma:
      severity: ignore

  github:
    base_branch: main
    labels:
      - dependencies
      - cleanup
    reviewers: []
    per_gem: false
    bundle_install: true

  license:
    enabled: true
    allowed:
      - MIT
      - Apache-2.0
      - BSD-2-Clause
      - BSD-3-Clause
      - ISC
      - Ruby
    deny_unknown: false

  archive:
    enabled: true
    github_token_env: GITHUB_TOKEN
YAML

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options, config_path:) ⇒ Config

Returns a new instance of Config.



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/gemxray/config.rb', line 129

def initialize(options, config_path:)
  @config_path = config_path
  @gemfile_path = File.expand_path(options.fetch(:gemfile_path))
  @format = options.fetch(:format).to_s
  @only = normalize_only(options[:only])
  @severity_threshold = normalize_severity(options.fetch(:severity))
  @ci_fail_threshold = normalize_severity(options.fetch(:ci_fail_on))
  @whitelist = Array(options[:whitelist]).map(&:to_s).uniq
  @scan_dirs = (DEFAULT_SCAN_DIRS + Array(options[:scan_dirs]).map(&:to_s)).uniq
  @overrides = options.fetch(:overrides, {})
  @redundant_depth = options.fetch(:redundant_depth).to_i
  @github = options.fetch(:github)
  @license = options.fetch(:license)
  @archive = options.fetch(:archive)
  @auto_fix = truthy?(options[:auto_fix])
  @dry_run = truthy?(options[:dry_run])
  @ci = truthy?(options[:ci])
  @comment = truthy?(options[:comment])
  @bundle_install = truthy?(options[:bundle_install])
end

Instance Attribute Details

#archiveObject (readonly)

Returns the value of attribute archive.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def archive
  @archive
end

#ci_fail_thresholdObject (readonly)

Returns the value of attribute ci_fail_threshold.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def ci_fail_threshold
  @ci_fail_threshold
end

#config_pathObject (readonly)

Returns the value of attribute config_path.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def config_path
  @config_path
end

#formatObject (readonly)

Returns the value of attribute format.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def format
  @format
end

#gemfile_pathObject (readonly)

Returns the value of attribute gemfile_path.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def gemfile_path
  @gemfile_path
end

#githubObject (readonly)

Returns the value of attribute github.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def github
  @github
end

#licenseObject (readonly)

Returns the value of attribute license.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def license
  @license
end

#onlyObject (readonly)

Returns the value of attribute only.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def only
  @only
end

#overridesObject (readonly)

Returns the value of attribute overrides.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def overrides
  @overrides
end

#redundant_depthObject (readonly)

Returns the value of attribute redundant_depth.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def redundant_depth
  @redundant_depth
end

#scan_dirsObject (readonly)

Returns the value of attribute scan_dirs.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def scan_dirs
  @scan_dirs
end

#severity_thresholdObject (readonly)

Returns the value of attribute severity_threshold.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def severity_threshold
  @severity_threshold
end

#whitelistObject (readonly)

Returns the value of attribute whitelist.



85
86
87
# File 'lib/gemxray/config.rb', line 85

def whitelist
  @whitelist
end

Class Method Details

.deep_merge(left, right) ⇒ Object



117
118
119
120
121
122
123
124
125
126
127
# File 'lib/gemxray/config.rb', line 117

def self.deep_merge(left, right)
  left.merge(right) do |_key, left_value, right_value|
    if left_value.is_a?(Hash) && right_value.is_a?(Hash)
      deep_merge(left_value, right_value)
    elsif left_value.is_a?(Array) && right_value.is_a?(Array)
      (left_value + right_value).uniq
    else
      right_value
    end
  end
end

.load(options = {}) ⇒ Object



89
90
91
92
93
94
95
96
# File 'lib/gemxray/config.rb', line 89

def self.load(options = {})
  raw_options = symbolize_keys(options)
  config_path = raw_options.delete(:config_path) || DEFAULT_CONFIG_PATH
  file_options = load_file_config(config_path)
  merged = deep_merge(DEFAULTS, deep_merge(file_options, raw_options))

  new(merged, config_path: config_path)
end

.load_file_config(path) ⇒ Object



98
99
100
101
102
# File 'lib/gemxray/config.rb', line 98

def self.load_file_config(path)
  return {} unless path && File.exist?(path)

  symbolize_keys(YAML.safe_load(File.read(path), aliases: true) || {})
end

.symbolize_keys(value) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/gemxray/config.rb', line 104

def self.symbolize_keys(value)
  case value
  when Hash
    value.each_with_object({}) do |(key, nested), result|
      result[key.to_sym] = symbolize_keys(nested)
    end
  when Array
    value.map { |item| symbolize_keys(item) }
  else
    value
  end
end

Instance Method Details

#archive_enabled?Boolean

Returns:

  • (Boolean)


241
242
243
# File 'lib/gemxray/config.rb', line 241

def archive_enabled?
  truthy?(archive.fetch(:enabled, false))
end

#archive_github_tokenObject



245
246
247
248
# File 'lib/gemxray/config.rb', line 245

def archive_github_token
  env_var = archive.fetch(:github_token_env, "GITHUB_TOKEN")
  ENV[env_var]
end

#auto_fix?Boolean

Returns:

  • (Boolean)


158
159
160
# File 'lib/gemxray/config.rb', line 158

def auto_fix?
  @auto_fix
end

#bundle_install?Boolean

Returns:

  • (Boolean)


180
181
182
# File 'lib/gemxray/config.rb', line 180

def bundle_install?
  @bundle_install
end

#ci?Boolean

Returns:

  • (Boolean)


166
167
168
# File 'lib/gemxray/config.rb', line 166

def ci?
  @ci
end

#ci_failure?(results) ⇒ Boolean

Returns:

  • (Boolean)


170
171
172
173
174
# File 'lib/gemxray/config.rb', line 170

def ci_failure?(results)
  return false unless ci?

  Array(results).any? { |result| severity_matches_threshold?(result.severity, ci_fail_threshold) }
end

#comment?Boolean

Returns:

  • (Boolean)


176
177
178
# File 'lib/gemxray/config.rb', line 176

def comment?
  @comment
end

#dry_run?Boolean

Returns:

  • (Boolean)


162
163
164
# File 'lib/gemxray/config.rb', line 162

def dry_run?
  @dry_run
end

#github_base_branchObject



209
210
211
# File 'lib/gemxray/config.rb', line 209

def github_base_branch
  github.fetch(:base_branch, "main")
end

#github_bundle_install?Boolean

Returns:

  • (Boolean)


225
226
227
# File 'lib/gemxray/config.rb', line 225

def github_bundle_install?
  truthy?(github.fetch(:bundle_install, true))
end

#github_labelsObject



213
214
215
# File 'lib/gemxray/config.rb', line 213

def github_labels
  Array(github.fetch(:labels, []))
end

#github_per_gem?Boolean

Returns:

  • (Boolean)


221
222
223
# File 'lib/gemxray/config.rb', line 221

def github_per_gem?
  truthy?(github.fetch(:per_gem, false))
end

#github_reviewersObject



217
218
219
# File 'lib/gemxray/config.rb', line 217

def github_reviewers
  Array(github.fetch(:reviewers, []))
end

#ignore_gem?(gem_name) ⇒ Boolean

Returns:

  • (Boolean)


192
193
194
195
# File 'lib/gemxray/config.rb', line 192

def ignore_gem?(gem_name)
  override = override_for(gem_name)
  override && override[:severity].to_s == "ignore"
end

#license_allowedObject



233
234
235
# File 'lib/gemxray/config.rb', line 233

def license_allowed
  Array(license.fetch(:allowed, []))
end

#license_deny_unknown?Boolean

Returns:

  • (Boolean)


237
238
239
# File 'lib/gemxray/config.rb', line 237

def license_deny_unknown?
  truthy?(license.fetch(:deny_unknown, false))
end

#license_enabled?Boolean

Returns:

  • (Boolean)


229
230
231
# File 'lib/gemxray/config.rb', line 229

def license_enabled?
  truthy?(license.fetch(:enabled, false))
end

#lockfile_pathObject



150
151
152
# File 'lib/gemxray/config.rb', line 150

def lockfile_path
  "#{gemfile_path}.lock"
end

#override_for(gem_name) ⇒ Object



188
189
190
# File 'lib/gemxray/config.rb', line 188

def override_for(gem_name)
  overrides[gem_name.to_sym] || overrides[gem_name.to_s]
end

#override_severity_for(gem_name) ⇒ Object



197
198
199
200
201
202
203
# File 'lib/gemxray/config.rb', line 197

def override_severity_for(gem_name)
  override = override_for(gem_name)
  severity = override && override[:severity]
  return nil if severity.nil? || severity.to_s == "ignore"

  normalize_severity(severity)
end

#project_rootObject



154
155
156
# File 'lib/gemxray/config.rb', line 154

def project_root
  File.dirname(gemfile_path)
end

#severity_in_scope?(severity) ⇒ Boolean

Returns:

  • (Boolean)


205
206
207
# File 'lib/gemxray/config.rb', line 205

def severity_in_scope?(severity)
  severity_matches_threshold?(severity, severity_threshold)
end

#whitelisted?(gem_name) ⇒ Boolean

Returns:

  • (Boolean)


184
185
186
# File 'lib/gemxray/config.rb', line 184

def whitelisted?(gem_name)
  whitelist.include?(gem_name.to_s)
end