Source code for tests.test_actions
# Copyright Kevin Deldycke <kevin@deldycke.com> and contributors.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""Tests for :mod:`repomatic.github.actions` run cancellation."""
from __future__ import annotations
from unittest.mock import patch
from repomatic.github.actions import cancel_superseded_runs
def _dispatch(listings: dict[str, str], cancel_error: str = ""):
"""Build a `run_gh_command` double serving listings and cancellations.
:param listings: Status name to newline-separated run IDs returned by
the listing call.
:param cancel_error: When set, every cancellation call raises a
`RuntimeError` with this message.
"""
def run(args):
# The endpoint is the last argument of the cancel call and precedes
# `--jq` in the listing call.
if "/cancel" in args[-1]:
if cancel_error:
raise RuntimeError(cancel_error)
return ""
endpoint = args[2]
for status, ids in listings.items():
if f"status={status}" in endpoint:
return ids
return ""
return run
[docs]
def test_cancel_superseded_runs_spares_current_run():
"""Every listed run is cancelled except the caller's own."""
run = _dispatch({"in_progress": "11\n22", "queued": "33"})
with patch("repomatic.github.actions.run_gh_command", side_effect=run) as mock_gh:
cancelled = cancel_superseded_runs("melon-branch", "22")
assert cancelled == 2
cancel_calls = [
call.args[0] for call in mock_gh.call_args_list if "/cancel" in call.args[0][-1]
]
assert [args[-1] for args in cancel_calls] == [
"repos/{owner}/{repo}/actions/runs/11/cancel",
"repos/{owner}/{repo}/actions/runs/33/cancel",
]
[docs]
def test_cancel_superseded_runs_queries_both_statuses():
"""Both the in-progress and queued listings are swept, paginated."""
run = _dispatch({})
with patch("repomatic.github.actions.run_gh_command", side_effect=run) as mock_gh:
cancelled = cancel_superseded_runs("melon-branch", "1")
assert cancelled == 0
listing_calls = [call.args[0] for call in mock_gh.call_args_list]
assert len(listing_calls) == 2
for args, status in zip(listing_calls, ("in_progress", "queued")):
assert args[1] == "--paginate"
assert f"branch=melon-branch&status={status}" in args[2]
[docs]
def test_cancel_superseded_runs_tolerates_cancel_failure():
"""A run that fails to cancel is skipped without aborting the sweep."""
run = _dispatch({"queued": "44\n55"}, cancel_error="HTTP 409: already done")
with patch("repomatic.github.actions.run_gh_command", side_effect=run):
cancelled = cancel_superseded_runs("melon-branch", "1")
assert cancelled == 0
[docs]
def test_cancel_superseded_runs_empty_listing():
"""No live runs means no cancellation calls and a zero count."""
run = _dispatch({"in_progress": "", "queued": ""})
with patch("repomatic.github.actions.run_gh_command", side_effect=run) as mock_gh:
cancelled = cancel_superseded_runs("melon-branch", "1")
assert cancelled == 0
assert all("/cancel" not in call.args[0][-1] for call in mock_gh.call_args_list)