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()