Skip to content

Commit 7a207ae

Browse files
committed
Work with full workflow artifact data object from GitHub API
The GitHub API is used to discover the sketches report workflow artifacts. The artifact archive is then downloaded from the URL provided by the API response. Previously, the artifact discovery methods only returned the download URL. The API response also contains the somewhat useful information of the artifact name. Previously this information was discarded because the name is already available indirectly from the sketches-reports-source input value. However, that will no longer be the case once pattern matching support for the sketches-reports-source input is added. The code is refactored to pass the full data object received from the API for the artifact between the functions. This gives direct access to the exact artifact name.
1 parent 9509908 commit 7a207ae

File tree

2 files changed

+45
-42
lines changed

2 files changed

+45
-42
lines changed

reportsizedeltas/reportsizedeltas.py

+15-15
Original file line numberDiff line numberDiff line change
@@ -140,15 +140,15 @@ def report_size_deltas_from_workflow_artifacts(self) -> None:
140140
print("::debug::Report already exists")
141141
continue
142142

143-
artifact_download_url = self.get_artifact_download_url_for_sha(
143+
artifact_data = self.get_artifact_data_for_sha(
144144
pr_user_login=pr_data["user"]["login"], pr_head_ref=pr_data["head"]["ref"], pr_head_sha=pr_head_sha
145145
)
146-
if artifact_download_url is None:
146+
if artifact_data is None:
147147
# Go on to the next PR
148148
print("::debug::No sketches report artifact found")
149149
continue
150150

151-
artifact_folder_object = self.get_artifact(artifact_download_url=artifact_download_url)
151+
artifact_folder_object = self.get_artifact(artifact_data=artifact_data)
152152

153153
sketches_reports = self.get_sketches_reports(artifact_folder_object=artifact_folder_object)
154154

@@ -195,8 +195,8 @@ def report_exists(self, pr_number: int, pr_head_sha: str) -> bool:
195195
# No reports found for the PR's head SHA
196196
return False
197197

198-
def get_artifact_download_url_for_sha(self, pr_user_login: str, pr_head_ref: str, pr_head_sha: str) -> str | None:
199-
"""Return the report artifact download URL associated with the given head commit hash.
198+
def get_artifact_data_for_sha(self, pr_user_login: str, pr_head_ref: str, pr_head_sha: str) -> str | None:
199+
"""Return the data for the report artifact associated with the given head commit hash.
200200
201201
Keyword arguments:
202202
pr_user_login -- user name of the PR author (used to reduce number of GitHub API requests)
@@ -222,18 +222,18 @@ def get_artifact_download_url_for_sha(self, pr_user_login: str, pr_head_ref: str
222222
for run_data in runs_data["workflow_runs"]:
223223
if run_data["head_sha"] == pr_head_sha:
224224
# Check if this run has the artifact we're looking for
225-
artifact_download_url = self.get_artifact_download_url_for_run(run_id=run_data["id"])
226-
if artifact_download_url is not None:
227-
return artifact_download_url
225+
artifact_data = self.get_artifact_data_for_run(run_id=run_data["id"])
226+
if artifact_data is not None:
227+
return artifact_data
228228

229229
page_number += 1
230230
page_count = api_data["page_count"]
231231

232232
# No matching artifact found
233233
return None
234234

235-
def get_artifact_download_url_for_run(self, run_id: str) -> str | None:
236-
"""Return the report artifact download URL associated with the given GitHub Actions workflow run.
235+
def get_artifact_data_for_run(self, run_id: str):
236+
"""Return the data for the report artifact associated with the given GitHub Actions workflow run.
237237
238238
Keyword arguments:
239239
run_id -- GitHub Actions workflow run ID
@@ -251,27 +251,27 @@ def get_artifact_download_url_for_run(self, run_id: str) -> str | None:
251251
for artifact_data in artifacts_data["artifacts"]:
252252
# The artifact is identified by a specific name
253253
if not artifact_data["expired"] and artifact_data["name"] == self.sketches_reports_source:
254-
return artifact_data["archive_download_url"]
254+
return artifact_data
255255

256256
page_number += 1
257257
page_count = api_data["page_count"]
258258

259259
# No matching artifact found
260260
return None
261261

262-
def get_artifact(self, artifact_download_url: str):
262+
def get_artifact(self, artifact_data):
263263
"""Download and unzip the artifact and return an object for the temporary directory containing it.
264264
265265
Keyword arguments:
266-
artifact_download_url -- URL to download the artifact from GitHub
266+
artifact_data -- data object for the artifact
267267
"""
268268
# Create temporary folder
269269
artifact_folder_object = tempfile.TemporaryDirectory(prefix="reportsizedeltas-")
270270
try:
271-
artifact_zip_file = artifact_folder_object.name + "/" + self.sketches_reports_source + ".zip"
271+
artifact_zip_file = artifact_folder_object.name + "/" + artifact_data["name"] + ".zip"
272272
# Download artifact
273273
with open(file=artifact_zip_file, mode="wb") as out_file:
274-
with self.raw_http_request(url=artifact_download_url) as fp:
274+
with self.raw_http_request(url=artifact_data["archive_download_url"]) as fp:
275275
out_file.write(fp.read())
276276

277277
# Unzip artifact

reportsizedeltas/tests/test_reportsizedeltas.py

+30-27
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ def test_report_size_deltas_from_local_reports(mocker, monkeypatch):
239239

240240

241241
def test_report_size_deltas_from_workflow_artifacts(mocker):
242-
artifact_download_url = "test_artifact_download_url"
242+
artifact_data = unittest.mock.sentinel.artifact_data
243243
artifact_folder_object = "test_artifact_folder_object"
244244
pr_head_sha = "pr-head-sha"
245245
sketches_reports = [{reportsizedeltas.ReportSizeDeltas.ReportKeys.commit_hash: pr_head_sha}]
@@ -258,9 +258,9 @@ def test_report_size_deltas_from_workflow_artifacts(mocker):
258258
)
259259
mocker.patch("reportsizedeltas.ReportSizeDeltas.report_exists", autospec=True, return_value=False)
260260
mocker.patch(
261-
"reportsizedeltas.ReportSizeDeltas.get_artifact_download_url_for_sha",
261+
"reportsizedeltas.ReportSizeDeltas.get_artifact_data_for_sha",
262262
autospec=True,
263-
return_value=artifact_download_url,
263+
return_value=artifact_data,
264264
)
265265
mocker.patch("reportsizedeltas.ReportSizeDeltas.get_artifact", autospec=True, return_value=artifact_folder_object)
266266
mocker.patch("reportsizedeltas.ReportSizeDeltas.get_sketches_reports", autospec=True, return_value=sketches_reports)
@@ -286,15 +286,15 @@ def test_report_size_deltas_from_workflow_artifacts(mocker):
286286

287287
# Test handling of no report artifact
288288
reportsizedeltas.ReportSizeDeltas.report_exists.return_value = False
289-
reportsizedeltas.ReportSizeDeltas.get_artifact_download_url_for_sha.return_value = None
289+
reportsizedeltas.ReportSizeDeltas.get_artifact_data_for_sha.return_value = None
290290
mocker.resetall()
291291

292292
report_size_deltas.report_size_deltas_from_workflow_artifacts()
293293

294294
report_size_deltas.comment_report.assert_not_called()
295295

296296
# Test handling of old sketches report artifacts
297-
reportsizedeltas.ReportSizeDeltas.get_artifact_download_url_for_sha.return_value = artifact_download_url
297+
reportsizedeltas.ReportSizeDeltas.get_artifact_data_for_sha.return_value = artifact_data
298298
reportsizedeltas.ReportSizeDeltas.get_sketches_reports.return_value = None
299299
mocker.resetall()
300300

@@ -321,15 +321,15 @@ def test_report_size_deltas_from_workflow_artifacts(mocker):
321321
report_size_deltas.report_size_deltas_from_workflow_artifacts()
322322

323323
report_exists_calls = []
324-
get_artifact_download_url_for_sha_calls = []
324+
get_artifact_data_for_sha_calls = []
325325
get_sketches_reports_calls = []
326326
generate_report_calls = []
327327
comment_report_calls = []
328328
for pr_data in json_data:
329329
report_exists_calls.append(
330330
unittest.mock.call(report_size_deltas, pr_number=pr_data["number"], pr_head_sha=json_data[0]["head"]["sha"])
331331
)
332-
get_artifact_download_url_for_sha_calls.append(
332+
get_artifact_data_for_sha_calls.append(
333333
unittest.mock.call(
334334
report_size_deltas,
335335
pr_user_login=pr_data["user"]["login"],
@@ -345,8 +345,8 @@ def test_report_size_deltas_from_workflow_artifacts(mocker):
345345
unittest.mock.call(report_size_deltas, pr_number=pr_data["number"], report_markdown=report)
346346
)
347347
report_size_deltas.report_exists.assert_has_calls(calls=report_exists_calls)
348-
report_size_deltas.get_artifact_download_url_for_sha.assert_has_calls(calls=get_artifact_download_url_for_sha_calls)
349-
report_size_deltas.get_artifact.assert_called_with(report_size_deltas, artifact_download_url=artifact_download_url)
348+
report_size_deltas.get_artifact_data_for_sha.assert_has_calls(calls=get_artifact_data_for_sha_calls)
349+
report_size_deltas.get_artifact.assert_called_with(report_size_deltas, artifact_data=artifact_data)
350350
report_size_deltas.get_sketches_reports.assert_has_calls(calls=get_sketches_reports_calls)
351351
report_size_deltas.generate_report.assert_has_calls(calls=generate_report_calls)
352352
report_size_deltas.comment_report.assert_has_calls(calls=comment_report_calls)
@@ -373,12 +373,12 @@ def test_report_exists():
373373
assert not report_size_deltas.report_exists(pr_number=pr_number, pr_head_sha="asdf")
374374

375375

376-
def test_get_artifact_download_url_for_sha():
376+
def test_get_artifact_data_for_sha():
377377
repository_name = "test_name/test_repo"
378378
pr_user_login = "test_pr_user_login"
379379
pr_head_ref = "test_pr_head_ref"
380380
pr_head_sha = "bar123"
381-
test_artifact_url = "test_artifact_url"
381+
test_artifact_data = unittest.mock.sentinel.artifact_data
382382
run_id = "4567"
383383

384384
report_size_deltas = get_reportsizedeltas_object(repository_name=repository_name)
@@ -387,11 +387,11 @@ def test_get_artifact_download_url_for_sha():
387387
report_size_deltas.api_request = unittest.mock.MagicMock(
388388
return_value={"json_data": json_data, "additional_pages": True, "page_count": 3}
389389
)
390-
report_size_deltas.get_artifact_download_url_for_run = unittest.mock.MagicMock(return_value=None)
390+
report_size_deltas.get_artifact_data_for_run = unittest.mock.MagicMock(return_value=None)
391391

392392
# No SHA match
393393
assert (
394-
report_size_deltas.get_artifact_download_url_for_sha(
394+
report_size_deltas.get_artifact_data_for_sha(
395395
pr_user_login=pr_user_login, pr_head_ref=pr_head_ref, pr_head_sha="foosha"
396396
)
397397
is None
@@ -409,30 +409,30 @@ def test_get_artifact_download_url_for_sha():
409409

410410
# SHA match, but no artifact for run
411411
assert (
412-
report_size_deltas.get_artifact_download_url_for_sha(
412+
report_size_deltas.get_artifact_data_for_sha(
413413
pr_user_login=pr_user_login, pr_head_ref=pr_head_ref, pr_head_sha=pr_head_sha
414414
)
415415
is None
416416
)
417417

418-
report_size_deltas.get_artifact_download_url_for_run = unittest.mock.MagicMock(return_value=test_artifact_url)
418+
report_size_deltas.get_artifact_data_for_run = unittest.mock.MagicMock(return_value=test_artifact_data)
419419

420420
# SHA match, artifact match
421-
assert test_artifact_url == (
422-
report_size_deltas.get_artifact_download_url_for_sha(
421+
assert test_artifact_data == (
422+
report_size_deltas.get_artifact_data_for_sha(
423423
pr_user_login=pr_user_login, pr_head_ref=pr_head_ref, pr_head_sha=pr_head_sha
424424
)
425425
)
426426

427-
report_size_deltas.get_artifact_download_url_for_run.assert_called_once_with(run_id=run_id)
427+
report_size_deltas.get_artifact_data_for_run.assert_called_once_with(run_id=run_id)
428428

429429

430430
@pytest.mark.parametrize("expired", [True, False])
431431
@pytest.mark.parametrize("artifact_name", ["test_sketches_reports_source", "incorrect-artifact-name"])
432-
def test_get_artifact_download_url_for_run(expired, artifact_name):
432+
def test_get_artifact_data_for_run(expired, artifact_name):
433433
repository_name = "test_name/test_repo"
434434
sketches_reports_source = "test_sketches_reports_source"
435-
archive_download_url = "archive_download_url"
435+
artifact_data = {"name": artifact_name, "archive_download_url": "archive_download_url", "expired": expired}
436436
run_id = "1234"
437437

438438
report_size_deltas = get_reportsizedeltas_object(
@@ -441,19 +441,19 @@ def test_get_artifact_download_url_for_run(expired, artifact_name):
441441

442442
json_data = {
443443
"artifacts": [
444-
{"name": artifact_name, "archive_download_url": archive_download_url, "expired": expired},
444+
artifact_data,
445445
{"name": "bar123", "archive_download_url": "wrong_artifact_url", "expired": False},
446446
]
447447
}
448448
report_size_deltas.api_request = unittest.mock.MagicMock(
449449
return_value={"json_data": json_data, "additional_pages": False, "page_count": 1}
450450
)
451451

452-
download_url = report_size_deltas.get_artifact_download_url_for_run(run_id=run_id)
452+
data = report_size_deltas.get_artifact_data_for_run(run_id=run_id)
453453
if not expired and artifact_name == sketches_reports_source:
454-
assert download_url == archive_download_url
454+
assert data == artifact_data
455455
else:
456-
assert download_url is None
456+
assert data is None
457457

458458
report_size_deltas.api_request.assert_called_once_with(
459459
request="repos/" + repository_name + "/actions/runs/" + str(run_id) + "/artifacts", page_number=1
@@ -472,7 +472,10 @@ def test_get_artifact(tmp_path, test_artifact_name, expected_success):
472472
real_artifact_name = "correct-artifact-name"
473473
artifact_archive_destination_path = artifact_destination_path.joinpath(real_artifact_name + ".zip")
474474

475-
artifact_download_url = artifact_destination_path.joinpath(test_artifact_name + ".zip").as_uri()
475+
artifact_data = {
476+
"archive_download_url": artifact_destination_path.joinpath(test_artifact_name + ".zip").as_uri(),
477+
"name": "artifact_name",
478+
}
476479

477480
# Create an archive file
478481
with zipfile.ZipFile(file=artifact_archive_destination_path, mode="a") as zip_ref:
@@ -482,14 +485,14 @@ def test_get_artifact(tmp_path, test_artifact_name, expected_success):
482485
report_size_deltas = get_reportsizedeltas_object()
483486

484487
if expected_success:
485-
artifact_folder_object = report_size_deltas.get_artifact(artifact_download_url=artifact_download_url)
488+
artifact_folder_object = report_size_deltas.get_artifact(artifact_data=artifact_data)
486489

487490
with artifact_folder_object as artifact_folder:
488491
# Verify that the artifact matches the source
489492
assert directories_are_same(left_directory=artifact_source_path, right_directory=artifact_folder)
490493
else:
491494
with pytest.raises(expected_exception=urllib.error.URLError):
492-
report_size_deltas.get_artifact(artifact_download_url=artifact_download_url)
495+
report_size_deltas.get_artifact(artifact_data=artifact_data)
493496

494497

495498
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)