mirror of
https://github.com/trustedsec/hate_crack.git
synced 2026-07-28 14:47:22 -07:00
fix(ci): add test CI, repair auto-tag releases, harden action pins (2.11.4)
The repo had no CI: ruff/ty/pytest ran only in local prek pre-push hooks, so a commit pushed without hooks installed reached main unvalidated -- and auto-tag would then cut a release from it. Adds ci.yml (ruff, ty, pytest on 3.13) and gates tagging on it. Auto-tagged versions also never produced a release. The tag is pushed with the default GITHUB_TOKEN, and GitHub suppresses workflow triggers for GITHUB_TOKEN-created events, so the tag-triggered release.yml never fired -- v2.11.3 was tagged with no release. auto-tag now creates the release itself, idempotently; release.yml stays as the manual-tag path. Also fixes version logic that matched the `!` breaking marker but only ever bumped minor (and never saw BREAKING CHANGE: footers, since only subjects were inspected), serializes concurrent merges that both computed the same tag, and repins softprops/action-gh-release from an arbitrary master commit to v2.6.2 with all workflows on one actions/checkout version. Clears the pre-existing ty error in notify/tailer.py that would have made the new type-check step red: _read_new_lines read self._file_pos (int | None) while its only None-guard lived in the caller, so the position is passed in explicitly as an int. Behavior unchanged. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
a0dc56ce08
commit
665c8ab47c
@@ -190,6 +190,49 @@ class TestCrackTailerStop:
|
||||
tailer.stop()
|
||||
|
||||
|
||||
class TestCrackTailerPollOnceInternals:
|
||||
"""Direct unit tests for _poll_once edge cases via the internal API."""
|
||||
|
||||
def _make_uninitialised(self, out_path: Path):
|
||||
"""Return a tailer whose _file_pos is still None (seek never called)."""
|
||||
tailer, notify, aggregate = _make_tailer(out_path)
|
||||
# Do NOT call start() or _seek_to_eof(); leave _file_pos = None.
|
||||
return tailer, notify, aggregate
|
||||
|
||||
def test_first_poll_with_file_pos_none_seeds_position(
|
||||
self, tmp_path: Path
|
||||
) -> None:
|
||||
"""_poll_once with _file_pos=None must record size and return without notifying."""
|
||||
out = tmp_path / "hashes.out"
|
||||
out.write_text("alice:hash:plain\n")
|
||||
tailer, notify, aggregate = self._make_uninitialised(out)
|
||||
assert tailer._file_pos is None
|
||||
tailer._poll_once()
|
||||
# Position seeded to current size; no notification fired.
|
||||
assert tailer._file_pos == out.stat().st_size
|
||||
assert notify.call_count == 0
|
||||
assert aggregate.call_count == 0
|
||||
|
||||
def test_truncation_resets_position_directly(self, tmp_path: Path) -> None:
|
||||
"""_poll_once must reset position and buffer when the file shrinks."""
|
||||
out = tmp_path / "hashes.out"
|
||||
content = "alice:hash:plain\nbob:hash:plain\n"
|
||||
out.write_text(content)
|
||||
tailer, notify, aggregate = _make_tailer(out)
|
||||
tailer._file_pos = len(content.encode()) # pretend we've read it all
|
||||
tailer._buffer = b"leftover"
|
||||
|
||||
# Truncate to a smaller file.
|
||||
out.write_text("c:h:p\n")
|
||||
tailer._poll_once()
|
||||
|
||||
# Position must have been reset and buffer cleared.
|
||||
assert tailer._file_pos == len(b"c:h:p\n")
|
||||
assert tailer._buffer == b""
|
||||
# One new line notified.
|
||||
assert notify.call_count == 1
|
||||
|
||||
|
||||
class TestCrackTailerFileHandling:
|
||||
def test_missing_file_then_appearing(self, tmp_path: Path) -> None:
|
||||
out = tmp_path / "missing.out"
|
||||
|
||||
Reference in New Issue
Block a user