diff --git a/migrate_profiles.py b/migrate_profiles.py index 6bf150c..211737f 100755 --- a/migrate_profiles.py +++ b/migrate_profiles.py @@ -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 " diff --git a/tests/test_migrate_profiles.py b/tests/test_migrate_profiles.py index abbe5df..37ed757 100644 --- a/tests/test_migrate_profiles.py +++ b/tests/test_migrate_profiles.py @@ -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() +