diff --git a/README.md b/README.md
index 8ec190e..7d6bfd0 100644
--- a/README.md
+++ b/README.md
@@ -59,6 +59,7 @@ It operates on a per-branch basis, meaning you can have different settings for d
Dependabot alerts and updates
GitHub Actions build status emails
GitHub Pages
+ Pull Request settings
Merge buttons
Repository features
Repository metadata
@@ -564,6 +565,9 @@ github:
del_branch_on_merge: true
~~~
+> [!WARNING]
+> This setting is deprecated and has been moved to [pull_requests.del_branch_on_merge](#pull_requests).
+
You can revert this by setting the variable back to false. (Merely removing the entry will not do that).
Dependabot alerts and updates
@@ -603,6 +607,27 @@ The `ghp_branch` setting can **only** be your default branch (e.g. master, main,
The `ghp_path` setting should **always** be specified. It can be either `/docs` or `/`. If not specified, it will default to `/docs`.
+Pull Request settings
+
+Projects can enable/disable various settings for PRs:
+
+- allow [auto-merging](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/automatically-merging-a-pull-request) of PRs
+- allow [updating](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/keeping-your-pull-request-in-sync-with-the-base-branch) head branches of PRs
+- automatically [delete](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-the-automatic-deletion-of-branches) head branches after merge
+
+Example:
+
+~~~yaml
+github:
+ pull_requests:
+ # allow auto-merge
+ allow_auto_merge: true
+ # enable updating head branches of pull requests
+ allow_update_branch: true
+ # auto-delete head branches after being merged
+ del_branch_on_merge: true
+~~~
+
Merge buttons
Projects can enable/disable the `merge PR` button in the GitHub UI and configure which actions to allow by adding the following configuration (or derivatives thereof):
diff --git a/asfyaml/feature/github/__init__.py b/asfyaml/feature/github/__init__.py
index 5b39eb0..f67efc1 100644
--- a/asfyaml/feature/github/__init__.py
+++ b/asfyaml/feature/github/__init__.py
@@ -132,7 +132,15 @@ class ASFGitHubFeature(ASFYamlFeature, name="github"):
}
),
),
+ strictyaml.Optional("pull_requests"): strictyaml.Map(
+ {
+ strictyaml.Optional("del_branch_on_merge"): strictyaml.Bool(),
+ strictyaml.Optional("allow_auto_merge"): strictyaml.Bool(),
+ strictyaml.Optional("allow_update_branch"): strictyaml.Bool(),
+ }
+ ),
# Delete branch on merge
+ # TODO: deprecated, use "pull_requests.del_branch_on_merge" instead
strictyaml.Optional("del_branch_on_merge"): strictyaml.Bool(),
# Dependabot
strictyaml.Optional("dependabot_alerts"): strictyaml.Bool(),
@@ -207,6 +215,7 @@ def run(self):
autolink,
features,
branch_protection,
+ pull_requests,
merge_buttons,
pages,
custom_subjects,
diff --git a/asfyaml/feature/github/housekeeping.py b/asfyaml/feature/github/housekeeping.py
index eb4e1ec..46e2f03 100644
--- a/asfyaml/feature/github/housekeeping.py
+++ b/asfyaml/feature/github/housekeeping.py
@@ -15,17 +15,13 @@
# specific language governing permissions and limitations
# under the License.
-"""GitHub housekeeping features: delete branch on merge, dependabot.."""
+"""GitHub housekeeping features: dependabot."""
from . import directive, ASFGitHubFeature
@directive
def housekeeping_features(self: ASFGitHubFeature):
- del_branch_on_merge = self.yaml.get("del_branch_on_merge", None)
- if del_branch_on_merge is not None and not self.noop("del_branch_on_merge"):
- self.ghrepo.edit(delete_branch_on_merge=del_branch_on_merge)
-
dependabot_alerts = self.yaml.get("dependabot_alerts", None)
if dependabot_alerts is not None and not self.noop("dependabot_alerts"):
if dependabot_alerts is True:
diff --git a/asfyaml/feature/github/pull_requests.py b/asfyaml/feature/github/pull_requests.py
new file mode 100644
index 0000000..52a3232
--- /dev/null
+++ b/asfyaml/feature/github/pull_requests.py
@@ -0,0 +1,65 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""Settings related to GitHub Pull Requests"""
+
+from github.GithubObject import NotSet, is_defined
+
+from . import directive, ASFGitHubFeature
+
+
+@directive
+def pull_requests(self: ASFGitHubFeature):
+ # retrieve the legacy "del_branch_on_merge" setting from the github object
+ legacy_del_branch_on_merge = self.yaml.get("del_branch_on_merge", NotSet)
+
+ pull_requests = self.yaml.get("pull_requests")
+ if pull_requests:
+ allow_auto_merge = pull_requests.get("allow_auto_merge", NotSet)
+ allow_update_branch = pull_requests.get("allow_update_branch", NotSet)
+ del_branch_on_merge = pull_requests.get("del_branch_on_merge", NotSet)
+
+ if is_defined(legacy_del_branch_on_merge):
+ raise Exception(
+ "found legacy setting 'github.del_branch_on_merge' while "
+ "'github.pull_requests' is present. Move setting to 'github.pull_requests'"
+ )
+ else:
+ allow_auto_merge = NotSet
+ allow_update_branch = NotSet
+ del_branch_on_merge = legacy_del_branch_on_merge
+
+ # check if we have any defined property
+ any_defined_property = any(
+ map(lambda x: is_defined(x), (del_branch_on_merge, allow_auto_merge, allow_update_branch))
+ )
+
+ if any_defined_property and not self.noop("pull_requests"):
+ if is_defined(allow_auto_merge):
+ print(f"Setting allow_auto_merge to '{allow_auto_merge}'")
+
+ if is_defined(allow_update_branch):
+ print(f"Setting allow_update_branch to '{allow_update_branch}'")
+
+ if is_defined(del_branch_on_merge):
+ print(f"Setting del_branch_on_merge to '{del_branch_on_merge}'")
+
+ self.ghrepo.edit(
+ allow_auto_merge=allow_auto_merge,
+ allow_update_branch=allow_update_branch,
+ delete_branch_on_merge=del_branch_on_merge,
+ )
diff --git a/tests/github_pull_requests.py b/tests/github_pull_requests.py
new file mode 100644
index 0000000..8c6e391
--- /dev/null
+++ b/tests/github_pull_requests.py
@@ -0,0 +1,81 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""Unit tests for .asf.yaml GitHub pull request features"""
+
+from helpers import YamlTest
+import asfyaml.asfyaml
+import asfyaml.dataobjects
+
+# Set .asf.yaml to debug mode
+asfyaml.asfyaml.DEBUG = True
+
+
+legacy_setting = YamlTest(
+ None,
+ None,
+ """
+github:
+ del_branch_on_merge: true
+""",
+)
+
+
+valid_pull_request_settings = YamlTest(
+ None,
+ None,
+ """
+github:
+ pull_requests:
+ del_branch_on_merge: true
+ allow_auto_merge: true
+ allow_update_branch: true
+""",
+)
+
+
+invalid_legacy_and_pull_requests = YamlTest(
+ asfyaml.asfyaml.ASFYAMLException,
+ "found legacy setting 'github.del_branch_on_merge' while 'github.pull_requests' is present. Move setting to 'github.pull_requests'",
+ """
+github:
+ del_branch_on_merge: true
+ pull_requests:
+ del_branch_on_merge: false
+ allow_auto_merge: true
+ allow_update_branch: true
+""",
+)
+
+
+def test_basic_yaml(test_repo: asfyaml.dataobjects.Repository):
+ print("[github] Testing pull requests")
+
+ tests_to_run = (
+ legacy_setting,
+ valid_pull_request_settings,
+ invalid_legacy_and_pull_requests,
+ )
+
+ for test in tests_to_run:
+ with test.ctx():
+ a = asfyaml.asfyaml.ASFYamlInstance(
+ repo=test_repo, committer="humbedooh", config_data=test.yaml, branch=asfyaml.dataobjects.DEFAULT_BRANCH
+ )
+ a.environments_enabled.add("noop")
+ a.no_cache = True
+ a.run_parts()