leeroy_jenkins 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4612f068204c29e5974fca44bc9caecb6748c7e9
4
- data.tar.gz: a83a55f9e5611c7faedf56993f8c39c5118159eb
3
+ metadata.gz: e7250c26ddbb7688160d7f465e969a04a31384d9
4
+ data.tar.gz: 4232370b71230e292664ccdb2d4845b9333c2533
5
5
  SHA512:
6
- metadata.gz: f3d432dd6f88cb2b13f19d74cb0749f9c5e6589b440d426c1a985632ab512e635e42f9ddf8e7e35aa1b04966d40c7774cb19cc32820859df58e25044ca79730e
7
- data.tar.gz: c741588ce832eaf3faaa90db0c11293bb9bfb59e6597de287de584ec6e1f7e0dc73bb60786e786c155a8ec984ed739ac9d1d265384250886f3d54c450de14469
6
+ metadata.gz: 4f4da81497645190fd871ccfc9eea476e57ea6e3b9867ec7ef71333f9408c4872ef58ab25368345053f1cb99554a64fb66a932d9049362470985b28ea960dc46
7
+ data.tar.gz: ac7db9f73e29117082e41dfdfed0fa05e1db14f0f9caa68fdf7f71ae6c4d72f048b47df801863338382ae648856f702dae1036630a726142db8a786cd4c157b3
@@ -0,0 +1,24 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ Style/WordArray:
4
+ Enabled: false
5
+
6
+ Style/HashSyntax:
7
+ Exclude:
8
+ - 'Rakefile'
9
+
10
+ Metrics/LineLength:
11
+ Exclude:
12
+ - 'lib/leeroy_jenkins/cli.rb'
13
+
14
+ Metrics/AbcSize:
15
+ Max: 25
16
+
17
+ Metrics/MethodLength:
18
+ Max: 20
19
+
20
+ Style/Documentation:
21
+ Enabled: false
22
+
23
+ Metrics/ParameterLists:
24
+ Max: 6
@@ -0,0 +1,18 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2016-08-09 13:57:32 -0500 using RuboCop version 0.42.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 3
10
+ Lint/AmbiguousRegexpLiteral:
11
+ Exclude:
12
+ - 'features/step_definitions/jenkins.rb'
13
+
14
+ # Offense count: 49
15
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
16
+ # URISchemes: http, https
17
+ Metrics/LineLength:
18
+ Max: 172
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # leeroy_jenkins
2
2
 
3
+ [![Gem](https://img.shields.io/gem/v/leeroy_jenkins.svg)](https://rubygems.org/gems/leeroy_jenkins)
4
+
3
5
  ## Description
4
6
  A CLI tool for managing Jenkins job configurations: bulk update, backup, and restore your Jenkins job configurations
5
7
 
@@ -21,14 +23,44 @@ Or install it yourself as:
21
23
 
22
24
  ## Usage
23
25
 
24
- Set your `LEEROY_JENKINS_USERNAME`, `LEEROY_JENKINS_PASSWORD`, and `LEEROY_JENKINS_SERVER_URL` appropriately for your Jenkins. These can also be overridden with command line options.
26
+ Set your `LEEROY_JENKINS_USERNAME`, `LEEROY_JENKINS_PASSWORD`, and `LEEROY_JENKINS_SERVER_URL` environment variables appropriately for your Jenkins. These can also be overridden with command line options. Run `leeroy --help` to see the available sub-commands and options:
25
27
 
26
28
  $ leeroy --help
27
- $ leeroy help [COMMAND_NAME]
29
+ Commands:
30
+ leeroy append NEW_NODE.xml # Append to XML nodes in jenkins jobs' config.xml
31
+ leeroy backup BACKUP_DIR_PATH # Save the config.xml of Jenkins jobs to disk, BACKUP_DIR created if it does not exist
32
+ leeroy delete # Delete XML nodes in jenkins jobs' config.xml
33
+ leeroy help [COMMAND] # Describe available commands or one specific command
34
+ leeroy replace NEW_NODE.xml # Replace XML nodes in jenkins jobs' config.xml
35
+ leeroy restore BACKUP_DIR_PATH # Restore config.xml files to Jenkins jobs from backups
28
36
 
29
- ## Development
37
+ Options:
38
+ [--dry-run], [--no-dry-run] # Show what leeroy would do, without doing it
39
+ # Default: true
40
+ [--jenkins-log-level=N] # Detail of the messages logged by the Jenkins API client: DEBUG (0), INFO (1), WARN (2), FATAL (3)
41
+ # Default: 3
42
+ # Possible values: 0, 1, 2, 3
43
+ [--jenkins-log-location=JENKINS_LOG_LOCATION] # Path to write messages logged by the Jenkins API client
44
+ # Default: /dev/stdout
45
+ [--job-regex=JOB_REGEX] # Regular expression to select jobs by name
46
+ # Default: .*
47
+ [--jobs=JOBS] # Path to a file containing a job name on each line
48
+ [--password=PASSWORD] # Override LEEROY_JENKINS_PASSWORD
49
+ [--server-url=SERVER_URL] # Override LEEROY_JENKINS_SERVER_URL
50
+ [--threads=N] # Number of threads to use for network and disk IO
51
+ # Default: 4
52
+ [--username=USERNAME] # Override LEEROY_JENKINS_USERNAME
53
+
54
+ For more specific examples and documentation of features, take a look in the `features` directory (the fixtures referenced there are [here](https://github.com/Jellyvision/leeroy_jenkins/tree/master/features/fixtures)):
30
55
 
31
- After checking out the repo, run `bundle install` to install dependencies. Then, run `bundle exec rspec` to run the unit tests. You can also run `bundle exec bin/console` for an interactive prompt that will allow you to experiment. Run `bundle exec exe/leeroy` to use the gem in this directory, ignoring other installed copies of this gem.
56
+ * [append](https://github.com/Jellyvision/leeroy_jenkins/blob/master/features/append.feature)
57
+ * [backup](https://github.com/Jellyvision/leeroy_jenkins/blob/master/features/backup.feature)
58
+ * [delete](https://github.com/Jellyvision/leeroy_jenkins/blob/master/features/delete.feature)
59
+ * [replace](https://github.com/Jellyvision/leeroy_jenkins/blob/master/features/replace.feature)
60
+ * [restore](https://github.com/Jellyvision/leeroy_jenkins/blob/master/features/restore.feature)
61
+
62
+ ## Development
32
63
 
33
- To run the acceptance tests, run `vagrant up` to start your own Jenkins instance. This may take 5-10 minutes, but when finished you'll be able to access Jenkins at `192.168.50.33:8080` in your web browser. Then run `bundle exec cucumber`.
64
+ After checking out the repo, run `bundle install` to install dependencies. Then, run `bundle exec rake rspec` to run the unit tests. Run `bundle exec rake rubocop` to lint. You can also run `bundle exec bin/console` to launch a pry session with all code and dependencies loaded. Run `bundle exec exe/leeroy` to use the gem in this directory, ignoring other installed copies of this gem.
34
65
 
66
+ To run the acceptance tests, run `vagrant up` to start your own Jenkins instance. This may take 5-10 minutes, but when finished you'll be able to access Jenkins at `192.168.50.33:8080` in your web browser. Then run `bundle exec rake cucumber`. `bundle exec rake verify` will lint, run unit tests, and run acceptance tests. This is also the default rake task.
data/Rakefile CHANGED
@@ -1,6 +1,21 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
3
2
 
4
- RSpec::Core::RakeTask.new(:spec)
3
+ desc 'Lint, run unit tests, and run acceptance tests.'
4
+ task :verify => [:rubocop, :rspec, :cucumber]
5
5
 
6
- task :default => :spec
6
+ desc 'Lint.'
7
+ task :rubocop do
8
+ sh 'bundle exec rubocop'
9
+ end
10
+
11
+ desc 'Run unit tests.'
12
+ task :rspec do
13
+ sh 'bundle exec rspec'
14
+ end
15
+
16
+ desc 'Run acceptance tests.'
17
+ task :cucumber do
18
+ sh 'bundle exec cucumber'
19
+ end
20
+
21
+ task :default => :verify
@@ -1,16 +1,20 @@
1
1
  Vagrant.configure 2 do |config|
2
- config.vm.box = "ubuntu/trusty64"
3
- config.vm.network "private_network", ip: "192.168.50.33"
2
+ config.vm.box = 'ubuntu/trusty64'
3
+ config.vm.network 'private_network', ip: '192.168.50.33'
4
4
 
5
- config.vm.provision "shell", inline: <<-SCRIPT
6
- apt-get update
7
- apt-get upgrade -y
5
+ config.vm.provision 'shell', inline: <<EOF
6
+ set -ex
8
7
 
9
- apt-get install openjdk-7-jdk -y
8
+ JENKINS_VERSION=1.658
10
9
 
11
- wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | apt-key add -
12
- sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
13
10
  apt-get update
14
- apt-get install jenkins -y
15
- SCRIPT
11
+
12
+ curl -sL \
13
+ -o /tmp/jenkins_${JENKINS_VERSION}_all.deb \
14
+ http://pkg.jenkins-ci.org/debian/binary/jenkins_${JENKINS_VERSION}_all.deb
15
+
16
+ apt-get install openjdk-7-jre-headless daemon -y
17
+ dpkg -i /tmp/jenkins_${JENKINS_VERSION}_all.deb
18
+
19
+ EOF
16
20
  end
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "leeroy_jenkins"
3
+ require 'bundler/setup'
4
+ require 'leeroy_jenkins'
5
5
 
6
- require "pry"
6
+ require 'pry'
7
7
  Pry.start
data/exe/leeroy CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "leeroy_jenkins"
3
+ require 'leeroy_jenkins'
4
4
 
5
5
  LeeroyJenkins::Cli.start ARGV
@@ -19,17 +19,17 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_dependency 'jenkins_api_client', '~> 1.4'
22
- spec.add_dependency 'thor', '~> 0.19.1'
23
22
  spec.add_dependency 'nokogiri', '~> 1.6'
24
23
  spec.add_dependency 'parallel', '~> 1.6'
24
+ spec.add_dependency 'thor', '~> 0.19.1'
25
25
 
26
+ spec.add_development_dependency 'aruba', '~> 0.14.1'
26
27
  spec.add_development_dependency 'bundler', '~> 1.10'
27
- spec.add_development_dependency 'rake', '~> 10.0'
28
- spec.add_development_dependency 'rspec', '~> 3.3'
29
- spec.add_development_dependency 'aruba', '~> 0.9.0'
30
- spec.add_development_dependency 'cucumber', '~> 2.1'
31
28
  spec.add_development_dependency 'pry', '~> 0.10.1'
32
29
  spec.add_development_dependency 'pry-doc', '~> 0.8.0'
33
30
  spec.add_development_dependency 'pry-stack_explorer', '~> 0.4.9'
34
- spec.add_development_dependency 'rubocop', '~> 0.37.2'
31
+ spec.add_development_dependency 'rake', '~> 10.0'
32
+ spec.add_development_dependency 'rspec', '~> 3.3'
33
+ spec.add_development_dependency 'rubocop', '~> 0.42.0'
34
+ spec.add_development_dependency 'simplecov', '~> 0.12.0'
35
35
  end
@@ -1,20 +1,21 @@
1
- require "jenkins_api_client"
2
- require "thor"
3
- require "nokogiri"
4
- require "parallel"
1
+ require 'jenkins_api_client'
2
+ require 'thor'
3
+ require 'nokogiri'
4
+ require 'parallel'
5
5
 
6
- require "leeroy_jenkins/version"
7
- require "leeroy_jenkins/cli"
8
- require "leeroy_jenkins/job_finder"
9
- require "leeroy_jenkins/jenkins_client_builder"
10
- require "leeroy_jenkins/job_updater"
11
- require "leeroy_jenkins/job_backupper"
12
- require "leeroy_jenkins/job_restorer"
6
+ require 'leeroy_jenkins/version'
7
+ require 'leeroy_jenkins/cli'
8
+ require 'leeroy_jenkins/result'
9
+ require 'leeroy_jenkins/job_finder'
10
+ require 'leeroy_jenkins/jenkins_client_builder'
11
+ require 'leeroy_jenkins/job_updater'
12
+ require 'leeroy_jenkins/job_backupper'
13
+ require 'leeroy_jenkins/job_restorer'
13
14
 
14
15
  module LeeroyJenkins
15
- def self.invalid_xml_document? raw_xml
16
+ def self.invalid_xml_document?(raw_xml)
16
17
  begin
17
- Nokogiri::XML(raw_xml) { |config| config.strict }
18
+ Nokogiri::XML(raw_xml, &:strict)
18
19
  rescue Nokogiri::XML::SyntaxError => e
19
20
  return e
20
21
  end
@@ -1,93 +1,87 @@
1
1
  module LeeroyJenkins
2
2
  class Cli < Thor
3
- class_option :log_level, required: false, type: :numeric, desc: 'The detail of the messages logged by the Jenkins API client. DEBUG (0), INFO (1), WARN (2), FATAL (3)', enum: [0, 1, 2, 3], default: 3
4
- class_option :log_location, required: false, type: :string, desc: 'Path to the log file', default: STDOUT
5
- class_option :username, required: false, type: :string, desc: 'Override LEEROY_JENKINS_USERNAME'
6
- class_option :password, required: false, type: :string, desc: 'Override LEEROY_JENKINS_PASSWORD'
7
- class_option :server_url, required: false, type: :string, desc: 'Override LEEROY_JENKINS_SERVER_URL'
8
- class_option :threads, required: false, type: :numeric, desc: 'Number of threads to use for network and disk IO', default: 4
9
-
10
- desc 'update-config', 'Modify jobs\' config.xml'
11
- option :job_regex, required: false, type: :string, desc: 'Regular expression to select jobs by name', default: '.*'
12
- option :new_xml, required: true, type: :string, desc: 'Path to an XML file'
13
- option :xpath, required: false, type: :string, desc: 'XPath of node(s) to modify in the config.xml of the specified job(s)', default: '/'
14
- option :dry_run, type: :boolean, desc: 'Write XML to STDOUT instead of to Jenkins', default: true
15
- option :at_xpath, required: false, type: :string, desc: 'Replace, append to, or delete the XML node(s) specified by the given XPath', enum: ['replace', 'append', 'delete'], default: 'replace'
16
- option :jobs, required: false, type: :string, desc: 'Path to a file containing a job name on each line'
17
- def update_config
18
- raw_xml_string = File.read options[:new_xml]
19
- if error = LeeroyJenkins.invalid_xml_document?(raw_xml_string)
20
- error "#{options[:new_xml]}} is not well-formed XML: #{error}"
21
- exit 1
22
- end
3
+ # exit non-zero on failure
4
+ # https://github.com/erikhuda/thor/issues/244
5
+ def self.exit_on_failure?
6
+ true
7
+ end
23
8
 
24
- jenkins_client = build_jenkins_client(options)
9
+ class_option :dry_run, type: :boolean, default: true, desc: 'Show what leeroy would do, without doing it'
10
+ class_option :jenkins_log_level, type: :numeric, default: 3, desc: 'Detail of the messages logged by the Jenkins API client: DEBUG (0), INFO (1), WARN (2), FATAL (3)', enum: [0, 1, 2, 3]
11
+ class_option :jenkins_log_location, type: :string, default: '/dev/stdout', desc: 'Path to write messages logged by the Jenkins API client'
12
+ class_option :job_regex, type: :string, default: '.*', desc: 'Regular expression to select jobs by name'
13
+ class_option :jobs, type: :string, desc: 'Path to a file containing a job name on each line'
14
+ class_option :password, type: :string, desc: 'Override LEEROY_JENKINS_PASSWORD'
15
+ class_option :server_url, type: :string, desc: 'Override LEEROY_JENKINS_SERVER_URL'
16
+ class_option :threads, type: :numeric, default: 4, desc: 'Number of threads to use for network and disk IO'
17
+ class_option :username, type: :string, desc: 'Override LEEROY_JENKINS_USERNAME'
25
18
 
26
- job_rows =
27
- if options[:jobs]
28
- File.read(options[:jobs]).split("\n")
29
- else
30
- nil
31
- end
19
+ desc 'append NEW_NODE.xml', 'Append to XML nodes in jenkins jobs\' config.xml'
20
+ option :xpath, type: :string, default: '/', desc: 'XPath of node(s) to modify in the config.xml of the specified job(s)'
21
+ def append(xml_file_path)
22
+ puts update_jobs(read_and_validate_xml_file(xml_file_path), __method__)
23
+ end
32
24
 
33
- job_names_to_update = JobFinder.new(jenkins_client).find_jobs(options[:job_regex], job_rows)
34
- job_updater = JobUpdater.new job_names_to_update, raw_xml_string, jenkins_client, options[:xpath], options[:at_xpath], options[:threads]
35
- result = options[:dry_run] ? job_updater.dry_run : job_updater.update_jobs!
25
+ desc 'replace NEW_NODE.xml', 'Replace XML nodes in jenkins jobs\' config.xml'
26
+ option :xpath, type: :string, default: '/', desc: 'XPath of node(s) to modify in the config.xml of the specified job(s)'
27
+ def replace(xml_file_path)
28
+ puts update_jobs(read_and_validate_xml_file(xml_file_path), __method__)
29
+ end
36
30
 
37
- if options[:dry_run]
38
- result.each do |key, value|
39
- puts "#{key}:"
40
- puts
41
- puts value
42
- end
43
- else
44
- result.each do |key, value|
45
- puts "#{key}: #{value}"
46
- end
47
- end
31
+ desc 'delete', 'Delete XML nodes in jenkins jobs\' config.xml'
32
+ option :xpath, type: :string, default: '/', desc: 'XPath of node(s) to modify in the config.xml of the specified job(s)'
33
+ def delete
34
+ puts update_jobs('', __method__)
48
35
  end
49
36
 
50
- desc 'backup', 'Save the config.xml of Jenkins jobs to disk'
51
- option :job_regex, required: false, type: :string, desc: 'Regular expression to select jobs by name', default: '.*'
52
- option :backup_dir, required: true, type: :string, desc: 'Path to the directory to save the config.xml file to, created if it does not exist'
53
- def backup
54
- jenkins_client = build_jenkins_client options
55
- job_names_to_backup = JobFinder.new(jenkins_client).find_jobs(options[:job_regex])
56
- JobBackupper.new(job_names_to_backup, jenkins_client, options[:backup_dir], options[:threads]).backup
37
+ desc 'backup BACKUP_DIR_PATH', 'Save the config.xml of Jenkins jobs to disk, BACKUP_DIR created if it does not exist'
38
+ def backup(backup_dir)
39
+ puts JobBackupper.new(job_names, jenkins_client, backup_dir, options[:threads]).backup(options[:dry_run])
57
40
  end
58
41
 
59
- desc 'restore', 'Restore config.xml files to Jenkins jobs from backups'
60
- option :backup_dir, required: true, type: :string, desc: 'Path to the directory where config.xml files were backed up'
61
- option :dry_run, type: :boolean, desc: 'Write XML to STDOUT instead of to Jenkins', default: true
62
- def restore
63
- jenkins_client = build_jenkins_client options
64
- job_restorer = JobRestorer.new jenkins_client, options[:backup_dir], options[:threads]
42
+ desc 'restore BACKUP_DIR_PATH', 'Restore config.xml files to Jenkins jobs from backups'
43
+ def restore(backup_dir)
44
+ job_restorer = JobRestorer.new(jenkins_client, backup_dir, options[:threads], job_rows, options[:job_regex])
65
45
  result = options[:dry_run] ? job_restorer.dry_run : job_restorer.restore!
66
46
 
67
- if options[:dry_run]
68
- result.each do |key, value|
69
- puts "#{key}:"
70
- puts
71
- puts value
72
- end
73
- else
74
- result.each do |key, value|
75
- puts "#{key}: #{value}"
76
- end
77
- end
47
+ puts result
78
48
  end
79
49
 
80
50
  private
81
51
 
82
- def build_jenkins_client options
83
- JenkinsClientBuilder.new(
52
+ def read_and_validate_xml_file(xml_file_path)
53
+ raw_xml_string = File.read(xml_file_path)
54
+ xml_parse_error = LeeroyJenkins.invalid_xml_document?(raw_xml_string)
55
+ die("#{xml_file_path} does not contain well-formed XML: #{xml_parse_error}") if xml_parse_error
56
+ raw_xml_string
57
+ end
58
+
59
+ def update_jobs(raw_xml_string, command_name)
60
+ job_updater = JobUpdater.new(job_names, raw_xml_string, jenkins_client, options[:xpath], command_name, options[:threads])
61
+ job_updater.update_jobs(options[:dry_run])
62
+ end
63
+
64
+ def jenkins_client
65
+ @jenkins_client ||= JenkinsClientBuilder.new(
84
66
  server_url: options[:server_url],
85
67
  username: options[:username],
86
68
  password: options[:password],
87
- log_level: options[:log_level],
88
- log_location: options[:log_location]
69
+ log_level: options[:jenkins_log_level],
70
+ log_location: options[:jenkins_log_location]
89
71
  ).build
90
72
  end
91
73
 
74
+ def job_names
75
+ JobFinder.new(jenkins_client).find_jobs(options[:job_regex], job_rows)
76
+ end
77
+
78
+ def job_rows
79
+ options[:jobs] ? File.read(options[:jobs]).split("\n") : []
80
+ end
81
+
82
+ def die(error_message)
83
+ error error_message
84
+ exit 1
85
+ end
92
86
  end
93
87
  end
@@ -1,4 +1,5 @@
1
1
  module LeeroyJenkins
2
+ # TODO: this isn't what a builder is
2
3
  class JenkinsClientBuilder
3
4
  attr_reader :server_url, :username, :password, :log_level, :log_location
4
5
 
@@ -9,32 +9,35 @@ module LeeroyJenkins
9
9
  @threads = threads
10
10
  end
11
11
 
12
- def get_job_configs
13
- pairs = map_job_configs do |job_name, job_config|
14
- [job_name, job_config]
12
+ def backup(dry = true)
13
+ Result.new(dry ? dry_run : backup!)
14
+ end
15
+
16
+ private
17
+
18
+ def backup!
19
+ FileUtils.mkdir_p(backup_dir) unless Dir.exist?(backup_dir)
20
+
21
+ pairs = Parallel.map(job_names_to_backup, in_threads: threads) do |job_name|
22
+ job_config = jenkins_client.job.get_config(job_name)
23
+ path = xml_file_path(job_name)
24
+ File.write(path, job_config)
25
+ [job_name, path]
15
26
  end
16
27
 
17
28
  Hash[pairs]
18
29
  end
19
30
 
20
- def backup
21
- unless Dir.exists? backup_dir
22
- FileUtils.mkdir_p backup_dir
31
+ def dry_run
32
+ pairs = job_names_to_backup.map do |job_name|
33
+ [job_name, xml_file_path(job_name)]
23
34
  end
24
35
 
25
- map_job_configs do |job_name, job_config|
26
- File.write "#{backup_dir}/#{job_name}.xml", job_config
27
- end
36
+ Hash[pairs]
28
37
  end
29
38
 
30
- private
31
-
32
- def map_job_configs &block
33
- Parallel.map(job_names_to_backup, in_threads: threads) do |job_name|
34
- job_config = jenkins_client.job.get_config job_name
35
- yield job_name, job_config
36
- end
39
+ def xml_file_path(job_name)
40
+ "#{backup_dir}/#{job_name}.xml"
37
41
  end
38
-
39
42
  end
40
43
  end
@@ -6,10 +6,10 @@ module LeeroyJenkins
6
6
  @jenkins_client = jenkins_client
7
7
  end
8
8
 
9
- def find_jobs(regex, job_names = nil)
9
+ def find_jobs(regex, job_names = [])
10
10
  jobs_matching_regex = jenkins_client.job.list(regex)
11
11
 
12
- if job_names
12
+ if job_names.any?
13
13
  jobs_matching_regex.select do |job|
14
14
  job_names.include? job
15
15
  end
@@ -1,39 +1,56 @@
1
1
  module LeeroyJenkins
2
2
  class JobRestorer
3
- attr_reader :backup_dir, :jenkins_client, :threads
3
+ attr_reader :backup_dir, :jenkins_client, :threads, :job_names, :job_regex
4
4
 
5
- def initialize(jenkins_client, backup_dir, threads)
5
+ def initialize(jenkins_client, backup_dir, threads, job_names, job_regex)
6
6
  @jenkins_client = jenkins_client
7
7
  @backup_dir = backup_dir
8
8
  @threads = threads
9
+ @job_names = job_names
10
+ @job_regex = Regexp.new(job_regex)
9
11
  end
10
12
 
11
13
  def dry_run
12
14
  pairs = Parallel.map(config_xml_file_paths, in_threads: threads) do |xml_path|
13
- job_name = File.basename xml_path, '.*'
15
+ job_name = File.basename(xml_path, '.*')
14
16
  [job_name, File.read(xml_path)]
15
17
  end
16
18
 
17
- Hash[pairs]
19
+ Result.new(Hash[pairs])
18
20
  end
19
21
 
20
22
  def restore!
21
23
  pairs = Parallel.map(config_xml_file_paths, in_threads: threads) do |xml_path|
22
- job_name = File.basename xml_path, '.*'
23
- http_status_code = jenkins_client.job.create_or_update job_name, File.read(xml_path)
24
+ job_name = File.basename(xml_path, '.*')
25
+
26
+ http_status_code = jenkins_client.job.create_or_update(
27
+ job_name, File.read(xml_path)
28
+ )
29
+
24
30
  [job_name, http_status_code]
25
31
  end
26
32
 
27
- Hash[pairs]
33
+ Result.new(Hash[pairs])
28
34
  end
29
35
 
30
36
  private
31
37
 
32
38
  def config_xml_file_paths
33
- Dir.entries(backup_dir).
34
- select { |file_name| file_name.end_with? '.xml' }.
35
- map { |file_name| "#{backup_dir}/#{file_name}" }
39
+ Dir.entries(backup_dir)
40
+ .select { |file_name| file_name.end_with? '.xml' }
41
+ .select { |file_name| restore_job?(file_name) }
42
+ .map { |file_name| "#{backup_dir}/#{file_name}" }
36
43
  end
37
44
 
45
+ def restore_job?(file_name)
46
+ # http://rubular.com/r/UxTupLRyg4
47
+ job_name = file_name.match(/^(?<job_name>[^.]+)\.xml$/)['job_name']
48
+
49
+ if job_names.any?
50
+ job_names.include?(job_name) && job_name =~ job_regex
51
+ else
52
+ job_name =~ job_regex
53
+ end
54
+ end
38
55
  end
39
56
  end
@@ -1,6 +1,11 @@
1
1
  module LeeroyJenkins
2
2
  class JobUpdater
3
- attr_reader :job_names_to_update, :new_xml, :jenkins_client, :xpath, :at_xpath, :threads
3
+ attr_reader :job_names_to_update,
4
+ :new_xml,
5
+ :jenkins_client,
6
+ :xpath,
7
+ :at_xpath,
8
+ :threads
4
9
 
5
10
  def initialize(job_names_to_update, new_xml, jenkins_client, xpath, at_xpath, threads)
6
11
  @job_names_to_update = job_names_to_update
@@ -11,9 +16,15 @@ module LeeroyJenkins
11
16
  @threads = threads
12
17
  end
13
18
 
19
+ def update_jobs(dry = true)
20
+ Result.new(dry ? dry_run : update_jobs!)
21
+ end
22
+
23
+ private
24
+
14
25
  def update_jobs!
15
26
  pairs = Parallel.map(job_names_to_update, in_threads: threads) do |job_name|
16
- http_status_code = jenkins_client.job.post_config job_name, construct_xml(job_name)
27
+ http_status_code = jenkins_client.job.post_config job_name, build_xml(job_name)
17
28
  [job_name, http_status_code]
18
29
  end
19
30
 
@@ -22,28 +33,26 @@ module LeeroyJenkins
22
33
 
23
34
  def dry_run
24
35
  pairs = Parallel.map(job_names_to_update, in_threads: threads) do |job_name|
25
- [job_name, construct_xml(job_name)]
36
+ [job_name, build_xml(job_name)]
26
37
  end
27
38
 
28
39
  Hash[pairs]
29
40
  end
30
41
 
31
- private
32
-
33
- def construct_xml job_name
42
+ def build_xml(job_name)
34
43
  element_to_insert = Nokogiri.XML(new_xml).root
35
- document_to_modify = Nokogiri.XML current_xml(job_name), &:noblanks
44
+ document_to_modify = Nokogiri.XML(current_xml(job_name), &:noblanks)
36
45
  elements_to_modify = document_to_modify.xpath(xpath).map do |node|
37
46
  node.document? ? node.root : node
38
47
  end
39
48
 
40
49
  elements_to_modify.each do |node|
41
50
  case at_xpath
42
- when 'replace'
51
+ when :replace
43
52
  node.replace element_to_insert
44
- when 'append'
53
+ when :append
45
54
  node << element_to_insert
46
- when 'delete'
55
+ when :delete
47
56
  node.remove
48
57
  end
49
58
  end
@@ -51,9 +60,8 @@ module LeeroyJenkins
51
60
  document_to_modify.canonicalize
52
61
  end
53
62
 
54
- def current_xml job_name
55
- jenkins_client.job.get_config job_name
63
+ def current_xml(job_name)
64
+ jenkins_client.job.get_config(job_name)
56
65
  end
57
-
58
66
  end
59
67
  end
@@ -0,0 +1,19 @@
1
+ module LeeroyJenkins
2
+ class Result
3
+ def initialize(result_hashes)
4
+ @result_hashes = result_hashes
5
+ end
6
+
7
+ def to_s
8
+ JSON.pretty_generate(result_hashes)
9
+ end
10
+
11
+ def ==(other)
12
+ other.class == self.class && result_hashes == other.result_hashes
13
+ end
14
+
15
+ protected
16
+
17
+ attr_reader :result_hashes
18
+ end
19
+ end
@@ -1,3 +1,3 @@
1
1
  module LeeroyJenkins
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leeroy_jenkins
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Rabovsky
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-02-12 00:00:00.000000000 Z
11
+ date: 2016-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jenkins_api_client
@@ -25,21 +25,21 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.4'
27
27
  - !ruby/object:Gem::Dependency
28
- name: thor
28
+ name: nokogiri
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.19.1
33
+ version: '1.6'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.19.1
40
+ version: '1.6'
41
41
  - !ruby/object:Gem::Dependency
42
- name: nokogiri
42
+ name: parallel
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
@@ -53,145 +53,145 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.6'
55
55
  - !ruby/object:Gem::Dependency
56
- name: parallel
56
+ name: thor
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.6'
61
+ version: 0.19.1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '1.6'
68
+ version: 0.19.1
69
69
  - !ruby/object:Gem::Dependency
70
- name: bundler
70
+ name: aruba
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.10'
75
+ version: 0.14.1
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '1.10'
82
+ version: 0.14.1
83
83
  - !ruby/object:Gem::Dependency
84
- name: rake
84
+ name: bundler
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '10.0'
89
+ version: '1.10'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '10.0'
96
+ version: '1.10'
97
97
  - !ruby/object:Gem::Dependency
98
- name: rspec
98
+ name: pry
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '3.3'
103
+ version: 0.10.1
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '3.3'
110
+ version: 0.10.1
111
111
  - !ruby/object:Gem::Dependency
112
- name: aruba
112
+ name: pry-doc
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 0.9.0
117
+ version: 0.8.0
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: 0.9.0
124
+ version: 0.8.0
125
125
  - !ruby/object:Gem::Dependency
126
- name: cucumber
126
+ name: pry-stack_explorer
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '2.1'
131
+ version: 0.4.9
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '2.1'
138
+ version: 0.4.9
139
139
  - !ruby/object:Gem::Dependency
140
- name: pry
140
+ name: rake
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 0.10.1
145
+ version: '10.0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 0.10.1
152
+ version: '10.0'
153
153
  - !ruby/object:Gem::Dependency
154
- name: pry-doc
154
+ name: rspec
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: 0.8.0
159
+ version: '3.3'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: 0.8.0
166
+ version: '3.3'
167
167
  - !ruby/object:Gem::Dependency
168
- name: pry-stack_explorer
168
+ name: rubocop
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
171
  - - "~>"
172
172
  - !ruby/object:Gem::Version
173
- version: 0.4.9
173
+ version: 0.42.0
174
174
  type: :development
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
- version: 0.4.9
180
+ version: 0.42.0
181
181
  - !ruby/object:Gem::Dependency
182
- name: rubocop
182
+ name: simplecov
183
183
  requirement: !ruby/object:Gem::Requirement
184
184
  requirements:
185
185
  - - "~>"
186
186
  - !ruby/object:Gem::Version
187
- version: 0.37.2
187
+ version: 0.12.0
188
188
  type: :development
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
- version: 0.37.2
194
+ version: 0.12.0
195
195
  description:
196
196
  email:
197
197
  - jeffr@jellyvision.com
@@ -202,7 +202,8 @@ extra_rdoc_files: []
202
202
  files:
203
203
  - ".gitignore"
204
204
  - ".rspec"
205
- - ".travis.yml"
205
+ - ".rubocop.yml"
206
+ - ".rubocop_todo.yml"
206
207
  - Gemfile
207
208
  - LICENSE.txt
208
209
  - README.md
@@ -218,6 +219,7 @@ files:
218
219
  - lib/leeroy_jenkins/job_finder.rb
219
220
  - lib/leeroy_jenkins/job_restorer.rb
220
221
  - lib/leeroy_jenkins/job_updater.rb
222
+ - lib/leeroy_jenkins/result.rb
221
223
  - lib/leeroy_jenkins/version.rb
222
224
  homepage: https://github.com/Jellyvision/leeroy_jenkins
223
225
  licenses:
@@ -1,4 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.2.2
4
- before_install: gem install bundler -v 1.10.6