diff --git a/lib/ghb/auto_merge_manager.rb b/lib/ghb/auto_merge_manager.rb index b31c071..cc22e28 100644 --- a/lib/ghb/auto_merge_manager.rb +++ b/lib/ghb/auto_merge_manager.rb @@ -25,9 +25,18 @@ def save issues: 'write' } + # Cancel superseded runs on rapid pushes to the same PR. + @auto_merge_workflow.concurrency = + { + group: 'auto-merge-${{github.event.pull_request.number}}', + 'cancel-in-progress': true + } + @auto_merge_workflow.do_job(:enable_automerge) do do_name('Enable Auto-merge') - do_if('github.event.pull_request.draft == false') + # Skip drafts, and never run the privileged pull_request_target token + # against code checked out from a fork. + do_if('github.event.pull_request.draft == false && github.event.pull_request.head.repo.full_name == github.repository') do_runs_on(DEFAULT_UBUNTU_VERSION) do_step('Checkout') do @@ -108,7 +117,10 @@ def save end end - @auto_merge_workflow.write('.github/workflows/auto-merge.yml') + @auto_merge_workflow.write( + '.github/workflows/auto-merge.yml', + header: "# AUTO-GENERATED by github-build (auto_merge_manager.rb). Do not edit directly; changes will be overwritten.\n" + ) end end end diff --git a/spec/ghb/auto_merge_manager_spec.rb b/spec/ghb/auto_merge_manager_spec.rb index c5bb1de..7797a82 100644 --- a/spec/ghb/auto_merge_manager_spec.rb +++ b/spec/ghb/auto_merge_manager_spec.rb @@ -56,11 +56,39 @@ expect(auto_merge_workflow.jobs[:enable_automerge].name).to(eq('Enable Auto-merge')) end - it 'skips draft pull requests' do + it 'skips drafts and blocks fork pull requests' do manager = described_class.new(auto_merge_workflow: auto_merge_workflow) manager.save - expect(auto_merge_workflow.jobs[:enable_automerge].if).to(eq('github.event.pull_request.draft == false')) + expect(auto_merge_workflow.jobs[:enable_automerge].if).to( + eq('github.event.pull_request.draft == false && github.event.pull_request.head.repo.full_name == github.repository') + ) + end + + it 'sets a per-PR concurrency group' do # rubocop:disable RSpec/ExampleLength + manager = described_class.new(auto_merge_workflow: auto_merge_workflow) + manager.save + + expect(auto_merge_workflow.concurrency).to( + eq( + { + group: 'auto-merge-${{github.event.pull_request.number}}', + 'cancel-in-progress': true + } + ) + ) + end + + it 'writes an auto-generated header into the workflow file' do # rubocop:disable RSpec/ExampleLength + manager = described_class.new(auto_merge_workflow: auto_merge_workflow) + manager.save + + expect(File).to( + have_received(:write).with( + '.github/workflows/auto-merge.yml', + a_string_starting_with('# AUTO-GENERATED by github-build') + ) + ) end it 'includes a checkout step with base sha' do # rubocop:disable RSpec/ExampleLength,RSpec/MultipleExpectations