Skip to content

Commit e6ee17f

Browse files
authored
Merge pull request #453 from fabiogallotti/add-pagination-for-artifacts
2 parents bc1744f + ac3108e commit e6ee17f

File tree

5 files changed

+136
-12
lines changed

5 files changed

+136
-12
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
.coverage
44
dev-env-vars
55
.coverage*
6+
__pycache__

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.PHONY: install
2+
install: ## install dependencies
3+
poetry install --with dev
4+
pre-commit install
5+
6+
.PHONY: lint
7+
lint: ## lint code
8+
pre-commit
9+
10+
.PHONY: test
11+
test: ## run all tests
12+
poetry run pytest tests

coverage_comment/github.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ def download_artifact(
5454
filename: pathlib.Path,
5555
) -> str:
5656
repo_path = github.repos(repository)
57-
artifacts = repo_path.actions.runs(run_id).artifacts.get().artifacts
57+
5858
try:
5959
artifact = next(
60-
iter(artifact for artifact in artifacts if artifact.name == artifact_name),
60+
artifact
61+
for artifact in _fetch_artifacts(repo_path, run_id)
62+
if artifact.name == artifact_name
6163
)
6264
except StopIteration:
63-
raise NoArtifact(
64-
f"Not artifact found with name {artifact_name} in run {run_id}"
65-
)
65+
raise NoArtifact(f"No artifact found with name {artifact_name} in run {run_id}")
6666

6767
zip_bytes = io.BytesIO(repo_path.actions.artifacts(artifact.id).zip.get(bytes=True))
6868
zipf = zipfile.ZipFile(zip_bytes)
@@ -73,6 +73,24 @@ def download_artifact(
7373
raise NoArtifact(f"File named {filename} not found in artifact {artifact_name}")
7474

7575

76+
def _fetch_artifacts(repo_path, run_id):
77+
page = 1
78+
total_fetched = 0
79+
80+
while True:
81+
result = repo_path.actions.runs(run_id).artifacts.get(page=str(page))
82+
if not result or not result.artifacts:
83+
break
84+
85+
yield from result.artifacts
86+
87+
total_fetched += len(result.artifacts)
88+
if total_fetched >= result.total_count:
89+
break
90+
91+
page += 1
92+
93+
7694
def get_branch_from_workflow_run(
7795
github: github_client.GitHub, repository: str, run_id: int
7896
) -> tuple[str, str]:

tests/integration/test_github.py

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def test_download_artifact(gh, session, zip_bytes):
5252
{"name": "foo", "id": 789},
5353
]
5454
session.register("GET", "/repos/foo/bar/actions/runs/123/artifacts")(
55-
json={"artifacts": artifacts}
55+
json={"artifacts": artifacts, "total_count": 2}
5656
)
5757

5858
session.register("GET", "/repos/foo/bar/actions/artifacts/789/zip")(
@@ -70,12 +70,44 @@ def test_download_artifact(gh, session, zip_bytes):
7070
assert result == "bar"
7171

7272

73+
def test_download_artifact_from_page_2(gh, session, zip_bytes):
74+
artifacts_page_1 = [
75+
{"name": "test", "id": 000},
76+
]
77+
artifacts_page_2 = [
78+
{"name": "bar", "id": 456},
79+
{"name": "foo", "id": 789},
80+
]
81+
session.register("GET", "/repos/foo/bar/actions/runs/123/artifacts")(
82+
json={"artifacts": artifacts_page_1, "total_count": 3}
83+
)
84+
session.register(
85+
"GET",
86+
"/repos/foo/bar/actions/runs/123/artifacts",
87+
params={"page": "2"},
88+
)(json={"artifacts": artifacts_page_2, "total_count": 3})
89+
90+
session.register("GET", "/repos/foo/bar/actions/artifacts/789/zip")(
91+
content=zip_bytes(filename="foo.txt", content="bar")
92+
)
93+
94+
result = github.download_artifact(
95+
github=gh,
96+
repository="foo/bar",
97+
artifact_name="foo",
98+
run_id=123,
99+
filename=pathlib.Path("foo.txt"),
100+
)
101+
102+
assert result == "bar"
103+
104+
73105
def test_download_artifact__no_artifact(gh, session):
74106
artifacts = [
75107
{"name": "bar", "id": 456},
76108
]
77109
session.register("GET", "/repos/foo/bar/actions/runs/123/artifacts")(
78-
json={"artifacts": artifacts}
110+
json={"artifacts": artifacts, "total_count": 1}
79111
)
80112

81113
with pytest.raises(github.NoArtifact):
@@ -89,12 +121,15 @@ def test_download_artifact__no_artifact(gh, session):
89121

90122

91123
def test_download_artifact__no_file(gh, session, zip_bytes):
92-
artifacts = [
93-
{"name": "foo", "id": 789},
94-
]
124+
artifacts = [{"name": "foo", "id": 789}]
95125
session.register("GET", "/repos/foo/bar/actions/runs/123/artifacts")(
96126
json={"artifacts": artifacts}
97127
)
128+
session.register(
129+
"GET",
130+
"/repos/foo/bar/actions/runs/123/artifacts",
131+
params={"page": "2"},
132+
)(json={})
98133

99134
session.register("GET", "/repos/foo/bar/actions/artifacts/789/zip")(
100135
content=zip_bytes(filename="foo.txt", content="bar")
@@ -109,6 +144,59 @@ def test_download_artifact__no_file(gh, session, zip_bytes):
109144
)
110145

111146

147+
def test_fetch_artifacts_empty_response(gh, session):
148+
session.register("GET", "/repos/foo/bar/actions/runs/123/artifacts")(
149+
json={"artifacts": [], "total_count": 0}
150+
)
151+
152+
repo_path = gh.repos("foo/bar")
153+
154+
result = github._fetch_artifacts(
155+
repo_path=repo_path,
156+
run_id=123,
157+
)
158+
159+
assert not list(result)
160+
161+
162+
def test_fetch_artifacts_single_page(gh, session):
163+
artifacts = [{"name": "bar", "id": 456}]
164+
165+
session.register("GET", "/repos/foo/bar/actions/runs/123/artifacts")(
166+
json={"artifacts": artifacts, "total_count": 1}
167+
)
168+
169+
repo_path = gh.repos("foo/bar")
170+
171+
result = github._fetch_artifacts(
172+
repo_path=repo_path,
173+
run_id=123,
174+
)
175+
176+
assert list(result) == artifacts
177+
178+
179+
def test_fetch_artifacts_multiple_pages(gh, session):
180+
artifacts_page_1 = [{"name": "bar", "id": 456}]
181+
artifacts_page_2 = [{"name": "bar", "id": 789}]
182+
183+
session.register("GET", "/repos/foo/bar/actions/runs/123/artifacts")(
184+
json={"artifacts": artifacts_page_1, "total_count": 2}
185+
)
186+
session.register(
187+
"GET", "/repos/foo/bar/actions/runs/123/artifacts", params={"page": "2"}
188+
)(json={"artifacts": artifacts_page_2, "total_count": 2})
189+
190+
repo_path = gh.repos("foo/bar")
191+
192+
result = github._fetch_artifacts(
193+
repo_path=repo_path,
194+
run_id=123,
195+
)
196+
197+
assert list(result) == artifacts_page_1 + artifacts_page_2
198+
199+
112200
def test_get_branch_from_workflow_run(gh, session):
113201
json = {
114202
"head_branch": "other",

tests/integration/test_main.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ def test_action__workflow_run__no_artifact(
811811
session.register(
812812
"GET",
813813
"/repos/py-cov-action/foobar/actions/runs/123/artifacts",
814-
)(json={"artifacts": [{"name": "wrong_name"}]})
814+
)(json={"artifacts": [{"name": "wrong_name"}], "total_count": 1})
815815

816816
result = main.action(
817817
config=workflow_run_config(),
@@ -852,7 +852,12 @@ def test_action__workflow_run__post_comment(
852852
session.register(
853853
"GET",
854854
"/repos/py-cov-action/foobar/actions/runs/123/artifacts",
855-
)(json={"artifacts": [{"name": "python-coverage-comment-action", "id": 789}]})
855+
)(
856+
json={
857+
"artifacts": [{"name": "python-coverage-comment-action", "id": 789}],
858+
"total_count": 1,
859+
}
860+
)
856861

857862
session.register(
858863
"GET",

0 commit comments

Comments
 (0)