travis 1.6.18.travis.596.5 → 1.6.18.travis.604.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/travis/cli.rb CHANGED
@@ -24,6 +24,7 @@ module Travis
24
24
  autoload :Disable, 'travis/cli/disable'
25
25
  autoload :Enable, 'travis/cli/enable'
26
26
  autoload :Encrypt, 'travis/cli/encrypt'
27
+ autoload :EncryptFile, 'travis/cli/encrypt_file'
27
28
  autoload :Endpoint, 'travis/cli/endpoint'
28
29
  autoload :Env, 'travis/cli/env'
29
30
  autoload :Help, 'travis/cli/help'
@@ -65,7 +66,7 @@ module Travis
65
66
 
66
67
  def command(name)
67
68
  const_name = command_name(name)
68
- constant = CLI.const_get(const_name) if const_name =~ /^[A-Z][a-z]+$/ and const_defined? const_name
69
+ constant = CLI.const_get(const_name) if const_name =~ /^[A-Z][A-Za-z]+$/ and const_defined? const_name
69
70
  if command? constant
70
71
  constant
71
72
  else
@@ -108,7 +109,7 @@ module Travis
108
109
  when nil, '-h', '-?' then 'Help'
109
110
  when '-v' then 'Version'
110
111
  when /^--/ then command_name(name[2..-1])
111
- else name.to_s.capitalize
112
+ else name.split('-').map(&:capitalize).join
112
113
  end
113
114
  end
114
115
 
@@ -47,7 +47,7 @@ module Travis
47
47
  on('--skip-completion-check', "don't check if auto-completion is set up")
48
48
 
49
49
  def self.command_name
50
- name[/[^:]*$/].downcase
50
+ name[/[^:]*$/].split(/(?=[A-Z])/).map(&:downcase).join('-')
51
51
  end
52
52
 
53
53
  @@abstract ||= [Command] # ignore the man behind the courtains!
@@ -388,6 +388,17 @@ module Travis
388
388
  agree(color("DANGER ZONE: ", [:red, :bold]) << message << " ") { |q| q.default = "no" }
389
389
  end
390
390
 
391
+ def write_file(file, content, force = false)
392
+ error "#{file} already exists" unless write_file?(file, force)
393
+ File.write(file, content)
394
+ end
395
+
396
+ def write_file?(file, force)
397
+ return true if force or not File.exist?(file)
398
+ return false unless interactive?
399
+ danger_zone? "Override existing #{color(file, :info)}?"
400
+ end
401
+
391
402
  def wrong_args(quantity)
392
403
  error "too #{quantity} arguments" do
393
404
  say help
@@ -0,0 +1,140 @@
1
+ # encoding: utf-8
2
+ require 'travis/cli'
3
+ require 'travis/tools/system'
4
+
5
+ require 'securerandom'
6
+ require 'openssl'
7
+ require 'digest'
8
+ require 'shellwords'
9
+
10
+ module Travis
11
+ module CLI
12
+ class EncryptFile < RepoCommand
13
+ attr_accessor :stage
14
+ description 'encrypts a file and adds decryption steps to .travis.yml'
15
+ on '-K', '--key KEY', 'encryption key to be used (randomly generated otherwise)'
16
+ on '--iv IV', 'encryption IV to be used (randomly generated otherwise)'
17
+ on '-d', '--decrypt', 'decrypt the file instead of encrypting it, requires key and iv'
18
+ on '-f', '--force', 'override output file if it exists'
19
+ on '-p', '--print-key', 'print (possibly generated) key and iv'
20
+ on '-w', '--decrypt-to PATH', 'where to write the decrypted file to on the Travis CI VM'
21
+ on '-a', '--add [STAGE]', 'automatically add command to .travis.yml (default stage is before_install)' do |c, stage|
22
+ c.stage = stage || 'before_install'
23
+ end
24
+
25
+ def run(input_path, output_path = nil)
26
+ self.decrypt_to ||= decrypt_to_for(input_path)
27
+ output_path ||= File.basename(output_path_for(input_path))
28
+ self.output = $stdout.tty? ? StringIO.new : $stderr if output_path == '-'
29
+ result = transcode(input_path)
30
+
31
+ if output_path == '-'
32
+ $stdout.puts result
33
+ else
34
+ say "storing result as #{color(output_path, :info)}"
35
+ write_file(output_path, result, force)
36
+ return if decrypt?
37
+
38
+ error "requires --decrypt-to option when reading from stdin" unless decrypt_to?
39
+
40
+ set_env_vars
41
+
42
+ command = decrypt_command(output_path)
43
+ stage ? store_command(command) : print_command(command)
44
+
45
+ notes(input_path, output_path)
46
+ end
47
+ end
48
+
49
+ def setup
50
+ super
51
+ self.key ||= SecureRandom.hex(32) unless decrypt?
52
+ self.iv ||= SecureRandom.hex(16) unless decrypt?
53
+ error "key must be 64 characters long and a valid hex number" unless key =~ /^[a-f0-9]{64}$/
54
+ error "iv must be 32 characters long and a valid hex number" unless iv =~ /^[a-f0-9]{32}$/
55
+ end
56
+
57
+ def print_command(command)
58
+ empty_line
59
+ say command, template(__FILE__)
60
+ end
61
+
62
+ def store_command(command)
63
+ travis_config[stage] = Array(travis_config[stage])
64
+ travis_config[stage].delete(command)
65
+ travis_config[stage].unshift(command)
66
+ save_travis_config
67
+ end
68
+
69
+ def decrypt_command(path)
70
+ "openssl aes-256-cbc -K $#{env_name(:key)} -iv $#{env_name(:iv)} -in #{escape_path(path)} -out #{escape_path(decrypt_to)} -d"
71
+ end
72
+
73
+ def set_env_vars
74
+ say "storing secure env variables for decryption"
75
+ repository.env_vars.upsert env_name(:key), key, :public => false
76
+ repository.env_vars.upsert env_name(:iv), iv, :public => false
77
+ end
78
+
79
+ def env_name(name)
80
+ @env_prefix ||= "encrypted_#{Digest.hexencode(Digest::SHA1.digest(Dir.pwd)[0..5])}"
81
+ "#{@env_prefix}_#{name}"
82
+ end
83
+
84
+ def notes(input_path, output_path)
85
+ say "\nkey: #{color(key, :info)}\niv: #{color(iv, :info)}" if print_key?
86
+ empty_line
87
+ say "Make sure to add #{color(output_path, :info)} to the git repository."
88
+ say "Make sure #{color("not", :underline)} to add #{color(input_path, :info)} to the git repository." if input_path != '-'
89
+ say "Commit all changes to your #{color('.travis.yml', :info)}."
90
+ end
91
+
92
+ def transcode(input_path)
93
+ description = "stdin#{' (waiting for input)' if $stdin.tty?}" if input_path == '-'
94
+ say "#{decrypt ? "de" : "en"}crypting #{color(description || input_path, :info)} for #{color(slug, :info)}"
95
+
96
+ data = input_path == '-' ? $stdin.read : File.binread(input_path)
97
+ aes = OpenSSL::Cipher.new('AES-256-CBC')
98
+ decrypt ? aes.decrypt : aes.encrypt
99
+ aes.key = [key].pack('H*')
100
+ aes.iv = [iv].pack('H*')
101
+
102
+ aes.update(data) + aes.final
103
+ end
104
+
105
+ def decrypt_to_for(input_path)
106
+ return if input_path == '-'
107
+ if input_path.start_with? Dir.home
108
+ input_path.sub(Dir.home, '~')
109
+ else
110
+ input_path
111
+ end
112
+ end
113
+
114
+ def escape_path(path)
115
+ Shellwords.escape(path).sub(/^\\~\//, '~\/')
116
+ end
117
+
118
+ def output_path_for(input_path)
119
+ case input_path
120
+ when '-' then return '-'
121
+ when /^(.+)\.enc$/ then return $1 if decrypt?
122
+ when /^(.+)\.dec$/ then return $1 unless decrypt?
123
+ end
124
+
125
+ if interactive? and input_path =~ /(\.enc|\.dec)$/
126
+ exit 1 unless danger_zone? "File extension of input file is #{color($1, :info)}, are you sure that is correct?"
127
+ end
128
+
129
+ "#{input_path}.#{decrypt ? 'dec' : 'enc'}"
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ __END__
136
+ Please add the following to your build scirpt (<[[ color('before_install', :info) ]]> stage in your <[[ color('.travis.yml', :info) ]]>, for instance):
137
+
138
+ %s
139
+
140
+ Pro Tip: You can add it automatically by running with <[[ color('--add', :info) ]]>.
@@ -10,7 +10,7 @@ module Travis
10
10
  say CLI.command(command).new.help
11
11
  else
12
12
  say "Usage: travis COMMAND ...\n\nAvailable commands:\n\n"
13
- commands.each { |c| say "\t#{color(c.command_name, :command).ljust(20)} #{color(c.description, :info)}" }
13
+ commands.each { |c| say "\t#{color(c.command_name, :command).ljust(22)} #{color(c.description, :info)}" }
14
14
  say "\nrun `#$0 help COMMAND` for more infos"
15
15
  end
16
16
  end
@@ -8,6 +8,10 @@ module Travis
8
8
  GIT_REGEX = %r{/?(.*/.+?)(\.git)?$}
9
9
  TRAVIS = %r{^https://(staging-)?api\.travis-ci\.(org|com)}
10
10
  on('-r', '--repo SLUG', 'repository to use (will try to detect from current git clone)') { |c, slug| c.slug = slug }
11
+ on('-R', '--store-repo SLUG', 'like --repo, but remembers value for current directory') do |c, slug|
12
+ c.slug = slug
13
+ c.send(:store_slug, slug)
14
+ end
11
15
 
12
16
  attr_accessor :slug
13
17
  abstract
@@ -52,11 +56,38 @@ module Travis
52
56
  end
53
57
 
54
58
  def find_slug
55
- git_head = `git name-rev --name-only HEAD 2>#{IO::NULL}`.chomp
56
- git_remote = `git config --get branch.#{git_head}.remote 2>#{IO::NULL}`.chomp
57
- git_remote = 'origin' if git_remote.empty?
58
- git_info = `git config --get remote.#{git_remote}.url 2>#{IO::NULL}`.chomp
59
- $1 if Addressable::URI.parse(git_info).path =~ GIT_REGEX
59
+ load_slug || store_slug(detect_slug)
60
+ end
61
+
62
+ def detect_slug
63
+ git_head = `git name-rev --name-only HEAD 2>#{IO::NULL}`.chomp
64
+ git_remote = `git config --get branch.#{git_head}.remote 2>#{IO::NULL}`.chomp
65
+ git_remote = 'origin' if git_remote.empty?
66
+ git_info = `git config --get remote.#{git_remote}.url 2>#{IO::NULL}`.chomp
67
+
68
+ if Addressable::URI.parse(git_info).path =~ GIT_REGEX
69
+ detectected_slug = $1
70
+ if interactive?
71
+ if agree("Detected repository as #{color(detectected_slug, :info)}, is this correct? ") { |q| q.default = 'yes' }
72
+ detectected_slug
73
+ else
74
+ ask("Repository slug: ") { |q| q.default = detectected_slug }
75
+ end
76
+ else
77
+ info "detected repository as #{color(detectected_slug, :bold)}"
78
+ detectected_slug
79
+ end
80
+ end
81
+ end
82
+
83
+ def load_slug
84
+ stored = `git config --get travis.slug`.chomp
85
+ stored unless stored.empty?
86
+ end
87
+
88
+ def store_slug(value)
89
+ `git config travis.slug #{value}` if value
90
+ value
60
91
  end
61
92
 
62
93
  def repo_config
data/travis.gemspec CHANGED
@@ -115,7 +115,8 @@ Gem::Specification.new do |s|
115
115
  "assets/travis.sh",
116
116
  "assets/travis.sh.erb",
117
117
  "bin/travis",
118
- "examples/cli.md",
118
+ "examples/cli/encrypt_file.md",
119
+ "examples/cli/private_dependencies.md",
119
120
  "examples/org_overview.rb",
120
121
  "examples/pro_auth.rb",
121
122
  "examples/stream.rb",
@@ -131,6 +132,7 @@ Gem::Specification.new do |s|
131
132
  "lib/travis/cli/disable.rb",
132
133
  "lib/travis/cli/enable.rb",
133
134
  "lib/travis/cli/encrypt.rb",
135
+ "lib/travis/cli/encrypt_file.rb",
134
136
  "lib/travis/cli/endpoint.rb",
135
137
  "lib/travis/cli/env.rb",
136
138
  "lib/travis/cli/help.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: travis
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.18.travis.596.5
4
+ version: 1.6.18.travis.604.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Haase
@@ -39,7 +39,7 @@ authors:
39
39
  autorequire:
40
40
  bindir: bin
41
41
  cert_chain: []
42
- date: 2014-07-26 00:00:00.000000000 Z
42
+ date: 2014-07-30 00:00:00.000000000 Z
43
43
  dependencies:
44
44
  - !ruby/object:Gem::Dependency
45
45
  name: faraday
@@ -312,7 +312,8 @@ files:
312
312
  - assets/travis.sh
313
313
  - assets/travis.sh.erb
314
314
  - bin/travis
315
- - examples/cli.md
315
+ - examples/cli/encrypt_file.md
316
+ - examples/cli/private_dependencies.md
316
317
  - examples/org_overview.rb
317
318
  - examples/pro_auth.rb
318
319
  - examples/stream.rb
@@ -328,6 +329,7 @@ files:
328
329
  - lib/travis/cli/disable.rb
329
330
  - lib/travis/cli/enable.rb
330
331
  - lib/travis/cli/encrypt.rb
332
+ - lib/travis/cli/encrypt_file.rb
331
333
  - lib/travis/cli/endpoint.rb
332
334
  - lib/travis/cli/env.rb
333
335
  - lib/travis/cli/help.rb