Skip to content

Commit

Permalink
Introduce approve.auto_approve_labels option (#817)
Browse files Browse the repository at this point in the history
Closes #554

Implemented as suggested by @chdsbd: 
> I think approve.auto_approve_labels and approve.auto_approve_usernames being separate such that one doesn't require  the other would match the behavior of other configuration options in Kodiak.

Also fixing some lint errors & enhances developer experience (see commits).
  • Loading branch information
paescuj authored Jun 9, 2022
1 parent 86559a0 commit 662b663
Show file tree
Hide file tree
Showing 15 changed files with 99 additions and 17 deletions.
3 changes: 3 additions & 0 deletions bot/.vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"recommendations": ["ms-python.python"]
}
3 changes: 1 addition & 2 deletions bot/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"python.pythonPath": ".venv/bin/python",
"python.defaultInterpreterPath": ".venv/bin/python",
"python.formatting.provider": "black",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
Expand All @@ -8,7 +8,6 @@
"python.linting.mypyEnabled": true,
"python.testing.pytestArgs": ["kodiak"],
"python.testing.unittestEnabled": false,
"python.testing.nosetestsEnabled": false,
"python.testing.pytestEnabled": true,
"python.linting.flake8Enabled": true,
"python.linting.pylintEnabled": true
Expand Down
7 changes: 6 additions & 1 deletion bot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The follow shows how to run commands for testing and development. For informatio
# bot/

# install dependencies
poetry config settings.virtualenvs.in-project true
poetry config virtualenvs.in-project true
poetry install

# format and lint using black, isort, mypy, flake8, pylint
Expand All @@ -32,3 +32,8 @@ ngrok http 3000
# running
s/dev --reload
```

If you have made any changes concerning the config, run the following command to update the schema:
```shell
poetry run kodiak gen-conf-json-schema > kodiak/test/fixtures/config/config-schema.json
```
2 changes: 2 additions & 0 deletions bot/kodiak/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ class Update(BaseModel):
class Approve(BaseModel):
# auto approve any PR created by a listed user.
auto_approve_usernames: List[str] = []
# auto approve any PR to which a listed label is assigned.
auto_approve_labels: List[str] = []


class InvalidVersion(ValueError):
Expand Down
13 changes: 10 additions & 3 deletions bot/kodiak/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -656,13 +656,20 @@ async def set_status(msg: str, markdown_content: Optional[str] = None) -> None:
is_draft_pull_request = (
pull_request.isDraft or pull_request.mergeStateStatus == MergeStateStatus.DRAFT
)
pull_request_auto_approve_labels = set(
config.approve.auto_approve_labels
).intersection(pull_request_labels)
has_auto_approve_label = len(pull_request_auto_approve_labels) > 0
if (
pull_request.author.login in config.approve.auto_approve_usernames
(
pull_request.author.login in config.approve.auto_approve_usernames
or has_auto_approve_label
)
and pull_request.state == PullRequestState.OPEN
and not is_draft_pull_request
):
# if the PR was created by an approve author and we have not previously
# given an approval, approve the PR.
# if the PR was created by an approve author or has an approve label
# and we have not previously given an approval, approve the PR.
sorted_reviews = sorted(bot_reviews, key=lambda x: x.createdAt)
kodiak_reviews = [
review for review in sorted_reviews if review.author.login == KODIAK_LOGIN
Expand Down
11 changes: 10 additions & 1 deletion bot/kodiak/test/fixtures/config/config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@
"approve": {
"title": "Approve",
"default": {
"auto_approve_usernames": []
"auto_approve_usernames": [],
"auto_approve_labels": []
},
"allOf": [
{
Expand Down Expand Up @@ -418,6 +419,14 @@
"items": {
"type": "string"
}
},
"auto_approve_labels": {
"title": "Auto Approve Labels",
"default": [],
"type": "array",
"items": {
"type": "string"
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions bot/kodiak/test/fixtures/config/v1-default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ require_automerge_label = true

[approve]
auto_approve_usernames = []
auto_approve_labels = []
3 changes: 2 additions & 1 deletion bot/kodiak/test/fixtures/config/v1-opposite.1.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ always = true
require_automerge_label = false

[approve]
auto_approve_usernames = ["dependabot"]
auto_approve_usernames = ["dependabot"] # default: []
auto_approve_labels = ["autoapprove"] # default: []
3 changes: 2 additions & 1 deletion bot/kodiak/test/fixtures/config/v1-opposite.2.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ always = true
require_automerge_label = false

[approve]
auto_approve_usernames = ["dependabot"]
auto_approve_usernames = ["dependabot"] # default: []
auto_approve_labels = ["autoapprove"] # default: []
10 changes: 8 additions & 2 deletions bot/kodiak/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ def test_config_default() -> None:
),
),
update=Update(always=True, require_automerge_label=False),
approve=Approve(auto_approve_usernames=["dependabot"]),
approve=Approve(
auto_approve_usernames=["dependabot"],
auto_approve_labels=["autoapprove"],
),
),
),
(
Expand Down Expand Up @@ -94,7 +97,10 @@ def test_config_default() -> None:
),
),
update=Update(always=True, require_automerge_label=False),
approve=Approve(auto_approve_usernames=["dependabot"]),
approve=Approve(
auto_approve_usernames=["dependabot"],
auto_approve_labels=["autoapprove"],
),
),
),
],
Expand Down
23 changes: 22 additions & 1 deletion bot/kodiak/test_evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1818,7 +1818,7 @@ async def test_mergeable_passing_update_always_enabled() -> None:


@pytest.mark.asyncio
async def test_mergeable_auto_approve() -> None:
async def test_mergeable_auto_approve_username() -> None:
"""
If a PR is opened by a user on the `approve.auto_approve_usernames` list Kodiak should approve the PR.
"""
Expand All @@ -1838,6 +1838,27 @@ async def test_mergeable_auto_approve() -> None:
assert api.update_branch.call_count == 0


@pytest.mark.asyncio
async def test_mergeable_auto_approve_label() -> None:
"""
If a PR has a label which is in the `approve.auto_approve_labels` list Kodiak should approve the PR.
"""
mergeable = create_mergeable()
api = create_api()
config = create_config()
pull_request = create_pull_request()
config.approve.auto_approve_labels = ["autoapprove"]
pull_request.labels.append("autoapprove")
await mergeable(api=api, config=config, pull_request=pull_request, bot_reviews=[])
assert api.approve_pull_request.call_count == 1
assert api.set_status.call_count == 1
assert "enqueued for merge (position=4th)" in api.set_status.calls[0]["msg"]
assert api.queue_for_merge.call_count == 1
assert api.dequeue.call_count == 0
assert api.merge.call_count == 0
assert api.update_branch.call_count == 0


@pytest.mark.asyncio
async def test_mergeable_auto_approve_existing_approval() -> None:
"""
Expand Down
9 changes: 5 additions & 4 deletions bot/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bot/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ inflection = "0.5.1"
markdown-html-finder = "^0.2.3"
markupsafe = "^1.1"
fastapi = "^0.47.0"
sentry-sdk = "^1.3.0"
sentry-sdk = "^1.5.12"
requests = "^2.22"
rure = "^0.2.2"
zstandard = "^0.13.0"
Expand Down
4 changes: 4 additions & 0 deletions bot/typings/rure/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from re import Match, RegexFlag
from typing import AnyStr, Optional, Pattern, overload

from rure import exceptions

__all__ = ["exceptions"]

_FlagsType = RegexFlag

@overload
Expand Down
22 changes: 22 additions & 0 deletions docs/docs/config-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,18 @@ This setting is useful when the "Required approving reviews" GitHub Branch Prote

See the "[Automated dependency updates with Dependabot](recipes.md#automated-dependency-updates-with-dependabot)" recipe for an example of this feature in action.

### `approve.auto_approve_labels`

- **type:** `string[]`
- **default:** `[]`
- **options:** List of label names

If a PR has a label assigned which is in the `approve.auto_approve_labels` list, Kodiak will automatically add an approval to the PR.

If Kodiak's review is dismissed, it will add a review again.

This setting is useful when the "Required approving reviews" GitHub Branch Protection setting is configured and dependency upgrade bots like dependabot, greenkeeper, etc, run on the repository. When these bots open a PR with the specified label(s), Kodiak can automatically add a review so dependency upgrade PRs can be automatically merged.

## configuration labels

Some configuration options set in `.kodiak.toml` can be overriden with pull request labels.
Expand Down Expand Up @@ -711,6 +723,16 @@ always = false # default: false
# (configured via `merge.automerge_label`). When disable, Kodiak will update any
# PR. This option only applies when `update.always = true`.
require_automerge_label = true # default: true

[approve]

# If a PR is opened by a user with a username in the `approve.auto_approve_usernames` list,
# Kodiak will automatically add an approval to the PR.
auto_approve_usernames = ["dependabot"] # default: []

# If a PR has a label assigned which is in the `approve.auto_approve_labels` list,
# Kodiak will automatically add an approval to the PR.
auto_approve_labels = ["dependencies"] # default: []
```

## other resources
Expand Down

0 comments on commit 662b663

Please sign in to comment.