From 70b6ab34b52afe94678239ecce395b14b80dcfcf Mon Sep 17 00:00:00 2001 From: Eric Joanis Date: Thu, 23 Apr 2026 11:50:01 -0400 Subject: [PATCH 1/4] refactor(tests): use pytest.main() for better output in all suites --- tests/test_align_cli.py | 6 +++--- tests/test_anchors.py | 6 ++++-- tests/test_api.py | 5 +++-- tests/test_audio.py | 6 ++++-- tests/test_config.py | 6 ++++-- tests/test_dna_text.py | 5 +++-- tests/test_dna_utils.py | 7 +++++-- tests/test_dtd.py | 6 ++++-- tests/test_force_align.py | 5 +++-- tests/test_g2p_cli.py | 5 +++-- tests/test_make_xml_cli.py | 6 ++++-- tests/test_misc.py | 5 +++-- tests/test_package_urls.py | 5 +++-- tests/test_silence.py | 5 +++-- tests/test_smil.py | 6 ++++-- tests/test_temp_file.py | 9 ++++++--- tests/test_tokenize_cli.py | 6 ++++-- tests/test_tokenize_xml.py | 6 ++++-- tests/test_web_api.py | 6 ++++-- 19 files changed, 71 insertions(+), 40 deletions(-) diff --git a/tests/test_align_cli.py b/tests/test_align_cli.py index 39708f04..f0cef5eb 100755 --- a/tests/test_align_cli.py +++ b/tests/test_align_cli.py @@ -6,13 +6,14 @@ import os import subprocess +import sys import tempfile from os.path import exists, join from pathlib import Path from typing import Union -from unittest import main from lxml.html import fromstring +from pytest import main from readalongs._version import READALONG_FILE_FORMAT_VERSION, VERSION from readalongs.cli import align, langs @@ -153,7 +154,6 @@ def test_invoke_align(self) -> None: str(output), ], ) - print("dir(result)", dir(results_output_exists)) self.assertNotEqual(results_output_exists.exit_code, 0) self.assertIn( "already exists, use -f to overwrite", results_output_exists.output @@ -652,4 +652,4 @@ def test_ffmpeg_is_present(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_anchors.py b/tests/test_anchors.py index 843b7449..515e9bf8 100755 --- a/tests/test_anchors.py +++ b/tests/test_anchors.py @@ -3,9 +3,11 @@ """Unit testing for the anchors functionality in readalongs align""" import os +import sys from contextlib import redirect_stderr from io import StringIO -from unittest import main + +from pytest import main from readalongs.align import align_audio from readalongs.log import LOGGER @@ -101,4 +103,4 @@ def test_anchors_align_modes(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_api.py b/tests/test_api.py index 52dc96a3..38d12337 100755 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -5,11 +5,12 @@ """ import re +import sys from contextlib import redirect_stderr from io import StringIO -from unittest import main import click +from pytest import main from readalongs import api from readalongs.log import LOGGER @@ -219,4 +220,4 @@ def test_extract_version_from_url(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_audio.py b/tests/test_audio.py index 307387a2..51436d5c 100755 --- a/tests/test_audio.py +++ b/tests/test_audio.py @@ -3,9 +3,11 @@ """Test suite for various audio contents handling methods""" import os +import sys from pathlib import Path from subprocess import run -from unittest import main + +from pytest import main from readalongs.audio_utils import ( extract_section, @@ -165,4 +167,4 @@ def test_write_audio_to_file(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_config.py b/tests/test_config.py index 3647c964..96ae1296 100755 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -4,10 +4,12 @@ import io import os +import sys from contextlib import redirect_stderr -from unittest import TestCase, main +from unittest import TestCase from lxml import etree +from pytest import main from readalongs.text.add_elements_to_xml import add_images, add_supplementary_xml from readalongs.text.util import load_xml @@ -79,4 +81,4 @@ def test_arbitrary_xml(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_dna_text.py b/tests/test_dna_text.py index 93253900..2d9cf317 100755 --- a/tests/test_dna_text.py +++ b/tests/test_dna_text.py @@ -2,11 +2,12 @@ """Test handling of DNA text in tokenization""" +import sys from contextlib import redirect_stderr from io import StringIO -from unittest import main from lxml import etree +from pytest import main from readalongs.text import tokenize_xml from readalongs.text.add_ids_to_xml import add_ids @@ -163,4 +164,4 @@ def test_dna_word_nested(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_dna_utils.py b/tests/test_dna_utils.py index fb21e902..cf7b0153 100755 --- a/tests/test_dna_utils.py +++ b/tests/test_dna_utils.py @@ -2,7 +2,10 @@ """Test suite for DNA segment manupulation methods""" -from unittest import TestCase, main +import sys +from unittest import TestCase + +from pytest import main from readalongs.dna_utils import ( calculate_adjustment, @@ -175,4 +178,4 @@ def test_dna_union(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_dtd.py b/tests/test_dtd.py index 78483c77..3396c0d8 100644 --- a/tests/test_dtd.py +++ b/tests/test_dtd.py @@ -3,10 +3,12 @@ """Test our XML DTD to make sure all valid examples validate and invalid ones don't""" import os +import sys from os.path import dirname -from unittest import TestCase, main +from unittest import TestCase from lxml import etree +from pytest import main from readalongs.text.util import load_xml @@ -111,4 +113,4 @@ def test_backwards_compatibility(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_force_align.py b/tests/test_force_align.py index d22d623a..7b79a812 100755 --- a/tests/test_force_align.py +++ b/tests/test_force_align.py @@ -6,13 +6,14 @@ import os import shutil -import unittest +import sys import wave from contextlib import redirect_stderr from io import StringIO from tempfile import TemporaryDirectory from lxml import etree +from pytest import main from soundswallower import get_model_path from readalongs.align import align_audio @@ -213,4 +214,4 @@ def test_convert_no_version(self): if __name__ == "__main__": LOGGER.setLevel("DEBUG") - unittest.main() + main([__file__, *sys.argv]) diff --git a/tests/test_g2p_cli.py b/tests/test_g2p_cli.py index 544d1da2..f8c71b9b 100755 --- a/tests/test_g2p_cli.py +++ b/tests/test_g2p_cli.py @@ -4,11 +4,12 @@ import os import re +import sys from contextlib import redirect_stderr from io import StringIO -from unittest import main from lxml import etree +from pytest import main from readalongs.align import align_audio from readalongs.cli import align, g2p, make_xml, tokenize @@ -489,4 +490,4 @@ def test_non_convertible_words(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_make_xml_cli.py b/tests/test_make_xml_cli.py index aa5ab889..4f754efa 100755 --- a/tests/test_make_xml_cli.py +++ b/tests/test_make_xml_cli.py @@ -5,8 +5,10 @@ import io import os import re +import sys from shutil import copyfile -from unittest import main + +from pytest import main # from readalongs.log import LOGGER from readalongs._version import READALONG_FILE_FORMAT_VERSION, VERSION @@ -299,4 +301,4 @@ def text2lines(text: str): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_misc.py b/tests/test_misc.py index 0aa342a0..e6937613 100755 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -4,12 +4,13 @@ import itertools import os +import sys import zipfile -from unittest import main import click from lxml import etree from pep440 import is_canonical +from pytest import main from readalongs._version import READALONG_FILE_FORMAT_VERSION, VERSION from readalongs.align import split_silences @@ -308,4 +309,4 @@ def test_version_is_pep440_compliant(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_package_urls.py b/tests/test_package_urls.py index 6247bd14..ad282aa7 100755 --- a/tests/test_package_urls.py +++ b/tests/test_package_urls.py @@ -1,8 +1,9 @@ #!/usr/bin/env python -from unittest import main +import sys import requests +from pytest import main from readalongs.text.make_package import ( FONTS_BUNDLE_URL, @@ -46,4 +47,4 @@ def test_fetch_bundles_fallback(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_silence.py b/tests/test_silence.py index a1bcff95..84dd4362 100755 --- a/tests/test_silence.py +++ b/tests/test_silence.py @@ -3,9 +3,10 @@ """Test suite for inserting silences into a readalong""" import os -from unittest import main +import sys from pydub import AudioSegment +from pytest import main from readalongs.cli import align from readalongs.text.util import load_xml @@ -83,4 +84,4 @@ def test_bad_silence(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_smil.py b/tests/test_smil.py index 8bd08fa4..ffd2b9fa 100644 --- a/tests/test_smil.py +++ b/tests/test_smil.py @@ -4,8 +4,10 @@ Unit test suite for the smil writing and parsing utilities """ +import sys from textwrap import dedent -from unittest import main + +from pytest import main from readalongs.text.make_smil import make_smil, parse_smil from tests.basic_test_case import BasicTestCase @@ -104,4 +106,4 @@ def test_parse_bad_smil(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_temp_file.py b/tests/test_temp_file.py index e468f6ac..f31a4dfc 100755 --- a/tests/test_temp_file.py +++ b/tests/test_temp_file.py @@ -3,14 +3,17 @@ """Test PortableNamedTemporaryFile class""" import os -import unittest +import sys from tempfile import NamedTemporaryFile +from unittest import TestCase + +from pytest import main from readalongs.log import LOGGER from readalongs.portable_tempfile import PortableNamedTemporaryFile -class TestTempFile(unittest.TestCase): +class TestTempFile(TestCase): """Test PortableNamedTemporaryFile class""" def test_basic_file(self): @@ -98,4 +101,4 @@ def test_seek(self): if __name__ == "__main__": LOGGER.setLevel("DEBUG") - unittest.main() + main([__file__, *sys.argv]) diff --git a/tests/test_tokenize_cli.py b/tests/test_tokenize_cli.py index 9618dd93..f3b3b27b 100755 --- a/tests/test_tokenize_cli.py +++ b/tests/test_tokenize_cli.py @@ -4,7 +4,9 @@ import io import os -from unittest import main +import sys + +from pytest import main from readalongs.cli import make_xml, tokenize from tests.basic_test_case import BasicTestCase @@ -67,4 +69,4 @@ def test_bad_input(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_tokenize_xml.py b/tests/test_tokenize_xml.py index 782488c4..ad60a803 100755 --- a/tests/test_tokenize_xml.py +++ b/tests/test_tokenize_xml.py @@ -2,11 +2,13 @@ """Unit test suite for our XML tokenizer module""" +import sys from contextlib import redirect_stderr from io import StringIO -from unittest import TestCase, main +from unittest import TestCase from lxml import etree +from pytest import main from readalongs.text import tokenize_xml from readalongs.text.util import parse_xml @@ -85,4 +87,4 @@ def test_comments(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) diff --git a/tests/test_web_api.py b/tests/test_web_api.py index ec9327cd..3c0bb791 100755 --- a/tests/test_web_api.py +++ b/tests/test_web_api.py @@ -3,13 +3,15 @@ import json import os import re +import sys from contextlib import redirect_stderr from io import StringIO from textwrap import dedent from time import perf_counter -from unittest import main from unittest.mock import patch +from pytest import main + from readalongs._version import READALONG_FILE_FORMAT_VERSION, VERSION from readalongs.log import LOGGER from readalongs.text.add_ids_to_xml import add_ids @@ -593,4 +595,4 @@ def test_convert_to_bad_format(self): if __name__ == "__main__": - main() + main([__file__, *sys.argv]) From 4a165bf800facdbb9b0b87b1a9692613a66cbe4e Mon Sep 17 00:00:00 2001 From: Eric Joanis Date: Thu, 23 Apr 2026 11:51:08 -0400 Subject: [PATCH 2/4] refactor(tests): convert run_tests to use pytest fully --- run_tests.py | 175 +++++++++++++++++++++------------------------------ 1 file changed, 71 insertions(+), 104 deletions(-) diff --git a/run_tests.py b/run_tests.py index 37b021a9..717a9bcb 100755 --- a/run_tests.py +++ b/run_tests.py @@ -4,154 +4,121 @@ Top-level runner for out test suites Invoke as - ./run.py [suite] + ./run_tests.py [suite] where [suite] can be one of: all: run everything, by searching the directory for all test suite files - prod: synonym for all - dev: run the standard development test suite - this is what we do in CI + dev: now a synonym for all (used to exclude some expensive tests) + api: run only the API-related tests + cli: run only the CLI-related tests e2e: run the end-to-end tests - other: run the other tests """ import argparse -import os -import re +import io import sys -from unittest import TestLoader, TestSuite, TextTestRunner +from contextlib import redirect_stdout +from pathlib import Path +from typing import List, Optional + +import pytest from readalongs.log import LOGGER -from tests.test_align_cli import TestAlignCli -from tests.test_anchors import TestAnchors -from tests.test_api import TestAlignApi -from tests.test_audio import TestAudio -from tests.test_config import TestConfig -from tests.test_dna_text import TestDNAText -from tests.test_dna_utils import TestDNAUtils -from tests.test_dtd import TestDTD -from tests.test_force_align import TestForceAlignment, TestXHTML -from tests.test_g2p_cli import TestG2pCli -from tests.test_make_xml_cli import TestMakeXMLCli -from tests.test_misc import TestMisc -from tests.test_package_urls import TestPackageURLs -from tests.test_silence import TestSilence -from tests.test_smil import TestSmilUtilities -from tests.test_temp_file import TestTempFile -from tests.test_tokenize_cli import TestTokenizeCli -from tests.test_tokenize_xml import TestTokenizer -from tests.test_web_api import TestWebApi - -LOADER = TestLoader() - -e2e_tests = [ - LOADER.loadTestsFromTestCase(test) for test in (TestForceAlignment, TestXHTML) -] - -api_tests = [ - LOADER.loadTestsFromTestCase(test) for test in [TestWebApi] -] # TODO: add some load testing with https://locust.io/ - -other_tests = [ - LOADER.loadTestsFromTestCase(test) - for test in [ - TestAnchors, - TestConfig, - TestDNAText, - TestDNAUtils, - TestTokenizer, - TestTokenizeCli, - TestTempFile, - TestMakeXMLCli, - TestAudio, - TestAlignCli, - TestAlignApi, - TestG2pCli, - TestMisc, - TestSilence, - TestSmilUtilities, - TestPackageURLs, - TestWebApi, - TestDTD, - ] -] - - -def list_tests(suite: TestSuite): - for subsuite in suite: - for match in re.finditer(r"tests=\[([^][]+)\]>", str(subsuite)): - yield from match[1].split(", ") - - -def describe_suite(suite: TestSuite): - full_suite = LOADER.discover(os.path.dirname(__file__)) - full_list = list(list_tests(full_suite)) - requested_list = list(list_tests(suite)) + +SUITES = { + "all": [], # relies on discovery to collect all tests + "dev": [], # synonym for all + "api": ["test_web_api", "test_api"], + "cli": ["test_align_cli", "test_g2p_cli", "test_make_xml_cli", "test_tokenize_cli"], + "e2e": ["test_force_align", "test_align_cli"], +} + +# TODO: add some load testing with https://locust.io/ + + +class PytestCollectorPlugin: + def __init__(self): + self.collected = [] + + def pytest_collection_modifyitems(self, session, config, items): + self.collected.extend([item.nodeid for item in items]) + + +def list_tests(suite: List[str]): + plugin = PytestCollectorPlugin() + pytest_args = ["--collect-only", *suite, "-q"] + if sys.version_info >= (3, 10): + with redirect_stdout(io.StringIO()): # broken with py 3.8/3.9... + pytest.main(pytest_args, plugins=[plugin]) + else: + pytest.main(pytest_args, plugins=[plugin]) + # print("===========\n", o.getvalue(), "\n================") + return plugin.collected + + +def describe_suite(suite_name, suite_filenames: List[str]): + full_list = list_tests([]) + requested_list = list_tests(suite_filenames) requested_set = set(requested_list) - print("Test suite includes:", *sorted(requested_list), sep="\n") + print(f"Test suite '{suite_name}' includes:", *sorted(requested_list), sep="\n") print( - "\nTest suite excludes:", + f"\nTest suite '{suite_name}' excludes:", *sorted(test for test in full_list if test not in requested_set), sep="\n", ) + print( + "\nTotal test cases", + f"found: {len(full_list)};", + f"included: {len(requested_list)};", + f"excluded: {len(full_list) - len(requested_list)}.", + ) -SUITES = ["all", "dev", "e2e", "prod", "api", "other"] - - -def run_tests(suite: str, describe: bool = False, verbosity=3) -> bool: +def run_tests(suite: Optional[str], describe=False, verbose=False) -> bool: """Run the specified test suite. Args: suite: one of SUITES, "dev" if the empty string describe: if True, list all the test cases instead of running them. - Returns: True iff success + Returns: Bool: True iff success """ if not suite: - LOGGER.info("No test suite specified, defaulting to dev.") + LOGGER.info("No test suite specified, defaulting to dev, which runs all tests.") suite = "dev" - if suite == "e2e": - test_suite = TestSuite(e2e_tests) - elif suite == "api": - test_suite = TestSuite(api_tests) - elif suite == "dev": - test_suite = TestSuite(other_tests + e2e_tests) - elif suite in ("prod", "all"): - test_suite = LOADER.discover(os.path.dirname(__file__)) - elif suite == "other": - test_suite = TestSuite(other_tests) - else: - LOGGER.error( - "Sorry, you need to select a Test Suite to run, one of: " + " ".join(SUITES) - ) + if suite not in SUITES: + LOGGER.error("Please specify a test suite to run among: " + ", ".join(SUITES)) return False + test_suite = SUITES[suite] + tests_dir = Path(__file__).parent / "tests" + test_suite_filenames = [str(tests_dir / f"{file}.py") for file in test_suite] if describe: - describe_suite(test_suite) + describe_suite(suite, test_suite_filenames) return True else: - runner = TextTestRunner(verbosity=verbosity) - success = runner.run(test_suite).wasSuccessful() - if not success: - LOGGER.error("Some tests failed. Please see log above.") - return success + pytest_args = ["--verbose"] if verbose else [] + return 0 == pytest.main([*test_suite_filenames, *pytest_args]) -if __name__ == "__main__": +def main() -> None: parser = argparse.ArgumentParser(description="Run ReadAlongs/Studio test suites.") - parser.add_argument("--quiet", "-q", action="store_true", help="reduce output") + parser.add_argument("--verbose", "-v", action="store_true", help="verbose output") parser.add_argument( "--describe", action="store_true", help="describe the selected test suite" ) parser.add_argument( "suite", nargs="?", - default="dev", help="the test suite to run [dev]", choices=SUITES, ) args = parser.parse_args() - result = run_tests(args.suite, args.describe, 1 if args.quiet else 3) + result = run_tests(args.suite, args.describe, args.verbose) if not result: sys.exit(1) + + +if __name__ == "__main__": + main() From 799a1e2315311231083880c2eb9e77f4370f874c Mon Sep 17 00:00:00 2001 From: Eric Joanis Date: Thu, 23 Apr 2026 11:55:42 -0400 Subject: [PATCH 3/4] ci: use updated run_test & pytest; exclude tests from codecov again --- .github/workflows/matrix-tests.yml | 2 +- .github/workflows/tests.yml | 10 +++++----- README.md | 2 +- pyproject.toml | 11 +++++++++++ tests/.coveragerc | 14 -------------- 5 files changed, 18 insertions(+), 21 deletions(-) delete mode 100644 tests/.coveragerc diff --git a/.github/workflows/matrix-tests.yml b/.github/workflows/matrix-tests.yml index c75f27a2..1a0356e3 100644 --- a/.github/workflows/matrix-tests.yml +++ b/.github/workflows/matrix-tests.yml @@ -37,4 +37,4 @@ jobs: run: | pip install -e .[all] - name: Run tests - run: python run_tests.py prod + run: python run_tests.py all diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 86276730..8e6d6a61 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -39,8 +39,8 @@ jobs: - name: Run tests run: | - coverage run --parallel-mode run_tests.py prod - DEVELOPMENT=1 coverage run --parallel-mode -m tests.test_web_api + coverage run -m pytest + DEVELOPMENT=1 coverage run tests/test_web_api.py coverage combine coverage xml @@ -114,7 +114,7 @@ jobs: pip install -e .[all] - name: Run tests on Windows - run: python run_tests.py prod + run: python run_tests.py all - name: Make sure the CLI outputs utf8 on Windows # Note: we're checking something CLI specific, from a prompt, so we don't want to run @@ -157,8 +157,8 @@ jobs: curl http://127.0.0.1:8000/api/v1/langs | grep Cree kill %1 - - name: Install test dependency - run: pip install httpx + - name: Install minimal test dependencies + run: pip install httpx pytest - name: unit test the web API run: python -m tests.test_web_api diff --git a/README.md b/README.md index e203e336..54be845d 100644 --- a/README.md +++ b/README.md @@ -160,7 +160,7 @@ or test the installed version (requires installing dev dependencies): pip install 'readalongs[dev]' # if you installed from PyPI, or pip install -e '.[dev]' # if you installed from a local clone - python run_tests.py dev + python run_tests.py recently, we also made the project compatible with Pytest, so this will run the tests too: diff --git a/pyproject.toml b/pyproject.toml index 468fff92..115f3fdd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -129,6 +129,16 @@ Repository = "https://github.com/ReadAlongs/Studio" Issues = "https://github.com/ReadAlongs/Studio/issues" Changelog = "https://github.com/ReadAlongs/Studio/releases" +[tool.coverage.run] +source_pkgs = ["readalongs"] +branch = true +parallel = true +omit = ["readalongs/waveform2svg/*", "readalongs/epub/*"] +exclude_also = ["if 0:", "if __name__ == .__main__.:"] + +[tool.coverage.report] +precision = 2 + [tool.mypy] plugins = ["pydantic.mypy"] ignore_missing_imports = true @@ -140,4 +150,5 @@ profile = "black" filterwarnings = [ "ignore:'audioop' is deprecated and slated for removal in Python 3.13:DeprecationWarning", "ignore:.*codecs.open.. is deprecated. Use open.. instead.*:DeprecationWarning", + "ignore:.*Module already imported so cannot be rewritten; anyio.*", ] diff --git a/tests/.coveragerc b/tests/.coveragerc deleted file mode 100644 index e4786078..00000000 --- a/tests/.coveragerc +++ /dev/null @@ -1,14 +0,0 @@ -# .coveragerc to control coverage.py -[run] -branch = True -source = readalongs -omit = */readalongs/waveform2svg/* - -[report] -precision = 2 -# Regexes for lines to exclude from consideration -exclude_lines = - # Don't complain if non-runnable code isn't run: - pragma: no cover - if 0: - if __name__ == .__main__.: From 0779eb63d7a210886993b5dc9e877185668d530a Mon Sep 17 00:00:00 2001 From: Eric Joanis Date: Mon, 27 Apr 2026 15:19:33 -0400 Subject: [PATCH 4/4] fix(ci): move setup-ffmpeg to v3.1 since v2 is now broken --- .github/workflows/matrix-tests.yml | 2 +- .github/workflows/tests.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/matrix-tests.yml b/.github/workflows/matrix-tests.yml index 1a0356e3..4f80992e 100644 --- a/.github/workflows/matrix-tests.yml +++ b/.github/workflows/matrix-tests.yml @@ -25,7 +25,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v6 - - uses: FedericoCarboni/setup-ffmpeg@v2 + - uses: FedericoCarboni/setup-ffmpeg@37062fbf7149fc5578d6c57e08aed62458b375d6 # @v3.1, with tool cache if : runner.os != 'macOS' - run: brew install ffmpeg if : runner.os == 'macOS' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8e6d6a61..34d3b6fc 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@v6 - - uses: FedericoCarboni/setup-ffmpeg@v2 + - uses: FedericoCarboni/setup-ffmpeg@37062fbf7149fc5578d6c57e08aed62458b375d6 # @v3.1, with tool cache - name: Set up Python uses: actions/setup-python@v6 @@ -100,7 +100,7 @@ jobs: steps: - uses: actions/checkout@v6 - - uses: FedericoCarboni/setup-ffmpeg@v2 + - uses: FedericoCarboni/setup-ffmpeg@37062fbf7149fc5578d6c57e08aed62458b375d6 # @v3.1, with tool cache - name: Set up Python uses: actions/setup-python@v6