Class: Prdigest::Config
- Inherits:
-
Object
- Object
- Prdigest::Config
- Defined in:
- lib/prdigest/config.rb
Constant Summary collapse
- REPOSITORY_SEGMENT =
/\A[A-Za-z0-9_.-]+\z/
Instance Attribute Summary collapse
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#raw ⇒ Object
readonly
Returns the value of attribute raw.
Class Method Summary collapse
- .load(path) ⇒ Object
- .normalize_repos(values, label: "repository") ⇒ Object
- .resolve_path(explicit: nil, env: ENV, system_path: "/etc/prdigest/config.yml") ⇒ Object
Instance Method Summary collapse
- #chat_id ⇒ Object
- #chat_id_allowlist ⇒ Object
- #delivery_state_path ⇒ Object
- #empty_message ⇒ Object
- #github_token(env = ENV) ⇒ Object
-
#initialize(raw, path: nil) ⇒ Config
constructor
A new instance of Config.
- #line_stats? ⇒ Boolean
- #max_catchup_days ⇒ Object
- #repos ⇒ Object
- #schedule_cron ⇒ Object
- #send_empty? ⇒ Boolean
- #state_path ⇒ Object
- #telegram_token(env = ENV) ⇒ Object
- #timezone ⇒ Object
- #validate! ⇒ Object
Constructor Details
#initialize(raw, path: nil) ⇒ Config
Returns a new instance of Config.
53 54 55 56 |
# File 'lib/prdigest/config.rb', line 53 def initialize(raw, path: nil) @raw = raw @path = path end |
Instance Attribute Details
#path ⇒ Object (readonly)
Returns the value of attribute path.
9 10 11 |
# File 'lib/prdigest/config.rb', line 9 def path @path end |
#raw ⇒ Object (readonly)
Returns the value of attribute raw.
9 10 11 |
# File 'lib/prdigest/config.rb', line 9 def raw @raw end |
Class Method Details
.load(path) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/prdigest/config.rb', line 23 def self.load(path) path = File.(path) raise ConfigError, "config not found: #{path}" unless File.file?(path) raw = YAML.safe_load_file(path, aliases: true) raise ConfigError, "config root must be a mapping" unless raw.is_a?(Hash) new(raw, path: path).tap(&:validate!) rescue ConfigError raise rescue StandardError => e raise ConfigError, "cannot load config: #{e.class}" end |
.normalize_repos(values, label: "repository") ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/prdigest/config.rb', line 37 def self.normalize_repos(values, label: "repository") normalized = Array(values).map { |value| value.to_s.strip } raise ConfigError, "#{label} must list at least one owner/name" if normalized.empty? invalid = normalized.find do |repository| parts = repository.split("/", -1) parts.length != 2 || parts.any? { |part| part.empty? || %w[. ..].include?(part) || !part.match?(REPOSITORY_SEGMENT) } end raise ConfigError, "#{label} entry must be owner/name; got #{invalid.inspect}" if invalid normalized.each_with_object({}) do |repository, unique| unique[repository.downcase] ||= repository end.values.freeze end |
.resolve_path(explicit: nil, env: ENV, system_path: "/etc/prdigest/config.yml") ⇒ Object
13 14 15 16 17 18 19 20 21 |
# File 'lib/prdigest/config.rb', line 13 def self.resolve_path(explicit: nil, env: ENV, system_path: "/etc/prdigest/config.yml") return File.(explicit) if explicit && !explicit.to_s.empty? from_env = env["PRDIGEST_CONFIG"].to_s return File.(from_env) unless from_env.empty? return system_path if File.file?(system_path) raise ConfigError, "config path is required (--config, PRDIGEST_CONFIG, or /etc/prdigest/config.yml)" end |
Instance Method Details
#chat_id ⇒ Object
76 77 78 79 80 |
# File 'lib/prdigest/config.rb', line 76 def chat_id Integer(raw.dig("telegram", "chat_id")) rescue TypeError, ArgumentError nil end |
#chat_id_allowlist ⇒ Object
82 83 84 85 86 |
# File 'lib/prdigest/config.rb', line 82 def chat_id_allowlist Array(raw.dig("telegram", "chat_id_allowlist")).map { |id| Integer(id) } rescue TypeError, ArgumentError [] end |
#delivery_state_path ⇒ Object
104 105 106 |
# File 'lib/prdigest/config.rb', line 104 def delivery_state_path raw.dig("state", "delivery_path") || File.join(File.dirname(state_path), "deliveries") end |
#empty_message ⇒ Object
96 97 98 |
# File 'lib/prdigest/config.rb', line 96 def raw.dig("digest", "empty_message") || "Merged PR digest — {date}\nTotal: 0 PRs" end |
#github_token(env = ENV) ⇒ Object
66 67 68 69 |
# File 'lib/prdigest/config.rb', line 66 def github_token(env = ENV) env_name = raw.dig("github", "token_env") || "GITHUB_TOKEN" env[env_name.to_s].to_s end |
#line_stats? ⇒ Boolean
88 89 90 |
# File 'lib/prdigest/config.rb', line 88 def line_stats? raw.dig("digest", "line_stats") != false end |
#max_catchup_days ⇒ Object
112 113 114 115 116 |
# File 'lib/prdigest/config.rb', line 112 def max_catchup_days Integer(raw.dig("schedule", "max_catchup_days") || 7) rescue TypeError, ArgumentError raise ConfigError, "schedule.max_catchup_days must be an integer from 1 to 30" end |
#repos ⇒ Object
62 63 64 |
# File 'lib/prdigest/config.rb', line 62 def repos self.class.normalize_repos(raw.dig("github", "repos"), label: "github.repos") end |
#schedule_cron ⇒ Object
108 109 110 |
# File 'lib/prdigest/config.rb', line 108 def schedule_cron raw.dig("schedule", "cron") || "5 9 * * *" end |
#send_empty? ⇒ Boolean
92 93 94 |
# File 'lib/prdigest/config.rb', line 92 def send_empty? raw.dig("digest", "send_empty") != false end |
#state_path ⇒ Object
100 101 102 |
# File 'lib/prdigest/config.rb', line 100 def state_path raw.dig("state", "path") || File.("~/.local/share/prdigest/state.json") end |
#telegram_token(env = ENV) ⇒ Object
71 72 73 74 |
# File 'lib/prdigest/config.rb', line 71 def telegram_token(env = ENV) env_name = raw.dig("telegram", "token_env") || "TELEGRAM_BOT_TOKEN" env[env_name.to_s].to_s end |
#timezone ⇒ Object
58 59 60 |
# File 'lib/prdigest/config.rb', line 58 def timezone raw.fetch("timezone", "UTC").to_s end |
#validate! ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/prdigest/config.rb', line 118 def validate! begin TZInfo::Timezone.get(timezone) rescue TZInfo::InvalidTimezoneIdentifier raise ConfigError, "timezone must be a resolvable IANA identifier" end unless (1..30).cover?(max_catchup_days) raise ConfigError, "schedule.max_catchup_days must be from 1 to 30" end repos raise ConfigError, "telegram.chat_id is required" if chat_id.nil? raise ConfigError, "telegram.chat_id_allowlist must not be empty" if chat_id_allowlist.empty? unless chat_id_allowlist.include?(chat_id) raise ConfigError, "telegram.chat_id must be present in chat_id_allowlist" end self end |