Skip to content
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

add requirement and detection that breaking changes are explained in release notes #586

Merged
merged 15 commits into from
Dec 17, 2024
Merged
22 changes: 22 additions & 0 deletions docs/src/guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,28 @@ very possible for a perfectly good name to not pass the automatic checks and
require manual merging. They simply exist to provide a fast path so that
manual review is not required for every new package.

### Providing and updating release notes

When invoking a registration with the `@JuliaRegister` bot, release notes can be added in the form
```
@JuliaRegistrator register

Release notes:

## Breaking changes

- Explanation of breaking change, ideally with upgrade tips
- ...
```

These can also be added/updated on the General PR by re-invoking with the above.

Doing this has two benefits:
- helps explanations during the registration process, especially for breaking changes
- release notes are picked up by TagBot such that they are added to the new release on the orignial repo

Automerge is disabled for breaking changes where release notes are not provided mentioning "breaking".

## List of all GitHub PR labels that can influence AutoMerge

AutoMerge reads certain labels on GitHub registration pull requests to influence its decisions.
Expand Down
31 changes: 31 additions & 0 deletions src/AutoMerge/guidelines.jl
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,35 @@ function meets_name_match_check(
return (true, "")
end

# This check checks for an explanation of why a breaking change is breaking
const guideline_breaking_explanation = Guideline(;
info = "Release notes have not been provided that explain why this is a breaking change.",
docs = "If this is a breaking change, release notes must be given that explain why this is a breaking change (i.e. mention \"breaking\"). To update the release notes, please see the \"Providing and updating release notes\" subsection under \"Additional information\" below.",
check=data -> meets_breaking_explanation_check(data))

function meets_breaking_explanation_check(data)
# Look up PR here in case the labels are slow to be applied by the Registrator bot
# which decides wheter to add the BREAKING label
IanButterworth marked this conversation as resolved.
Show resolved Hide resolved
pr = GitHub.pull_request(data.api, data.registry, data.pr.number; auth=data.auth)
if any(==("BREAKING"), pr.labels)
release_notes = get_release_notes(pr.body)
if release_notes === nothing
return false, "This is a breaking change, but no release notes have been provided."
elseif !occursin(r"breaking", lowercase(release_notes))
return false, "This is a breaking change, but the release notes do not mention it."
ericphanson marked this conversation as resolved.
Show resolved Hide resolved
else
return true, ""
end
else
return true, ""
end
end

function get_release_notes(body::AbstractString)
pattern = r"<!-- BEGIN RELEASE NOTES -->(?s)(.*?)<!-- END RELEASE NOTES -->"
m = match(pattern, body)
return m === nothing ? nothing : m.captures[1]
end

# This check looks for similar (but not exactly matching) names. It can be
# overridden by a label.
Expand Down Expand Up @@ -1078,6 +1107,7 @@ function get_automerge_guidelines(
this_is_jll_package::Bool,
this_pr_can_use_special_jll_exceptions::Bool,
use_distance_check::Bool,
use_breaking_explanation_check::Bool = !this_is_jll_package,
package_author_approved::Bool # currently unused for new packages
)
guidelines = [
Expand Down Expand Up @@ -1111,6 +1141,7 @@ function get_automerge_guidelines(
(guideline_dependency_confusion, true),
# this is the non-optional part of name checking
(guideline_name_match_check, true),
(guideline_breaking_explanation, use_breaking_explanation_check),
# We always run the `guideline_distance_check`
# check last, because if the check fails, it
# prints the list of similar package names in
Expand Down
29 changes: 29 additions & 0 deletions test/automerge-unit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,35 @@ end
@test !AutoMerge.range_did_not_narrow(r2, r3)[1]
@test !AutoMerge.range_did_not_narrow(r3, r2)[1]
end

@testset "Breaking change releases must have explanatory release notes" begin
body_good = """
<!-- BEGIN RELEASE NOTES -->
`````
## Breaking changes
- something
- something else
`````
<!-- END RELEASE NOTES -->
"""
body_bad = """
<!-- BEGIN RELEASE NOTES -->
`````
## Features
- something
- something else
`````
<!-- END RELEASE NOTES -->
"""
body_bad_no_notes = ""

@test AutoMerge.meets_breaking_explanation_check(["BREAKING"], body_good)[1]
@test !AutoMerge.meets_breaking_explanation_check(["BREAKING"], body_bad)[1]
@test !AutoMerge.meets_breaking_explanation_check(["BREAKING"], body_bad_no_notes)[1]

# Maybe this should fail as the label isn't applied by JuliaRegistrator, so the version isn't breaking?
@test AutoMerge.meets_breaking_explanation_check([], body_good)[1]
end
end

@testset "Guidelines for both new packages and new versions" begin
Expand Down
Loading