Files
autogits/integration/tests/workflow_pr_remove_package.py
T

346 lines
14 KiB
Python

import pytest
import requests
import time
import json
import base64
@pytest.mark.t001
@pytest.mark.xdist_group(name="branch_main")
def test_issue_processor_remove_package_via_issue(main_env, test_user_client, unique_id):
"""
Test scenario TC-RM-001: Package removal via [RM] issue.
"""
gitea_env, test_full_repo_name, merge_branch_name = main_env
pkg_name = f"pkgRM1_{unique_id}"
# Pre-create the org label for package removal so the bot can apply it
gitea_env.create_org_label("myproducts", "request/Remove Package", "#ff0000")
# 1. Create a new repository in mypool's organization
gitea_env.setup_repo("mypool", pkg_name)
# Add workflow-pr as admin collaborator to the repository so it can rename branches
gitea_env._request("PUT", f"repos/mypool/{pkg_name}/collaborators/workflow-pr", json={
"permission": "admin"
})
# 4. Get latest commit SHA for pkgRM1
resp, _ = gitea_env._request("GET", f"repos/mypool/{pkg_name}/branches/main")
pkg_sha = resp.json()["commit"]["id"]
# 5. Read current .gitmodules of myproducts/mySLFO
try:
resp, _ = gitea_env._request("GET", "repos/myproducts/mySLFO/contents/.gitmodules")
old_gitmodules = base64.b64decode(resp.json()["content"]).decode("utf-8")
except Exception:
old_gitmodules = ""
# 6. Update .gitmodules with our submodule
new_gitmodules = old_gitmodules + f"\n[submodule \"{pkg_name}\"]\n path = {pkg_name}\n url = ../../mypool/{pkg_name}.git\n"
gitea_env.create_file("myproducts", "mySLFO", ".gitmodules", new_gitmodules, branch="main", message=f"Add submodule {pkg_name}")
time.sleep(2)
# 7. Add gitlink via diffpatch
diff_content = f"""diff --git a/{pkg_name} b/{pkg_name}
new file mode 160000
index 00000000..{pkg_sha}
--- /dev/null
+++ b/{pkg_name}
@@ -0,0 +1 @@
+Subproject commit {pkg_sha}
"""
data = {
"branch": "main",
"content": diff_content,
"message": f"Add {pkg_name} gitlink"
}
gitea_env._request("POST", "repos/myproducts/mySLFO/diffpatch", json=data)
time.sleep(2)
# 8. Create [RM] issue in myproducts/mySLFO
issue_data = {
"title": f"[RM] Remove {pkg_name} from main",
"body": f"{pkg_name}",
"ref": "refs/heads/main"
}
response, _ = test_user_client._request("POST", "repos/myproducts/mySLFO/issues", json=issue_data)
issue = response.json()
issue_number = issue["number"]
print(f"Created [RM] issue #{issue_number}")
time.sleep(2)
# 9. Wait for project PR for package removal to be created
prj_pr_number = None
for _ in range(60):
resp, _ = gitea_env._request("GET", "repos/myproducts/mySLFO/pulls", params={"state": "open"})
pulls = resp.json()
for p in pulls:
if p["title"] == f"[RM] Remove packages: {pkg_name}":
prj_pr_number = p["number"]
break
if prj_pr_number:
break
time.sleep(2)
assert prj_pr_number is not None, f"Project PR for package removal of {pkg_name} was not created"
# 10. Check if branch in mypool/{pkg_name} was renamed to main-removed
renamed = False
for _ in range(60):
resp, _ = gitea_env._request("GET", f"repos/mypool/{pkg_name}/branches")
branches = [b["name"] for b in resp.json()]
if "main-removed" in branches and "main" not in branches:
renamed = True
break
time.sleep(2)
assert renamed, f"Package branch for {pkg_name} was not renamed to main-removed"
# 11. Check if Remove Package label was applied to the issue (with polling for asynchronous application)
label_applied = False
labels = []
for _ in range(60):
resp, _ = gitea_env._request("GET", f"repos/myproducts/mySLFO/issues/{issue_number}")
labels = [l["name"] for l in resp.json()["labels"]]
if any("Remove Package" in label for label in labels):
label_applied = True
break
time.sleep(2)
assert label_applied, f"Expected Remove Package label on issue #{issue_number}, found: {labels}"
@pytest.mark.t002
@pytest.mark.dependency(name="issue_011")
@pytest.mark.xdist_group(name="branch_main")
def test_package_removed_without_issue(main_env, test_user_client, unique_id):
"""
Test scenario TC-RM-002: Bypassed package removal detection.
"""
gitea_env, test_full_repo_name, merge_branch_name = main_env
pkg_name = f"pkgRM2_{unique_id}"
# Pre-create the org label for package removal so the bot can apply it
gitea_env.create_org_label("myproducts", "request/Remove Package", "#ff0000")
# 1. Create a new repository in mypool organization
gitea_env.setup_repo("mypool", pkg_name)
# Add workflow-pr as admin collaborator to the repository so it can rename branches
gitea_env._request("PUT", f"repos/mypool/{pkg_name}/collaborators/workflow-pr", json={
"permission": "admin"
})
# 4. Get latest commit SHA for pkgRM2
resp, _ = gitea_env._request("GET", f"repos/mypool/{pkg_name}/branches/main")
pkg_sha = resp.json()["commit"]["id"]
# 5. Read current .gitmodules of myproducts/mySLFO
try:
resp, _ = gitea_env._request("GET", "repos/myproducts/mySLFO/contents/.gitmodules")
old_gitmodules = base64.b64decode(resp.json()["content"]).decode("utf-8")
except Exception:
old_gitmodules = ""
# 6. Update .gitmodules with our submodule
new_gitmodules = old_gitmodules + f"\n[submodule \"{pkg_name}\"]\n path = {pkg_name}\n url = ../../mypool/{pkg_name}.git\n"
gitea_env.create_file("myproducts", "mySLFO", ".gitmodules", new_gitmodules, branch="main", message=f"Add submodule {pkg_name}")
time.sleep(2)
# 7. Add gitlink via diffpatch
diff_content = f"""diff --git a/{pkg_name} b/{pkg_name}
new file mode 160000
index 00000000..{pkg_sha}
--- /dev/null
+++ b/{pkg_name}
@@ -0,0 +1 @@
+Subproject commit {pkg_sha}
"""
data = {
"branch": "main",
"content": diff_content,
"message": f"Add {pkg_name} gitlink"
}
gitea_env._request("POST", "repos/myproducts/mySLFO/diffpatch", json=data)
time.sleep(2)
# 8. Read the .gitmodules content again
resp, _ = gitea_env._request("GET", "repos/myproducts/mySLFO/contents/.gitmodules")
current_gitmodules = base64.b64decode(resp.json()["content"]).decode("utf-8")
# Remove our submodule section
section_to_remove = f'\n[submodule "{pkg_name}"]\n path = {pkg_name}\n url = ../../mypool/{pkg_name}.git\n'
if section_to_remove in current_gitmodules:
removed_gitmodules = current_gitmodules.replace(section_to_remove, "")
else:
# Fallback if whitespace differs
removed_gitmodules = current_gitmodules.replace(f'[submodule "{pkg_name}"]', "").replace(f'path = {pkg_name}', "").replace(f'url = ../../mypool/{pkg_name}.git', "")
# . Update .gitmodules on the removal branch
# 11. Delete submodule gitlink via diffpatch on the removal branch
del_diff = f"""diff --git a/{pkg_name} b/{pkg_name}
deleted file mode 160000
index {pkg_sha}..00000000
--- a/{pkg_name}
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit {pkg_sha}
"""
data = {
"branch": f"main",
"content": del_diff,
"message": f"Delete {pkg_name} gitlink"
}
gitea_env._request("POST", "repos/myproducts/mySLFO/diffpatch", json=data)
time.sleep(2)
# 14. Check if branch in mypool/{pkg_name} was renamed to main-removed
renamed = False
for _ in range(60):
resp, _ = gitea_env._request("GET", f"repos/mypool/{pkg_name}/branches")
branches = [b["name"] for b in resp.json()]
if "main-removed" in branches and "main" not in branches:
renamed = True
break
time.sleep(2)
assert renamed, f"Package branch for {pkg_name} was not renamed to main-removed after manual PR merge"
@pytest.mark.t003
@pytest.mark.xdist_group(name="branch_main")
def test_issue_processor_readd_package(main_env, test_user_client, ownerB_client, unique_id):
"""
Test scenario TC-RM-003: Package re-addition after removal.
"""
gitea_env, test_full_repo_name, merge_branch_name = main_env
pkg_name = f"pkgRM3_{unique_id}"
# Pre-create the org labels so the bot can apply them
gitea_env.create_org_label("myproducts", "request/Remove Package", "#ff0000")
gitea_env.create_org_label("myproducts", "request/Add Package", "#00ff00")
# 1. Create a new repository in mypool's organization
gitea_env.setup_repo("mypool", pkg_name)
# Add workflow-pr as admin collaborator to the repository so it can rename/delete branches
gitea_env._request("PUT", f"repos/mypool/{pkg_name}/collaborators/workflow-pr", json={
"permission": "admin"
})
# 4. Get latest commit SHA for pkgRM3
resp, _ = gitea_env._request("GET", f"repos/mypool/{pkg_name}/branches/main")
pkg_sha = resp.json()["commit"]["id"]
# 5. Read current .gitmodules of myproducts/mySLFO
try:
resp, _ = gitea_env._request("GET", "repos/myproducts/mySLFO/contents/.gitmodules")
old_gitmodules = base64.b64decode(resp.json()["content"]).decode("utf-8")
except Exception:
old_gitmodules = ""
# 6. Update .gitmodules with our submodule
new_gitmodules = old_gitmodules + f"\n[submodule \"{pkg_name}\"]\n path = {pkg_name}\n url = ../../mypool/{pkg_name}.git\n"
gitea_env.create_file("myproducts", "mySLFO", ".gitmodules", new_gitmodules, branch="main", message=f"Add submodule {pkg_name}")
# 7. Add gitlink via diffpatch
diff_content = f"""diff --git a/{pkg_name} b/{pkg_name}
new file mode 160000
index 00000000..{pkg_sha}
--- /dev/null
+++ b/{pkg_name}
@@ -0,0 +1 @@
+Subproject commit {pkg_sha}
"""
data = {
"branch": "main",
"content": diff_content,
"message": f"Add {pkg_name} gitlink"
}
gitea_env._request("POST", "repos/myproducts/mySLFO/diffpatch", json=data)
# 8. Create [RM] issue in myproducts/mySLFO
issue_data = {
"title": f"[RM] Remove {pkg_name} from main",
"body": f"{pkg_name}",
"ref": "refs/heads/main"
}
response, _ = test_user_client._request("POST", "repos/myproducts/mySLFO/issues", json=issue_data)
issue = response.json()
issue_number = issue["number"]
print(f"Created [RM] issue #{issue_number}")
# 9. Wait for project PR for package removal to be created
prj_pr_number = None
for _ in range(60):
resp, _ = gitea_env._request("GET", "repos/myproducts/mySLFO/pulls", params={"state": "open"})
pulls = resp.json()
for p in pulls:
if p["title"] == f"[RM] Remove packages: {pkg_name}":
prj_pr_number = p["number"]
break
if prj_pr_number:
break
time.sleep(2)
assert prj_pr_number is not None, f"Project PR for package removal of {pkg_name} was not created"
# 10. Wait for package branch to be renamed to main-removed
renamed = False
for _ in range(60):
resp, _ = gitea_env._request("GET", f"repos/mypool/{pkg_name}/branches")
branches = [b["name"] for b in resp.json()]
if "main-removed" in branches and "main" not in branches:
renamed = True
break
time.sleep(2)
assert renamed, f"Package branch for {pkg_name} was not renamed to main-removed"
# 11. Approve the removal Project PR so it gets merged and closes the issue
gitea_env.approve_requested_reviews("myproducts/mySLFO", prj_pr_number)
# Wait for Project PR to be merged
merged = False
for _ in range(60):
prj_details = gitea_env.get_pr_details("myproducts/mySLFO", prj_pr_number)
if prj_details.get("merged"):
merged = True
break
time.sleep(2)
assert merged, "Removal project PR was not merged"
# Wait for issue to be closed
gitea_env.wait_for_issue_closed("myproducts/mySLFO", issue_number)
# 12. Create [ADD] issue to re-add the package (which currently has main-removed branch only)
add_issue_data = {
"title": f"[ADD] Re-add {pkg_name}",
"body": f"mypool/{pkg_name}#main-removed",
"ref": "refs/heads/main"
}
response, _ = test_user_client._request("POST", "repos/myproducts/mySLFO/issues", json=add_issue_data)
add_issue = response.json()
add_issue_number = add_issue["number"]
print(f"Created [ADD] issue #{add_issue_number}")
# Wait for the "approval required" comment
comment_found = gitea_env.wait_for_comment("myproducts/mySLFO", add_issue_number, "<!-- autogits: approval-required -->", timeout=120)
assert comment_found, f"[Issue myproducts/mySLFO#{add_issue_number}] Bot did not post the approval required comment"
# Comment "approve" as ownerB to trigger the package PR and project PR creation
ownerB_client.create_issue_comment("myproducts/mySLFO", add_issue_number, "approve")
# 13. Wait for package PR to be created (which should succeed by detecting and using main-removed branch)
pkg_pr_number = gitea_env.wait_for_package_pr(f"mypool/{pkg_name}", add_issue_number)
# 14. Wait for project PR to be created
prj_pr2_number = gitea_env.wait_for_project_pr(f"mypool/{pkg_name}", pkg_pr_number)
# 15. Merge both PRs for the package re-addition
gitea_env.approve_and_wait_merge(f"mypool/{pkg_name}", pkg_pr_number, prj_pr2_number)
# 16. Verify that the re-addition successfully completed and deleted the main-removed branch
deleted_removed_branch = False
for _ in range(60):
resp, _ = gitea_env._request("GET", f"repos/mypool/{pkg_name}/branches")
branches = [b["name"] for b in resp.json()]
if "main" in branches and "main-removed" not in branches:
deleted_removed_branch = True
break
time.sleep(2)
assert deleted_removed_branch, f"Former removed branch main-removed was not deleted after merge"