Skip to content
This repository was archived by the owner on Apr 4, 2018. It is now read-only.

Commit 2531eb2

Browse files
committed
Add ability to disallow pull requests from forks
In some cases you may want to only allow pull requests from within your own team. This is useful in scenarios where you cannot have untrusted code being pulled into your Concourse pipeline. This commit adds the ability to optionally set a `disallow_forks` configuration, which if set to true will only consider pull requests valid if they are raised from within the same repository. The value of this configuration is false by default and does not interfere with the normal behaviour of the resource.
1 parent fbe8dda commit 2531eb2

File tree

5 files changed

+81
-5
lines changed

5 files changed

+81
-5
lines changed

Diff for: README.md

+2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ concourse version 1.2.x and higher and the [`version: every`](http://concourse.c
7373
See the [`git-config(1)` manual page](https://www.kernel.org/pub/software/scm/git/docs/git-config.html)
7474
for more information and documentation of existing git options.
7575

76+
* `disallow_forks`: *Optional*. If set to `true` it will only detect pull requests raised from within the same repository. Pull requests from forks will not generate new versions of the resource within Concourse. The default value is `false`.
77+
7678
## Behavior
7779

7880
### `check`: Check for new pull requests

Diff for: assets/lib/commands/check.rb

+11-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ class Check < Commands::Base
1010

1111
def output
1212
if return_all_versions?
13-
repo.pull_requests
13+
if disallow_forks?
14+
repo.pull_requests.select { |pr| !pr.from_fork? }
15+
else
16+
repo.pull_requests
17+
end
1418
else
1519
next_pull_request
1620
end
@@ -22,11 +26,16 @@ def return_all_versions?
2226
input['source']['every'] == true
2327
end
2428

29+
def disallow_forks?
30+
input['source']['disallow_forks'] == true
31+
end
32+
2533
def next_pull_request
2634
pull_request = repo.next_pull_request(
2735
id: input['version']['pr'],
2836
sha: input['version']['ref'],
29-
base: input['source']['base']
37+
base: input['source']['base'],
38+
disallow_forks: disallow_forks?,
3039
)
3140

3241
if pull_request

Diff for: assets/lib/pull_request.rb

+12
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ def ready?
1010
statuses.empty?
1111
end
1212

13+
def from_fork?
14+
base_repo != head_repo
15+
end
16+
1317
def equals?(id:, sha:)
1418
[self.sha, self.id.to_s] == [sha, id.to_s]
1519
end
@@ -36,6 +40,14 @@ def url
3640

3741
private
3842

43+
def base_repo
44+
@pr['base']['label'].split(':').first
45+
end
46+
47+
def head_repo
48+
@pr['head']['label'].split(':').first
49+
end
50+
3951
def statuses
4052
@statuses ||= Octokit.statuses(@repo.name, sha).select do |status|
4153
status['context'] =~ /^concourse-ci/

Diff for: assets/lib/repository.rb

+11-3
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,24 @@ def pull_request(id:)
1919
PullRequest.new(repo: self, pr: pr)
2020
end
2121

22-
def next_pull_request(id: nil, sha: nil, base: nil)
22+
def next_pull_request(id: nil, sha: nil, base: nil, disallow_forks: false)
2323
return if pull_requests(base: base).empty?
2424

2525
if id && sha
2626
current = pull_requests.find { |pr| pr.equals?(id: id, sha: sha) }
27-
return if current && current.ready?
27+
if disallow_forks
28+
return if current && current.ready? && !current.from_fork?
29+
else
30+
return if current && current.ready?
31+
end
2832
end
2933

3034
pull_requests.find do |pr|
31-
pr != current && pr.ready?
35+
if disallow_forks
36+
pr != current && pr.ready? && !pr.from_fork?
37+
else
38+
pr != current && pr.ready?
39+
end
3240
end
3341
end
3442

Diff for: spec/commands/check_spec.rb

+45
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,49 @@ def stub_json(uri, body)
187187
end
188188
end
189189
end
190+
191+
context 'when the head of the only pull request is on a fork' do
192+
before do
193+
stub_json('https://api.github.com/repos/jtarchie/test/statuses/abcdef', [])
194+
stub_json('https://api.github.com/repos/jtarchie/test/pulls?direction=asc&per_page=100&sort=updated&state=open', [
195+
{ number: 1, head: { sha: 'abcdef', label: 'someotherrepo:master' }, base: { label: 'thisrepo:master' } }
196+
])
197+
end
198+
199+
context 'and `disallow_forks` is not set' do
200+
it 'returns the pull request' do
201+
expect(check('source' => { 'repo' => 'jtarchie/test' })).to eq [{ 'ref' => 'abcdef', 'pr' => '1' }]
202+
end
203+
end
204+
205+
context 'and `disallow_forks` is set to true' do
206+
it 'returns nothing' do
207+
expect(check('source' => { 'repo' => 'jtarchie/test', 'disallow_forks' => true })).to eq []
208+
end
209+
end
210+
end
211+
212+
context 'when there is a mix of pull requests from forks and non-forks' do
213+
before do
214+
stub_json('https://api.github.com/repos/jtarchie/test/statuses/abcdef', [])
215+
stub_json('https://api.github.com/repos/jtarchie/test/statuses/ghijkl', [])
216+
stub_json('https://api.github.com/repos/jtarchie/test/pulls?direction=asc&per_page=100&sort=updated&state=open', [
217+
{ number: 1, head: { sha: 'abcdef', label: 'someotherrepo:master' }, base: { label: 'thisrepo:master' } },
218+
{ number: 2, head: { sha: 'ghijkl', label: 'thisrepo:master' }, base: { label: 'thisrepo:master' } },
219+
])
220+
end
221+
222+
context 'and `disallow_forks` is not set' do
223+
it 'returns the most recently updated pull request' do
224+
expect(check('source' => { 'repo' => 'jtarchie/test' })).to eq [{ 'ref' => 'abcdef', 'pr' => '1' }]
225+
end
226+
end
227+
228+
context 'and `disallow_forks` is set to true' do
229+
it 'returns the most recently updated internal pull request' do
230+
expect(check('source' => { 'repo' => 'jtarchie/test', 'disallow_forks' => true })).to eq [{ 'ref' => 'ghijkl', 'pr' => '2' }]
231+
end
232+
end
233+
end
234+
190235
end

0 commit comments

Comments
 (0)