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
10 changes: 10 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Valhalla

## Testy
System Python nie ma zależności ani `pytest`, a `python3 -m venv` nie działa (brak `ensurepip`). Używaj `uv` (za proxy z własnym CA potrzebne `--system-certs`):

```
uv venv <dir>/venv
VIRTUAL_ENV=<dir>/venv uv pip install --system-certs -r requirements.txt
<dir>/venv/bin/python -m pytest -q test
```
25 changes: 19 additions & 6 deletions test/ci_provider/gitlab/merge_request_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ def test_add_comment_exception(self, mock_warn, mock_info, mock_resolve, mock_ge
@patch("valhalla.ci_provider.gitlab.merge_request.resolve")
@patch("valhalla.ci_provider.gitlab.merge_request.info")
@patch("valhalla.ci_provider.gitlab.merge_request.warn")
def test_enable_auto_merge(self, mock_warn, mock_info, mock_resolve, mock_get_project_id,
@patch("valhalla.ci_provider.gitlab.merge_request.Repo")
@patch("valhalla.ci_provider.gitlab.merge_request.time.sleep")
def test_enable_auto_merge(self, mock_sleep, mock_repo, mock_warn, mock_info, mock_resolve, mock_get_project_id,
mock_get_gitlab_client):
with patch.dict('os.environ', {'CI_COMMIT_BRANCH': 'feature-branch'}):
# given:
Expand All @@ -196,8 +198,11 @@ def test_enable_auto_merge(self, mock_warn, mock_info, mock_resolve, mock_get_pr
mock_gitlab_client.projects.get.return_value = mock_project
mock_get_gitlab_client.return_value = mock_gitlab_client

mock_mr_obj = MagicMock()
mock_project.mergerequests.get.return_value = mock_mr_obj
mock_repo.return_value.head.commit.hexsha = "new-sha"
stale_mr_obj = MagicMock(sha="old-sha", detailed_merge_status="mergeable")
checking_mr_obj = MagicMock(sha="new-sha", detailed_merge_status="checking")
mock_mr_obj = MagicMock(sha="new-sha", detailed_merge_status="mergeable")
mock_project.mergerequests.get.side_effect = [stale_mr_obj, checking_mr_obj, mock_mr_obj]

merge_request = GitLabValhallaMergeRequest()
config = MergeRequestConfig(enabled=True, target_branch="main", title="T", description="D", reviewers=[],
Expand All @@ -208,15 +213,20 @@ def test_enable_auto_merge(self, mock_warn, mock_info, mock_resolve, mock_get_pr
hook.enable_auto_merge()

# then:
mock_mr_obj.merge.assert_called_once_with(merge_when_pipeline_succeeds=True)
self.assertEqual(mock_sleep.call_count, 2)
stale_mr_obj.merge.assert_not_called()
checking_mr_obj.merge.assert_not_called()
mock_mr_obj.merge.assert_called_once_with(sha="new-sha", merge_when_pipeline_succeeds=True)
mock_info.assert_any_call("Auto-merge enabled, merge request will be merged when approvals and pipeline succeed")

@patch("valhalla.ci_provider.gitlab.merge_request.get_gitlab_client")
@patch("valhalla.ci_provider.gitlab.merge_request.get_project_id")
@patch("valhalla.ci_provider.gitlab.merge_request.resolve")
@patch("valhalla.ci_provider.gitlab.merge_request.info")
@patch("valhalla.ci_provider.gitlab.merge_request.warn")
def test_enable_auto_merge_exception(self, mock_warn, mock_info, mock_resolve, mock_get_project_id,
@patch("valhalla.ci_provider.gitlab.merge_request.Repo")
@patch("valhalla.ci_provider.gitlab.merge_request.time.sleep")
def test_enable_auto_merge_exception(self, mock_sleep, mock_repo, mock_warn, mock_info, mock_resolve, mock_get_project_id,
mock_get_gitlab_client):
with patch.dict('os.environ', {'CI_COMMIT_BRANCH': 'feature-branch'}):
# given:
Expand All @@ -226,6 +236,8 @@ def test_enable_auto_merge_exception(self, mock_warn, mock_info, mock_resolve, m
mock_project = MagicMock()
mock_gitlab_client.projects.get.return_value = mock_project
mock_get_gitlab_client.return_value = mock_gitlab_client
mock_repo.return_value.head.commit.hexsha = "new-sha"
mock_project.mergerequests.get.return_value = MagicMock(sha="new-sha", detailed_merge_status="need_rebase")
mock_project.mergerequests.get.return_value.merge.side_effect = Exception("405 Method Not Allowed")

merge_request = GitLabValhallaMergeRequest()
Expand All @@ -237,7 +249,8 @@ def test_enable_auto_merge_exception(self, mock_warn, mock_info, mock_resolve, m
hook.enable_auto_merge()

# then:
mock_warn.assert_any_call("Could not enable auto-merge for merge request because: 405 Method Not Allowed")
mock_warn.assert_any_call("Could not enable auto-merge for merge request because: 405 Method Not Allowed "
"(detailed_merge_status: need_rebase)")

@patch("valhalla.ci_provider.gitlab.merge_request.get_gitlab_client")
@patch("valhalla.ci_provider.gitlab.merge_request.get_project_id")
Expand Down
18 changes: 16 additions & 2 deletions valhalla/ci_provider/gitlab/merge_request.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import os
import time
from typing import List

from git import Repo

from valhalla.ci_provider.git_host import MergeRequest
from valhalla.ci_provider.gitlab.common import get_gitlab_client, get_project_id
from valhalla.common.get_config import MergeRequestConfig
Expand Down Expand Up @@ -52,12 +55,23 @@ def _add_comment(comment: str):
warn(f"Could not add comment to merge request because: {e}")

def _enable_auto_merge():
mr_obj = None
try:
head_sha = Repo('.').head.commit.hexsha
mr_obj = self.project.mergerequests.get(mr_iid, iid=True)
mr_obj.merge(merge_when_pipeline_succeeds=True)
# GitLab refreshes the MR asynchronously after push; enabling auto-merge before that
# (or without sha) makes GitLab abort it with "source branch was updated" or reject it with 405
for _ in range(30):
if (mr_obj.sha == head_sha and
getattr(mr_obj, 'detailed_merge_status', None) not in ('checking', 'preparing', 'unchecked')):
break
time.sleep(2)
mr_obj = self.project.mergerequests.get(mr_iid, iid=True)
mr_obj.merge(sha=head_sha, merge_when_pipeline_succeeds=True)
info("Auto-merge enabled, merge request will be merged when approvals and pipeline succeed")
except Exception as e:
warn(f"Could not enable auto-merge for merge request because: {e}")
status = getattr(mr_obj, 'detailed_merge_status', 'unknown')
warn(f"Could not enable auto-merge for merge request because: {e} (detailed_merge_status: {status})")

return MergeRequestHook(mr_iid, _add_comment, _enable_auto_merge if merge_request_config.auto_merge else None)

Expand Down
Loading