# frozen_string_literal: true require 'travis/cli' module Travis module CLI class Encrypt < RepoCommand description 'encrypts values for the .travis.yml' attr_accessor :config_key on('-a', '--add [KEY]', 'adds it to .travis.yml under KEY (default: env.global)') do |c, value| c.config_key = value || 'env.global' end on('-s', '--[no-]split', 'treat each line as a separate input') on('-p', '--append', "don't override existing values, instead treat as list") on('-x', '--override', 'override existing value') def run(*args) confirm = force_interactive.nil? || force_interactive error 'cannot combine --override and --append' if append? && override? error '--append without --add makes no sense' if append? && !add? error '--override without --add makes no sense' if override? && !add? self.override |= !config_key.start_with?('env.') if add? && !append? if args.first =~ %r{\w+/\w+} && !args.first.include?('=') warn 'WARNING: The name of the repository is now passed to the command with the -r option:' warn " #{command("encrypt [...] -r #{args.first}")}" warn ' If you tried to pass the name of the repository as the first argument, you' warn " probably won't get the results you wanted.\n" end data = args.join(' ') if data.empty? say color('Reading from stdin, press Ctrl+D when done', :info) if $stdin.tty? data = $stdin.read end data = split? ? data.split("\n") : [data.strip] warn_env_assignments(data) encrypted = data.map { |data| repository.encrypt(data) } if config_key set_config(encrypted.map { |e| { 'secure' => e } }) confirm_and_save_travis_config confirm else list = encrypted.map { |data| format(data.inspect, ' secure: %s') } say(list.join("\n"), template(__FILE__), :none) end rescue OpenSSL::PKey::RSAError => e error "#{e.message.sub(' for key size', '')} - consider using " << color('travis encrypt-file', %i[red bold]) << color(' or ', :red) << color('travis env set', %i[red bold]) end private def add? !!config_key end def set_config(result) parent_config[last_key] = merge_config(result) end def merge_config(result) case subconfig = (parent_config[last_key] unless override?) when nil then result.size == 1 ? result.first : result when Array then subconfig + result else result.unshift(subconfig) end end def subconfig; end def key_chain @key_chain ||= config_key.split('.') end def last_key key_chain.last end def parent_config @parent_config ||= traverse_config(travis_config, *key_chain[0..-2]) end def traverse_config(hash, key = nil, *rest) return hash unless key hash[key] = case value = hash[key] when nil then {} when Hash then value else { 'matrix' => Array(value) } end traverse_config(hash[key], *rest) end def warn_env_assignments(data) return unless /env/.match(config_key) && data.find { |d| /=/.match(d).nil? } warn "Environment variables in #{config_key} should be formatted as FOO=bar" end end end end __END__ Please add the following to your <[[ color('.travis.yml', :info) ]]> file: %s Pro Tip: You can add it automatically by running with <[[ color('--add', :info) ]]>.