leeroy_jenkins 0.3.0 → 0.4.0

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.
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