import pytest import re import time from pathlib import Path from tests.lib.common_test_utils import GiteaAPIClient def assert_is(*args): assert args[0], args[1] def assert_not(*args): assert not args[0], args[1] def _check_pr_results(gitea_env, to_check, retries, assert_func, assert_template): # ManualMergeOnly still requires regular reviews to be satisfied. # We poll until required reviewers have approved. # check if nothing gets merged in retries*2 sec for _ in range(retries): # Approve all requested reviews for sec in ('packages', 'projects'): for key, val in to_check[sec].items(): pp, nr = key.split('#') print(f"approving all requested review for {pp}#{nr}") gitea_env.approve_requested_reviews(pp, nr) # Trigger approvals for whatever is already requested for sec in ('packages', 'projects'): for key, val in to_check[sec].items(): pp, nr = key.split('#') reviewers = val.get('mandatory_reviewers', set()) maintainers = val.get('maintainers', []) # Check if mandatory reviewers and at least one maintainer have approved pkg_reviews = gitea_env.list_reviews(pp, nr) approved_reviewers = {r["user"]["login"] for r in pkg_reviews if r["state"] == "APPROVED"} if reviewers: print(f"***** Found reviewers {reviewers}") if reviewers.issubset(approved_reviewers) and any(m in approved_reviewers for m in maintainers): print("******** All mandatory reviewers approved") to_check[sec][key]['approved'] = True else: print(f"******** Not all mandatory reviewers approved {approved_reviewers}") to_check[sec][key]['approved'] = False elif (approved_reviewers): print(f"***** Approved reviewers found {approved_reviewers}") to_check[sec][key]['approved'] = True else: if not pkg_reviews: print(f"***** No reviews requested {key}") to_check[sec][key]['approved'] = True else: print(f"***** No approved reviewers found for {key} {approved_reviewers}") to_check[sec][key]['approved'] = False details = gitea_env.get_pr_details(pp, nr) assert not details.get("merged"), f"PR for {sec} {key} merged prematurely (ManualMergeOnly ignored?)" time.sleep(2) for sec in ('packages', 'projects'): for key in to_check[sec]: assert to_check[sec][key]['approved'], f"Timed out waiting for required approvals for {key}." print("All PRs have all required approvals but are not merged (as expected with ManualMergeOnly).") for sec in ('packages', 'projects'): for key, val in to_check[sec].items(): pp, nr = key.split('#') if val.get('mergers', False): for client in val['mergers']: # 4. Comment "merge ok" from a requested reviewer (ownerA) print(f"Commenting 'merge ok' on PR {key} from a maintainer...") client.create_issue_comment(pp, nr, "merge ok") if val.get('not_to_be_merged'): time.sleep(val['not_to_be_merged']['within']) for nm in val['not_to_be_merged']['pr']: npp, nnr = nm.split('#') details = gitea_env.get_pr_details(npp, nnr) assert not details.get("merged"), f"PR {nm} should not be merged" # 5. Verify both PRs are merged print("Polling for PR merge status...") for sec in ('packages', 'projects'): for p in to_check[sec]: to_check[sec][p]['merged'] = False for i in range(40): # Poll for up to 40 seconds for sec in ('packages', 'projects'): for p in to_check[sec]: if not to_check[sec][p]['merged']: pp, nr = p.split('#') details = gitea_env.get_pr_details(pp, nr) to_check[sec][p]['merged'] = True if details.get("merged") else False not_merged = 0 for sec in ('packages', 'projects'): for p in to_check[sec]: if not to_check[sec][p]['merged']: not_merged += 1 if not not_merged: break time.sleep(1) for sec in ('packages', 'projects'): for p in to_check[sec]: assert_func(to_check[sec][p]['merged'], assert_template.format(p)) @pytest.mark.t001 def test_001_automerge(automerge_env, test_user_client): """ Test scenario TC-MERGE-001: 1. Create a PackageGit PR. 2. Ensure all mandatory reviews are completed on both project and package PRs. 3. Verify the PR is merged automatically. """ gitea_env, test_full_repo_name, merge_branch_name = automerge_env # 1. Create a package PR diff = """diff --git a/automerge_test.txt b/automerge_test.txt new file mode 100644 index 00000000..473a0f4c """ print(f"--- Creating package PR in mypool/pkgA on branch {merge_branch_name} ---") package_pr = test_user_client.create_gitea_pr("mypool/pkgA", diff, "Test Automerge Fixture", base_branch=merge_branch_name) package_pr_number = package_pr["number"] print(f"Created package PR mypool/pkgA#{package_pr_number}") # 2. Make sure the workflow-pr service created related project PR project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr_number) assert project_pr_number is not None, "Workflow bot did not create a project PR." print(f"Found project PR: myproducts/mySLFO#{project_pr_number}") # 3. Approve reviews and verify merged pkg_merged, prj_merged = gitea_env.approve_and_wait_merge("mypool/pkgA", package_pr_number, project_pr_number) assert pkg_merged, f"Package PR mypool/pkgA#{package_pr_number} was not merged automatically." assert prj_merged, f"Project PR myproducts/mySLFO#{project_pr_number} was not merged automatically." print("Both PRs merged successfully.") @pytest.mark.t002 def test_002_manual_merge(manual_merge_env, test_user_client, ownerA_client): """ Test scenario TC-MERGE-002: 1. Create a PackageGit PR with ManualMergeOnly set to true. 2. Ensure all mandatory reviews are completed on both project and package PRs. 3. Comment "merge ok" on the package PR from the account of a requested reviewer. 4. Verify the PR is merged. """ gitea_env, test_full_repo_name, merge_branch_name = manual_merge_env # 1. Create a package PR diff = """diff --git a/manual_merge_test.txt b/manual_merge_test.txt new file mode 100644 index 00000000..473a0f4c """ print(f"--- Creating package PR in mypool/pkgA on branch {merge_branch_name} ---") package_pr = gitea_env.create_gitea_pr("mypool/pkgA", diff, "Test Manual Merge Fixture", base_branch=merge_branch_name) package_pr_number = package_pr["number"] print(f"Created package PR mypool/pkgA#{package_pr_number}") # 2. Make sure the workflow-pr service created related project PR project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr_number) assert project_pr_number is not None, "Workflow bot did not create a project PR." print(f"Found project PR: myproducts/mySLFO#{project_pr_number}") # 3. Approve reviews and verify NOT merged print("Waiting for required review requests and approving them...") # Expected reviewers based on manual-merge branch config and pkgA maintainership to_check = { "packages" : { f"mypool/pkgA#{package_pr_number}": { "mandatory_reviewers": {"usera", "userb"}, "maintainers": {"ownerA", "ownerX", "ownerY"}, "mergers": {ownerA_client} } }, "projects" : { f"myproducts/mySLFO#{project_pr_number}": {} } } retries = 30 _check_pr_results(gitea_env, to_check, retries, assert_is, "PR {} was not merged after 'merge ok'.") print("Both PRs merged after 'merge ok'.") @pytest.mark.t003 def test_003_refuse_manual_merge(manual_merge_env, test_user_client, ownerB_client): """ Test scenario TC-MERGE-003: 1. Create a PackageGit PR with ManualMergeOnly set to true. 2. Ensure all mandatory reviews are completed on both project and package PRs. 3. Comment "merge ok" on the package PR from the account of a not requested reviewer. 4. Verify the PR is not merged. """ gitea_env, test_full_repo_name, merge_branch_name = manual_merge_env # 1. Create a package PR diff = """diff --git a/manual_merge_test.txt b/manual_merge_test.txt new file mode 100644 index 00000000..473a0f4c """ print(f"--- Creating package PR in mypool/pkgA on branch {merge_branch_name} ---") package_pr = test_user_client.create_gitea_pr("mypool/pkgA", diff, "Test Manual Merge Fixture", base_branch=merge_branch_name) package_pr_number = package_pr["number"] print(f"Created package PR mypool/pkgA#{package_pr_number}") # 2. Make sure the workflow-pr service created related project PR project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr_number) assert project_pr_number is not None, "Workflow bot did not create a project PR." print(f"Found project PR: myproducts/mySLFO#{project_pr_number}") # 3. Approve reviews and verify NOT merged print("Waiting for required review requests and approving them...") # Expected reviewers based on manual-merge branch config and pkgA maintainership to_check = { "packages" : { f"mypool/pkgA#{package_pr_number}": { "mandatory_reviewers": {"usera", "userb"}, "maintainers": {"ownerA", "ownerX", "ownerY"}, "mergers": {ownerB_client} } }, "projects" : { f"myproducts/mySLFO#{project_pr_number}": {} } } retries = 30 _check_pr_results(gitea_env, to_check, retries, assert_not, "PR {} was merged after 'merge ok'.") print("Both PRs merged not after 'merge ok'.") @pytest.mark.t004 def test_004_multiple_packages_manual_merge(manual_merge_env, test_user_client, ownerA_client, ownerB_client): """ Test scenario TC-MERGE-004: 1. Create a ProjectGit PR that references multiple PackageGit PRs with ManualMergeOnly set to true. 2. Ensure all mandatory reviews are completed on both project and package PRs. 3. Comment merge ok on each package PR from the account of a package maintainer. 4. Verify PR is merged only after merge ok is commented on all associated PackageGit PRs. """ gitea_env, test_full_repo_name, merge_branch_name = manual_merge_env # 1. Create a package PR diff = """diff --git a/manual_merge_test.txt b/manual_merge_test.txt new file mode 100644 index 0000000..e69de29 """ print(f"--- Creating package PR in mypool/pkgA on branch {merge_branch_name} ---") package_pr1 = test_user_client.create_gitea_pr("mypool/pkgA", diff, "Test Manual Merge Fixture (MultiPKG)", base_branch=merge_branch_name) package_pr1_number = package_pr1["number"] print(f"Created package PR mypool/pkgA#{package_pr1_number}") print(f"--- Creating package PR in mypool/pkgB on branch {merge_branch_name} ---") package_pr2 = test_user_client.create_gitea_pr("mypool/pkgB", diff, "Test Manual Merge Fixture (MultiPKG)", base_branch=merge_branch_name) package_pr2_number = package_pr2["number"] print(f"Created package PR mypool/pkgB#{package_pr2_number}") project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr1_number) assert project_pr_number is not None, "Workflow bot did not create a project PR (pkgA)." print(f"Found project PR: myproducts/mySLFO#{project_pr_number}") print(f"--- Closing the first project-pr #{project_pr_number} ---") result = gitea_env.close_pr("myproducts/mySLFO", project_pr_number) pr_state = result.get('state', '') assert pr_state == 'closed', f"Closing first project PR failed. New state: '{pr_state}'." print(f"New state of myproducts/mySLFO#{project_pr_number}: {pr_state}") project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgB", package_pr2_number) assert project_pr_number is not None, "Workflow bot did not create a project PR (pkgB)." print(f"Found project PR: myproducts/mySLFO#{project_pr_number}") pr_details = gitea_env.get_pr_details("myproducts/mySLFO", project_pr_number) pr_body = pr_details.get('body', '') new_line = f"PR: mypool/pkgA!{package_pr1_number}" pr_body = re.sub(r'^(PR: .*)$', r'\1\n' + new_line, pr_body, flags=re.MULTILINE) gitea_env.update_gitea_pr_properties("myproducts/mySLFO", project_pr_number, body=pr_body) # 3. Approve reviews and verify NOT merged print("Waiting for all expected review requests and approving them...") # ManualMergeOnly still requires regular reviews to be satisfied. # We poll until all expected reviewers are requested, then approve them. to_check = { "packages" : { f"mypool/pkgA#{package_pr1_number}": { "mandatory_reviewers": {"usera", "userb"}, "maintainers": {"ownerA", "ownerX", "ownerY"}, "mergers": {ownerA_client}, "not_to_be_merged": { "within": 20, # seconds to wait "pr":[ f"mypool/pkgB#{package_pr2_number}", f"myproducts/mySLFO#{project_pr_number}" ] } }, f"mypool/pkgB#{package_pr2_number}": { "mandatory_reviewers": {"usera", "userb"}, "maintainers": {"ownerB", "ownerX", "ownerY"}, "mergers": {ownerB_client}, } }, "projects" : { f"myproducts/mySLFO#{project_pr_number}": {} } } retries = 30 _check_pr_results(gitea_env, to_check, retries, assert_is, "PR {} was not merged after 'merge ok'.") print("All PRs merged after 'merge ok'.") @pytest.mark.t005 def test_005_packages_manual_merge_pr_by_owner(manual_merge_env, test_user_client, ownerA_client): """ Test scenario TC-MERGE-005: 1. Create a PackageGit PR with ManualMergeOnly set to true. 2. Ensure all mandatory reviews are completed on both project and package PRs. 3. Comment merge ok on the package PR from the account of a project maintainer. 4. The PR is merged. """ gitea_env, test_full_repo_name, merge_branch_name = manual_merge_env # 1. Create a package PR diff = """diff --git a/manual_merge_test.txt b/manual_merge_test.txt new file mode 100644 index 00000000..473a0f4c """ print(f"--- Creating package PR in mypool/pkgA on branch {merge_branch_name} ---") package_pr = gitea_env.create_gitea_pr("mypool/pkgA", diff, "Test Manual Merge Fixture", base_branch=merge_branch_name) package_pr_number = package_pr["number"] print(f"Created package PR mypool/pkgA#{package_pr_number}") # 2. Make sure the workflow-pr service created related project PR project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr_number) assert project_pr_number is not None, "Workflow bot did not create a project PR." print(f"Found project PR: myproducts/mySLFO#{project_pr_number}") # 3. Approve reviews and verify NOT merged print("Waiting for required review requests and approving them...") # Expected reviewers based on manual-merge branch config and pkgA maintainership to_check = { "packages" : { f"mypool/pkgA#{package_pr_number}": { "mandatory_reviewers": {"usera", "userb"}, "maintainers": {"ownerA", "ownerX", "ownerY"}, "mergers": {ownerA_client} } }, "projects" : { f"myproducts/mySLFO#{project_pr_number}": {} } } retries = 30 _check_pr_results(gitea_env, to_check, retries, assert_is, "PR {} was not merged after 'merge ok'.") print("Both PRs merged after 'merge ok'.") @pytest.mark.t006 def test_006_package_manual_merge_pr_by_maintainer(manual_merge_env, test_user_client, ownerX_client): """ Test scenario TC-MERGE-006: 1. Create a PackageGit PR with ManualMergeProject set to true. 2. Ensure all mandatory reviews are completed on both project and package PRs. 3. Comment merge ok on the project PR from the account of a project maintainer. 4. The PR is merged. """ gitea_env, test_full_repo_name, merge_branch_name = manual_merge_env # 1. Create a package PR diff = """diff --git a/manual_merge_test.txt b/manual_merge_test.txt new file mode 100644 index 00000000..473a0f4c """ print(f"--- Creating package PR in mypool/pkgA on branch {merge_branch_name} ---") package_pr = gitea_env.create_gitea_pr("mypool/pkgA", diff, "Test Manual Merge Project Fixture", base_branch=merge_branch_name) package_pr_number = package_pr["number"] print(f"Created package PR mypool/pkgA#{package_pr_number}") # 2. Make sure the workflow-pr service created related project PR project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr_number) assert project_pr_number is not None, "Workflow bot did not create a project PR." print(f"Found project PR: myproducts/mySLFO#{project_pr_number}") # 3. Approve reviews and verify NOT merged print("Waiting for required review requests and approving them...") # Expected reviewers based on manual-merge branch config and pkgA maintainership to_check = { "packages" : { f"mypool/pkgA#{package_pr_number}": { "mandatory_reviewers": {"usera", "userb", "ownerA", "ownerX", "ownerY"}, "maintainers": {"ownerA", "ownerX", "ownerY"}, } }, "projects" : { f"myproducts/mySLFO#{project_pr_number}": { "mergers": {ownerX_client} } } } retries = 30 _check_pr_results(gitea_env, to_check, retries, assert_is, "PR {} was not merged after 'merge ok'.") print("Both PRs merged after 'merge ok'.") @pytest.mark.t007 def test_007_package_manual_merge_prjpr_by_pkgmaintainer(manual_merge_env, test_user_client, ownerA_client): """ Test scenario TC-MERGE-007: 1. Create a PackageGit PR with ManualMergeProject set to true. 2. Ensure all mandatory reviews are completed on both project and package PRs. 3. Comment merge ok on the project PR from the account of a package maintainer. 4. The PR is not merged. """ gitea_env, test_full_repo_name, merge_branch_name = manual_merge_env # 1. Create a package PR diff = """diff --git a/manual_merge_test.txt b/manual_merge_test.txt new file mode 100644 index 00000000..473a0f4c """ print(f"--- Creating package PR in mypool/pkgA on branch {merge_branch_name} ---") package_pr = gitea_env.create_gitea_pr("mypool/pkgA", diff, "Test Manual Merge Project Fixture", base_branch=merge_branch_name) package_pr_number = package_pr["number"] print(f"Created package PR mypool/pkgA#{package_pr_number}") # 2. Make sure the workflow-pr service created related project PR project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr_number) assert project_pr_number is not None, "Workflow bot did not create a project PR." print(f"Found project PR: myproducts/mySLFO#{project_pr_number}") # 3. Approve reviews and verify NOT merged print("Waiting for required review requests and approving them...") # Expected reviewers based on manual-merge branch config and pkgA maintainership to_check = { "packages" : { f"mypool/pkgA#{package_pr_number}": { "mandatory_reviewers": {"usera", "userb", "ownerA", "ownerX", "ownerY"}, "maintainers": {"ownerA", "ownerX", "ownerY"}, } }, "projects" : { f"myproducts/mySLFO#{project_pr_number}": { "mergers": {ownerA_client} } } } retries = 30 _check_pr_results(gitea_env, to_check, retries, assert_not, "PR {} was merged after 'merge ok'.") print("Both PRs not merged after 'merge ok'.") @pytest.mark.t008 def test_008_merge_mode_ff_only_success(merge_ff_env, test_user_client): """ Test MergeMode "ff-only" - Success case (FF-mergeable) """ gitea_env, test_full_repo_name, merge_branch_name = merge_ff_env # 1. Create a package PR (this will be FF-mergeable by default) diff = """diff --git a/ff_test.txt b/ff_test.txt new file mode 100644 index 00000000..473a0f4c """ package_pr = test_user_client.create_gitea_pr("mypool/pkgA", diff, "Test FF Merge", base_branch=merge_branch_name) package_pr_number = package_pr["number"] project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr_number) assert project_pr_number is not None pkg_merged, prj_merged = gitea_env.approve_and_wait_merge("mypool/pkgA", package_pr_number, project_pr_number) assert pkg_merged and prj_merged @pytest.mark.t009 def test_009_merge_mode_ff_only_failure(merge_ff_env, ownerA_client): """ Test MergeMode "ff-only" - Failure case (Content Conflict, should NOT merge) """ gitea_env, test_full_repo_name, merge_branch_name = merge_ff_env ts = time.strftime("%H%M%S") filename = f"ff_fail_test_{ts}.txt" # 1. Create a package PR that adds a file diff = f"""diff --git a/{filename} b/{filename} new file mode 100644 index 00000000..473a0f4c --- /dev/null +++ b/{filename} @@ -0,0 +1 @@ +PR content """ package_pr = ownerA_client.create_gitea_pr("mypool/pkgA", diff, "Test FF Merge Failure (Conflict)", base_branch=merge_branch_name) package_pr_number = package_pr["number"] # 2. Wait for project PR to be created project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr_number) assert project_pr_number is not None print("Making PR non-FF by creating a content conflict in the base branch...") gitea_env.create_file("mypool", "pkgA", filename, "Conflicting base content\n", branch=merge_branch_name) print("Approving reviews initially...") gitea_env.approve_requested_reviews("mypool/pkgA", package_pr_number) gitea_env.approve_requested_reviews("myproducts/mySLFO", project_pr_number) print("Pushing another change to PR branch to trigger sync...") gitea_env.modify_gitea_pr("mypool/pkgA", package_pr_number, "diff --git a/sync_test.txt b/sync_test.txt\nnew file mode 100644\nindex 00000000..473a0f4c\n", "Trigger Sync") # The bot should detect it's not FF and NOT merge, and re-request reviews because of the new commit print("Waiting for reviews to be re-requested and approving again...") time.sleep(10) # Wait for bot to process sync # Approve again and verify it is NOT merged print("Approving again and verifying PR is NOT merged (because it's not FF)...") for i in range(15): gitea_env.approve_requested_reviews("mypool/pkgA", package_pr_number) gitea_env.approve_requested_reviews("myproducts/mySLFO", project_pr_number) time.sleep(1) pkg_details = gitea_env.get_pr_details("mypool/pkgA", package_pr_number) assert not pkg_details.get("merged"), "Package PR merged despite NOT being FF-mergeable!" print("FF-only failure (not merged after sync) verified.") @pytest.mark.t010 def test_010_merge_mode_devel_success(merge_devel_env, ownerA_client): """ Test MergeMode "devel" - Success case (Content Conflict, should still merge via force-push) """ gitea_env, test_full_repo_name, merge_branch_name = merge_devel_env ts = time.strftime("%H%M%S") filename = f"devel_test_{ts}.txt" # 1. Create a package PR that adds a file diff = f"""diff --git a/{filename} b/{filename} new file mode 100644 index 00000000..473a0f4c --- /dev/null +++ b/{filename} @@ -0,0 +1 @@ +PR content """ package_pr = ownerA_client.create_gitea_pr("mypool/pkgA", diff, "Test Devel Merge (Conflict)", base_branch=merge_branch_name) package_pr_number = package_pr["number"] # 2. Create a content conflict by committing the same file to the base branch gitea_env.create_file("mypool", "pkgA", filename, "Conflicting base content\n", branch=merge_branch_name) project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr_number) assert project_pr_number is not None # Before merge, get the head sha of the package pr and project pr pkg_details = gitea_env.get_pr_details("mypool/pkgA", package_pr_number) pkg_head_sha = pkg_details["head"]["sha"] prj_details = gitea_env.get_pr_details("myproducts/mySLFO", project_pr_number) prj_head_sha = prj_details["head"]["sha"] pkg_merged, prj_merged = gitea_env.approve_and_wait_merge("mypool/pkgA", package_pr_number, project_pr_number) assert pkg_merged and prj_merged print("Devel merge (force-push) successful.") # Verify that pkgA submodule points to the correct SHA pkgA_submodule_info = gitea_env.get_file_info("myproducts", "mySLFO", "pkgA", branch=merge_branch_name) assert pkgA_submodule_info["sha"] == pkg_head_sha, f"Submodule pkgA should point to {pkg_head_sha} but points to {pkgA_submodule_info['sha']}" @pytest.mark.t011 def test_011_merge_mode_replace_success(merge_replace_env, ownerA_client): """ Test MergeMode "replace" - Success case (Content Conflict, bot should add merge commit) """ gitea_env, test_full_repo_name, merge_branch_name = merge_replace_env ts = time.strftime("%H%M%S") filename = f"replace_test_{ts}.txt" # 1. Create a package PR that adds a file diff = f"""diff --git a/{filename} b/{filename} new file mode 100644 index 00000000..473a0f4c --- /dev/null +++ b/{filename} @@ -0,0 +1 @@ +PR content """ package_pr = ownerA_client.create_gitea_pr("mypool/pkgA", diff, "Test Replace Merge (Conflict)", base_branch=merge_branch_name) package_pr_number = package_pr["number"] # Enable "Allow edits from maintainers" ownerA_client.update_gitea_pr_properties("mypool/pkgA", package_pr_number, allow_maintainer_edit=True) # 2. Create a content conflict by committing the same file to the base branch gitea_env.create_file("mypool", "pkgA", filename, "Conflicting base content\n", branch=merge_branch_name) project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr_number) assert project_pr_number is not None # Before merge, get the head sha of the package pr and project pr pkg_details = gitea_env.get_pr_details("mypool/pkgA", package_pr_number) pkg_head_sha = pkg_details["head"]["sha"] prj_details = gitea_env.get_pr_details("myproducts/mySLFO", project_pr_number) prj_head_sha = prj_details["head"]["sha"] pkg_merged, prj_merged = gitea_env.approve_and_wait_merge("mypool/pkgA", package_pr_number, project_pr_number, timeout=60) assert pkg_merged and prj_merged print("Replace merge successful.") # Verify that the project branch HEAD is a merge commit resp, _ = gitea_env._request("GET", f"repos/myproducts/mySLFO/branches/{merge_branch_name}") branch_info = resp.json() new_head_sha = branch_info["commit"]["id"] resp, _ = gitea_env._request("GET", f"repos/myproducts/mySLFO/git/commits/{new_head_sha}") commit_details = resp.json() assert len(commit_details["parents"]) > 1, f"Project branch {merge_branch_name} HEAD should be a merge commit but has {len(commit_details['parents'])} parents" # Verify that pkgA submodule points to the correct SHA pkgA_submodule_info = gitea_env.get_file_info("myproducts", "mySLFO", "pkgA", branch=merge_branch_name) assert pkgA_submodule_info["sha"] == pkg_head_sha, f"Submodule pkgA should point to {pkg_head_sha} but points to {pkgA_submodule_info['sha']}" @pytest.mark.t012 def test_012_merge_mode_devel_ff_success(merge_devel_env, ownerA_client): """ Test MergeMode "devel" - Success case (No Conflict, should fast-forward) """ gitea_env, test_full_repo_name, merge_branch_name = merge_devel_env ts = time.strftime("%H%M%S") filename = f"devel_ff_test_{ts}.txt" # 1. Create a package PR (this will be FF-mergeable by default) diff = f"""diff --git a/{filename} b/{filename} new file mode 100644 index 00000000..473a0f4c --- /dev/null +++ b/{filename} @@ -0,0 +1 @@ +PR content """ package_pr = ownerA_client.create_gitea_pr("mypool/pkgA", diff, "Test Devel FF Merge", base_branch=merge_branch_name) package_pr_number = package_pr["number"] project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr_number) assert project_pr_number is not None pkg_details = gitea_env.get_pr_details("mypool/pkgA", package_pr_number) pkg_head_sha = pkg_details["head"]["sha"] pkg_merged, prj_merged = gitea_env.approve_and_wait_merge("mypool/pkgA", package_pr_number, project_pr_number) assert pkg_merged and prj_merged print("Devel FF merge successful.") # Verify that the package base branch HEAD is the same as the PR head (FF) resp, _ = gitea_env._request("GET", f"repos/mypool/pkgA/branches/{merge_branch_name}") branch_info = resp.json() new_head_sha = branch_info["commit"]["id"] assert new_head_sha == pkg_head_sha, f"Package branch {merge_branch_name} HEAD should be {pkg_head_sha} but is {new_head_sha}" resp, _ = gitea_env._request("GET", f"repos/mypool/pkgA/git/commits/{new_head_sha}") commit_details = resp.json() assert len(commit_details["parents"]) == 1, f"Package branch {merge_branch_name} HEAD should have 1 parent but has {len(commit_details['parents'])}" @pytest.mark.t013 def test_013_merge_mode_replace_ff_success(merge_replace_env, ownerA_client): """ Test MergeMode "replace" - Success case (No Conflict, should fast-forward) """ gitea_env, test_full_repo_name, merge_branch_name = merge_replace_env ts = time.strftime("%H%M%S") filename = f"replace_ff_test_{ts}.txt" # 1. Create a package PR (this will be FF-mergeable by default) diff = f"""diff --git a/{filename} b/{filename} new file mode 100644 index 00000000..473a0f4c --- /dev/null +++ b/{filename} @@ -0,0 +1 @@ +PR content """ package_pr = ownerA_client.create_gitea_pr("mypool/pkgA", diff, "Test Replace FF Merge", base_branch=merge_branch_name) package_pr_number = package_pr["number"] project_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", package_pr_number) assert project_pr_number is not None pkg_details = gitea_env.get_pr_details("mypool/pkgA", package_pr_number) pkg_head_sha = pkg_details["head"]["sha"] pkg_merged, prj_merged = gitea_env.approve_and_wait_merge("mypool/pkgA", package_pr_number, project_pr_number, timeout=60) assert pkg_merged and prj_merged print("Replace FF merge successful.") # Verify that the package base branch HEAD is the same as the PR head (FF) resp, _ = gitea_env._request("GET", f"repos/mypool/pkgA/branches/{merge_branch_name}") branch_info = resp.json() new_head_sha = branch_info["commit"]["id"] assert new_head_sha == pkg_head_sha, f"Package branch {merge_branch_name} HEAD should be {pkg_head_sha} but is {new_head_sha}" resp, _ = gitea_env._request("GET", f"repos/mypool/pkgA/git/commits/{new_head_sha}") commit_details = resp.json() assert len(commit_details["parents"]) == 1, f"Package branch {merge_branch_name} HEAD should have 1 parent but has {len(commit_details['parents'])}"