Skip to content

Fixing bug when filtering pull requests without labels #771

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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
4 changes: 4 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ Metrics/ClassLength:
Metrics/MethodLength:
Enabled: false

Metrics/ModuleLength:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disabled this cop for all specs instead of the per-spec solution that was used previously. Let me know if this is not desirable.

Exclude:
- 'spec/**/*'

Naming/FileName:
Exclude:
- 'bin/git-generate-changelog'
Expand Down
12 changes: 7 additions & 5 deletions lib/github_changelog_generator/generator/generator_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,14 @@ def include_issues_by_labels(issues)
# @param [Array] issues Issues & PRs to filter when without labels
# @return [Array] Issues & PRs without labels or empty array if
# add_issues_wo_labels or add_pr_wo_labels are false
def filter_wo_labels(issues)
if (!issues.empty? && issues.first.key?("pull_requests") && options[:add_pr_wo_labels]) || options[:add_issues_wo_labels]
issues
else
issues.select { |issue| issue["labels"].map { |l| l["name"] }.any? }
def filter_wo_labels(items)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to change the internals of this method beyond the initial issue of pull_request being incorrectly plural.

The original implementation, with the corrected value, would return all pull requests even when :add_pr_wo_labels was false when :add_issues_wo_labels was true. This was exposed when writing tests.

if items.any? && items.first.key?("pull_request")
return items if options[:add_pr_wo_labels]
elsif options[:add_issues_wo_labels]
return items
end
# The default is to filter items without labels
items.select { |item| item["labels"].map { |l| l["name"] }.any? }
end

# @todo Document this
Expand Down
2 changes: 0 additions & 2 deletions spec/unit/generator/entry_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# frozen_string_literal: true

# rubocop:disable Metrics/ModuleLength
module GitHubChangelogGenerator
RSpec.describe Entry do
def label(name)
Expand Down Expand Up @@ -757,4 +756,3 @@ def default_sections
end
end
end
# rubocop:enable Metrics/ModuleLength
143 changes: 99 additions & 44 deletions spec/unit/generator/generator_processor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,82 +5,137 @@ module GitHubChangelogGenerator
let(:default_options) { GitHubChangelogGenerator::Parser.default_options.merge(verbose: false) }
let(:options) { {} }
let(:generator) { described_class.new(default_options.merge(options)) }

let(:bad_label) { { "name" => "BAD" } }
let(:bad_issue) { { "labels" => [bad_label] } }
let(:good_label) { { "name" => "GOOD" } }
let(:good_issue) { { "labels" => [good_label] } }
let(:unlabeled_issue) { { "labels" => [] } }
let(:issues) { [bad_issue, good_issue, unlabeled_issue] }

describe "#exclude_issues_by_labels" do
subject do
generator.exclude_issues_by_labels(issues)
end
describe "pull requests" do
let(:bad_pull_request) { { "pull_request" => {}, "labels" => [bad_label] } }
let(:good_pull_request) { { "pull_request" => {}, "labels" => [good_label] } }
let(:unlabeled_pull_request) { { "pull_request" => {}, "labels" => [] } }
let(:pull_requests) { [bad_pull_request, good_pull_request, unlabeled_pull_request] }

let(:expected_issues) { issues }
describe "#filter_wo_labels" do
subject do
generator.filter_wo_labels(pull_requests)
end

it { is_expected.to eq(expected_issues) }
let(:expected_pull_requests) { pull_requests }

context "when 'exclude_lables' is provided" do
let(:options) { { exclude_labels: %w[BAD BOO] } }
let(:expected_issues) { [good_issue, unlabeled_issue] }
it { is_expected.to eq(expected_pull_requests) }

it { is_expected.to eq(expected_issues) }
end
context "when 'add_pr_wo_labels' is false" do
let(:options) { { add_pr_wo_labels: false } }
let(:expected_pull_requests) { [bad_pull_request, good_pull_request] }

context "with no option given" do
subject(:generator) { described_class.new }
it "passes everything through when no option given" do
result = generator.exclude_issues_by_labels(issues)
it { is_expected.to eq(expected_pull_requests) }
end

context "when 'add_pr_wo_labels' is true" do
let(:options) { { add_pr_wo_labels: true } }

expect(result).to eq(issues)
it { is_expected.to eq(expected_pull_requests) }
end
end
end

describe "#get_filtered_issues" do
subject do
generator.get_filtered_issues(issues)
end
describe "issues" do
let(:bad_issue) { { "labels" => [bad_label] } }
let(:good_issue) { { "labels" => [good_label] } }
let(:unlabeled_issue) { { "labels" => [] } }
let(:issues) { [bad_issue, good_issue, unlabeled_issue] }

let(:expected_issues) { issues }

it { is_expected.to eq(expected_issues) }
describe "#filter_wo_labels" do
subject do
generator.filter_wo_labels(issues)
end

context "when 'exclude_labels' is provided" do
let(:options) { { exclude_labels: %w[BAD BOO] } }
let(:expected_issues) { [good_issue, unlabeled_issue] }
let(:expected_issues) { issues }

it { is_expected.to eq(expected_issues) }

context "when 'add_issues_wo_labels' is false" do
let(:options) { { add_issues_wo_labels: false } }
let(:expected_issues) { [bad_issue, good_issue] }

it { is_expected.to eq(expected_issues) }
end

context "when 'add_issues_wo_labels' is true" do
let(:options) { { add_issues_wo_labels: true } }

it { is_expected.to eq(expected_issues) }
end
end

context "when 'add_issues_wo_labels' is false" do
let(:options) { { add_issues_wo_labels: false } }
let(:expected_issues) { [bad_issue, good_issue] }
describe "#exclude_issues_by_labels" do
subject do
generator.exclude_issues_by_labels(issues)
end

let(:expected_issues) { issues }

it { is_expected.to eq(expected_issues) }

context "with 'exclude_labels'" do
let(:options) { { add_issues_wo_labels: false, exclude_labels: %w[GOOD] } }
let(:expected_issues) { [bad_issue] }
context "when 'exclude_labels' is provided" do
let(:options) { { exclude_labels: %w[BAD BOO] } }
let(:expected_issues) { [good_issue, unlabeled_issue] }

it { is_expected.to eq(expected_issues) }
end

context "with 'include_labels'" do
let(:options) { { add_issues_wo_labels: false, include_labels: %w[GOOD] } }
let(:expected_issues) { [good_issue] }
context "with no option given" do
subject(:generator) { described_class.new }
it "passes everything through when no option given" do
result = generator.exclude_issues_by_labels(issues)

it { is_expected.to eq(expected_issues) }
expect(result).to eq(issues)
end
end
end

context "when 'include_labels' is specified" do
let(:options) { { include_labels: %w[GOOD] } }
let(:expected_issues) { [good_issue, unlabeled_issue] }
describe "#get_filtered_issues" do
subject do
generator.get_filtered_issues(issues)
end

let(:expected_issues) { issues }

it { is_expected.to eq(expected_issues) }

context "when 'exclude_labels' is provided" do
let(:options) { { exclude_labels: %w[BAD BOO] } }
let(:expected_issues) { [good_issue, unlabeled_issue] }

it { is_expected.to eq(expected_issues) }
end

context "when 'add_issues_wo_labels' is false" do
let(:options) { { add_issues_wo_labels: false } }
let(:expected_issues) { [bad_issue, good_issue] }

it { is_expected.to eq(expected_issues) }

context "with 'exclude_labels'" do
let(:options) { { add_issues_wo_labels: false, exclude_labels: %w[GOOD] } }
let(:expected_issues) { [bad_issue] }

it { is_expected.to eq(expected_issues) }
end

context "with 'include_labels'" do
let(:options) { { add_issues_wo_labels: false, include_labels: %w[GOOD] } }
let(:expected_issues) { [good_issue] }

it { is_expected.to eq(expected_issues) }
end
end

context "when 'include_labels' is specified" do
let(:options) { { include_labels: %w[GOOD] } }
let(:expected_issues) { [good_issue, unlabeled_issue] }

it { is_expected.to eq(expected_issues) }
end
end
end
end
Expand Down