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

[#130188061] Add ability to disallow pull requests from forks #1

Merged
merged 3 commits into from
Nov 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ concourse version 1.2.x and higher and the [`version: every`](http://concourse.c
See the [`git-config(1)` manual page](https://www.kernel.org/pub/software/scm/git/docs/git-config.html)
for more information and documentation of existing git options.

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

## Behavior

### `check`: Check for new pull requests
Expand Down
2 changes: 2 additions & 0 deletions assets/check
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ set -e
exec 3>&1 # make stdout available as fd 3 for the result
exec 1>&2 # redirect all output to stderr for logging

. $(dirname $0)/common.sh

payload=$(mktemp $TMPDIR/pullrequest-resource.XXXXXX)
cat > $payload <&0

Expand Down
13 changes: 11 additions & 2 deletions assets/lib/commands/check.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Check < Commands::Base

def output
if return_all_versions?
repo.pull_requests
all_pull_requests
else
next_pull_request
end
Expand All @@ -22,11 +22,20 @@ def return_all_versions?
input['source']['every'] == true
end

def disallow_forks?
input['source']['disallow_forks'] == true
end

def all_pull_requests
repo.pull_requests(disallow_forks: disallow_forks?)
end

def next_pull_request
pull_request = repo.next_pull_request(
id: input['version']['pr'],
sha: input['version']['ref'],
base: input['source']['base']
base: input['source']['base'],
disallow_forks: disallow_forks?,
)

if pull_request
Expand Down
12 changes: 12 additions & 0 deletions assets/lib/pull_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ def ready?
statuses.empty?
end

def from_fork?
base_repo != head_repo
end

def equals?(id:, sha:)
[self.sha, self.id.to_s] == [sha, id.to_s]
end
Expand All @@ -36,6 +40,14 @@ def url

private

def base_repo
@pr['base']['repo']['full_name']
end

def head_repo
@pr['head']['repo']['full_name']
end

def statuses
@statuses ||= Octokit.statuses(@repo.name, sha).select do |status|
status['context'] =~ /^concourse-ci/
Expand Down
24 changes: 16 additions & 8 deletions assets/lib/repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,40 @@ def initialize(name:)
@name = name
end

def pull_requests(args = {})
@pull_requests ||= Octokit.pulls(name, pulls_options(args)).map do |pr|
PullRequest.new(repo: self, pr: pr)
end
def pull_requests(base: nil, disallow_forks: false)
@pull_requests ||= load_pull_requests(base: base, disallow_forks: disallow_forks)
end

def pull_request(id:)
pr = Octokit.pull_request(name, id)
PullRequest.new(repo: self, pr: pr)
end

def next_pull_request(id: nil, sha: nil, base: nil)
return if pull_requests(base: base).empty?
def next_pull_request(id: nil, sha: nil, base: nil, disallow_forks: false)
return if pull_requests(base: base, disallow_forks: disallow_forks).empty?

if id && sha
current = pull_requests.find { |pr| pr.equals?(id: id, sha: sha) }
current = pull_requests(disallow_forks: disallow_forks).find { |pr| pr.equals?(id: id, sha: sha) }
return if current && current.ready?
end

pull_requests.find do |pr|
pull_requests(disallow_forks: disallow_forks).find do |pr|
pr != current && pr.ready?
end
end

private

def load_pull_requests(base: nil, disallow_forks: false)
pulls = Octokit.pulls(name, pulls_options(base: base)).map do |pr|
PullRequest.new(repo: self, pr: pr)
end
if disallow_forks
pulls = pulls.select { |pr| !pr.from_fork? }
end
pulls
end

def pulls_options(base: nil)
base ? default_opts.merge(base: base) : default_opts
end
Expand Down
33 changes: 28 additions & 5 deletions spec/commands/check_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,25 @@ def stub_json(uri, body)
stub_json(
'https://api.github.com:443/repos/jtarchie/test/pulls?direction=asc&per_page=100&sort=updated&state=open',
[
{ number: 1, head: { sha: 'abcdef' } },
{ number: 2, head: { sha: 'zyxwvu' } }
{ number: 1, head: { sha: 'abcdef', repo: { full_name: 'jtarchie/test' } }, base: { repo: { full_name: 'jtarchie/test' } } },
{ number: 3, head: { sha: 'ghijkl', repo: { full_name: 'jtarchie/test' } }, base: { repo: { full_name: 'jtarchie/test' } } },
{ number: 2, head: { sha: 'zyxwvu', repo: { full_name: 'someother/repo' } }, base: { repo: { full_name: 'jtarchie/test' } } },
]
)
end

it 'returns all PRs oldest to newest last' do
expect(check('source' => { 'repo' => 'jtarchie/test', 'every' => true }, 'version' => {})).to eq [
{ 'ref' => 'abcdef', 'pr' => '1' },
{ 'ref' => 'zyxwvu', 'pr' => '2' }
{ 'ref' => 'ghijkl', 'pr' => '3' },
{ 'ref' => 'zyxwvu', 'pr' => '2' },
]
end

it 'filters out PRs from forked repos when requested' do
expect(check('source' => { 'repo' => 'jtarchie/test', 'every' => true, 'disallow_forks' => true }, 'version' => {})).to eq [
{ 'ref' => 'abcdef', 'pr' => '1' },
{ 'ref' => 'ghijkl', 'pr' => '3' },
]
end
end
Expand Down Expand Up @@ -158,9 +167,11 @@ def stub_json(uri, body)

context 'when there is more than one open pull request' do
before do
stub_json('https://api.github.com/repos/jtarchie/test/statuses/abcdef', [])
stub_json('https://api.github.com/repos/jtarchie/test/statuses/zyxwvu', [])
stub_json('https://api.github.com/repos/jtarchie/test/pulls?direction=asc&per_page=100&sort=updated&state=open', [
{ number: 2, head: { sha: 'zyxwvu' } },
{ number: 1, head: { sha: 'abcdef' } }
{ number: 2, head: { sha: 'zyxwvu', repo: { full_name: 'someotherowner/repo' } }, base: { repo: { full_name: 'jtarchie/test' } } },
{ number: 1, head: { sha: 'abcdef', repo: { full_name: 'jtarchie/test' } }, base: { repo: { full_name: 'jtarchie/test' } } },
])
end

Expand All @@ -185,6 +196,18 @@ def stub_json(uri, body)
expect(check(payload)).to eq []
end
end

context 'and `disallow_forks` is not set' do
it 'returns the most recently updated pull request' do
expect(check('source' => { 'repo' => 'jtarchie/test' })).to eq [{ 'ref' => 'zyxwvu', 'pr' => '2' }]
end
end

context 'and `disallow_forks` is set to true' do
it 'returns the most recently updated internal pull request' do
expect(check('source' => { 'repo' => 'jtarchie/test', 'disallow_forks' => true })).to eq [{ 'ref' => 'abcdef', 'pr' => '1' }]
end
end
end
end
end