Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@ name: CI

# Checks only: nothing is committed or published. Runs in an Arch Linux
# container with the official repositories, like the package build.
# A branch with a pull request is checked once, by the pull_request event
# (push alone would run the same commit twice). main is checked on push.
on:
pull_request:
push:
branches: [ "**" ]
branches: [ main ]
workflow_dispatch:

permissions:
contents: read

# A newer commit on the same pull request or branch replaces the run in progress.
concurrency:
group: ci-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
python:
runs-on: ubuntu-latest
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/translate-and-build-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,19 @@ on:
permissions:
contents: write

# One run per branch at a time: each one commits and pushes translations.
concurrency:
group: translate-${{ github.ref }}
cancel-in-progress: false

jobs:
build:
# Only in the biglinux organization: forks have neither the translation
# keys nor the builder token, and the translation step would hang until
# GitHub's 6-hour limit.
if: github.repository_owner == 'biglinux'
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

Expand Down
19 changes: 8 additions & 11 deletions tests/test_history_recovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,14 @@ def test_save_never_overwrites_an_existing_entry(hdir, tmp_path):


def test_unwritable_folder_is_reported_not_raised(tmp_path, monkeypatch):
# The Music folder is read-only: the history folder cannot be created.
locked = tmp_path / "locked"
locked.mkdir()
locked.chmod(0o500)
monkeypatch.setattr(hs, "_MUSIC_DIR", locked)
try:
assert hs.save_reading(text="x", backend="rhvoice", voice_id="v") is None
assert hs.new_recording("rhvoice", time.time()) is None
assert hs.repair_history()["error"] == "" # nothing to repair, no crash
finally:
locked.chmod(0o700)
# The history folder cannot be created. (Its parent is a file, not a
# read-only folder: CI runs as root, and root ignores permissions.)
blocker = tmp_path / "blocker"
blocker.write_text("")
monkeypatch.setattr(hs, "_MUSIC_DIR", blocker / "Music")
assert hs.save_reading(text="x", backend="rhvoice", voice_id="v") is None
assert hs.new_recording("rhvoice", time.time()) is None
assert hs.repair_history()["error"] == "" # nothing to repair, no crash


def test_durations_of_older_entries_are_filled_in(hdir, tmp_path):
Expand Down
23 changes: 11 additions & 12 deletions tests/test_tts_streaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,18 +327,17 @@ def test_readings_in_sequence_each_have_an_entry(fakes):


def test_history_folder_without_permission_never_breaks_reading(fakes, monkeypatch):
locked = fakes / "locked" # read-only Music folder: no history folder possible
locked.mkdir()
locked.chmod(0o500)
monkeypatch.setattr(hs, "_MUSIC_DIR", locked)
try:
svc = ts.TTSService(settings=_settings())
assert svc.speak("Ainda assim leio.", backend="rhvoice", voice_id="x", volume=50)
_run_watch(svc)
assert svc.state is TTSState.IDLE # the reading itself is fine
assert played(fakes)
finally:
locked.chmod(0o700)
# No history folder possible: its parent is a file (root-proof, unlike a
# read-only folder — CI runs as root).
blocker = fakes / "blocker"
blocker.write_text("")
monkeypatch.setattr(hs, "_MUSIC_DIR", blocker / "Music")
svc = ts.TTSService(settings=_settings())
assert svc.speak("Ainda assim leio.", backend="rhvoice", voice_id="x", volume=50)
_run_watch(svc)
assert svc.state is TTSState.IDLE # the reading itself is fine
assert played(fakes)
assert not hs.get_history_dir().exists()


@pytest.mark.parametrize(("backend", "voice"), [("rhvoice", "x"), ("kokoro", "kokoro:pf_dora")])
Expand Down
Loading