nexus_cli 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ .rake_tasks~
3
+ tmp/
4
+ pkg/
data/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Author:: Kyle Allan (<kallan@riotgames.com>)
2
+
3
+ Copyright 2011, 2012 Riot Games
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
@@ -0,0 +1,57 @@
1
+ Description
2
+ ===========
3
+
4
+ A CLI wrapper around Sonatype Nexus REST calls.
5
+
6
+ Requirements
7
+ ============
8
+
9
+ * Ruby
10
+
11
+ Installation
12
+ ============
13
+
14
+ 1. Install the Gem
15
+ 2. Create a file in your user's home directory named `.nexus_cli`
16
+ 3. Give the file the following information:
17
+
18
+ ```
19
+ url: "http://whatever"
20
+ username: "username"
21
+ password: "password"
22
+ ```
23
+
24
+ Usage
25
+ =====
26
+
27
+ There are two calls that can be made. push\_artifact and pull\_artifact. Both calls will push or pull artifacts from Nexus using the Maven-flavored syntax: `groupId:artifactId:version:extension`
28
+
29
+ Pull Artifact Example
30
+ ---------------------
31
+ ```
32
+ nexus-cli pull_artifact com.mycompany.artifacts:myartifact:1.0.0:tgz
33
+ ```
34
+ Push Artifact Example
35
+ ---------------------
36
+ ```
37
+ nexus-cli push_artifact com.mycompany.artifacts:myartifact:1.0.0:tgz ~/path/to/file/to/push/myartifact.tgz
38
+ ```
39
+
40
+ License and Author
41
+ ==================
42
+
43
+ Author:: Kyle Allan (<kallan@riotgames.com>)
44
+
45
+ Copyright:: 2012 Riot Games Inc.
46
+
47
+ Licensed under the Apache License, Version 2.0 (the "License");
48
+ you may not use this file except in compliance with the License.
49
+ You may obtain a copy of the License at
50
+
51
+ http://www.apache.org/licenses/LICENSE-2.0
52
+
53
+ Unless required by applicable law or agreed to in writing, software
54
+ distributed under the License is distributed on an "AS IS" BASIS,
55
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
56
+ See the License for the specific language governing permissions and
57
+ limitations under the License.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.3
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $:.push File.expand_path("../../lib", __FILE__)
3
+ require 'nexus_cli'
4
+
5
+ NexusCli::Cli.start
@@ -0,0 +1,17 @@
1
+ @cli
2
+ Feature: Pull Artifact
3
+ As a CLI user
4
+ I need a command to pull artifacts from the Nexus repository
5
+ So I have a way to get artifacts from a remote system to my local machine
6
+
7
+ Scenario: Pull an artifact
8
+ When I get the artifact "com.riotgames.tar:mytar:1.0.3:tgz"
9
+ Then I should have a copy of the "mytar-1.0.3.tgz" artifact on my computer
10
+
11
+ Scenario: Pull an artifact to a specific place
12
+ When I want the artifact "com.riotgames.tar:mytar:1.0.3:tgz" in a temp directory
13
+ Then I should have a copy of the "mytar-1.0.3.tgz" artifact in a temp directory
14
+
15
+ Scenario: Attempt to pull an artifact with the wrong parameters
16
+ When I run `nexus-cli pull_artifact com.riotgames.whatever:something`
17
+ Then I should expect an error because I need more colon separated values
@@ -0,0 +1,8 @@
1
+ Feature: Push Artifact
2
+ As a CLI User
3
+ I need a command to push artifacts into the Nexus repository
4
+ So I have a way to get artifacts from Nexus when I want them
5
+
6
+ Scenario: Push an Artifact
7
+ When I push an artifact into the Nexus
8
+ Then I should be able to ask the Nexus for information about it and get a result
@@ -0,0 +1,32 @@
1
+ When /^I get the artifact "([^"]*)"$/ do |arg1|
2
+ NexusCli::Remote.pull_artifact arg1, nil
3
+ end
4
+
5
+ Then /^I should have a copy of the "([^"]*)" artifact on my computer$/ do |arg1|
6
+ File.exists?(arg1).should be_true
7
+ end
8
+
9
+ When /^I want the artifact "([^"]*)" in a temp directory$/ do |arg1|
10
+ NexusCli::Remote.pull_artifact arg1, ENV["TMPDIR"]
11
+ end
12
+
13
+ Then /^I should have a copy of the "([^"]*)" artifact in a temp directory$/ do |arg1|
14
+ path = File.join(ENV["TMPDIR"], arg1)
15
+ File.exists?(path).should be_true
16
+ end
17
+
18
+ Then /^I should expect an error because I need more colon separated values$/ do
19
+ assert_exit_status(100)
20
+ end
21
+
22
+ When /^I push an artifact into the Nexus$/ do
23
+ file = File.new("myFile.tgz", 'w')
24
+ file.puts "some data"
25
+ file.close
26
+ file = File.open("myFile.tgz", 'r')
27
+ NexusCli::Remote.push_artifact "com.foo.bar:myFile:1.0.0:tgz", file
28
+ end
29
+
30
+ Then /^I should be able to ask the Nexus for information about it and get a result$/ do
31
+ NexusCli::Remote.get_artifact_info "com.foo.bar:myFile:1.0.0:tgz"
32
+ end
@@ -0,0 +1,15 @@
1
+ require 'aruba/cucumber'
2
+
3
+ $:.push "#{File.dirname(__FILE__)}/../../lib/"
4
+ require 'nexus_cli'
5
+ require 'rspec'
6
+
7
+ After do |scenario|
8
+ FileUtils.rm_f("mytar-1.0.3.tgz")
9
+
10
+ tmp_path = File.join(ENV["TMPDIR"], "mytar-1.0.3.tgz")
11
+ FileUtils.rm_f(tmp_path)
12
+
13
+ NexusCli::Remote.delete_artifact('com.foo.bar:myFile:1.0.0:tgz')
14
+ FileUtils.rm_f("myFile.tgz")
15
+ end
@@ -0,0 +1,12 @@
1
+ require "nexus_cli/remote"
2
+ require "nexus_cli/cli"
3
+ require "nexus_cli/errors"
4
+ require "nexus_cli/kernel"
5
+
6
+ module NexusCli
7
+ class << self
8
+ def root
9
+ @root ||= Pathname.new(File.expand_path('../', File.dirname(__FILE__)))
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,39 @@
1
+ require 'thor'
2
+
3
+ module NexusCli
4
+ module Cli
5
+ def self.included(base)
6
+ base.send :include, ::Thor::Actions
7
+ base.class_eval do
8
+
9
+ desc "pull_artifact artifact", "Pulls an artifact from Nexus and places it on your machine."
10
+ method_option :destination, :default => nil # defaults to the current working directory
11
+ def pull_artifact(artifact)
12
+ begin
13
+ path_to_artifact = Remote.pull_artifact(artifact, options[:destination])
14
+ puts "Artifact has been retrived and can be found at path: #{path_to_artifact}"
15
+ rescue NexusCliError => e
16
+ puts e.message
17
+ exit e.status_code
18
+ end
19
+ end
20
+
21
+ desc "push_artifact artifact file", "Pushes an artifact from your machine onto the Nexus."
22
+ def push_artifact(artifact, file)
23
+ Remote.push_artifact(artifact, file)
24
+ puts "Artifact #{artifact} has been successfully pushed to Nexus."
25
+ end
26
+
27
+ desc "get_artifact_info artifact", "Gets and returns the XML information about a particular artifact."
28
+ def get_artifact_info(artifact)
29
+ begin
30
+ puts Remote.get_artifact_info(artifact)
31
+ rescue NexusCliError => e
32
+ puts e.message
33
+ exit e.status_code
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,41 @@
1
+ module NexusCli
2
+ class NexusCliError < StandardError
3
+ class << self
4
+ def status_code(code)
5
+ define_method(:status_code) { code }
6
+ end
7
+ end
8
+ end
9
+
10
+ class ArtifactMalformedException < NexusCliError
11
+ def message
12
+ "Please submit your request using 4 colon-separated values. `groupId:artifactId:version:extension`"
13
+ end
14
+ status_code(100)
15
+ end
16
+
17
+ class ArtifactNotFoundException < NexusCliError
18
+ def message
19
+ "The artifact you requested information for could not be found. Please ensure it exists inside the Nexus."
20
+ end
21
+ status_code(101)
22
+ end
23
+
24
+ class InvalidSettingsException < NexusCliError
25
+ def initialize(key)
26
+ @missing_setting = key
27
+ end
28
+
29
+ def message
30
+ "The .nexus_cli file is missing the value: #{@missing_setting}"
31
+ end
32
+ status_code(102)
33
+ end
34
+
35
+ class MissingSettingsFile < NexusCliError
36
+ def message
37
+ "The .nexus_cli file is missing or corrupt."
38
+ end
39
+ status_code(103)
40
+ end
41
+ end
@@ -0,0 +1,33 @@
1
+ # From ActiveSupport: https://github.com/rails/rails/blob/c2c8ef57d6f00d1c22743dc43746f95704d67a95/activesupport/lib/active_support/core_ext/kernel/reporting.rb#L39
2
+
3
+ require 'rbconfig'
4
+
5
+ module Kernel
6
+ # Silences any stream for the duration of the block.
7
+ #
8
+ # silence_stream(STDOUT) do
9
+ # puts 'This will never be seen'
10
+ # end
11
+ #
12
+ # puts 'But this will'
13
+ def silence_stream(stream)
14
+ old_stream = stream.dup
15
+ stream.reopen(RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL:' : '/dev/null')
16
+ stream.sync = true
17
+ yield
18
+ ensure
19
+ stream.reopen(old_stream)
20
+ end
21
+
22
+ # Silences both STDOUT and STDERR, even for subprocesses.
23
+ #
24
+ # quietly { system 'bundle install' }
25
+ #
26
+ def quietly
27
+ silence_stream(STDOUT) do
28
+ silence_stream(STDERR) do
29
+ yield
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,96 @@
1
+ require 'restclient'
2
+ require 'yaml'
3
+
4
+ module NexusCli
5
+ class Remote
6
+ class << self
7
+
8
+ def configuration=(config = {})
9
+ validate_config(config)
10
+ @configuration = config
11
+ end
12
+
13
+ def configuration
14
+ return @configuration if @configuration
15
+ begin
16
+ config = YAML::load_file(File.expand_path("~/.nexus_cli"))
17
+ rescue Errno::ENOENT
18
+ raise MissingSettingsFile
19
+ end
20
+ validate_config(config)
21
+ @configuration = config
22
+ end
23
+
24
+ def nexus
25
+ @nexus ||= RestClient::Resource.new configuration["url"], :user => configuration["username"], :password => configuration["password"]
26
+ end
27
+
28
+ def pull_artifact(artifact, destination)
29
+ split_artifact = artifact.split(":")
30
+ if(split_artifact.size < 4)
31
+ raise ArtifactMalformedException
32
+ end
33
+ begin
34
+ fileData = nexus['service/local/artifact/maven/redirect'].get ({params: {r: configuration['repository'], g: split_artifact[0], a: split_artifact[1], v: split_artifact[2], e: split_artifact[3]}})
35
+ rescue RestClient::ResourceNotFound
36
+ raise ArtifactNotFoundException
37
+ end
38
+ artifact = nil
39
+ destination = File.join(File.expand_path(destination || "."), "#{split_artifact[1]}-#{split_artifact[2]}.#{split_artifact[3]}")
40
+ artifact = File.open(destination, 'w')
41
+ artifact.write(fileData)
42
+ artifact.close()
43
+ File.expand_path(artifact.path)
44
+ end
45
+
46
+ def push_artifact(artifact, file)
47
+ #Build up the pieces that will make up the PUT request
48
+ split_artifact = artifact.split(":")
49
+ if(split_artifact.size < 4)
50
+ raise ArtifactMalformedException
51
+ end
52
+ artifact_id = split_artifact[0].gsub(".", "/")
53
+ group_id = split_artifact[1].gsub(".", "/")
54
+ version = split_artifact[2]
55
+ file_name = "#{split_artifact[1]}-#{version}.#{split_artifact[3]}"
56
+
57
+ put_string = "content/repositories/releases/#{artifact_id}/#{group_id}/#{version}/#{file_name}"
58
+ #nexus[put_string].put File.read(file), :accept => "*/*"
59
+ Kernel.quietly {`curl -T #{file} #{configuration['url']}#{put_string} -u #{configuration['username']}:#{configuration['password']}`}
60
+ end
61
+
62
+ def delete_artifact(artifact)
63
+ split_artifact = artifact.split(":")
64
+ if(split_artifact.size < 4)
65
+ raise ArtifactMalformedException
66
+ end
67
+ artifact_id = split_artifact[0].gsub(".", "/")
68
+ group_id = split_artifact[1].gsub(".", "/")
69
+ version = split_artifact[2]
70
+
71
+ delete_string = "content/repositories/releases/#{artifact_id}/#{group_id}/#{version}"
72
+ Kernel.quietly {`curl --request DELETE #{configuration['url']}#{delete_string} -u #{configuration['username']}:#{configuration['password']}`}
73
+ end
74
+
75
+ def get_artifact_info(artifact)
76
+ split_artifact = artifact.split(":")
77
+ if(split_artifact.size < 4)
78
+ raise ArtifactMalformedException
79
+ end
80
+ begin
81
+ nexus['service/local/artifact/maven/resolve'].get ({params: {r: configuration['repository'], g: split_artifact[0], a: split_artifact[1], v: split_artifact[2], e: split_artifact[3]}})
82
+ rescue RestClient::ResourceNotFound => e
83
+ raise ArtifactNotFoundException
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def validate_config(configuration)
90
+ ["url", "repository", "username","password"].each do |key|
91
+ raise InvalidSettingsException.new(key) unless configuration.has_key?(key)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,6 @@
1
+ module NexusCli
2
+ # @return [String]
3
+ def self.version
4
+ @version ||= File.read(File.expand_path("../../../VERSION", __FILE__)).strip
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'nexus_cli/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "nexus_cli"
7
+ s.version = NexusCli.version
8
+ s.authors = ["Kyle Allan"]
9
+ s.email = ["kallan@riotgames.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{A command-line wrapper for making REST calls to Sonatype Nexus.}
12
+ s.description = s.summary
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ #s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency 'thor'
20
+ s.add_dependency 'rest-client'
21
+
22
+ s.add_development_dependency 'rspec'
23
+ s.add_development_dependency 'aruba'
24
+ s.add_development_dependency 'cucumber'
25
+ end
@@ -0,0 +1,38 @@
1
+ require 'nexus_cli'
2
+ require 'restclient'
3
+
4
+ describe NexusCli do
5
+ it "gives you errors when configuration is missing a password" do
6
+ expect {NexusCli::Remote.configuration = {url: "http://somewebsite.com", username: "admin"}}.to raise_error(NexusCli::InvalidSettingsException)
7
+ end
8
+
9
+ it "gives you errors when configuration is missing a username" do
10
+ expect {NexusCli::Remote.configuration = {url: "http://somewebsite.com", password: "admin"}}.to raise_error(NexusCli::InvalidSettingsException)
11
+ end
12
+
13
+ it "gives you errors when you attempt to pull an artifact don't give a valid artifact name" do
14
+ expect {NexusCli::Remote.pull_artifact "com.something:something:1.0.0", nil}.to raise_error(NexusCli::ArtifactMalformedException)
15
+ end
16
+
17
+ it "gives you errors when you attempt to push an artifact don't give a valid artifact name" do
18
+ expect {NexusCli::Remote.push_artifact "com.something:something:1.0.0", nil}.to raise_error(NexusCli::ArtifactMalformedException)
19
+ end
20
+
21
+ it "gives you errors when you attempt to get an artifact's info and don't give a valid artifact name" do
22
+ expect {NexusCli::Remote.get_artifact_info "com.something:something:1.0.0"}.to raise_error(NexusCli::ArtifactMalformedException)
23
+ end
24
+
25
+ it "gives you errors when you attempt to delete an artifact and don't give a valid artifact name" do
26
+ expect {NexusCli::Remote.get_artifact_info "com.something:something:1.0.0"}.to raise_error(NexusCli::ArtifactMalformedException)
27
+ end
28
+
29
+ it "gives you errors when you attempt to pull an artifact and it cannot be found" do
30
+ RestClient::Resource.any_instance.stub(:get).and_raise(RestClient::ResourceNotFound)
31
+ expect {NexusCli::Remote.pull_artifact "com.something:something:1.0.0:tgz", nil}.to raise_error(NexusCli::ArtifactNotFoundException)
32
+ end
33
+
34
+ it "gives you errors when you attempt to get an artifact's info and it cannot be found" do
35
+ RestClient::Resource.any_instance.stub(:get).and_raise(RestClient::ResourceNotFound)
36
+ expect {NexusCli::Remote.get_artifact_info "com.something:something:1.0.0:tgz"}.to raise_error(NexusCli::ArtifactNotFoundException)
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nexus_cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kyle Allan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: &70121685045360 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70121685045360
25
+ - !ruby/object:Gem::Dependency
26
+ name: rest-client
27
+ requirement: &70121685044720 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70121685044720
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70121685060120 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70121685060120
47
+ - !ruby/object:Gem::Dependency
48
+ name: aruba
49
+ requirement: &70121685058960 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70121685058960
58
+ - !ruby/object:Gem::Dependency
59
+ name: cucumber
60
+ requirement: &70121685058340 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70121685058340
69
+ description: A command-line wrapper for making REST calls to Sonatype Nexus.
70
+ email:
71
+ - kallan@riotgames.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - LICENSE
78
+ - README.md
79
+ - Rakefile
80
+ - VERSION
81
+ - bin/nexus-cli
82
+ - features/cli/pull_artifact.feature
83
+ - features/cli/push_artifact.feature
84
+ - features/step_definitions/cli_steps.rb
85
+ - features/support/env.rb
86
+ - lib/nexus_cli.rb
87
+ - lib/nexus_cli/cli.rb
88
+ - lib/nexus_cli/errors.rb
89
+ - lib/nexus_cli/kernel.rb
90
+ - lib/nexus_cli/remote.rb
91
+ - lib/nexus_cli/version.rb
92
+ - nexus_cli.gemspec
93
+ - spec/remote_spec.rb
94
+ homepage: ''
95
+ licenses: []
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ segments:
107
+ - 0
108
+ hash: -1715274154422444014
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ segments:
116
+ - 0
117
+ hash: -1715274154422444014
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 1.8.11
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: A command-line wrapper for making REST calls to Sonatype Nexus.
124
+ test_files:
125
+ - features/cli/pull_artifact.feature
126
+ - features/cli/push_artifact.feature
127
+ - features/step_definitions/cli_steps.rb
128
+ - features/support/env.rb
129
+ - spec/remote_spec.rb