jenkins_pipeline_builder 0.4.2 → 0.5.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +65 -0
  3. data/LICENSE +1 -1
  4. data/README.md +64 -2
  5. data/Rakefile +13 -11
  6. data/bin/generate +2 -4
  7. data/jenkins_pipeline_builder.gemspec +14 -11
  8. data/lib/jenkins_pipeline_builder.rb +2 -1
  9. data/lib/jenkins_pipeline_builder/builders.rb +89 -33
  10. data/lib/jenkins_pipeline_builder/cli/base.rb +21 -29
  11. data/lib/jenkins_pipeline_builder/cli/helper.rb +12 -15
  12. data/lib/jenkins_pipeline_builder/cli/pipeline.rb +6 -1
  13. data/lib/jenkins_pipeline_builder/cli/view.rb +2 -2
  14. data/lib/jenkins_pipeline_builder/compiler.rb +58 -56
  15. data/lib/jenkins_pipeline_builder/generator.rb +362 -172
  16. data/lib/jenkins_pipeline_builder/job_builder.rb +48 -45
  17. data/lib/jenkins_pipeline_builder/module_registry.rb +4 -6
  18. data/lib/jenkins_pipeline_builder/publishers.rb +53 -38
  19. data/lib/jenkins_pipeline_builder/pull_request.rb +156 -0
  20. data/lib/jenkins_pipeline_builder/triggers.rb +24 -25
  21. data/lib/jenkins_pipeline_builder/utils.rb +13 -7
  22. data/lib/jenkins_pipeline_builder/version.rb +2 -2
  23. data/lib/jenkins_pipeline_builder/view.rb +120 -98
  24. data/lib/jenkins_pipeline_builder/wrappers.rb +44 -44
  25. data/lib/jenkins_pipeline_builder/xml_helper.rb +4 -4
  26. data/spec/func_tests/spec_helper.rb +2 -2
  27. data/spec/func_tests/view_spec.rb +6 -6
  28. data/spec/unit_tests/compiler_spec.rb +7 -7
  29. data/spec/unit_tests/fixtures/files/Job-Gem-Build.xml +2 -2
  30. data/spec/unit_tests/fixtures/files/Job-Gem-Build.yaml +1 -0
  31. data/spec/unit_tests/fixtures/files/concurrent_build.xml +17 -0
  32. data/spec/unit_tests/fixtures/files/concurrent_build.yaml +4 -0
  33. data/spec/unit_tests/fixtures/files/downstream_blocking.xml +19 -0
  34. data/spec/unit_tests/fixtures/files/downstream_blocking.yaml +15 -0
  35. data/spec/unit_tests/fixtures/files/groovy_postbuild.xml +29 -0
  36. data/spec/unit_tests/fixtures/files/groovy_postbuild.yaml +9 -0
  37. data/spec/unit_tests/generator_spec.rb +30 -25
  38. data/spec/unit_tests/module_registry_spec.rb +9 -9
  39. data/spec/unit_tests/resolve_dependencies_spec.rb +108 -89
  40. data/spec/unit_tests/spec_helper.rb +1 -1
  41. metadata +62 -4
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2014 Igor Moochnick
2
+ # Copyright (c) 2014 Constant Contact
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -23,7 +23,7 @@
23
23
  module JenkinsPipelineBuilder
24
24
  class JobBuilder
25
25
  def self.change_description(description, n_xml)
26
- desc = n_xml.xpath("//description").first
26
+ desc = n_xml.xpath('//description').first
27
27
  desc.content = "#{description}"
28
28
  end
29
29
 
@@ -34,118 +34,121 @@ module JenkinsPipelineBuilder
34
34
  XmlHelper.update_node_text(n_xml, '//scm/excludedUsers', params[:excluded_users]) if params[:excluded_users]
35
35
  XmlHelper.update_node_text(n_xml, '//scm/userRemoteConfigs/hudson.plugins.git.UserRemoteConfig/name', params[:remote_name]) if params[:remote_name]
36
36
  XmlHelper.update_node_text(n_xml, '//scm/skipTag', params[:skip_tag]) if params[:skip_tag]
37
+ XmlHelper.update_node_text(n_xml, '//scm/userRemoteConfigs/hudson.plugins.git.UserRemoteConfig/refspec', params[:refspec]) if params[:refspec]
37
38
  end
38
39
 
39
40
  def self.hipchat_notifier(params, n_xml)
40
- raise "No HipChat room specified" unless params[:room]
41
+ fail 'No HipChat room specified' unless params[:room]
41
42
 
42
- properties = n_xml.xpath("//properties").first
43
+ properties = n_xml.xpath('//properties').first
43
44
  Nokogiri::XML::Builder.with(properties) do |xml|
44
- xml.send('jenkins.plugins.hipchat.HipChatNotifier_-HipChatJobProperty') {
45
+ xml.send('jenkins.plugins.hipchat.HipChatNotifier_-HipChatJobProperty') do
45
46
  xml.room params[:room]
46
47
  xml.startNotification params[:'start-notify'] || false
47
- }
48
+ end
48
49
  end
49
50
  end
50
51
 
51
52
  def self.use_specific_priority(params, n_xml)
52
53
  n_builders = n_xml.xpath('//properties').first
53
54
  Nokogiri::XML::Builder.with(n_builders) do |xml|
54
- xml.send('jenkins.advancedqueue.AdvancedQueueSorterJobProperty', 'plugin' => 'PrioritySorter') {
55
+ xml.send('jenkins.advancedqueue.AdvancedQueueSorterJobProperty', 'plugin' => 'PrioritySorter') do
55
56
  xml.useJobPriority params[:use_priority]
56
57
  xml.priority params[:job_priority] || -1
57
- }
58
+ end
58
59
  end
59
60
  end
60
61
 
61
62
  def self.build_parameters(params, n_xml)
62
63
  n_builders = n_xml.xpath('//properties').first
63
64
  Nokogiri::XML::Builder.with(n_builders) do |xml|
64
- xml.send('hudson.model.ParametersDefinitionProperty') {
65
- xml.parameterDefinitions {
65
+ xml.send('hudson.model.ParametersDefinitionProperty') do
66
+ xml.parameterDefinitions do
66
67
  param_proc = lambda do |xml, params, type|
67
- xml.send(type) {
68
+ xml.send(type) do
68
69
  xml.name params[:name]
69
70
  xml.description params[:description]
70
71
  xml.defaultValue params[:default]
71
72
  if params[:type] == 'choice'
72
- puts 'choice'
73
- puts params
74
- xml.choices('class' => 'java.util.Arrays$ArrayList') {
75
- xml.a('class' => 'string-array') {
73
+ xml.choices('class' => 'java.util.Arrays$ArrayList') do
74
+ xml.a('class' => 'string-array') do
76
75
  params[:values].each do |value|
77
76
  xml.string value
78
77
  end
79
- }
80
- }
78
+ end
79
+ end
81
80
  end
82
- }
81
+ end
83
82
  end
84
83
  params.each do |param|
85
84
  case param[:type]
86
- when 'string'
87
- paramType = 'hudson.model.StringParameterDefinition'
88
- when 'bool'
89
- paramType = 'hudson.model.BooleanParameterDefinition'
90
- when 'text'
91
- paramType = 'hudson.model.TextParameterDefinition'
92
- when 'password'
93
- paramType = 'hudson.model.PasswordParameterDefinition'
94
- when 'choice'
95
- paramType = 'hudson.model.ChoiceParameterDefinition'
96
- else
97
- paramType = 'hudson.model.StringParameterDefinition'
98
- end
85
+ when 'string'
86
+ paramType = 'hudson.model.StringParameterDefinition'
87
+ when 'bool'
88
+ paramType = 'hudson.model.BooleanParameterDefinition'
89
+ when 'text'
90
+ paramType = 'hudson.model.TextParameterDefinition'
91
+ when 'password'
92
+ paramType = 'hudson.model.PasswordParameterDefinition'
93
+ when 'choice'
94
+ paramType = 'hudson.model.ChoiceParameterDefinition'
95
+ else
96
+ paramType = 'hudson.model.StringParameterDefinition'
97
+ end
99
98
 
100
99
  param_proc.call xml, param, paramType
101
100
  end
102
- }
103
- }
101
+ end
102
+ end
104
103
  end
105
104
  end
106
105
 
107
106
  def self.discard_old_param(params, n_xml)
108
107
  properties = n_xml.child
109
108
  Nokogiri::XML::Builder.with(properties) do |xml|
110
- xml.send('logRotator', 'class' => 'hudson.tasks.LogRotator') {
109
+ xml.send('logRotator', 'class' => 'hudson.tasks.LogRotator') do
111
110
  xml.daysToKeep params[:days] if params[:days]
112
111
  xml.numToKeep params[:number] || -1
113
112
  xml.artifactDaysToKeep params[:artifact_days] || -1
114
113
  xml.artifactNumToKeep params[:artifact_number] || -1
115
- }
114
+ end
116
115
  end
117
116
  end
118
117
 
119
118
  def self.throttle_job(params, n_xml)
120
119
  properties = n_xml.xpath('//properties').first
121
- cat_set = params[:option]=="category"
120
+ cat_set = params[:option] == 'category'
122
121
  Nokogiri::XML::Builder.with(properties) do |xml|
123
- xml.send('hudson.plugins.throttleconcurrents.ThrottleJobProperty', 'plugin' => 'throttle-concurrents') {
122
+ xml.send('hudson.plugins.throttleconcurrents.ThrottleJobProperty', 'plugin' => 'throttle-concurrents') do
124
123
  xml.maxConcurrentPerNode params[:max_per_node] || 0
125
124
  xml.maxConcurrentTotal params[:max_total] || 0
126
125
  xml.throttleEnabled true
127
- xml.throttleOption params[:option] || "alone"
128
- xml.categories {
126
+ xml.throttleOption params[:option] || 'alone'
127
+ xml.categories do
129
128
  xml.string params[:category] if cat_set
130
- }
131
- }
129
+ end
130
+ end
132
131
  end
133
132
  end
134
133
 
135
134
  def self.prepare_environment(params, n_xml)
136
135
  properties = n_xml.xpath('//properties').first
137
136
  Nokogiri::XML::Builder.with(properties) do |xml|
138
- xml.send('EnvInjectJobProperty') {
139
- xml.info{
137
+ xml.send('EnvInjectJobProperty') do
138
+ xml.info do
140
139
  xml.propertiesContent params[:properties_content] if params[:properties_content]
141
140
  xml.loadFilesFromMaster params[:load_from_master] if params[:load_from_master]
142
- }
141
+ end
143
142
  xml.on true
144
143
  xml.keepJenkinsSystemVariables params[:keep_environment] if params[:keep_environment]
145
144
  xml.keepBuildVariables params[:keep_build] if params[:keep_build]
146
- }
145
+ end
147
146
  end
148
147
  end
149
148
 
149
+ def self.concurrent_build(params, n_xml)
150
+ concurrentBuild = n_xml.xpath('//concurrentBuild').first
151
+ concurrentBuild.content = (params == true) ? 'true' : 'false'
152
+ end
150
153
  end
151
154
  end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2014 Igor Moochnick
2
+ # Copyright (c) 2014 Constant Contact
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -30,14 +30,12 @@ module JenkinsPipelineBuilder
30
30
 
31
31
  def get(path)
32
32
  parts = path.split('/')
33
- self.get_by_path_collection(parts, @registry)
33
+ get_by_path_collection(parts, @registry)
34
34
  end
35
35
 
36
36
  def get_by_path_collection(path, registry)
37
37
  item = registry[path.shift.to_sym]
38
- if path.count == 0
39
- return item
40
- end
38
+ return item if path.count == 0
41
39
 
42
40
  get_by_path_collection(path, item)
43
41
  end
@@ -67,7 +65,7 @@ module JenkinsPipelineBuilder
67
65
  sub_registry = registry_item[:registry]
68
66
  method = registry_item[:method]
69
67
  method.call(sub_registry, value, n_xml)
70
- elsif registry_item.kind_of?(Method)
68
+ elsif registry_item.kind_of?(Method) || registry_item.kind_of?(Proc)
71
69
  registry_item.call(value, n_xml) unless registry_item.nil?
72
70
  end
73
71
  end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2014 Igor Moochnick
2
+ # Copyright (c) 2014 Constant Contact
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -23,106 +23,121 @@
23
23
  module JenkinsPipelineBuilder
24
24
  class Publishers
25
25
  def self.description_setter(params, xml)
26
- xml.send('hudson.plugins.descriptionsetter.DescriptionSetterPublisher') {
26
+ xml.send('hudson.plugins.descriptionsetter.DescriptionSetterPublisher') do
27
27
  xml.regexp params[:regexp]
28
28
  xml.regexpForFailed params[:regexp]
29
29
  xml.description params[:description]
30
30
  xml.descriptionForFailed params[:description]
31
31
  xml.setForMatrix false
32
- }
32
+ end
33
33
  end
34
34
 
35
35
  def self.push_to_projects(params, xml)
36
- xml.send('hudson.plugins.parameterizedtrigger.BuildTrigger') {
37
- xml.configs {
38
- xml.send('hudson.plugins.parameterizedtrigger.BuildTriggerConfig') {
39
- xml.configs {
40
- params[:data] = [ { params: "" } ] unless params[:data]
36
+ xml.send('hudson.plugins.parameterizedtrigger.BuildTrigger') do
37
+ xml.configs do
38
+ xml.send('hudson.plugins.parameterizedtrigger.BuildTriggerConfig') do
39
+ xml.configs do
40
+ params[:data] = [{ params: '' }] unless params[:data]
41
41
  params[:data].each do |config|
42
42
  if config[:params]
43
- xml.send('hudson.plugins.parameterizedtrigger.PredefinedBuildParameters') {
43
+ xml.send('hudson.plugins.parameterizedtrigger.PredefinedBuildParameters') do
44
44
  xml.properties config[:params]
45
- }
45
+ end
46
46
  end
47
47
  if config[:file]
48
- xml.send('hudson.plugins.parameterizedtrigger.FileBuildParameters') {
48
+ xml.send('hudson.plugins.parameterizedtrigger.FileBuildParameters') do
49
49
  xml.propertiesFile config[:file]
50
50
  xml.failTriggerOnMissing false
51
- }
51
+ end
52
52
  end
53
53
  end
54
- }
54
+ end
55
55
  xml.projects params[:project]
56
56
  xml.condition params[:condition] || 'SUCCESS'
57
57
  xml.triggerWithNoParameters params[:trigger_with_no_parameters] || false
58
- }
59
- }
60
- }
58
+ end
59
+ end
60
+ end
61
61
  end
62
62
 
63
63
  def self.push_to_hipchat(params, xml)
64
64
  params = {} if params == true
65
- xml.send('jenkins.plugins.hipchat.HipChatNotifier') {
65
+ xml.send('jenkins.plugins.hipchat.HipChatNotifier') do
66
66
  xml.jenkinsUrl params[:jenkinsUrl] || ''
67
67
  xml.authToken params[:authToken] || ''
68
68
  xml.room params[:room] || ''
69
- }
69
+ end
70
70
  end
71
71
 
72
72
  def self.push_to_git(params, xml)
73
- xml.send('hudson.plugins.git.GitPublisher') {
73
+ xml.send('hudson.plugins.git.GitPublisher') do
74
74
  xml.configVersion params[:configVersion] || 2
75
75
  xml.pushMerge params[:'push-merge'] || false
76
76
  xml.pushOnlyIfSuccess params[:'push-only-if-success'] || false
77
- xml.branchesToPush {
78
- xml.send('hudson.plugins.git.GitPublisher_-BranchToPush') {
77
+ xml.branchesToPush do
78
+ xml.send('hudson.plugins.git.GitPublisher_-BranchToPush') do
79
79
  xml.targetRepoName params[:targetRepoName] || 'origin'
80
80
  xml.branchName params[:branchName] || 'master'
81
- }
82
- }
83
- }
81
+ end
82
+ end
83
+ end
84
84
  end
85
85
 
86
86
  def self.publish_junit(params, xml)
87
- xml.send('hudson.tasks.junit.JUnitResultArchiver') {
87
+ xml.send('hudson.tasks.junit.JUnitResultArchiver') do
88
88
  xml.testResults params[:test_results] || ''
89
89
  xml.keepLongStdio false
90
90
  xml.testDataPublishers
91
- }
91
+ end
92
92
  end
93
93
 
94
94
  def self.coverage_metric(name, params, xml)
95
- xml.send('hudson.plugins.rubyMetrics.rcov.model.MetricTarget') {
95
+ xml.send('hudson.plugins.rubyMetrics.rcov.model.MetricTarget') do
96
96
  xml.metric name
97
97
  xml.healthy params[:healthy]
98
98
  xml.unhealthy params[:unhealthy]
99
99
  xml.unstable params[:unstable]
100
- }
100
+ end
101
101
  end
102
102
 
103
103
  def self.publish_rcov(params, xml)
104
- xml.send('hudson.plugins.rubyMetrics.rcov.RcovPublisher') {
104
+ xml.send('hudson.plugins.rubyMetrics.rcov.RcovPublisher') do
105
105
  xml.reportDir params[:report_dir]
106
- xml.targets {
106
+ xml.targets do
107
107
  coverage_metric('TOTAL_COVERAGE', params[:total], xml)
108
108
  coverage_metric('CODE_COVERAGE', params[:code], xml)
109
- }
110
- }
109
+ end
110
+ end
111
111
  end
112
112
 
113
113
  def self.post_build_script(params, xml)
114
- xml.send('org.jenkinsci.plugins.postbuildscript.PostBuildScript') {
115
- xml.buildSteps {
114
+ xml.send('org.jenkinsci.plugins.postbuildscript.PostBuildScript') do
115
+ xml.buildSteps do
116
116
  if params[:shell_command]
117
- xml.send('hudson.tasks.Shell') {
117
+ xml.send('hudson.tasks.Shell') do
118
118
  xml.command params[:shell_command]
119
- }
119
+ end
120
120
  end
121
- }
121
+ end
122
122
  xml.scriptOnlyIfSuccess params[:on_success]
123
123
  xml.scriptOnlyIfFailure params[:on_failure]
124
124
  xml.executeOn params[:execute_on] || 'BOTH'
125
- }
125
+ end
126
+ end
127
+
128
+ def self.groovy_postbuild(params, xml)
129
+ xml.send('org.jvnet.hudson.plugins.groovypostbuild.GroovyPostbuildRecorder', 'plugin' => 'groovy-postbuild') do
130
+ xml.groovyScript params[:groovy_script]
131
+ xml.behavior params[:behavior] || '0'
132
+ xml.runFormMatrixParent 'false'
133
+ if params[:additional_classpaths]
134
+ params[:additional_classpaths].each do |path|
135
+ xml.send('org.jvnet.hudson.plugins.groovypostbuild.GroovyScriptPath') do
136
+ xml.path path[:path] || '/'
137
+ end
138
+ end
139
+ end
140
+ end
126
141
  end
127
142
  end
128
143
  end
@@ -0,0 +1,156 @@
1
+ #
2
+ # Copyright (c) 2014 Constant Contact
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+
23
+ module JenkinsPipelineBuilder
24
+ class PullRequestGenerator
25
+ # Initializes a new View object.
26
+ #
27
+ # @param generator [Generator] the client object
28
+ #
29
+ # @return [View] the view object
30
+ #
31
+ def initialize(generator)
32
+ @generator = generator
33
+ @client = generator.client
34
+ @logger = @client.logger
35
+ end
36
+
37
+ # Check for Github Pull Requests
38
+ #
39
+ # args[:git_url] URL to the github main page ex. https://www.github.com/
40
+ # args[:git_repo] Name of repo only, not url ex. jenkins_pipeline_builder
41
+ # args[:git_org] The Orig user ex. igorshare
42
+ # @return = array of pull request numbers
43
+ def check_for_pull(args)
44
+ fail 'Please specify all arguments' unless args[:git_url] && args[:git_org] && args[:git_repo]
45
+ # Build the Git URL
46
+ git_url = "#{args[:git_url]}api/v3/repos/#{args[:git_org]}/#{args[:git_repo]}/pulls"
47
+
48
+ # Download the JSON Data from the API
49
+ resp = Net::HTTP.get_response(URI.parse(git_url))
50
+ pulls = JSON.parse(resp.body)
51
+ pulls.map { |p| p['number'] }
52
+ end
53
+
54
+ # Purge old builds
55
+ def purge_old(pull_requests, project)
56
+ reqs = pull_requests.clone.map { |req| "#{project[:name]}-PR#{req}" }
57
+ @logger.info "Current pull requests: #{reqs}"
58
+ # Read File
59
+ old_requests = File.new('pull_requests.csv', 'a+').read.split(',')
60
+
61
+ # Pop off current pull requests
62
+ old_requests.delete_if { |req| reqs.include?("#{req}") }
63
+
64
+ # Delete the old requests from jenkins
65
+ @logger.info "Purging old requests: #{old_requests}"
66
+ old_requests.each do |req|
67
+ jobs = @client.job.list "#{req}.*"
68
+ jobs.each do |job|
69
+ @client.job.delete job
70
+ end
71
+ end
72
+ # Write File
73
+ File.open('pull_requests.csv', 'w+') { |file| file.write reqs.join(',') }
74
+ end
75
+
76
+ def run(project, job_collection, generator_job)
77
+ @logger.info 'Begin running Pull Request Generator'
78
+ pull_requests = check_for_pull generator_job[:value]
79
+ purge_old(pull_requests, project)
80
+ main_collection = job_collection
81
+ @logger.info pull_requests
82
+ pull_requests.each do |number|
83
+ # Manipulate the YAML
84
+ req = JenkinsPipelineBuilder::PullRequest.new(project, number, main_collection, generator_job)
85
+ @generator.job_collection.merge req.jobs
86
+ project = req.project
87
+
88
+ # Overwrite the jobs from the generator to the project
89
+ project[:value][:jobs] = generator_job[:value][:jobs]
90
+
91
+ # Build the jobs
92
+ success, compiled_project = @generator.resolve_project(project)
93
+ compiled_project[:value][:jobs].each do |i|
94
+ job = i[:result]
95
+ success, payload = @generator.compile_job_to_xml(job)
96
+ @generator.create_or_update(job, payload) if success
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ class PullRequest
103
+ attr_reader :project # The root project YAML as a hash
104
+ attr_reader :number # The pull request number
105
+ attr_reader :jobs # The jobs in the pull request as an array of hashes
106
+ attr_reader :generator # The generator job YAML as a hash
107
+
108
+ # Initialize
109
+ def initialize(project, number, jobs, generator)
110
+ @project = project.clone
111
+ @number = number
112
+ @jobs = jobs.clone
113
+ @generator = generator.clone
114
+
115
+ run!
116
+ end
117
+
118
+ private
119
+
120
+ # Apply all changes
121
+ def run!
122
+ update_jobs!
123
+ change_git!
124
+ change_name!
125
+ end
126
+
127
+ # Change the git branch for each job
128
+ def change_git!
129
+ @jobs.each_value do |job|
130
+ job[:value][:scm_branch] = "origin/pr/#{@number}/head"
131
+ job[:value][:scm_params] = {} unless job[:value][:scm_params]
132
+ job[:value][:scm_params][:refspec] = 'refs/pull/*:refs/remotes/origin/pr/*'
133
+ end
134
+ end
135
+
136
+ # Change the name of the pull request project
137
+ def change_name!
138
+ @project[:name] = "#{@project[:name]}-PR#{@number}" if @project[:name]
139
+ @project[:value][:name] = "#{@project[:value][:name]}-PR#{@number}" if @project[:value][:name]
140
+ end
141
+
142
+ # Apply any specified changes to each job
143
+ def update_jobs!
144
+ @jobs.each_value do |job|
145
+ name = job[:name]
146
+ changes = nil
147
+ # Search the generator for changes
148
+ @generator[:value][:jobs].each do |gen|
149
+ changes = gen[name.to_sym] if gen.is_a?(Hash) && gen.keys[0] == name.to_sym
150
+ end
151
+ # Apply changes
152
+ Utils.hash_merge!(job[:value], changes) unless changes.nil?
153
+ end
154
+ end
155
+ end
156
+ end