From e5392bb33fa2bcc05e90c2a12f040f04667a3121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Sat, 29 Jan 2022 15:51:57 +0100 Subject: [PATCH] Undeploy builds on PR close --- src/runboat/api.py | 5 +---- src/runboat/controller.py | 12 ++++++++++++ src/runboat/webhooks.py | 26 ++++++++++++++++---------- tests/test_webhook.py | 28 +++++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/runboat/api.py b/src/runboat/api.py index 7f923cb..295a989 100644 --- a/src/runboat/api.py +++ b/src/runboat/api.py @@ -101,10 +101,7 @@ async def undeploy_builds( branch: str | None = None, pr: int | None = None, ) -> None: - for build in controller.db.search( - repo=repo, target_branch=target_branch, branch=branch, pr=pr - ): - await build.undeploy() + await controller.undeploy_builds(repo, target_branch, branch, pr) @router.post( diff --git a/src/runboat/controller.py b/src/runboat/controller.py index 82202d8..64e86b4 100644 --- a/src/runboat/controller.py +++ b/src/runboat/controller.py @@ -106,6 +106,18 @@ class Controller: if build is None: await Build.deploy(commit_info) + async def undeploy_builds( + self, + repo: str | None = None, + target_branch: str | None = None, + branch: str | None = None, + pr: int | None = None, + ) -> None: + for build in self.db.search( + repo=repo, target_branch=target_branch, branch=branch, pr=pr + ): + await build.undeploy() + async def get_build(self, build_name: str, db_only: bool = True) -> Build | None: build = self.db.get(build_name) if build is not None: diff --git a/src/runboat/webhooks.py b/src/runboat/webhooks.py index c2b6b49..9198159 100644 --- a/src/runboat/webhooks.py +++ b/src/runboat/webhooks.py @@ -20,17 +20,17 @@ async def receive_payload( # TODO check x-hub-signature payload = await request.json() if x_github_event == "pull_request": + repo = payload["repository"]["full_name"] + target_branch = payload["pull_request"]["base"]["ref"] + if not settings.is_repo_and_branch_supported(repo, target_branch): + _logger.debug( + "Ignoring %s payload for unsupported repo %s or target branch %s", + x_github_event, + repo, + target_branch, + ) + return if payload["action"] in ("opened", "synchronize"): - repo = payload["repository"]["full_name"] - target_branch = payload["pull_request"]["base"]["ref"] - if not settings.is_repo_and_branch_supported(repo, target_branch): - _logger.debug( - "Ignoring %s payload for unsupported repo %s or target branch %s", - x_github_event, - repo, - target_branch, - ) - return background_tasks.add_task( controller.deploy_commit, CommitInfo( @@ -40,6 +40,12 @@ async def receive_payload( git_commit=payload["pull_request"]["head"]["sha"], ), ) + elif payload["action"] in ("closed",): + background_tasks.add_task( + controller.undeploy_builds, + repo=repo, + pr=payload["pull_request"]["number"], + ) elif x_github_event == "push": repo = payload["repository"]["full_name"] target_branch = payload["ref"].split("/")[-1] diff --git a/tests/test_webhook.py b/tests/test_webhook.py index 143b5cf..fc75914 100644 --- a/tests/test_webhook.py +++ b/tests/test_webhook.py @@ -85,7 +85,7 @@ def test_webhook_github_pr(action: str, mocker: MockerFixture) -> None: ) -@pytest.mark.parametrize("action", ["opened", "synchronize"]) +@pytest.mark.parametrize("action", ["opened", "synchronize", "closed"]) def test_webhook_github_pr_unsupported_branch( action: str, mocker: MockerFixture ) -> None: @@ -111,3 +111,29 @@ def test_webhook_github_pr_unsupported_branch( ) response.raise_for_status() mock.assert_not_called() + + +def test_webhook_github_pr_close(mocker: MockerFixture) -> None: + mock = mocker.patch("fastapi.BackgroundTasks.add_task") + response = client.post( + "/webhooks/github", + headers={ + "X-GitHub-Event": "pull_request", + }, + json={ + "action": "closed", + "repository": {"full_name": "oca/mis-builder"}, + "pull_request": { + "base": { + "ref": "15.0", + }, + "number": 381, + }, + }, + ) + response.raise_for_status() + mock.assert_called_with( + controller.undeploy_builds, + repo="oca/mis-builder", + pr=381, + )