|
|
|
|
@@ -4,6 +4,80 @@ import time
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
from tests.lib.common_test_utils import GiteaAPIClient
|
|
|
|
|
|
|
|
|
|
def wait_for_manual_merge_approvals(gitea_env, staging_bot_client, package_pr_number, project_pr_number):
|
|
|
|
|
"""
|
|
|
|
|
Wait for required approvals on both package and project PRs for manual merge tests.
|
|
|
|
|
"""
|
|
|
|
|
print("Waiting for required review requests and approving them...")
|
|
|
|
|
# Expected reviewers based on manual-merge branch config and pkgA maintainership
|
|
|
|
|
mandatory_reviewers = {"usera", "userb"}
|
|
|
|
|
maintainers = {"ownerA", "ownerX", "ownerY"}
|
|
|
|
|
|
|
|
|
|
# ManualMergeOnly still requires regular reviews to be satisfied.
|
|
|
|
|
# We poll until required reviewers have approved.
|
|
|
|
|
all_approved = False
|
|
|
|
|
approved_reviewers = set()
|
|
|
|
|
for _ in range(60): # Poll for up to 60 seconds (1s interval)
|
|
|
|
|
# Trigger approvals for whatever is already requested
|
|
|
|
|
gitea_env.approve_requested_reviews("mypool/pkgA", package_pr_number)
|
|
|
|
|
gitea_env.approve_requested_reviews("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
|
|
|
|
|
# Explicitly handle staging bot if it is requested or pending
|
|
|
|
|
prj_reviews = gitea_env.list_reviews("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
if any(r["user"]["login"] == "autogits_obs_staging_bot" and r["state"] in ["REQUEST_REVIEW", "PENDING"] for r in prj_reviews):
|
|
|
|
|
print("Staging bot has a pending/requested review. Approving...")
|
|
|
|
|
staging_bot_client.create_review("myproducts/mySLFO", project_pr_number, event="APPROVED", body="Staging bot approves")
|
|
|
|
|
|
|
|
|
|
# Check if mandatory reviewers and at least one maintainer have approved
|
|
|
|
|
pkg_reviews = gitea_env.list_reviews("mypool/pkgA", package_pr_number)
|
|
|
|
|
approved_reviewers = {r["user"]["login"] for r in pkg_reviews if r["state"] == "APPROVED"}
|
|
|
|
|
|
|
|
|
|
if mandatory_reviewers.issubset(approved_reviewers) and any(m in approved_reviewers for m in maintainers):
|
|
|
|
|
# And check project PR for bot approval
|
|
|
|
|
prj_approved = any(r["user"]["login"] == "autogits_obs_staging_bot" and r["state"] == "APPROVED" for r in prj_reviews)
|
|
|
|
|
if prj_approved:
|
|
|
|
|
all_approved = True
|
|
|
|
|
print(f"Required reviewers approved: mandatory={mandatory_reviewers}, maintainer={[m for m in maintainers if m in approved_reviewers]}, staging_bot=True")
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
pkg_details = gitea_env.get_pr_details("mypool/pkgA", package_pr_number)
|
|
|
|
|
prj_details = gitea_env.get_pr_details("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
|
|
|
|
|
assert not pkg_details.get("merged"), "Package PR merged prematurely (ManualMergeOnly ignored?)"
|
|
|
|
|
assert not prj_details.get("merged"), "Project PR merged prematurely (ManualMergeOnly ignored?)"
|
|
|
|
|
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
assert all_approved, f"Timed out waiting for required approvals. Mandatory: {mandatory_reviewers}, Maintainers: {maintainers}. Current approved: {approved_reviewers}"
|
|
|
|
|
print("Both PRs have all required approvals but are not merged (as expected with ManualMergeOnly).")
|
|
|
|
|
|
|
|
|
|
def wait_for_merge_status(gitea_env, package_pr_number, project_pr_number, timeout_seconds=20):
|
|
|
|
|
"""
|
|
|
|
|
Poll for PR merge status on both package and project PRs.
|
|
|
|
|
"""
|
|
|
|
|
print("Polling for PR merge status...")
|
|
|
|
|
package_merged = False
|
|
|
|
|
project_merged = False
|
|
|
|
|
|
|
|
|
|
for i in range(int(timeout_seconds / 0.5)): # Poll with 0.5s interval
|
|
|
|
|
if not package_merged:
|
|
|
|
|
pkg_details = gitea_env.get_pr_details("mypool/pkgA", package_pr_number)
|
|
|
|
|
if pkg_details.get("merged"):
|
|
|
|
|
package_merged = True
|
|
|
|
|
print(f"Package PR mypool/pkgA#{package_pr_number} merged.")
|
|
|
|
|
|
|
|
|
|
if not project_merged:
|
|
|
|
|
prj_details = gitea_env.get_pr_details("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
if prj_details.get("merged"):
|
|
|
|
|
project_merged = True
|
|
|
|
|
print(f"Project PR myproducts/mySLFO#{project_pr_number} merged.")
|
|
|
|
|
|
|
|
|
|
if package_merged and project_merged:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
|
return package_merged, project_merged
|
|
|
|
|
|
|
|
|
|
@pytest.mark.t001
|
|
|
|
|
def test_001_automerge(automerge_env, test_user_client):
|
|
|
|
|
"""
|
|
|
|
|
@@ -62,74 +136,14 @@ index 00000000..473a0f4c
|
|
|
|
|
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
|
|
|
|
|
mandatory_reviewers = {"usera", "userb"}
|
|
|
|
|
maintainers = {"ownerA", "ownerX", "ownerY"}
|
|
|
|
|
|
|
|
|
|
# ManualMergeOnly still requires regular reviews to be satisfied.
|
|
|
|
|
# We poll until required reviewers have approved.
|
|
|
|
|
all_approved = False
|
|
|
|
|
for _ in range(30):
|
|
|
|
|
# Trigger approvals for whatever is already requested
|
|
|
|
|
gitea_env.approve_requested_reviews("mypool/pkgA", package_pr_number)
|
|
|
|
|
gitea_env.approve_requested_reviews("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
|
|
|
|
|
# Explicitly handle staging bot if it is requested or pending
|
|
|
|
|
prj_reviews = gitea_env.list_reviews("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
if any(r["user"]["login"] == "autogits_obs_staging_bot" and r["state"] in ["REQUEST_REVIEW", "PENDING"] for r in prj_reviews):
|
|
|
|
|
print("Staging bot has a pending/requested review. Approving...")
|
|
|
|
|
staging_bot_client.create_review("myproducts/mySLFO", project_pr_number, event="APPROVED", body="Staging bot approves")
|
|
|
|
|
|
|
|
|
|
# Check if mandatory reviewers and at least one maintainer have approved
|
|
|
|
|
pkg_reviews = gitea_env.list_reviews("mypool/pkgA", package_pr_number)
|
|
|
|
|
approved_reviewers = {r["user"]["login"] for r in pkg_reviews if r["state"] == "APPROVED"}
|
|
|
|
|
|
|
|
|
|
if mandatory_reviewers.issubset(approved_reviewers) and any(m in approved_reviewers for m in maintainers):
|
|
|
|
|
# And check project PR for bot approval
|
|
|
|
|
prj_approved = any(r["user"]["login"] == "autogits_obs_staging_bot" and r["state"] == "APPROVED" for r in prj_reviews)
|
|
|
|
|
if prj_approved:
|
|
|
|
|
all_approved = True
|
|
|
|
|
print(f"Required reviewers approved: mandatory={mandatory_reviewers}, maintainer={[m for m in maintainers if m in approved_reviewers]}, staging_bot=True")
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
pkg_details = gitea_env.get_pr_details("mypool/pkgA", package_pr_number)
|
|
|
|
|
prj_details = gitea_env.get_pr_details("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
|
|
|
|
|
assert not pkg_details.get("merged"), "Package PR merged prematurely (ManualMergeOnly ignored?)"
|
|
|
|
|
assert not prj_details.get("merged"), "Project PR merged prematurely (ManualMergeOnly ignored?)"
|
|
|
|
|
|
|
|
|
|
time.sleep(2)
|
|
|
|
|
|
|
|
|
|
assert all_approved, f"Timed out waiting for required approvals. Mandatory: {mandatory_reviewers}, Maintainers: {maintainers}. Current approved: {approved_reviewers}"
|
|
|
|
|
print("Both PRs have all required approvals but are not merged (as expected with ManualMergeOnly).")
|
|
|
|
|
wait_for_manual_merge_approvals(gitea_env, staging_bot_client, package_pr_number, project_pr_number)
|
|
|
|
|
|
|
|
|
|
# 4. Comment "merge ok" from a requested reviewer (ownerA)
|
|
|
|
|
print("Commenting 'merge ok' on package PR from a maintainer...")
|
|
|
|
|
ownerA_client.create_issue_comment("mypool/pkgA", package_pr_number, "merge ok")
|
|
|
|
|
|
|
|
|
|
# 5. Verify both PRs are merged
|
|
|
|
|
print("Polling for PR merge status...")
|
|
|
|
|
package_merged = False
|
|
|
|
|
project_merged = False
|
|
|
|
|
|
|
|
|
|
for i in range(20): # Poll for up to 20 seconds
|
|
|
|
|
if not package_merged:
|
|
|
|
|
pkg_details = gitea_env.get_pr_details("mypool/pkgA", package_pr_number)
|
|
|
|
|
if pkg_details.get("merged"):
|
|
|
|
|
package_merged = True
|
|
|
|
|
print(f"Package PR mypool/pkgA#{package_pr_number} merged.")
|
|
|
|
|
|
|
|
|
|
if not project_merged:
|
|
|
|
|
prj_details = gitea_env.get_pr_details("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
if prj_details.get("merged"):
|
|
|
|
|
project_merged = True
|
|
|
|
|
print(f"Project PR myproducts/mySLFO#{project_pr_number} merged.")
|
|
|
|
|
|
|
|
|
|
if package_merged and project_merged:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
package_merged, project_merged = wait_for_merge_status(gitea_env, package_pr_number, project_pr_number)
|
|
|
|
|
|
|
|
|
|
assert package_merged, f"Package PR mypool/pkgA#{package_pr_number} was not merged after 'merge ok'."
|
|
|
|
|
assert project_merged, f"Project PR myproducts/mySLFO#{project_pr_number} was not merged after 'merge ok'."
|
|
|
|
|
@@ -162,74 +176,14 @@ index 00000000..473a0f4c
|
|
|
|
|
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
|
|
|
|
|
mandatory_reviewers = {"usera", "userb"}
|
|
|
|
|
maintainers = {"ownerA", "ownerX", "ownerY"}
|
|
|
|
|
|
|
|
|
|
# ManualMergeOnly still requires regular reviews to be satisfied.
|
|
|
|
|
# We poll until required reviewers have approved.
|
|
|
|
|
all_approved = False
|
|
|
|
|
for _ in range(30):
|
|
|
|
|
# Trigger approvals for whatever is already requested
|
|
|
|
|
gitea_env.approve_requested_reviews("mypool/pkgA", package_pr_number)
|
|
|
|
|
gitea_env.approve_requested_reviews("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
|
|
|
|
|
# Explicitly handle staging bot if it is requested or pending
|
|
|
|
|
prj_reviews = gitea_env.list_reviews("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
if any(r["user"]["login"] == "autogits_obs_staging_bot" and r["state"] in ["REQUEST_REVIEW", "PENDING"] for r in prj_reviews):
|
|
|
|
|
print("Staging bot has a pending/requested review. Approving...")
|
|
|
|
|
staging_bot_client.create_review("myproducts/mySLFO", project_pr_number, event="APPROVED", body="Staging bot approves")
|
|
|
|
|
|
|
|
|
|
# Check if mandatory reviewers and at least one maintainer have approved
|
|
|
|
|
pkg_reviews = gitea_env.list_reviews("mypool/pkgA", package_pr_number)
|
|
|
|
|
approved_reviewers = {r["user"]["login"] for r in pkg_reviews if r["state"] == "APPROVED"}
|
|
|
|
|
|
|
|
|
|
if mandatory_reviewers.issubset(approved_reviewers) and any(m in approved_reviewers for m in maintainers):
|
|
|
|
|
# And check project PR for bot approval
|
|
|
|
|
prj_approved = any(r["user"]["login"] == "autogits_obs_staging_bot" and r["state"] == "APPROVED" for r in prj_reviews)
|
|
|
|
|
if prj_approved:
|
|
|
|
|
all_approved = True
|
|
|
|
|
print(f"Required reviewers approved: mandatory={mandatory_reviewers}, maintainer={[m for m in maintainers if m in approved_reviewers]}, staging_bot=True")
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
pkg_details = gitea_env.get_pr_details("mypool/pkgA", package_pr_number)
|
|
|
|
|
prj_details = gitea_env.get_pr_details("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
|
|
|
|
|
assert not pkg_details.get("merged"), "Package PR merged prematurely (ManualMergeOnly ignored?)"
|
|
|
|
|
assert not prj_details.get("merged"), "Project PR merged prematurely (ManualMergeOnly ignored?)"
|
|
|
|
|
|
|
|
|
|
time.sleep(2)
|
|
|
|
|
|
|
|
|
|
assert all_approved, f"Timed out waiting for required approvals. Mandatory: {mandatory_reviewers}, Maintainers: {maintainers}. Current approved: {approved_reviewers}"
|
|
|
|
|
print("Both PRs have all required approvals but are not merged (as expected with ManualMergeOnly).")
|
|
|
|
|
wait_for_manual_merge_approvals(gitea_env, staging_bot_client, package_pr_number, project_pr_number)
|
|
|
|
|
|
|
|
|
|
# 4. Comment "merge ok" from a requested reviewer (ownerB)
|
|
|
|
|
print("Commenting 'merge ok' on package PR as user ownerB ...")
|
|
|
|
|
ownerB_client.create_issue_comment("mypool/pkgA", package_pr_number, "merge ok")
|
|
|
|
|
|
|
|
|
|
# 5. Verify both PRs are merged
|
|
|
|
|
print("Polling for PR merge status...")
|
|
|
|
|
package_merged = False
|
|
|
|
|
project_merged = False
|
|
|
|
|
|
|
|
|
|
for i in range(20): # Poll for up to 20 seconds
|
|
|
|
|
if not package_merged:
|
|
|
|
|
pkg_details = gitea_env.get_pr_details("mypool/pkgA", package_pr_number)
|
|
|
|
|
if pkg_details.get("merged"):
|
|
|
|
|
package_merged = True
|
|
|
|
|
print(f"Package PR mypool/pkgA#{package_pr_number} merged.")
|
|
|
|
|
|
|
|
|
|
if not project_merged:
|
|
|
|
|
prj_details = gitea_env.get_pr_details("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
if prj_details.get("merged"):
|
|
|
|
|
project_merged = True
|
|
|
|
|
print(f"Project PR myproducts/mySLFO#{project_pr_number} merged.")
|
|
|
|
|
|
|
|
|
|
if package_merged and project_merged:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
package_merged, project_merged = wait_for_merge_status(gitea_env, package_pr_number, project_pr_number)
|
|
|
|
|
|
|
|
|
|
assert not package_merged, f"Package PR mypool/pkgA#{package_pr_number} was merged after 'merge ok'."
|
|
|
|
|
assert not project_merged, f"Project PR myproducts/mySLFO#{project_pr_number} was merged after 'merge ok'."
|
|
|
|
|
@@ -300,10 +254,10 @@ index 00000000..473a0f4c
|
|
|
|
|
|
|
|
|
|
# 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):
|
|
|
|
|
for i in range(30): # Poll with 0.5s interval
|
|
|
|
|
gitea_env.approve_requested_reviews("mypool/pkgA", package_pr_number)
|
|
|
|
|
gitea_env.approve_requested_reviews("myproducts/mySLFO", project_pr_number)
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
|
|
|
|
|
|
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!"
|
|
|
|
|
|