Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions test/ci_provider/github/merge_request_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,45 @@ def test_enable_auto_merge_exception(self, mock_warn, mock_info, mock_resolve, m

# then
mock_warn.assert_any_call("Could not enable auto-merge for pull request because: Network error")


class GitHubMergeRequestEmptyCommitTest(unittest.TestCase):

@patch("valhalla.ci_provider.github.merge_request.get_valhalla_token", return_value="token")
@patch("valhalla.ci_provider.github.merge_request.GitRepository")
@patch("valhalla.ci_provider.github.merge_request.GitHubClient")
@patch("valhalla.ci_provider.github.merge_request.resolve")
@patch("valhalla.ci_provider.github.merge_request.info")
@patch("valhalla.ci_provider.github.merge_request.warn")
def test_create_empty_commit_and_retry_when_no_commits_between(self, mock_warn, mock_info, mock_resolve,
mock_client_cls, mock_git_cls, mock_token):
# given
with patch.dict('os.environ', {'GITHUB_REF_NAME': 'release-1.0.0'}):
mock_resolve.side_effect = lambda x: x
mock_client = MagicMock()
mock_client.api_url = "https://api.github.com"
mock_client.repo = "owner/repo"

no_commits_response = MagicMock()
no_commits_response.status_code = 422
no_commits_response.text = '{"errors":[{"message":"No commits between main and release-1.0.0"}]}'
pr_response = MagicMock()
pr_response.status_code = 201
pr_response.json.return_value = {"html_url": "https://github.com/owner/repo/pull/3", "number": 3}

mock_client.post.side_effect = [no_commits_response, pr_response]
mock_client_cls.return_value = mock_client
mock_git = mock_git_cls.return_value

pr = GitHubValhallaPullRequest()
config = MergeRequestConfig(enabled=True, target_branch="main", title="t", description="d", reviewers=[])

# when
pr.create(config)

# then
mock_git.commit_empty.assert_called_once()
mock_git.push.assert_called_once_with("token")
self.assertEqual(2, mock_client.post.call_count)
mock_info.assert_any_call("Created pull request: https://github.com/owner/repo/pull/3")
mock_warn.assert_not_called()
13 changes: 13 additions & 0 deletions valhalla/ci_provider/github/merge_request.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import os

from valhalla.ci_provider.get_token import get_valhalla_token
from valhalla.ci_provider.github.common import get_default_branch_fallback, GitHubClient
from valhalla.commit.commit import GitRepository
from valhalla.common.get_config import MergeRequestConfig
from valhalla.common.logger import info, warn
from valhalla.common.resolver import resolve


from valhalla.ci_provider.merge_request_hook import MergeRequestHook

EMPTY_COMMIT_MSG = "Empty commit to create PR to start release"


class GitHubValhallaPullRequest:
def __init__(self):
Expand Down Expand Up @@ -39,6 +43,15 @@ def create(self, merge_request_config: MergeRequestConfig):
}

resp = self.client.post(url, json=payload)
# GitHub does not allow empty pull requests, see:
# https://stackoverflow.com/questions/46577500/why-cant-i-create-an-empty-pull-request-for-discussion-prior-to-developing-chan
if resp.status_code == 422 and "No commits between" in resp.text:
info("GitHub does not allow creating pull request without commits, creating empty commit")
git = GitRepository(None, None)
git.commit_empty(EMPTY_COMMIT_MSG)
git.push(get_valhalla_token())
resp = self.client.post(url, json=payload)

if resp.status_code >= 300:
warn(f"Failed to create pull request: {resp.status_code} {resp.text}")
return MergeRequestHook.Skip()
Expand Down
5 changes: 5 additions & 0 deletions valhalla/commit/commit.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ def commit(self, msg: str, add=True) -> bool:
self.status()
return True

def commit_empty(self, msg: str):
msg += " [VALHALLA SKIP]"
self.repository.git.commit("--allow-empty", "-m", resolve(msg))
info(f"Created empty commit: {self.repository.head.commit}")

def push(self, token):
info("Preparing to push")
branch = self.repository.active_branch
Expand Down
Loading