Skip to content

Commit

Permalink
Add: New CLI for updating a GitHub Pull Request
Browse files Browse the repository at this point in the history
Changed `pontos-github pr` to use subcommands for creating and updating
pull requests. This requires updates of all workflows using the CLI.
  • Loading branch information
bjoernricks committed Apr 1, 2022
1 parent c4c53a5 commit 1fabf1f
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 33 deletions.
89 changes: 71 additions & 18 deletions pontos/github/argparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@

""" Argument parser for pontos-github """

from argparse import ArgumentParser, FileType, Namespace
import os

from argparse import ArgumentParser, FileType, Namespace
from pathlib import Path
from typing import List

from pontos.github.cmds import file_status, pull_request, labels
from pontos.github.cmds import (
create_pull_request,
file_status,
labels,
pull_request,
update_pull_request,
)
from pontos.github.api import FileStatus

body_template = Path(__file__).parent / "pr_template.md"
Expand All @@ -35,11 +42,13 @@ def from_env(name: str) -> str:
def parse_args(
args: List[str] = None,
) -> Namespace:
"""Parsing args for nasl-lint
"""
Parsing args for Pontos GitHub
Arguments:
args The programm arguments passed by exec
term The terminal to print"""
args The program arguments passed by exec
term The terminal to print
"""

parser = ArgumentParser(
description="Greenbone GitHub API.",
Expand All @@ -61,26 +70,52 @@ def parse_args(
pr_parser.set_defaults(func=pull_request)

pr_parser.add_argument(
"repo", help=("GitHub repository (owner/name) to use")
"-t",
"--token",
default="GITHUB_TOKEN",
type=from_env,
help=(
"GitHub Token to access the repository. "
"Default looks for environment variable 'GITHUB_TOKEN'"
),
)

pr_parser.add_argument(
pr_subparsers = pr_parser.add_subparsers(
title="method",
dest="pr_method",
metavar="name",
description="valid pull request method",
help="pull request method",
required=True,
)

create_pr_parser = pr_subparsers.add_parser(
"create", help="Create Pull Request"
)

create_pr_parser.set_defaults(pr_func=create_pull_request)

create_pr_parser.add_argument(
"repo", help="GitHub repository (owner/name) to use"
)

create_pr_parser.add_argument(
"head",
help=("Branch to create a pull request from"),
)

pr_parser.add_argument(
create_pr_parser.add_argument(
"target",
default="main",
help="Branch as as target for the pull. Default: %(default)s",
)

pr_parser.add_argument(
create_pr_parser.add_argument(
"title",
help=("Title for the pull request"),
help="Title for the pull request",
)

pr_parser.add_argument(
create_pr_parser.add_argument(
"-b",
"--body",
default=body_template.read_text(encoding="utf-8"),
Expand All @@ -89,14 +124,32 @@ def parse_args(
),
)

pr_parser.add_argument(
"-t",
"--token",
default="GITHUB_TOKEN",
type=from_env,
update_pr_parser = pr_subparsers.add_parser(
"update", help="update Pull Request"
)

update_pr_parser.set_defaults(pr_func=update_pull_request)

update_pr_parser.add_argument(
"repo", help="GitHub repository (owner/name) to use"
)
update_pr_parser.add_argument(
"pull_request", type=int, help="Pull Request to update"
)
update_pr_parser.add_argument(
"--target",
help="Branch as as target for the pull.",
)
update_pr_parser.add_argument(
"--title",
help="Title for the pull request",
)

update_pr_parser.add_argument(
"-b",
"--body",
help=(
"GitHub Token to access the repository. "
"Default looks for environment variable 'GITHUB_TOKEN'"
"Description for the pull request. Can be formatted in Markdown."
),
)

Expand Down
32 changes: 32 additions & 0 deletions pontos/github/cmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@


def pull_request(args: Namespace):
args.pr_func(args)


def create_pull_request(args: Namespace):
git = GitHubRESTApi(token=args.token)

try:
Expand Down Expand Up @@ -59,6 +63,34 @@ def pull_request(args: Namespace):
ok("Pull Request created.")


def update_pull_request(args: Namespace):
git = GitHubRESTApi(token=args.token)

try:
if args.target:
# check if branches exist
if not git.branch_exists(repo=args.repo, branch=args.target):
error(
f"Target branch {args.target} is not existing or "
"authorisation failed."
)
sys.exit(1)

ok(f"Target branch {args.target} exists.")
git.update_pull_request(
repo=args.repo,
pull_request=args.pull_request,
base_branch=args.target,
title=args.title,
body=args.body,
)
except requests.exceptions.RequestException as e:
error(str(e))
sys.exit(1)

ok("Pull Request updated.")


def file_status(args: Namespace):
git = GitHubRESTApi(token=args.token)

Expand Down
61 changes: 46 additions & 15 deletions tests/github/test_argparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,21 @@
from pontos.github.api import FileStatus

from pontos.github.argparser import parse_args
from pontos.github.cmds import file_status, pull_request
from pontos.github.cmds import (
file_status,
create_pull_request,
update_pull_request,
)


class TestArgparsing(unittest.TestCase):
def setUp(self):
self.term = Mock()

def test_pr_parse_args(self):
def test_create_pr_parse_args(self):
argv = [
"pr",
"create",
"foo/bar",
"baz",
"main",
Expand All @@ -45,21 +50,47 @@ def test_pr_parse_args(self):

template = Path().cwd() / 'pontos/github/pr_template.md'

expected_args = Namespace(
body=template.read_text(encoding='utf-8'),
command='pr',
func=pull_request,
head='baz',
repo='foo/bar',
target='main',
title='baz in main',
token='GITHUB_TOKEN',
)
self.assertEqual(parsed_args.command, "pr")
self.assertEqual(parsed_args.token, "GITHUB_TOKEN")
self.assertEqual(parsed_args.body, template.read_text(encoding='utf-8'))
self.assertEqual(parsed_args.pr_func, create_pull_request)
self.assertEqual(parsed_args.repo, "foo/bar")
self.assertEqual(parsed_args.target, "main")
self.assertEqual(parsed_args.title, "baz in main")

def test_create_pr_parse_args_fail(self):
argv = ["pr", "create", "foo/bar"]

with self.assertRaises(SystemExit):
parse_args(argv)

self.assertEqual(parsed_args, expected_args)
def test_update_pr_parse_args(self):
argv = [
"pr",
"update",
"foo/bar",
"123",
"--body",
"foo",
"--target",
"main",
"--title",
"baz in main",
]

parsed_args = parse_args(argv)

def test_pr_parse_args_fail(self):
argv = ["pr", "foo/bar"]
self.assertEqual(parsed_args.command, "pr")
self.assertEqual(parsed_args.token, "GITHUB_TOKEN")
self.assertEqual(parsed_args.body, "foo")
self.assertEqual(parsed_args.pr_func, update_pull_request)
self.assertEqual(parsed_args.repo, "foo/bar")
self.assertEqual(parsed_args.pull_request, 123)
self.assertEqual(parsed_args.target, "main")
self.assertEqual(parsed_args.title, "baz in main")

def test_update_pr_parse_args_fail(self):
argv = ["pr", "update", "foo/bar"]

with self.assertRaises(SystemExit):
parse_args(argv)
Expand Down

0 comments on commit 1fabf1f

Please sign in to comment.