Patch fixes for v3.0.2#7
Merged
Merged
Conversation
- Fix uv-dynamic-versioning: bump must be a boolean, not string (was breaking `uv sync` and editable installs on current versions). - Remove broken `strif:main` script entry point (no such function). - Add Python 3.10 to classifiers (was missing despite `requires-python >=3.10`). - Fix file descriptor leak in `temp_output_file`: cleanup now closes the fd returned by `mkstemp`, not just removes the file. - Reorder `is_truthy` so the bool branch runs (was dead code since bool is a subclass of int). Behavior was correct by coincidence; now correct by construction. - Fix `move_file` to check `dest_path.exists()` for the backup decision (was checking `src_path.exists()` — confusing read, accidentally worked). - `copy_to_backup` is now silent on missing source, matching `move_to_backup`. Previously raised `FileNotFoundError`. - Remove `_RANDOM.seed()` — no-op on `random.SystemRandom`. - Add `DEV_NULL` to `__all__` so it's available as a convenience handle via `from strif import DEV_NULL`. Tests: add `tests/test_files.py` with coverage for `atomic_output_file` (happy path, exception leaves partial, backup, make_parents, target-is-dir raises, force replaces dir), `temp_output_file` (no fd leak, double-close tolerated), `temp_output_dir`, `is_truthy` (bool, string, numeric, sized, strict), `copy_to_backup`, and `move_file`. 26 tests total now pass.
Initialize tbd issue tracker with prefix `strif` (rendered as `strif-N`). Adds .tbd/ config and .claude/ integration files. Sync branch: tbd-sync. Note: this commit is orthogonal to the v3.0.2 patch fixes also on this branch — feel free to split out before merging if you prefer to land them separately.
Done via `copier update --vcs-ref=v0.2.25`. Project-specific content (README body, src/, tests/) preserved by three-way merge. Workflow modernization: - actions/checkout v4 -> v6, astral-sh/setup-uv v5 -> v7 - uv 0.6.14 -> 0.10.2 - `uv sync --all-extras --dev` -> `uv sync --all-extras` (dev deps are now in [dependency-groups], `--all-extras` already covers them) - Publish step: switched from `pypa/gh-action-pypi-publish@release/v1` to `uv publish --trusted-publishing always` (PyPA action is now the documented alternative in a comment, for easy reversion) CI matrix conflict resolved manually: kept Python 3.10 support and added 3.14 — strif still requires-python = ">=3.10,<4.0", so 3.10-3.14 is the matrix. Dev dependency upgrades: - pytest 8.3.5 -> 9.0.2 - ruff 0.11.0 -> 0.15.1 - rich 13.9.4 -> 14.3.2 - basedpyright 1.28.2 -> 1.38.0 - funlog 0.2.0 -> 0.2.1 - new: pytest-sugar 1.1.1 (prettier pytest output) - pyproject: add Python 3.14 classifier; fix commented ruff rule trailing-comma syntax Other: - Docs moved from project root to docs/ subdir (installation.md, development.md, publishing.md). README links updated. - LICENSE: copyright year 2025 -> 2026 - devtools/lint.py: KeyboardInterrupt handler, `--stats` on basedpyright - Makefile: drop `--dev` from `uv sync`, `make upgrade` now upgrades all deps including dev 26 tests still pass, lint clean.
Adopt the pattern used in jlevy/tbd so any agent (or human) can cut a release end-to-end with just `git tag vX.Y.Z && git push --tags`. Removes the manual "create a GitHub Release" step that previously required a UI click or an extra `gh release create` call. Changes: - Trigger on `push: tags: ['v*']` instead of `release: published`. - Add `contents: write` permission so the workflow can create releases. - Add softprops/action-gh-release@v2 step to auto-create the GitHub Release with generate_release_notes (uses PR titles since last tag). - Auto-set prerelease=true when the tag contains `-` (e.g., `-rc.1`). - Keep `workflow_dispatch` for manual fallback. Docs (docs/publishing.md) updated to describe the new flow: push tag, optionally edit notes after via `gh release edit`. First-time-setup section also updated to use the new tag-push trigger.
Found during pre-release supply-chain audit. pygments is a transitive dep (pulled via rich for terminal syntax highlighting in lint output) and the CVE was present in master too — not introduced by this PR. rich 15.0.0 already allows pygments<3.0.0,>=2.13.0, so the bump is compatible. pip-audit reports zero known vulnerabilities after this change. Dev-only dep — strif's published wheel has zero runtime dependencies, so this never reached end users.
Pre-release hardening: third-party GitHub Actions can be moved between commits by re-pointing a major-version tag. Pinning to immutable SHAs prevents that class of supply-chain attack on the publish pipeline. Pinned (commented with the resolved tag for readability): - actions/checkout@v6 -> @de0fac2e4500dabe0009e67214ff5f5447ce83dd (v6.0.2) - astral-sh/setup-uv@v7 -> @37802adc94f370d6bfd71619e3f0bf239e1f3b78 (v7.6.0) - softprops/action-gh-release@v2 -> @3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 (v2.6.2) softprops/action-gh-release was the highest-priority target (single- maintainer User repo, runs with `contents: write` in the workflow that also has PyPI trusted publishing access). Comment added at the use site to flag this and to remind future bumpers to update SHA + version together. When upgrading any of these later, get the new SHA via: gh api repos/<owner>/<repo>/git/ref/tags/<tag> --jq '.object.sha' 26 tests still pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Originally scoped as patch fixes for v3.0.2; grew during the session to also include tbd setup, a copier template upgrade to v0.2.25, and a publishing workflow modernization. Four commits, each logically distinct — happy to split before merge if you'd rather land them separately.
Commits
54e255bFixes for v3.0.2 patch release — the original patch work. See bug-fix list below.58eea68Add tbd v0.1.28 project setup — adds.tbd/and.claude/fromtbd setup --auto --prefix=strif. Orthogonal to the patch fixes.606e08aUpgrade simple-modern-uv template from v0.2.7 to v0.2.25 —copier update --vcs-ref=v0.2.25. Bumps GH Actions, uv, and dev deps. Reorgs docs intodocs/.beaae43Make publish.yml tag-triggered with auto GitHub Release — mirrors the jlevy/tbd pattern so any agent can release end-to-end with justgit tag vX.Y.Z && git push --tags.Bug fixes (commit 1, the patch fixes)
uv-dynamic-versioning:bump = "true"(string) is rejected — must be boolean. Freshuv syncand editable installs were failing.temp_output_file:mkstemp()returns(fd, path)but cleanup only removed the file. Confirmed with/proc/self/fdaccounting — 5 successivewithblocks leaked 5 FDs. Fix closes the fd in cleanup, wrapped intry/except OSErrorso user-closed FDs don't blow up.strif = "strif:main"referenced a nonexistent function. Removed; a real CLI is deferred to a later minor release.is_truthyhad a deadboolbranch:isinstance(True, int)is True, so the bool check was never reached. Reordered so the bool branch is checked first.move_filewas checking the wrong path for the backup-decision condition (src_path.exists()instead ofdest_path.exists()).copy_to_backupraised on missing source, while its siblingmove_to_backupsilently returned. Now consistent.requires-python = ">=3.10"._RANDOM.seed()is a no-op onrandom.SystemRandom. Removed.DEV_NULLwas defined but not exported — added to__all__.Tests (commit 1)
New
tests/test_files.pywith 18 tests covering each fixed function plus the previously-untested headlineatomic_output_file. Uses pytest'stmp_pathfixture. Total suite is 26 tests, all green.Template upgrade (commit 3)
copier update --vcs-ref=v0.2.25. Project-specific content preserved by three-way merge.checkout@v4 → @v6,setup-uv@v5 → @v7, uv0.6.14 → 0.10.2uv sync --all-extras --dev→uv sync --all-extras(dev deps in[dependency-groups]are auto-included)["3.10", "3.11", "3.12", "3.13", "3.14"]docs/subdirectoryPublishing workflow (commit 4)
Adopts the jlevy/tbd pattern:
push: tags: ['v*'](wasrelease: published)softprops/action-gh-release@v2with generated notes-tags as prereleasesworkflow_dispatchretained for manual fallbackOnce merged, releasing v3.0.2 is
git tag v3.0.2 && git push --tags.Test plan
uv run pytest— 26/26 passuv run python devtools/lint.py— cleanuv syncsucceeds (was failing before thebump = truefix)v3.0.2to trigger the modernized publish workflowhttps://claude.ai/code/session_01Td1N9waEtmcArZh5jNBdLH