Module: CodexNotify::ConfigSupport
- Included in:
- Config, EnvSourceLoader, HookConfig
- Defined in:
- lib/codex_notify/config_support.rb
Defined Under Namespace
Classes: Error
Constant Summary collapse
- DEFAULT_ENV_PATH =
'.env'- DEFAULT_ENV_POLICY =
'restricted'- ENV_POLICIES =
%w[legacy restricted].freeze
- REPOSITORY_ALLOWED_KEYS =
%w[ CODEX_NOTIFY_DESTINATION CODEX_NOTIFY_TITLE CODEX_NOTIFY_USER_NAME CODEX_NOTIFY_MODE ].freeze
- REPOSITORY_CREDENTIAL_PATTERN =
/\ASLACK_(?:BOT_TOKEN|CHANNEL)(?:__.*)?\z/
Instance Method Summary collapse
- #add_common_options(parser, options) ⇒ Object
- #apply_destination(options, sources, policy:, stderr: $stderr) ⇒ Object
- #eligible_sources(sources, policy:) ⇒ Object
- #getenv_any(keys) ⇒ Object
- #load_env_file(path = DEFAULT_ENV_PATH, override: false, stderr: $stderr, legacy_checkout_root: nil) ⇒ Object
- #resolve_env_paths(path = DEFAULT_ENV_PATH, legacy_checkout_root: nil) ⇒ Object
- #resolve_policy(sources, stderr: $stderr) ⇒ Object
- #system_user_name ⇒ Object
- #trusted_sources(sources) ⇒ Object
- #warn_if_legacy_tool_source(source, keys, stderr:) ⇒ Object
- #warn_ignored_repository_values(sources, policy:, stderr:) ⇒ Object
Instance Method Details
#add_common_options(parser, options) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/codex_notify/config_support.rb', line 56 def (parser, ) parser.on('--config PATH') do |value| .config_file = value end parser.on('--migrate-config', 'Create trusted YAML from a legacy env file') do .migrate_config = true end parser.on('--env-file PATH') do |value| .env_file = value .env_file_explicit = true if .respond_to?(:env_file_explicit=) end parser.on('--token TOKEN', 'Deprecated: use the XDG config file or SLACK_BOT_TOKEN') do |value| .token = value .token_from_cli = true end parser.on('--channel CHANNEL') { |value| .channel = value } parser.on('--destination NAME') { |value| .destination = value } if .respond_to?(:destination=) parser.on('--user-name NAME') { |value| .user_name = value } parser.on('--title TITLE') { |value| .title = value } if .respond_to?(:outbox_action=) parser.on('--outbox-status') { .outbox_action = :status } parser.on('--drain-outbox') { .outbox_action = :drain } parser.on('--retry-outbox ID') do |value| .outbox_action = :retry .outbox_id = value end end end |
#apply_destination(options, sources, policy:, stderr: $stderr) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/codex_notify/config_support.rb', line 94 def apply_destination(, sources, policy:, stderr: $stderr) eligible = eligible_sources(sources, policy:) resolution = DestinationResolver.new( selection_sources: sources, profile_sources: trusted_sources(sources), default_sources: eligible ).resolve(destination: .destination, token: .token, channel: .channel) .destination = resolution.destination .token = resolution.token .channel = resolution.channel used_sources = [resolution.token_source, resolution.channel_source].compact source_keys = [ [resolution.token_source, 'SLACK_BOT_TOKEN'], [resolution.channel_source, 'SLACK_CHANNEL'] ] repository_keys = source_keys.filter_map { |source, key| key if source&.kind == :repository } if repository_keys.any? source = used_sources.find { |candidate| candidate.kind == :repository } ConfigDiagnostics.warn_deprecated_repository_credentials(source.path, repository_keys, stderr:) end tool_keys = [ [resolution.token_source, resolution.destination ? "destination #{resolution.destination} token" : 'SLACK_BOT_TOKEN'], [resolution.channel_source, resolution.destination ? "destination #{resolution.destination} channel" : 'SLACK_CHANNEL'] ].filter_map { |source, key| key if source&.kind == :tool } warn_if_legacy_tool_source(used_sources.find { |source| source.kind == :tool }, tool_keys, stderr:) end |
#eligible_sources(sources, policy:) ⇒ Object
124 125 126 127 128 |
# File 'lib/codex_notify/config_support.rb', line 124 def eligible_sources(sources, policy:) return sources unless policy == 'restricted' sources.restrict_kind(:repository, keys: REPOSITORY_ALLOWED_KEYS) end |
#getenv_any(keys) ⇒ Object
48 49 50 51 52 53 54 |
# File 'lib/codex_notify/config_support.rb', line 48 def getenv_any(keys) keys.each do |key| value = ENV[key] return value if value && !value.empty? end nil end |
#load_env_file(path = DEFAULT_ENV_PATH, override: false, stderr: $stderr, legacy_checkout_root: nil) ⇒ Object
33 34 35 36 37 38 39 40 |
# File 'lib/codex_notify/config_support.rb', line 33 def load_env_file(path = DEFAULT_ENV_PATH, override: false, stderr: $stderr, legacy_checkout_root: nil) env_paths = resolve_env_paths(path, legacy_checkout_root:) return if env_paths.empty? env_paths.each { |env_path| ConfigDiagnostics.warn_if_env_file_insecure(env_path, stderr:) } loader = override ? Dotenv.method(:overload) : Dotenv.method(:load) loader.call(*env_paths.map(&:to_s)) end |
#resolve_env_paths(path = DEFAULT_ENV_PATH, legacy_checkout_root: nil) ⇒ Object
22 23 24 25 26 27 28 29 30 31 |
# File 'lib/codex_notify/config_support.rb', line 22 def resolve_env_paths(path = DEFAULT_ENV_PATH, legacy_checkout_root: nil) env_path = Pathname(path) return [env_path] if env_path.absolute? candidates = [Pathname(Dir.pwd).join(env_path)] candidates << Pathname(legacy_checkout_root).join(env_path) if legacy_checkout_root candidates.map(&:expand_path).select(&:exist?).each_with_object([]) do |candidate, paths| paths << candidate unless paths.any? { |path| File.identical?(path, candidate) } end end |
#resolve_policy(sources, stderr: $stderr) ⇒ Object
85 86 87 88 89 90 91 92 |
# File 'lib/codex_notify/config_support.rb', line 85 def resolve_policy(sources, stderr: $stderr) result = trusted_sources(sources).lookup('CODEX_NOTIFY_ENV_POLICY') policy = result ? result.value.strip.downcase : DEFAULT_ENV_POLICY raise Error, "environment policy must be one of: #{ENV_POLICIES.join(', ')}" unless ENV_POLICIES.include?(policy) warn_if_legacy_tool_source(result&.source, ['CODEX_NOTIFY_ENV_POLICY'], stderr:) policy end |
#system_user_name ⇒ Object
42 43 44 45 46 |
# File 'lib/codex_notify/config_support.rb', line 42 def system_user_name ENV['USER'] || ENV['USERNAME'] || Etc.getlogin || 'user' rescue StandardError ENV['USER'] || ENV['USERNAME'] || 'user' end |
#trusted_sources(sources) ⇒ Object
130 131 132 |
# File 'lib/codex_notify/config_support.rb', line 130 def trusted_sources(sources) sources.excluding_kind(:repository) end |
#warn_if_legacy_tool_source(source, keys, stderr:) ⇒ Object
150 151 152 153 154 |
# File 'lib/codex_notify/config_support.rb', line 150 def warn_if_legacy_tool_source(source, keys, stderr:) return unless source&.kind == :tool && keys.any? ConfigDiagnostics.warn_deprecated_tool_config(source.path, keys, stderr:) end |
#warn_ignored_repository_values(sources, policy:, stderr:) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/codex_notify/config_support.rb', line 134 def warn_ignored_repository_values(sources, policy:, stderr:) sources.select { |source| source.kind == :repository }.each do |source| policy_value = source.values['CODEX_NOTIFY_ENV_POLICY'] if policy_value && !policy_value.empty? ConfigDiagnostics.warn_ignored_repository_policy(source.path, stderr:) end ignored = source.values.keys.grep(REPOSITORY_CREDENTIAL_PATTERN) ignored.select! { |key| key.include?('__') } if policy == 'legacy' next if ignored.empty? reason = policy == 'restricted' ? policy : nil ConfigDiagnostics.warn_ignored_repository_credentials(source.path, ignored.sort, policy: reason, stderr:) end end |