jenkins_pipeline_builder 0.12.4 → 0.13.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 +8 -8
- data/lib/jenkins_pipeline_builder.rb +0 -1
- data/lib/jenkins_pipeline_builder/generator.rb +28 -37
- data/lib/jenkins_pipeline_builder/pull_request_generator.rb +32 -127
- data/lib/jenkins_pipeline_builder/version.rb +1 -1
- data/spec/lib/jenkins_pipeline_builder/fixtures/generator_tests/pullrequest_pipeline/PullRequest-40-PullRequestGenerator.yaml +0 -6
- data/spec/lib/jenkins_pipeline_builder/fixtures/generator_tests/pullrequest_pipeline/project.yaml +5 -4
- data/spec/lib/jenkins_pipeline_builder/generator_spec.rb +20 -19
- data/spec/lib/jenkins_pipeline_builder/pull_request_generator_spec.rb +117 -84
- metadata +2 -5
- data/lib/jenkins_pipeline_builder/pull_request.rb +0 -92
- data/spec/lib/jenkins_pipeline_builder/pull_request_spec.rb +0 -161
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZGMzZGY0Yzk1MzZiMGYzNzc1ZGZlODIwNmQ3NDRjMWZkYWEzZWVkMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
OWNkMTcwZDE1NTgxYTU1MWU0MTlhZGNmOTZjNGEwYjE5NTIwNTIzMA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NmE2YTA2MGI3NmU1MjkxMzI0YjkzNjY1NmE2ZGYwOTMwMzY2NDU5Yzg5ZWM3
|
10
|
+
YjJmMjcyY2NhNjkwOWJhZTY0ZTgyODcxNjY0NWExZGU3MmY3ZmU0MDFhMTY3
|
11
|
+
NDUyMjA5MTBlOTg4YTc5YzA2NjM5NjFiNGZhY2ViODgxMzBlODQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NmJiYjMyOGU5MDgyN2Y3MjI4MDEyZDVhNGZkOGEzZjE1YjNlMTE2YzRmNDZl
|
14
|
+
N2M5ZWIyYmFhNzZlZDg3ZjFmOTRkODRmOTFkYmVjYTNmYWEzY2ViMTYxNDVk
|
15
|
+
YzU2ZWJjYzM5N2VmMWY1NDAzYTUyY2ExMTg1ZTQ5OGNmMDI5Mzk=
|
@@ -28,7 +28,6 @@ require 'jenkins_pipeline_builder/utils'
|
|
28
28
|
require 'jenkins_pipeline_builder/compiler'
|
29
29
|
require 'jenkins_pipeline_builder/module_registry'
|
30
30
|
require 'jenkins_pipeline_builder/pull_request_generator'
|
31
|
-
require 'jenkins_pipeline_builder/pull_request'
|
32
31
|
require 'jenkins_pipeline_builder/view'
|
33
32
|
require 'jenkins_pipeline_builder/job_collection'
|
34
33
|
require 'jenkins_pipeline_builder/job'
|
@@ -1,6 +1,5 @@
|
|
1
1
|
#
|
2
2
|
# Copyright (c) 2014 Constant Contact
|
3
|
-
#
|
4
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
4
|
# of this software and associated documentation files (the "Software"), to deal
|
6
5
|
# in the Software without restriction, including without limitation the rights
|
@@ -48,29 +47,22 @@ module JenkinsPipelineBuilder
|
|
48
47
|
|
49
48
|
def bootstrap(path, project_name = nil)
|
50
49
|
logger.info "Bootstrapping pipeline from path #{path}"
|
51
|
-
|
52
|
-
job_collection.
|
53
|
-
|
54
|
-
if job_collection.projects.any?
|
55
|
-
errors = publish_project(project_name)
|
56
|
-
else
|
57
|
-
errors = publish_jobs(job_collection.standalone_jobs)
|
58
|
-
end
|
59
|
-
print_compile_errors errors
|
60
|
-
errors
|
50
|
+
load_job_collection path
|
51
|
+
publish(project_name || job_collection.projects.first[:name])
|
61
52
|
end
|
62
53
|
|
63
54
|
def pull_request(path, project_name)
|
64
55
|
logger.info "Pull Request Generator Running from path #{path}"
|
65
|
-
|
66
|
-
job_collection.
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
56
|
+
load_job_collection path
|
57
|
+
defaults = job_collection.defaults[:value]
|
58
|
+
pr_generator = PullRequestGenerator.new defaults
|
59
|
+
pr_generator.delete_closed_prs
|
60
|
+
errors = []
|
61
|
+
pr_generator.open_prs.each do |pr|
|
62
|
+
pr_generator.convert! job_collection, pr
|
63
|
+
error = publish(project_name)
|
64
|
+
errors << error unless error.empty?
|
72
65
|
end
|
73
|
-
print_compile_errors errors
|
74
66
|
errors.empty?
|
75
67
|
end
|
76
68
|
|
@@ -112,6 +104,21 @@ module JenkinsPipelineBuilder
|
|
112
104
|
|
113
105
|
private
|
114
106
|
|
107
|
+
def load_job_collection(path)
|
108
|
+
job_collection.load_from_path(path)
|
109
|
+
job_collection.remote_dependencies.cleanup
|
110
|
+
end
|
111
|
+
|
112
|
+
def publish(project_name)
|
113
|
+
if job_collection.projects.any?
|
114
|
+
errors = publish_project(project_name)
|
115
|
+
else
|
116
|
+
errors = publish_jobs(job_collection.standalone_jobs)
|
117
|
+
end
|
118
|
+
print_compile_errors errors
|
119
|
+
errors
|
120
|
+
end
|
121
|
+
|
115
122
|
def process_project(project)
|
116
123
|
project_body = project[:value]
|
117
124
|
jobs = prepare_jobs(project_body[:jobs]) if project_body[:jobs]
|
@@ -139,15 +146,6 @@ module JenkinsPipelineBuilder
|
|
139
146
|
end
|
140
147
|
end
|
141
148
|
|
142
|
-
def process_pull_request_project(project)
|
143
|
-
logger.info "Using Project #{project}"
|
144
|
-
|
145
|
-
pull_request_generator = JenkinsPipelineBuilder::PullRequestGenerator.new project, self
|
146
|
-
|
147
|
-
return {} if pull_request_generator.valid?
|
148
|
-
{ pull_request_generator.pull_generator[:name] => pull_request_generator.errors }
|
149
|
-
end
|
150
|
-
|
151
149
|
def prepare_jobs(jobs)
|
152
150
|
jobs.map! do |job|
|
153
151
|
job.is_a?(String) ? { job.to_sym => {} } : job
|
@@ -221,15 +219,8 @@ module JenkinsPipelineBuilder
|
|
221
219
|
end
|
222
220
|
|
223
221
|
def publish_project(project_name)
|
224
|
-
|
225
|
-
|
226
|
-
job_collection.projects.each do |project|
|
227
|
-
next if project[:name] != project_name && !project_name.nil?
|
228
|
-
found = true
|
229
|
-
errors = create_jobs_and_views(project)
|
230
|
-
end
|
231
|
-
fail "Project #{project_name} not found!" unless found
|
232
|
-
errors
|
222
|
+
project = job_collection.projects.find { |p| p[:name] == project_name }
|
223
|
+
create_jobs_and_views(project || fail("Project #{project_name} not found!"))
|
233
224
|
end
|
234
225
|
|
235
226
|
def publish_jobs(jobs, errors = {})
|
@@ -19,149 +19,54 @@
|
|
19
19
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
20
|
# THE SOFTWARE.
|
21
21
|
#
|
22
|
-
|
23
22
|
module JenkinsPipelineBuilder
|
24
23
|
class PullRequestGenerator
|
25
24
|
class NotFound < StandardError; end
|
25
|
+
attr_accessor :open_prs, :application_name
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
@project = project
|
31
|
-
@generator = generator
|
32
|
-
@purge = []
|
33
|
-
@create = []
|
34
|
-
@errors = {}
|
35
|
-
|
36
|
-
@pull_generator = find
|
37
|
-
payload = compile_generator
|
38
|
-
return unless payload
|
39
|
-
@jobs = filter_jobs
|
40
|
-
|
41
|
-
# old init
|
42
|
-
@pull_requests = check_for_pull payload
|
43
|
-
find_old_pull_requests
|
44
|
-
generate_pull_requests
|
45
|
-
|
46
|
-
collection.merge! @jobs
|
47
|
-
@errors.merge! create_jobs
|
48
|
-
|
49
|
-
purge_jobs
|
50
|
-
end
|
51
|
-
|
52
|
-
def valid?
|
53
|
-
errors.empty?
|
27
|
+
def initialize(defaults = {})
|
28
|
+
@application_name = defaults[:application_name]
|
29
|
+
@open_prs = active_prs defaults[:github_site], defaults[:git_org], defaults[:git_repo_name]
|
54
30
|
end
|
55
31
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
@pull_requests.each do |number|
|
60
|
-
req = JenkinsPipelineBuilder::PullRequest.new(project, number, jobs, @pull_generator)
|
61
|
-
@jobs.merge! req.jobs
|
62
|
-
project_new = req.project
|
63
|
-
|
64
|
-
# Overwrite the jobs from the generator to the project
|
65
|
-
project_new[:value][:jobs] = req.jobs.keys
|
66
|
-
@create << project_new
|
67
|
-
end
|
32
|
+
def convert!(job_collection, pr)
|
33
|
+
job_collection.defaults[:value][:application_name] = "#{application_name}-PR#{pr}"
|
34
|
+
job_collection.jobs.each { |j| override j[:value], pr }
|
68
35
|
end
|
69
36
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
37
|
+
def delete_closed_prs
|
38
|
+
return if JenkinsPipelineBuilder.debug
|
39
|
+
jobs_to_delete = JenkinsPipelineBuilder.client.job.list "#{application_name}-PR.*"
|
40
|
+
open_prs.each do |n|
|
41
|
+
jobs_to_delete.reject! { |j| j.start_with? "#{application_name}-PR#{n}" }
|
76
42
|
end
|
43
|
+
jobs_to_delete.each { |j| JenkinsPipelineBuilder.client.job.delete j }
|
77
44
|
end
|
78
45
|
|
79
|
-
|
80
|
-
errors = {}
|
81
|
-
create.each do |pull_project|
|
82
|
-
success, compiled_project = generator.resolve_project(pull_project)
|
83
|
-
compiled_project[:value][:jobs].each do |i|
|
84
|
-
job = i[:result]
|
85
|
-
job = Job.new job
|
86
|
-
success, payload = job.create_or_update
|
87
|
-
errors[job.name] = payload unless success
|
88
|
-
end
|
89
|
-
end
|
90
|
-
errors
|
91
|
-
end
|
92
|
-
|
93
|
-
def collection
|
94
|
-
generator.job_collection.collection
|
95
|
-
end
|
96
|
-
|
97
|
-
def filter_jobs
|
98
|
-
jobs = {}
|
99
|
-
pull_jobs = pull_generator[:value][:jobs] || []
|
100
|
-
pull_jobs.each do |job|
|
101
|
-
if job.is_a? String
|
102
|
-
jobs[job.to_s] = collection[job.to_s]
|
103
|
-
else
|
104
|
-
jobs[job.keys.first.to_s] = collection[job.keys.first.to_s]
|
105
|
-
end
|
106
|
-
end
|
107
|
-
fail 'No jobs found for pull request' if jobs.empty?
|
108
|
-
jobs
|
109
|
-
end
|
110
|
-
|
111
|
-
def compile_generator
|
112
|
-
defaults = generator.job_collection.defaults
|
113
|
-
settings = defaults.nil? ? {} : defaults[:value] || {}
|
114
|
-
compiler = Compiler.new generator
|
115
|
-
settings = compiler.get_settings_bag(project, settings)
|
116
|
-
success, payload = generator.resolve_job_by_name(pull_generator[:name], settings)
|
117
|
-
return payload if success
|
46
|
+
private
|
118
47
|
|
119
|
-
|
120
|
-
|
48
|
+
def override(job, pr)
|
49
|
+
git_version = JenkinsPipelineBuilder.registry.registry[:job][:scm_params].installed_version
|
50
|
+
job[:scm_branch] = "origin/pr/#{pr}/head"
|
51
|
+
job[:scm_params] ||= {}
|
52
|
+
job[:scm_params][:refspec] = "refs/pull/#{pr}/head:refs/remotes/origin/pr/#{pr}/head"
|
53
|
+
job[:scm_params][:changelog_to_branch] ||= {}
|
54
|
+
job[:scm_params][:changelog_to_branch]
|
55
|
+
.merge!(remote: 'origin', branch: "pr/#{pr}/head") if Gem::Version.new(2.0) < git_version
|
121
56
|
end
|
122
57
|
|
123
|
-
def
|
124
|
-
|
125
|
-
pull_job = nil
|
126
|
-
project_jobs.each do |job|
|
127
|
-
job = job.keys.first if job.is_a? Hash
|
128
|
-
job = collection[job.to_s]
|
129
|
-
|
130
|
-
pull_job = job if job[:value][:job_type] == 'pull_request_generator'
|
131
|
-
end
|
132
|
-
fail NotFound, 'No jobs of type pull_request_generator found' unless pull_job
|
133
|
-
pull_job
|
134
|
-
end
|
135
|
-
|
136
|
-
# Check for Github Pull Requests
|
137
|
-
#
|
138
|
-
# args[:git_url] URL to the github main page ex. https://www.github.com/
|
139
|
-
# args[:git_repo] Name of repo only, not url ex. jenkins_pipeline_builder
|
140
|
-
# args[:git_org] The Orig user ex. constantcontact
|
141
|
-
# @return = array of pull request numbers
|
142
|
-
def check_for_pull(args)
|
143
|
-
fail 'Please specify all arguments' unless args[:git_url] && args[:git_org] && args[:git_repo]
|
58
|
+
def active_prs(git_url, git_org, git_repo)
|
59
|
+
(git_url && git_org && git_repo) || fail('Please set github_site, git_org and git_repo_name in your project.')
|
144
60
|
# Build the Git URL
|
145
|
-
|
146
|
-
|
61
|
+
url = "#{git_url}/api/v3/repos/#{git_org}/#{git_repo}/pulls"
|
147
62
|
# Download the JSON Data from the API
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
# Read File
|
156
|
-
# FIXME: Shouldn't this be opening just with read permissions?
|
157
|
-
old_requests = File.new('pull_requests.csv', 'a+').read.split(',')
|
158
|
-
|
159
|
-
# Pop off current pull requests
|
160
|
-
old_requests.delete_if { |req| reqs.include?("#{req}") }
|
161
|
-
@purge = old_requests
|
162
|
-
|
163
|
-
# Write File
|
164
|
-
File.open('pull_requests.csv', 'w+') { |file| file.write reqs.join(',') }
|
63
|
+
begin
|
64
|
+
resp = Net::HTTP.get_response(URI.parse(url))
|
65
|
+
pulls = JSON.parse(resp.body)
|
66
|
+
pulls.map { |p| p['number'] }
|
67
|
+
rescue StandardError
|
68
|
+
raise 'Failed connecting to github!'
|
69
|
+
end
|
165
70
|
end
|
166
71
|
end
|
167
72
|
end
|
@@ -1,11 +1,5 @@
|
|
1
1
|
- job:
|
2
2
|
name: '{{name}}-40-PullRequestGenerator'
|
3
|
-
job_type: pull_request_generator
|
4
|
-
git_url: '{{git_url}}'
|
5
|
-
git_repo: '{{git_repo}}'
|
6
|
-
git_org: '{{git_org}}'
|
7
|
-
jobs:
|
8
|
-
- '{{name}}-10-SampleJob'
|
9
3
|
builders:
|
10
4
|
- shell_command: |
|
11
5
|
generate -v || gem install jenkins_pipeline_builder
|
data/spec/lib/jenkins_pipeline_builder/fixtures/generator_tests/pullrequest_pipeline/project.yaml
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
- defaults:
|
2
2
|
name: global
|
3
|
+
application_name: 'testapp'
|
3
4
|
description: 'Test pipeline for generator_spec.rb'
|
4
|
-
|
5
|
-
git_org: '
|
6
|
-
|
5
|
+
github_site: 'https://github.com'
|
6
|
+
git_org: 'testorg'
|
7
|
+
git_repo_name: 'generator_tests'
|
7
8
|
|
8
|
-
- project:
|
9
|
+
- project:
|
9
10
|
name: PullRequest
|
10
11
|
jobs:
|
11
12
|
- '{{name}}-10-SampleJob'
|
@@ -135,31 +135,32 @@ describe JenkinsPipelineBuilder::Generator do
|
|
135
135
|
let(:path) { File.expand_path('../fixtures/generator_tests/pullrequest_pipeline', __FILE__) }
|
136
136
|
it 'produces no errors while creating pipeline PullRequest' do
|
137
137
|
job_name = 'PullRequest'
|
138
|
-
|
139
|
-
|
138
|
+
pr_generator = double('pr_generator')
|
139
|
+
expect(JenkinsPipelineBuilder::PullRequestGenerator).to receive(:new)
|
140
|
+
.with(hash_including(application_name: 'testapp',
|
141
|
+
github_site: 'https://github.com',
|
142
|
+
git_org: 'testorg',
|
143
|
+
git_repo_name: 'generator_tests'))
|
144
|
+
.and_return(pr_generator)
|
145
|
+
expect(pr_generator).to receive(:delete_closed_prs)
|
146
|
+
expect(pr_generator).to receive(:convert!)
|
147
|
+
expect(pr_generator).to receive(:open_prs).and_return [1]
|
140
148
|
success = @generator.pull_request(path, job_name)
|
141
149
|
expect(success).to be_truthy
|
142
150
|
end
|
143
151
|
|
144
152
|
it 'correctly creates jobs when there are multiple pulls open' do
|
145
153
|
job_name = 'PullRequest'
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
).
|
155
|
-
expect(
|
156
|
-
name: 'PullRequest-PR2-10-SampleJob', scm_branch: 'origin/pr/2/head', scm_params: {
|
157
|
-
refspec: 'refs/pull/2/head:refs/remotes/origin/pr/2/head',
|
158
|
-
changelog_to_branch: { remote: 'origin', branch: 'pr/2/head' }
|
159
|
-
}
|
160
|
-
).and_return job2
|
161
|
-
expect(job1).to receive(:create_or_update).and_return true
|
162
|
-
expect(job2).to receive(:create_or_update).and_return true
|
154
|
+
pr_generator = double('pr_generator')
|
155
|
+
expect(JenkinsPipelineBuilder::PullRequestGenerator).to receive(:new)
|
156
|
+
.with(hash_including(application_name: 'testapp',
|
157
|
+
github_site: 'https://github.com',
|
158
|
+
git_org: 'testorg',
|
159
|
+
git_repo_name: 'generator_tests'))
|
160
|
+
.and_return(pr_generator)
|
161
|
+
expect(pr_generator).to receive(:delete_closed_prs)
|
162
|
+
expect(pr_generator).to receive(:convert!).twice
|
163
|
+
expect(pr_generator).to receive(:open_prs).and_return [1, 2]
|
163
164
|
expect(@generator.pull_request(path, job_name)).to be_truthy
|
164
165
|
end
|
165
166
|
# Things to check for
|
@@ -1,99 +1,132 @@
|
|
1
1
|
require File.expand_path('../spec_helper', __FILE__)
|
2
|
-
require '
|
2
|
+
require 'json'
|
3
3
|
|
4
4
|
describe JenkinsPipelineBuilder::PullRequestGenerator do
|
5
|
-
let(:
|
6
|
-
let(:
|
5
|
+
let(:application_name) { 'testapp' }
|
6
|
+
let(:github_site) { 'https://github.com' }
|
7
|
+
let(:git_org) { 'git_org' }
|
8
|
+
let(:git_repo_name) { 'git_repo' }
|
9
|
+
let(:prs) { (1..10).map { |n| "#{application_name}-PR#{n}" } }
|
10
|
+
let(:closed_prs) { (1..6).map { |n| "#{application_name}-PR#{n}" } }
|
11
|
+
let(:open_prs_json) { (7..10).map { |n| { number: n } }.to_json }
|
12
|
+
let(:url) { "#{github_site}/api/v3/repos/#{git_org}/#{git_repo_name}/pulls" }
|
13
|
+
let(:params) do
|
7
14
|
{
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
jobs: [
|
13
|
-
{
|
14
|
-
name: '{{name}}-00',
|
15
|
-
type: :job,
|
16
|
-
job_type: 'pull_request_generator',
|
17
|
-
git_url: 'https://www.github.com/',
|
18
|
-
git_repo: 'jenkins_pipeline_builder',
|
19
|
-
git_org: 'constantcontact',
|
20
|
-
jobs: [
|
21
|
-
'{{name}}-10',
|
22
|
-
'{{name}}-11'
|
23
|
-
],
|
24
|
-
builders: [{ shell_command: 'generate -v || gem install jenkins_pipeline_builder\ngenerate pipeline -c config/{{login_config}} pull_request pipeline/ {{name}}\n' }]
|
25
|
-
},
|
26
|
-
'{{name}}-10',
|
27
|
-
'{{name}}-11']
|
28
|
-
}
|
15
|
+
github_site: github_site,
|
16
|
+
git_org: git_org,
|
17
|
+
git_repo_name: git_repo_name,
|
18
|
+
application_name: application_name
|
29
19
|
}
|
30
20
|
end
|
31
|
-
let(:
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
type: :'job-template',
|
36
|
-
value: {
|
37
|
-
name: '{{name}}-10',
|
38
|
-
description: '{{description}}',
|
39
|
-
publishers: [{ downstream: { project: '{{job@{{name}}-11}}' } }]
|
40
|
-
}
|
41
|
-
},
|
42
|
-
'{{name}}-11' => {
|
43
|
-
name: '{{name}}-11',
|
44
|
-
type: :'job-template',
|
45
|
-
value: {
|
46
|
-
name: '{{name}}-11',
|
47
|
-
description: '{{description}}' }
|
48
|
-
}
|
49
|
-
}
|
21
|
+
let(:job_collection) do
|
22
|
+
double('job_collection',
|
23
|
+
defaults: { value: { application_name: application_name } },
|
24
|
+
jobs: [{ value: { scm_branch: 'master', scm_params: { random: 'foo' } } }])
|
50
25
|
end
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
'{{name}}-11'],
|
69
|
-
pull_request_number: '6'
|
70
|
-
}
|
71
|
-
}
|
72
|
-
]
|
26
|
+
subject { JenkinsPipelineBuilder::PullRequestGenerator.new params }
|
27
|
+
|
28
|
+
context '#initialize' do
|
29
|
+
it 'fails when one of the params is not set' do
|
30
|
+
expect do
|
31
|
+
JenkinsPipelineBuilder::PullRequestGenerator.new(application_name: 'name')
|
32
|
+
end.to raise_error('Please set github_site, git_org and git_repo_name in your project.')
|
33
|
+
end
|
34
|
+
it 'fails when github is not reponding properly' do
|
35
|
+
stub_request(:get, url)
|
36
|
+
.with(headers: { 'Accept' => '*/*',
|
37
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
38
|
+
'Host' => 'github.com',
|
39
|
+
'User-Agent' => 'Ruby' })
|
40
|
+
.to_raise 'error'
|
41
|
+
expect { subject }.to raise_error('Failed connecting to github!')
|
42
|
+
end
|
73
43
|
end
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
44
|
+
|
45
|
+
context '#delete_closed_prs' do
|
46
|
+
it 'deletes closed prs' do
|
47
|
+
stub_request(:get, url)
|
48
|
+
.with(headers: { 'Accept' => '*/*',
|
49
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
50
|
+
'Host' => 'github.com',
|
51
|
+
'User-Agent' => 'Ruby' })
|
52
|
+
.to_return(status: 200, body: open_prs_json, headers: {})
|
53
|
+
job = double('job')
|
54
|
+
expect(job).to receive(:list).with("#{application_name}-PR.*").and_return prs
|
55
|
+
client = double('client', job: job)
|
56
|
+
expect(JenkinsPipelineBuilder).to receive(:debug).and_return false
|
57
|
+
allow(JenkinsPipelineBuilder).to receive(:client).and_return client
|
58
|
+
closed_prs.each { |pr| expect(job).to receive(:delete).with(pr) }
|
59
|
+
subject.delete_closed_prs
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'does not fail when there are no closed prs' do
|
63
|
+
stub_request(:get, url)
|
64
|
+
.with(headers: { 'Accept' => '*/*',
|
65
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
66
|
+
'Host' => 'github.com',
|
67
|
+
'User-Agent' => 'Ruby' })
|
68
|
+
.to_return(status: 200, body: open_prs_json, headers: {})
|
69
|
+
job = double('job')
|
70
|
+
expect(job).to receive(:list).with("#{application_name}-PR.*").and_return prs - closed_prs
|
71
|
+
client = double('client', job: job)
|
72
|
+
expect(JenkinsPipelineBuilder).to receive(:debug).and_return false
|
73
|
+
allow(JenkinsPipelineBuilder).to receive(:client).and_return client
|
74
|
+
expect(job).not_to receive(:delete)
|
75
|
+
subject.delete_closed_prs
|
76
|
+
end
|
79
77
|
end
|
80
|
-
|
81
|
-
|
82
|
-
|
78
|
+
|
79
|
+
context '#convert!' do
|
80
|
+
it 'converts the job application name' do
|
81
|
+
stub_request(:get, url)
|
82
|
+
.with(headers: { 'Accept' => '*/*',
|
83
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
84
|
+
'Host' => 'github.com',
|
85
|
+
'User-Agent' => 'Ruby' })
|
86
|
+
.to_return(status: 200, body: open_prs_json, headers: {})
|
87
|
+
collection = job_collection.clone
|
88
|
+
subject.convert! collection, 8
|
89
|
+
expect(collection.defaults[:value][:application_name]).to eq "#{application_name}-PR8"
|
83
90
|
end
|
84
91
|
|
85
|
-
it '
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
92
|
+
it 'overrides the git params' do
|
93
|
+
stub_request(:get, url)
|
94
|
+
.with(headers: { 'Accept' => '*/*',
|
95
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
96
|
+
'Host' => 'github.com',
|
97
|
+
'User-Agent' => 'Ruby' })
|
98
|
+
.to_return(status: 200, body: open_prs_json, headers: {})
|
99
|
+
pr = 8
|
100
|
+
collection = job_collection.clone
|
101
|
+
subject.convert! collection, pr
|
102
|
+
expect(collection.jobs.first[:value]).to eq(
|
103
|
+
scm_branch: "origin/pr/#{pr}/head",
|
104
|
+
scm_params: {
|
105
|
+
refspec: "refs/pull/#{pr}/head:refs/remotes/origin/pr/#{pr}/head",
|
106
|
+
changelog_to_branch: { remote: 'origin', branch: "pr/#{pr}/head" },
|
107
|
+
random: 'foo'
|
108
|
+
}
|
109
|
+
)
|
91
110
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
111
|
+
|
112
|
+
it 'does not override extra params' do
|
113
|
+
stub_request(:get, url)
|
114
|
+
.with(headers: { 'Accept' => '*/*',
|
115
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
116
|
+
'Host' => 'github.com',
|
117
|
+
'User-Agent' => 'Ruby' })
|
118
|
+
.to_return(status: 200, body: open_prs_json, headers: {})
|
119
|
+
pr = 8
|
120
|
+
collection = job_collection.clone
|
121
|
+
subject.convert! collection, pr
|
122
|
+
expect(collection.jobs.first[:value]).to eq(
|
123
|
+
scm_branch: "origin/pr/#{pr}/head",
|
124
|
+
scm_params: {
|
125
|
+
refspec: "refs/pull/#{pr}/head:refs/remotes/origin/pr/#{pr}/head",
|
126
|
+
changelog_to_branch: { remote: 'origin', branch: "pr/#{pr}/head" },
|
127
|
+
random: 'foo'
|
128
|
+
}
|
129
|
+
)
|
97
130
|
end
|
98
131
|
end
|
99
132
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jenkins_pipeline_builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Igor Moochnick
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-11-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -370,7 +370,6 @@ files:
|
|
370
370
|
- lib/jenkins_pipeline_builder/job_collection.rb
|
371
371
|
- lib/jenkins_pipeline_builder/module_registry.rb
|
372
372
|
- lib/jenkins_pipeline_builder/project.rb
|
373
|
-
- lib/jenkins_pipeline_builder/pull_request.rb
|
374
373
|
- lib/jenkins_pipeline_builder/pull_request_generator.rb
|
375
374
|
- lib/jenkins_pipeline_builder/remote_dependencies.rb
|
376
375
|
- lib/jenkins_pipeline_builder/utils.rb
|
@@ -427,7 +426,6 @@ files:
|
|
427
426
|
- spec/lib/jenkins_pipeline_builder/job_spec.rb
|
428
427
|
- spec/lib/jenkins_pipeline_builder/module_registry_spec.rb
|
429
428
|
- spec/lib/jenkins_pipeline_builder/pull_request_generator_spec.rb
|
430
|
-
- spec/lib/jenkins_pipeline_builder/pull_request_spec.rb
|
431
429
|
- spec/lib/jenkins_pipeline_builder/spec_helper.rb
|
432
430
|
- spec/lib/jenkins_pipeline_builder/utils_spec.rb
|
433
431
|
- spec/lib/jenkins_pipeline_builder/view_spec.rb
|
@@ -505,7 +503,6 @@ test_files:
|
|
505
503
|
- spec/lib/jenkins_pipeline_builder/job_spec.rb
|
506
504
|
- spec/lib/jenkins_pipeline_builder/module_registry_spec.rb
|
507
505
|
- spec/lib/jenkins_pipeline_builder/pull_request_generator_spec.rb
|
508
|
-
- spec/lib/jenkins_pipeline_builder/pull_request_spec.rb
|
509
506
|
- spec/lib/jenkins_pipeline_builder/spec_helper.rb
|
510
507
|
- spec/lib/jenkins_pipeline_builder/utils_spec.rb
|
511
508
|
- spec/lib/jenkins_pipeline_builder/view_spec.rb
|
@@ -1,92 +0,0 @@
|
|
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
|
-
module JenkinsPipelineBuilder
|
23
|
-
class PullRequest
|
24
|
-
attr_reader :project # The root project YAML as a hash
|
25
|
-
attr_reader :number # The pull request number
|
26
|
-
attr_reader :jobs # The jobs in the pull request as an array of hashes
|
27
|
-
attr_reader :pull_generator # The generator job YAML as a hash
|
28
|
-
|
29
|
-
def initialize(project, number, jobs, pull_generator)
|
30
|
-
@project = Marshal.load(Marshal.dump(project))
|
31
|
-
@number = number
|
32
|
-
@jobs = Marshal.load(Marshal.dump(jobs))
|
33
|
-
@pull_generator = Marshal.load(Marshal.dump(pull_generator))
|
34
|
-
@project[:value][:pull_request_number] = "#{@number}"
|
35
|
-
|
36
|
-
run!
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def run!
|
42
|
-
git_version = JenkinsPipelineBuilder.registry.registry[:job][:scm_params].installed_version
|
43
|
-
if git_version >= Gem::Version.new(2.0)
|
44
|
-
@jobs.each_value do |j|
|
45
|
-
override_git_2_params j
|
46
|
-
end
|
47
|
-
end
|
48
|
-
update_jobs!
|
49
|
-
change_git!
|
50
|
-
change_name!
|
51
|
-
end
|
52
|
-
|
53
|
-
def override_git_2_params(job)
|
54
|
-
job[:value][:scm_params] ||= {}
|
55
|
-
job[:value][:scm_params][:changelog_to_branch] = { remote: 'origin', branch: 'pr/{{pull_request_number}}/head' }
|
56
|
-
end
|
57
|
-
|
58
|
-
# Change the git branch for each job
|
59
|
-
def change_git!
|
60
|
-
@jobs.each_value do |job|
|
61
|
-
job[:value][:scm_branch] = 'origin/pr/{{pull_request_number}}/head'
|
62
|
-
job[:value][:scm_params] = {} unless job[:value][:scm_params]
|
63
|
-
refspec = 'refs/pull/{{pull_request_number}}/head:refs/remotes/origin/pr/{{pull_request_number}}/head'
|
64
|
-
job[:value][:scm_params][:refspec] = refspec
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Change the name of the pull request project
|
69
|
-
def change_name!
|
70
|
-
@project[:name] = "#{@project[:name]}-PR#{@number}" if @project[:name]
|
71
|
-
@project[:value][:name] = "#{@project[:value][:name]}-PR#{@number}" if @project[:value][:name]
|
72
|
-
|
73
|
-
return unless pull_generator[:value][:inject_pr_into]
|
74
|
-
|
75
|
-
key = pull_generator[:value][:inject_pr_into].to_sym
|
76
|
-
project[:value][key] = "{{#{key}}}-PR#{@number}" if project[:value]
|
77
|
-
end
|
78
|
-
|
79
|
-
# Apply any specified changes to each job
|
80
|
-
def update_jobs!
|
81
|
-
@jobs.each_value do |job|
|
82
|
-
name = job[:name]
|
83
|
-
changes = nil
|
84
|
-
@pull_generator[:value][:jobs].each do |gen|
|
85
|
-
changes = gen[name.to_sym] if gen.is_a?(Hash) && gen.keys[0] == name.to_sym
|
86
|
-
end
|
87
|
-
# Apply changes
|
88
|
-
Utils.hash_merge!(job[:value], changes) unless changes.nil?
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
@@ -1,161 +0,0 @@
|
|
1
|
-
require File.expand_path('../spec_helper', __FILE__)
|
2
|
-
require 'webmock/rspec'
|
3
|
-
|
4
|
-
describe JenkinsPipelineBuilder::PullRequest do
|
5
|
-
before :each do
|
6
|
-
JenkinsPipelineBuilder.registry.registry[:job][:scm_params].installed_version = '1000.0'
|
7
|
-
end
|
8
|
-
after :each do
|
9
|
-
JenkinsPipelineBuilder.registry.registry[:job][:scm_params].clear_installed_version
|
10
|
-
end
|
11
|
-
let(:project) do
|
12
|
-
{
|
13
|
-
name: 'pull_req_test',
|
14
|
-
type: :project,
|
15
|
-
value: {
|
16
|
-
name: 'pull_req_test',
|
17
|
-
jobs: ['{{name}}-00', '{{name}}-10', '{{name}}-11']
|
18
|
-
}
|
19
|
-
}
|
20
|
-
end
|
21
|
-
let(:value) { { jobs: ['{{name}}-10', '{{name}}-11'] } }
|
22
|
-
let(:pull_request) do
|
23
|
-
{
|
24
|
-
name: '{{name}}-00',
|
25
|
-
type: :job,
|
26
|
-
job_type: 'pull_request_generator',
|
27
|
-
git_url: 'https://www.github.com/',
|
28
|
-
git_repo: 'jenkins_pipeline_builder',
|
29
|
-
git_org: 'constantcontact',
|
30
|
-
value: value,
|
31
|
-
builders: [
|
32
|
-
{ shell_command: 'echo "shell command"' }
|
33
|
-
]
|
34
|
-
}
|
35
|
-
end
|
36
|
-
let(:job1) { '{{name}}-10' }
|
37
|
-
let(:job2) { '{{name}}-11' }
|
38
|
-
let(:jobs) do
|
39
|
-
{
|
40
|
-
job1 => {
|
41
|
-
name: job1,
|
42
|
-
type: :'job-template',
|
43
|
-
value: {
|
44
|
-
name: job1,
|
45
|
-
description: '{{description}}',
|
46
|
-
publishers: [{ downstream: { project: "{{job@#{job2}}}" } }]
|
47
|
-
}
|
48
|
-
},
|
49
|
-
job2 => {
|
50
|
-
name: job2,
|
51
|
-
type: :'job-template',
|
52
|
-
value: {
|
53
|
-
name: job2,
|
54
|
-
description: '{{description}}'
|
55
|
-
}
|
56
|
-
}
|
57
|
-
}
|
58
|
-
end
|
59
|
-
let(:post_scm_params) do
|
60
|
-
{
|
61
|
-
changelog_to_branch: {
|
62
|
-
remote: 'origin',
|
63
|
-
branch: 'pr/{{pull_request_number}}/head'
|
64
|
-
},
|
65
|
-
refspec: 'refs/pull/{{pull_request_number}}/head:refs/remotes/origin/pr/{{pull_request_number}}/head'
|
66
|
-
}
|
67
|
-
end
|
68
|
-
let(:post_jobs) do
|
69
|
-
{
|
70
|
-
'{{name}}-10' => {
|
71
|
-
name: '{{name}}-10',
|
72
|
-
type: :'job-template',
|
73
|
-
value: {
|
74
|
-
name: '{{name}}-10',
|
75
|
-
description: '{{description}}',
|
76
|
-
publishers: [{ downstream: { project: '{{job@{{name}}-11}}' } }],
|
77
|
-
scm_branch: 'origin/pr/{{pull_request_number}}/head',
|
78
|
-
scm_params: post_scm_params
|
79
|
-
}
|
80
|
-
},
|
81
|
-
'{{name}}-11' => {
|
82
|
-
name: '{{name}}-11',
|
83
|
-
type: :'job-template',
|
84
|
-
value: {
|
85
|
-
name: '{{name}}-11',
|
86
|
-
description: '{{description}}',
|
87
|
-
scm_branch: 'origin/pr/{{pull_request_number}}/head',
|
88
|
-
scm_params: post_scm_params
|
89
|
-
}
|
90
|
-
}
|
91
|
-
}
|
92
|
-
end
|
93
|
-
describe '#initialize' do
|
94
|
-
it 'process pull_request' do
|
95
|
-
pull = described_class.new(project, 2, jobs, pull_request)
|
96
|
-
post_project = {
|
97
|
-
name: 'pull_req_test-PR2',
|
98
|
-
type: :project,
|
99
|
-
value: {
|
100
|
-
name: 'pull_req_test-PR2',
|
101
|
-
jobs: ['{{name}}-00', '{{name}}-10', '{{name}}-11'],
|
102
|
-
pull_request_number: '2'
|
103
|
-
}
|
104
|
-
}
|
105
|
-
|
106
|
-
expect(pull.project).to eq(post_project)
|
107
|
-
expect(pull.jobs).to eq(post_jobs)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
describe '#git_version_0' do
|
112
|
-
let(:post_scm_params) do
|
113
|
-
{ refspec: 'refs/pull/{{pull_request_number}}/head:refs/remotes/origin/pr/{{pull_request_number}}/head' }
|
114
|
-
end
|
115
|
-
|
116
|
-
before :each do
|
117
|
-
JenkinsPipelineBuilder.registry.registry[:job][:scm_params].installed_version = '0'
|
118
|
-
end
|
119
|
-
it 'process pull_request' do
|
120
|
-
pull = described_class.new(project, 2, jobs, pull_request)
|
121
|
-
expect(pull.jobs).to eq(post_jobs)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
describe '#git_version_2' do
|
126
|
-
before :each do
|
127
|
-
JenkinsPipelineBuilder.registry.registry[:job][:scm_params].installed_version = '2.0'
|
128
|
-
end
|
129
|
-
it 'process pull_request' do
|
130
|
-
pull = described_class.new(project, 2, jobs, pull_request)
|
131
|
-
expect(pull.jobs).to eq(post_jobs)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
context 'when the job does not have {{name}} in it' do
|
136
|
-
let(:project) do
|
137
|
-
{
|
138
|
-
name: 'pull_req_test',
|
139
|
-
type: :project,
|
140
|
-
app_name: 'my_app',
|
141
|
-
value: {
|
142
|
-
name: 'pull_req_test',
|
143
|
-
app_name: 'my_app',
|
144
|
-
jobs: ['{{app_name}}-00', '{{app_name}}-10', '{{app_name}}-11']
|
145
|
-
}
|
146
|
-
}
|
147
|
-
end
|
148
|
-
let(:value) do
|
149
|
-
{
|
150
|
-
inject_pr_into: :app_name,
|
151
|
-
jobs: ['{{app_name}}-10', '{{app_name}}-11']
|
152
|
-
}
|
153
|
-
end
|
154
|
-
let(:job1) { '{{app_name}}-10' }
|
155
|
-
let(:job2) { '{{app_name}}-11' }
|
156
|
-
it 'injects the pr number into the job name when told to' do
|
157
|
-
pull = described_class.new project, 2, jobs, pull_request
|
158
|
-
expect(pull.project[:value][:app_name]).to eq '{{app_name}}-PR2'
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|