mirror of
https://github.com/josegonzalez/python-github-backup.git
synced 2026-04-30 20:45:35 +02:00
238 lines
8.4 KiB
Python
238 lines
8.4 KiB
Python
"""Tests for pull request review backups."""
|
|
|
|
import json
|
|
import os
|
|
|
|
from github_backup import github_backup
|
|
|
|
|
|
def test_parse_args_pull_reviews_flag():
|
|
args = github_backup.parse_args(["--pull-reviews", "testuser"])
|
|
assert args.include_pull_reviews is True
|
|
|
|
|
|
def test_backup_pulls_includes_review_data(create_args, tmp_path, monkeypatch):
|
|
args = create_args(include_pulls=True, include_pull_reviews=True)
|
|
repository = {"full_name": "owner/repo"}
|
|
calls = []
|
|
|
|
def fake_retrieve_data(passed_args, template, query_args=None, paginated=True, **kwargs):
|
|
calls.append((template, query_args))
|
|
if template == "https://api.github.com/repos/owner/repo/pulls":
|
|
if query_args["state"] == "open":
|
|
return [
|
|
{
|
|
"number": 1,
|
|
"updated_at": "2026-02-01T00:00:00Z",
|
|
"title": "Add feature",
|
|
}
|
|
]
|
|
return []
|
|
if template == "https://api.github.com/repos/owner/repo/pulls/1/reviews":
|
|
return [
|
|
{
|
|
"id": 123,
|
|
"state": "APPROVED",
|
|
"body": "Looks good",
|
|
"submitted_at": "2026-02-01T00:00:00Z",
|
|
}
|
|
]
|
|
raise AssertionError("Unexpected template: {0}".format(template))
|
|
|
|
monkeypatch.setattr(github_backup, "retrieve_data", fake_retrieve_data)
|
|
|
|
github_backup.backup_pulls(
|
|
args, tmp_path, repository, "https://api.github.com/repos"
|
|
)
|
|
|
|
with open(tmp_path / "pulls" / "1.json", encoding="utf-8") as f:
|
|
pull = json.load(f)
|
|
|
|
assert pull["review_data"] == [
|
|
{
|
|
"body": "Looks good",
|
|
"id": 123,
|
|
"state": "APPROVED",
|
|
"submitted_at": "2026-02-01T00:00:00Z",
|
|
}
|
|
]
|
|
assert (
|
|
"https://api.github.com/repos/owner/repo/pulls/1/reviews",
|
|
None,
|
|
) in calls
|
|
|
|
|
|
def test_pull_reviews_backfill_ignores_repository_checkpoint(
|
|
create_args, tmp_path, monkeypatch
|
|
):
|
|
args = create_args(
|
|
include_pulls=True,
|
|
include_pull_reviews=True,
|
|
incremental=True,
|
|
)
|
|
args.since = "2026-01-01T00:00:00Z"
|
|
repository = {"full_name": "owner/repo"}
|
|
|
|
def fake_retrieve_data(passed_args, template, query_args=None, paginated=True, **kwargs):
|
|
if template == "https://api.github.com/repos/owner/repo/pulls":
|
|
if query_args["state"] == "open":
|
|
return [
|
|
{
|
|
"number": 1,
|
|
"updated_at": "2025-01-01T00:00:00Z",
|
|
"title": "Old pull request",
|
|
}
|
|
]
|
|
return []
|
|
if template == "https://api.github.com/repos/owner/repo/pulls/1/reviews":
|
|
return [{"id": 123, "state": "APPROVED"}]
|
|
raise AssertionError("Unexpected template: {0}".format(template))
|
|
|
|
monkeypatch.setattr(github_backup, "retrieve_data", fake_retrieve_data)
|
|
|
|
github_backup.backup_pulls(
|
|
args, tmp_path, repository, "https://api.github.com/repos"
|
|
)
|
|
|
|
with open(tmp_path / "pulls" / "1.json", encoding="utf-8") as f:
|
|
pull = json.load(f)
|
|
|
|
assert pull["review_data"] == [{"id": 123, "state": "APPROVED"}]
|
|
assert (tmp_path / "pulls" / "reviews_last_update").read_text() == (
|
|
"2025-01-01T00:00:00Z"
|
|
)
|
|
|
|
|
|
def test_pull_reviews_uses_review_checkpoint_when_older_than_repository_checkpoint(
|
|
create_args, tmp_path, monkeypatch
|
|
):
|
|
args = create_args(
|
|
include_pulls=True,
|
|
include_pull_reviews=True,
|
|
incremental=True,
|
|
)
|
|
args.since = "2026-01-01T00:00:00Z"
|
|
repository = {"full_name": "owner/repo"}
|
|
pulls_dir = tmp_path / "pulls"
|
|
pulls_dir.mkdir()
|
|
(pulls_dir / "reviews_last_update").write_text("2025-01-01T00:00:00Z")
|
|
|
|
def fake_retrieve_data(passed_args, template, query_args=None, paginated=True, **kwargs):
|
|
if template == "https://api.github.com/repos/owner/repo/pulls":
|
|
if query_args["state"] == "open":
|
|
return [
|
|
{
|
|
"number": 1,
|
|
"updated_at": "2025-06-01T00:00:00Z",
|
|
"title": "Review changed while feature was disabled",
|
|
},
|
|
{
|
|
"number": 2,
|
|
"updated_at": "2024-12-01T00:00:00Z",
|
|
"title": "Too old",
|
|
},
|
|
]
|
|
return []
|
|
if template == "https://api.github.com/repos/owner/repo/pulls/1/reviews":
|
|
return [{"id": 123, "state": "COMMENTED"}]
|
|
raise AssertionError("Unexpected template: {0}".format(template))
|
|
|
|
monkeypatch.setattr(github_backup, "retrieve_data", fake_retrieve_data)
|
|
|
|
github_backup.backup_pulls(
|
|
args, tmp_path, repository, "https://api.github.com/repos"
|
|
)
|
|
|
|
assert os.path.exists(tmp_path / "pulls" / "1.json")
|
|
assert not os.path.exists(tmp_path / "pulls" / "2.json")
|
|
assert (tmp_path / "pulls" / "reviews_last_update").read_text() == (
|
|
"2025-06-01T00:00:00Z"
|
|
)
|
|
|
|
|
|
def test_pull_reviews_preserves_existing_optional_pull_data(
|
|
create_args, tmp_path, monkeypatch
|
|
):
|
|
args = create_args(include_pulls=True, include_pull_reviews=True)
|
|
repository = {"full_name": "owner/repo"}
|
|
pulls_dir = tmp_path / "pulls"
|
|
pulls_dir.mkdir()
|
|
with open(pulls_dir / "1.json", "w", encoding="utf-8") as f:
|
|
json.dump(
|
|
{
|
|
"number": 1,
|
|
"updated_at": "2026-01-01T00:00:00Z",
|
|
"comment_data": [{"id": 10, "body": "inline comment"}],
|
|
"comment_regular_data": [{"id": 11, "body": "regular comment"}],
|
|
"commit_data": [{"sha": "abc"}],
|
|
},
|
|
f,
|
|
)
|
|
|
|
def fake_retrieve_data(passed_args, template, query_args=None, paginated=True, **kwargs):
|
|
if template == "https://api.github.com/repos/owner/repo/pulls":
|
|
if query_args["state"] == "open":
|
|
return [
|
|
{
|
|
"number": 1,
|
|
"updated_at": "2026-02-01T00:00:00Z",
|
|
"title": "Add reviews",
|
|
}
|
|
]
|
|
return []
|
|
if template == "https://api.github.com/repos/owner/repo/pulls/1/reviews":
|
|
return [{"id": 123, "state": "APPROVED"}]
|
|
raise AssertionError("Unexpected template: {0}".format(template))
|
|
|
|
monkeypatch.setattr(github_backup, "retrieve_data", fake_retrieve_data)
|
|
|
|
github_backup.backup_pulls(
|
|
args, tmp_path, repository, "https://api.github.com/repos"
|
|
)
|
|
|
|
with open(pulls_dir / "1.json", encoding="utf-8") as f:
|
|
pull = json.load(f)
|
|
|
|
assert pull["review_data"] == [{"id": 123, "state": "APPROVED"}]
|
|
assert pull["comment_data"] == [{"id": 10, "body": "inline comment"}]
|
|
assert pull["comment_regular_data"] == [{"id": 11, "body": "regular comment"}]
|
|
assert pull["commit_data"] == [{"sha": "abc"}]
|
|
|
|
|
|
def test_pull_reviews_does_not_advance_checkpoint_on_review_error(
|
|
create_args, tmp_path, monkeypatch
|
|
):
|
|
args = create_args(
|
|
include_pulls=True,
|
|
include_pull_reviews=True,
|
|
incremental=True,
|
|
)
|
|
args.since = "2026-01-01T00:00:00Z"
|
|
repository = {"full_name": "owner/repo"}
|
|
pulls_dir = tmp_path / "pulls"
|
|
pulls_dir.mkdir()
|
|
(pulls_dir / "reviews_last_update").write_text("2025-01-01T00:00:00Z")
|
|
|
|
def fake_retrieve_data(passed_args, template, query_args=None, paginated=True, **kwargs):
|
|
if template == "https://api.github.com/repos/owner/repo/pulls":
|
|
if query_args["state"] == "open":
|
|
return [
|
|
{
|
|
"number": 1,
|
|
"updated_at": "2025-06-01T00:00:00Z",
|
|
"title": "Review retrieval fails",
|
|
}
|
|
]
|
|
return []
|
|
if template == "https://api.github.com/repos/owner/repo/pulls/1/reviews":
|
|
raise Exception("temporary API failure")
|
|
raise AssertionError("Unexpected template: {0}".format(template))
|
|
|
|
monkeypatch.setattr(github_backup, "retrieve_data", fake_retrieve_data)
|
|
|
|
github_backup.backup_pulls(
|
|
args, tmp_path, repository, "https://api.github.com/repos"
|
|
)
|
|
|
|
assert (pulls_dir / "reviews_last_update").read_text() == "2025-01-01T00:00:00Z"
|