Skip to content

Commit

Permalink
[ADD] ocabot migration issue maintainer
Browse files Browse the repository at this point in the history
New ocabot command for maintaining migration issues:

``/ocabot migration``, followed by the module name, performing the following:

* Look for an issue in that repository with the name "Migration to version
  ``{version}``", where ``{version}`` is the name of the target branch.
* Add or edit a line in that issue, linking the module to the pull request
  (PR) and the author of it.
* TODO: When the PR is merged, the line gets ticked.
* Put the milestone corresponding to the target branch in the PR.

Co-authored-by: Pedro M. Baeza <pedro.baeza@tecnativa.com>
  • Loading branch information
victoralmau and pedrobaeza committed Feb 23, 2021
1 parent f699baa commit efc3950
Show file tree
Hide file tree
Showing 7 changed files with 255 additions and 1 deletion.
11 changes: 11 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,15 @@ can be used to ask the bot to do the following:
* when the version was bumped, generate a wheel and rsync it to the PEP 503
simple index

``/ocabot migration``, followed by the module name, performing the following:

* Look for an issue in that repository with the name "Migration to version
``{version}``", where ``{version}`` is the name of the target branch.
* Add or edit a line in that issue, linking the module to the pull request
(PR) and the author of it.
* TODO: When the PR is merged, the line gets ticked.
* Put the milestone corresponding to the target branch in the PR.

TODO (help wanted)
------------------

Expand Down Expand Up @@ -204,6 +213,8 @@ Contributors
* Jose Angel Fentanez <joseangel@vauxoo.com>
* Simone Rubino <simone.rubino@agilebg.com>
* Sylvain Le Gal (https://twitter.com/legalsylvain)
* Tecnativa - Pedro M. Baeza
* Tecnativa - Víctor Martínez

Maintainers
===========
Expand Down
19 changes: 18 additions & 1 deletion src/oca_github_bot/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import re

from .tasks import merge_bot
from .tasks import merge_bot, migration_issue_bot

BOT_COMMAND_RE = re.compile(
# Do not start with > (Github comment), not consuming it
Expand Down Expand Up @@ -59,6 +59,8 @@ def __init__(self, name, options):
def create(cls, name, options):
if name == "merge":
return BotCommandMerge(name, options)
elif name == "migration":
return BotCommandMigrationIssue(name, options)
else:
raise InvalidCommandError(name)

Expand Down Expand Up @@ -90,6 +92,21 @@ def delay(self, org, repo, pr, username, dry_run=False):
)


class BotCommandMigrationIssue(BotCommand):
module = None # mandatory str: module name

def parse_options(self, options):
if len(options) == 1:
self.module = options[0]
else:
raise InvalidOptionsError(self.name, options)

def delay(self, org, repo, pr, username, dry_run=False):
migration_issue_bot.migration_issue_start.delay(
org, repo, pr, username, module=self.module, dry_run=dry_run
)


def parse_commands(text):
""" Parse a text and return an iterator of BotCommand objects. """
for mo in BOT_COMMAND_RE.finditer(text):
Expand Down
6 changes: 6 additions & 0 deletions src/oca_github_bot/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ def func_wrapper(*args, **kwargs):

DRY_RUN = os.environ.get("DRY_RUN", "").lower() in ("1", "true", "yes")

# Coma separated list of task to run
# By default all configured tasks are run.
# Available tasks:
# delete_branch,tag_approved,tag_ready_to_merge,gen_addons_table,
# gen_addons_readme,gen_addons_icon,setuptools_odoo,merge_bot,tag_needs_review,
# migration_issue_bot
BOT_TASKS = os.environ.get("BOT_TASKS", "all").split(",")

BOT_TASKS_DISABLED = os.environ.get("BOT_TASKS_DISABLED", "").split(",")
Expand Down
1 change: 1 addition & 0 deletions src/oca_github_bot/tasks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
heartbeat,
main_branch_bot,
mention_maintainer,
migration_issue_bot,
tag_approved,
tag_needs_review,
tag_ready_to_merge,
Expand Down
114 changes: 114 additions & 0 deletions src/oca_github_bot/tasks/migration_issue_bot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Copyright 2019 Tecnativa - Pedro M. Baeza
# Copyright 2021 Tecnativa - Víctor Martínez
# Distributed under the MIT License (http://opensource.org/licenses/MIT).

import re

from .. import github
from ..config import switchable
from ..process import check_call
from ..queue import getLogger, task
from .merge_bot import _user_can_merge

_logger = getLogger(__name__)


def _create_or_find_branch_milestone(repo, branch):
for milestone in repo.milestones():
if milestone.title == branch:
return milestone
return repo.create_milestone(branch)


def _find_issue(repo, milestone, target_branch):
issue_title = f"Migration to version {target_branch}"
issue = False
for i in repo.issues(milestone=milestone.number):
if i.title == issue_title:
issue = i
break
return issue


def _set_lines_issue(gh_pr, issue, module):
lines = []
added = False
module_list = False
new_line = f"- [ ] {module} - By @{gh_pr.user.login} - #{gh_pr.number}"
for line in issue.body.split("\n"):
if line.startswith(f"- [ ] {module}"):
lines.append(new_line)
continue
elif not added:
splits = re.split(r"- \[ \] ([0-9a-zA-Z_]*)", line)
if len(splits) >= 2:
# Flag for detecting if we have passed already module list
module_list = True
line_module = splits[1]
if line_module > module:
lines.append(new_line)
added = True
elif module_list:
lines.append(new_line)
added = True
lines.append(line)
return lines


@task()
@switchable("migration_issue_bot")
def migration_issue_start(org, repo, pr, username, module=None, dry_run=False):
with github.login() as gh:
gh_pr = gh.pull_request(org, repo, pr)
target_branch = gh_pr.base.ref
pr_branch = f"tmp-pr-{pr}"
try:
with github.temporary_clone(org, repo, target_branch) as clone_dir:
# Create merge bot branch from PR and rebase it on target branch
# This only serves for checking permissions
check_call(
["git", "fetch", "origin", f"pull/{pr}/head:{pr_branch}"],
cwd=clone_dir,
)
check_call(["git", "checkout", pr_branch], cwd=clone_dir)
if not _user_can_merge(
gh, org, repo, username, clone_dir, target_branch
):
github.gh_call(
gh_pr.create_comment,
f"Sorry @{username} you are not allowed to mark the addon to"
f"be migrated.\n\n"
f"To do so you must either have push permissions on "
f"the repository, or be a declared maintainer of all "
f"modified addons.\n\n"
f"If you wish to adopt an addon and become it's "
f"[maintainer]"
f"(https://odoo-community.org/page/maintainer-role), "
f"open a pull request to add "
f"your GitHub login to the `maintainers` key of its "
f"manifest.",
)
return
# Assign milestone to PR
milestone = _create_or_find_branch_milestone(repo, target_branch)
gh_pr.issue().edit(milestone=milestone.number)
# Find issue
issue = _find_issue(repo, milestone, target_branch)
if not issue:
github.gh_call(
gh_pr.create_comment,
f"There's no issue in this repo with the title '{issue_title}' "
f"and the milestone {target_branch}, so not possible to add "
f"the comment.",
)
return
# Change issue to add the PR in the module list
lines = _set_lines_issue(gh_pr, issue, module)
issue.edit(body="\n".join(lines))
except Exception as e:
github.gh_call(
gh_pr.create_comment,
f"@{username} The migration issue commenter process could not "
f"start, because of exception {e}.",
)
raise
68 changes: 68 additions & 0 deletions tests/cassettes/test_create_or_find_branch_milestone.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
interactions:
- request:
body: null
headers:
Accept:
- application/vnd.github.v3.full+json
Accept-Charset:
- utf-8
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Type:
- application/json
User-Agent:
- github3.py/1.3.0
authorization:
- DUMMY
method: GET
uri: https://api.github.com/repos/OCA/contract
response:
body:
string: '{"message":"Bad credentials","documentation_url":"https://docs.github.com/rest"}'
headers:
Access-Control-Allow-Origin:
- '*'
Access-Control-Expose-Headers:
- ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining,
X-RateLimit-Used, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes,
X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset
Content-Length:
- '80'
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json; charset=utf-8
Date:
- Mon, 22 Feb 2021 16:13:08 GMT
Referrer-Policy:
- origin-when-cross-origin, strict-origin-when-cross-origin
Server:
- GitHub.com
Strict-Transport-Security:
- max-age=31536000; includeSubdomains; preload
Vary:
- Accept-Encoding, Accept, X-Requested-With
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- deny
X-GitHub-Media-Type:
- github.v3; param=full; format=json
X-GitHub-Request-Id:
- 1ACE:CF7C:5A9C753:64D7CA5:6033D814
X-RateLimit-Limit:
- '60'
X-RateLimit-Remaining:
- '59'
X-RateLimit-Reset:
- '1614013988'
X-XSS-Protection:
- 1; mode=block
x-ratelimit-used:
- '1'
status:
code: 401
message: ''
version: 1
37 changes: 37 additions & 0 deletions tests/test_migration_issue_bot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright 2021 Tecnativa - Víctor Martínez
# Distributed under the MIT License (http://opensource.org/licenses/MIT).

import pytest

from oca_github_bot.tasks.migration_issue_bot import (
_create_or_find_branch_milestone,
_find_issue,
_set_lines_issue,
)

def _get_repository(gh, org, repo):
return gh.repository(org, repo)


@pytest.mark.vcr()
def test_create_or_find_branch_milestone(gh):
repo = _get_repository(gh, "OCA", "contract")
milestone = _create_or_find_branch_milestone(repo, "8.0")
assert milestone.name == "8.0"


@pytest.mark.vcr()
def test_find_issue(gh):
repo = _get_repository(gh, "OCA", "contract")
milestone = _create_or_find_branch_milestone(repo, "8.0")
issue = _find_issue(repo, milestone, "14.0")
assert issue.name == "Migration to version 14.0"


@pytest.mark.vcr()
def test_set_lines_issue(gh):
repo = _get_repository(gh, "OCA", "contract")
milestone = _create_or_find_branch_milestone(repo, "13.0")
issue = _find_issue(repo, milestone, "14.0")
lines = _set_lines_issue(gh, issue, "contract")
assert len(lines) > 0

0 comments on commit efc3950

Please sign in to comment.