feat(profiles): support reconciler cleanup capability and migration (Closes #687) #688
+12
-1
@@ -26,6 +26,12 @@ REVIEWER_DEFAULT_ALLOWED = [
|
||||
"read", "review", "comment", "approve", "request_changes", "merge"
|
||||
]
|
||||
REVIEWER_DEFAULT_FORBIDDEN = ["branch", "commit", "push", "open_pr"]
|
||||
RECONCILER_DEFAULT_ALLOWED = [
|
||||
"read", "pr.close", "pr.comment", "issue.comment", "issue.close", "gitea.branch.delete"
|
||||
]
|
||||
RECONCILER_DEFAULT_FORBIDDEN = [
|
||||
"approve", "merge", "review", "pr.create", "branch.push", "commit"
|
||||
]
|
||||
|
||||
|
||||
def infer_role(name, execution_profile):
|
||||
@@ -90,9 +96,11 @@ def migrate_v1_to_v2(v1_data):
|
||||
ident_name = "reviewer"
|
||||
elif role == "author":
|
||||
ident_name = "author"
|
||||
elif role == "reconciler":
|
||||
ident_name = "reconciler"
|
||||
else:
|
||||
role = prof.get("role")
|
||||
if role not in (None, "author", "reviewer"):
|
||||
if role not in (None, "author", "reviewer", "reconciler"):
|
||||
raise ValueError(
|
||||
f"Profile '{name}' has unsupported role {role!r}"
|
||||
)
|
||||
@@ -132,6 +140,9 @@ def migrate_v1_to_v2(v1_data):
|
||||
elif role == "reviewer":
|
||||
identity_data["allowed_operations"] = list(REVIEWER_DEFAULT_ALLOWED)
|
||||
identity_data["forbidden_operations"] = list(REVIEWER_DEFAULT_FORBIDDEN)
|
||||
elif role == "reconciler":
|
||||
identity_data["allowed_operations"] = list(RECONCILER_DEFAULT_ALLOWED)
|
||||
identity_data["forbidden_operations"] = list(RECONCILER_DEFAULT_FORBIDDEN)
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Profile '{name}' has no explicit operation lists and no "
|
||||
|
||||
@@ -306,6 +306,60 @@ class TestMigrateProfiles(unittest.TestCase):
|
||||
migrate_profiles.main()
|
||||
self.assertEqual(cm.exception.code, 1)
|
||||
|
||||
def test_reconciler_profile_migration(self):
|
||||
"""Verify that reconciler profiles with explicit operations migrate correctly."""
|
||||
v1_data = {
|
||||
"version": 1,
|
||||
"profiles": {
|
||||
"prgs-reconciler": {
|
||||
"base_url": "redacted-prgs-service",
|
||||
"username": "reconciler-agent",
|
||||
"auth": {"type": "keychain", "id": "reconciler-ref"},
|
||||
"execution_profile": "prgs-reconciler",
|
||||
"allowed_operations": ["read", "pr.close", "gitea.branch.delete"],
|
||||
"forbidden_operations": ["merge", "approve"]
|
||||
}
|
||||
}
|
||||
}
|
||||
v2_data = migrate_profiles.migrate_v1_to_v2(v1_data)
|
||||
reconciler = (
|
||||
v2_data["environments"]["prgs"]["services"]["gitea"]
|
||||
["identities"]["reconciler"]
|
||||
)
|
||||
self.assertEqual(reconciler["role"], "reconciler")
|
||||
self.assertEqual(reconciler["allowed_operations"], ["read", "pr.close", "gitea.branch.delete"])
|
||||
self.assertEqual(reconciler["forbidden_operations"], ["merge", "approve"])
|
||||
self.assertEqual(v2_data["aliases"]["prgs-reconciler"], "prgs.gitea.reconciler")
|
||||
|
||||
def test_reconciler_profile_defaults(self):
|
||||
"""Verify that reconciler profiles without explicit operations get defaults."""
|
||||
v1_data = {
|
||||
"version": 1,
|
||||
"profiles": {
|
||||
"prgs-reconciler": {
|
||||
"base_url": "redacted-prgs-service",
|
||||
"username": "reconciler-agent",
|
||||
"auth": {"type": "keychain", "id": "reconciler-ref"},
|
||||
"execution_profile": "prgs-reconciler",
|
||||
}
|
||||
}
|
||||
}
|
||||
v2_data = migrate_profiles.migrate_v1_to_v2(v1_data)
|
||||
reconciler = (
|
||||
v2_data["environments"]["prgs"]["services"]["gitea"]
|
||||
["identities"]["reconciler"]
|
||||
)
|
||||
self.assertEqual(reconciler["role"], "reconciler")
|
||||
self.assertEqual(
|
||||
reconciler["allowed_operations"],
|
||||
migrate_profiles.RECONCILER_DEFAULT_ALLOWED,
|
||||
)
|
||||
self.assertEqual(
|
||||
reconciler["forbidden_operations"],
|
||||
migrate_profiles.RECONCILER_DEFAULT_FORBIDDEN,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user