Skip to content

fix(uv): allow prereleases so OVOS alpha floor-pins resolve - #62

Merged
JarbasAl merged 13 commits into
devfrom
fix/uv-allow-prereleases
Jun 28, 2026
Merged

JarbasAl merged 13 commits into
devfrom
fix/uv-allow-prereleases

Conversation

@JarbasAl

@JarbasAl JarbasAl commented Jun 28, 2026

Copy link
Copy Markdown
Member

Problem

The reusable workflows now use uv. uv's default prerelease mode
(if-necessary-or-explicit) accepts a prerelease only when all of a package's
versions are prereleases, or for a direct dep with a prerelease specifier. A
transitive prerelease floor-pin against a package that also has a stable
release is rejected — which is how much of the OVOS ecosystem is wired:

Because only ovos-phal-plugin-ipgeo<0.1.9a1 is available and
ovos-phal[extras]==0.2.16a1 depends on ovos-phal-plugin-ipgeo>=0.1.9a1,
we can conclude that ovos-phal[extras]==0.2.16a1 cannot be used.

(ovos-phal-plugin-ipgeo has a stable 0.1.7 and a prerelease 0.1.9a1; PHAL
floor-pins the alpha.) pip honoured these floor-pins implicitly, so ovos-core's
mycroft extra resolved under pip and breaks under uv.

Fix

Each reusable workflow gains a uv_prerelease input (default allow) wired
to the UV_PRERELEASE env. The all-alpha default restores pip-parity out of the
box; a caller can override it (disallow to assert a repo resolves on stables only,
if-necessary, explicit). Upper-bound caps (<X.0.0) still bound resolution.

jobs:
  build:
    uses: OpenVoiceOS/gh-automations/.github/workflows/build-tests.yml@dev
    with:
      uv_prerelease: allow   # default; override per repo if desired

Scope

15 reusable workflows that uv pip install the package under test gain the input:
build-tests, coverage, coverage-pages, ovoscope, opm-check, pip-audit,
license-check, lint, type-check, spec-lint, locale-check, intent-case-tests,
tts-intelligibility, downstream-check, python-support. test.yml is
gh-automations' own self-test (not workflow_call) so it keeps the literal.

🤖 Generated with Claude Code

JarbasAl and others added 11 commits June 28, 2026 17:00
- Add  bootstrap step after Setup Python in every workflow
- Replace  /  with
- Replace  with
- Replace  with pip @ file:///build/pip-26.1.2-py3-none-any.whl
- Remove  (uv manages itself)
- Update docs references (maintenance.md, release-flow.md, workflow-reference.md)

uv resolves dependencies 10-100x faster than pip, reducing CI cycle time.
…reter

uv pip refuses to install into a non-venv interpreter without --system /
UV_SYSTEM_PYTHON. actions/setup-python provides no active venv, so every
'uv pip install' step would fail on the runner. Declare UV_SYSTEM_PYTHON=1
at workflow level in each uv workflow.

Also correct locale-check's 'uv build' flags: --no-isolation/--outdir are
python-build flags; uv uses --no-build-isolation/--out-dir (silently masked
by continue-on-error, leaving SOURCES.txt ungenerated).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Validates the pip->uv migration inside this PR with no downstream consumers:
a runtime matrix (3.10-3.14) exercising every uv verb the migration uses
against a throwaway package, plus a static guard that every uv workflow
declares UV_SYSTEM_PYTHON. Delete before merging to dev.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a throwaway root package (pyproject.toml + selftest_pkg/) so the uv
self-test invokes the actual build-tests/coverage/type-check/license-check/
pip-audit reusable workflows against an installable target, exercising
uv build + uv pip install/-e/freeze end to end across 3.10-3.14. All calls
use pr_comment:false and run on push to this branch only, so nothing posts
to PR #60. Remove with _selftest-uv.yml before merging to dev.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The called workflows' jobs declare pull-requests/contents/security-events
write; a caller granting only contents:read startup-fails at compile time.
Grant the union so the reusable calls compile (features stay disabled).
Both steps declared 'continue-on-error: true' twice. PyYAML keeps the last,
but GitHub Actions rejects duplicate mapping keys, so type-check.yml and
docs-check.yml fail to compile ('workflow file issue') on dev — breaking
every downstream caller of these reusable workflows. Pre-existing, unrelated
to the uv migration. Semantics unchanged (continue-on-error stays true).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The shared workflows moved to uv. uv's default prerelease mode only accepts a
prerelease when ALL of a package's versions are prereleases — so a TRANSITIVE
prerelease floor-pin against a package that also has a stable release fails, e.g.
ovos-PHAL[extras]'s ovos-phal-plugin-ipgeo>=0.1.9a1 (stable 0.1.7 coexists):

    Because only ovos-phal-plugin-ipgeo<0.1.9a1 is available and
    ovos-phal[extras]==0.2.16a1 depends on ovos-phal-plugin-ipgeo>=0.1.9a1,
    we can conclude that ovos-phal[extras]==0.2.16a1 cannot be used.

pip honoured these floor-pins implicitly; the OVOS ecosystem is built entirely on
pre-1.0 alphas and relies on that. Set UV_PRERELEASE=allow on every uv-based
reusable workflow to restore pip-parity. Version caps (<X.0.0) still bound
resolution, so this does not pull in unintended majors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@JarbasAl, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 17 minutes and 13 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4da32672-bd5c-4f3e-a700-d67c100fc4b6

📥 Commits

Reviewing files that changed from the base of the PR and between 0eb1701 and d0450af.

📒 Files selected for processing (15)
  • .github/workflows/build-tests.yml
  • .github/workflows/coverage-pages.yml
  • .github/workflows/coverage.yml
  • .github/workflows/downstream-check.yml
  • .github/workflows/intent-case-tests.yml
  • .github/workflows/license-check.yml
  • .github/workflows/lint.yml
  • .github/workflows/locale-check.yml
  • .github/workflows/opm-check.yml
  • .github/workflows/ovoscope.yml
  • .github/workflows/pip-audit.yml
  • .github/workflows/python-support.yml
  • .github/workflows/spec-lint.yml
  • .github/workflows/tts-intelligibility.yml
  • .github/workflows/type-check.yml
📝 Walkthrough

Walkthrough

All GitHub Actions reusable and top-level workflows are migrated from python -m pip/pip to uv for dependency installation and uv build for package building. Each workflow gains UV_SYSTEM_PYTHON and UV_PRERELEASE environment variables and an explicit pip install uv step. A temporary selftest workflow and dummy Python package are added to validate the migration on the migrate-to-uv branch.

Changes

uv Migration across all workflows

Layer / File(s) Summary
Temporary selftest package and workflow
pyproject.toml, selftest_pkg/__init__.py, selftest_pkg/core.py, selftest_pkg/tests/test_dummy.py, .github/workflows/_selftest-uv.yml
Adds a disposable uv-selftest-dummy package with typed functions and pytest tests, plus _selftest-uv.yml which exercises five migrated reusable workflows and enforces UV_SYSTEM_PYTHON presence via an env-coverage guard job.
build-tests, coverage, coverage-pages
.github/workflows/build-tests.yml, .github/workflows/coverage.yml, .github/workflows/coverage-pages.yml
Adds UV_SYSTEM_PYTHON/UV_PRERELEASE env vars, Install uv steps, and replaces all pip-based build tool installs, python -m build calls, wheel/tarball installs, and editable installs with uv equivalents.
lint, type-check, spec-lint, docs-check
.github/workflows/lint.yml, .github/workflows/type-check.yml, .github/workflows/spec-lint.yml, .github/workflows/docs-check.yml
Migrates ruff, pre-commit, mypy, and ovos-spec-tools installs to uv pip; removes a stray continue-on-error: true in docs-check.yml and another in type-check.yml.
ovoscope, intent-case-tests, tts-intelligibility, opm-check, python-support
.github/workflows/ovoscope.yml, .github/workflows/intent-case-tests.yml, .github/workflows/tts-intelligibility.yml, .github/workflows/opm-check.yml, .github/workflows/python-support.yml
Adds UV env vars and Install uv steps; migrates all pipeline plugin installs, ovoscope @dev/PyPI paths, test extras installs, editable installs, force-reinstall local checkout steps, and post_install_pip pinning to uv pip.
pip-audit, license-check, downstream-check, locale-check, test
.github/workflows/pip-audit.yml, .github/workflows/license-check.yml, .github/workflows/downstream-check.yml, .github/workflows/locale-check.yml, .github/workflows/test.yml
Migrates audit/license tooling installs, pip freeze, constraints-based installs, locale builds (uv build --no-build-isolation), and test dependency installs to uv.
publish-alpha, publish-stable
.github/workflows/publish-alpha.yml, .github/workflows/publish-stable.yml
Installs uv in the version-bump job and replaces the python -m build sequence with uv build in the PyPI publish jobs.
Documentation
docs/maintenance.md, docs/release-flow.md, docs/workflow-reference.md
Updates all workflow command examples and guidance to reference uv pip install and uv build instead of python -m pip and python -m build.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • OpenVoiceOS/gh-automations#35: Modifies coverage.yml's editable extras install flow, the same section this PR migrates from pip to uv.
  • OpenVoiceOS/gh-automations#58: Adds the post_install_pip input and pinning step to ovoscope.yml that this PR migrates to uv pip install --force-reinstall --no-deps.
  • OpenVoiceOS/gh-automations#59: Changes pipeline plugin fallback install specifiers in ovoscope.yml, the same install commands this PR switches to uv.

Poem

🐇 Hoppity hop, no more pip to wait,
uv zips in fast — dependencies: great!
System Python found, prerelease: allow,
Every workflow's lean, I'll take a bow.
The rabbit approves this speedy new route~ 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: enabling uv prerelease resolution for OVOS alpha floor-pins.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/uv-allow-prereleases

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Each reusable workflow now exposes a 'uv_prerelease' input (default 'allow') wired
to UV_PRERELEASE, so a caller can override it (e.g. 'disallow' to assert a repo
resolves on stables only, or 'if-necessary'). The all-alpha default keeps pip
parity out of the box. test.yml is gh-automations' own self-test (not workflow_call)
so it keeps the literal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
docs/release-flow.md (1)

126-126: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update python -m build to uv build in the Stable release diagram.

The Stable release publish_pypi job still documents python -m build. Per the workflow migration, this should be uv build.

📝 Proposed fix
-    │       python -m build
+    │       uv build
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/release-flow.md` at line 126, The Stable release diagram in release-flow
still shows the old Python packaging command; update the publish_pypi job step
from python -m build to uv build. Make this change in the release-flow
documentation where the Stable release flow is described, so the diagram matches
the migrated workflow command.
.github/workflows/python-support.yml (1)

88-100: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Build the installer command as an argv array.

Line 100 invokes "$INSTALL_CMD" as a single executable name, so the shell looks for a binary literally called uv pip install or uv pip install -e. That makes the install step fail in both modes. Switching to an array fixes the command and also avoids inline template expansion for install-mode/install_extras.

Suggested fix
       - name: Install package
         id: install
         continue-on-error: true
+        env:
+          INSTALL_MODE: ${{ matrix.install-mode }}
+          INSTALL_EXTRAS: ${{ inputs.install_extras }}
         run: |
           uv pip install ovos-plugin-manager
-          
-          INSTALL_CMD="uv pip install"
-          if [ "${{ matrix.install-mode }}" == "editable" ]; then
-            INSTALL_CMD="uv pip install -e"
+
+          INSTALL_CMD=(uv pip install)
+          if [ "$INSTALL_MODE" == "editable" ]; then
+            INSTALL_CMD+=(-e)
           fi
-          
+
           if [ -f setup.py ] || [ -f pyproject.toml ]; then
-            "$INSTALL_CMD" ".${{ inputs.install_extras }}"
+            "${INSTALL_CMD[@]}" ".${INSTALL_EXTRAS}"
           else
              echo "No setup.py or pyproject.toml found — check your repo root."
              exit 1
           fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/python-support.yml around lines 88 - 100, The install step
in python-support.yml builds INSTALL_CMD as a single string, but the shell later
treats it as one executable name, so the package install fails for both normal
and editable modes. Update the Install package step to construct the installer
as an argv array and invoke it with proper argument expansion, using the same
control flow around matrix.install-mode and inputs.install_extras so the command
is passed to uv pip install correctly.

Source: Linters/SAST tools

.github/workflows/ovoscope.yml (1)

283-320: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Treat install inputs as data, not shell source.

This step now injects pre_install_pip, install_extras, and post_install_pip straight into the script. In a reusable workflow, that lets a caller smuggle shell syntax into the runner process. Move them into env: and expand the environment variables instead.

Suggested fix
       - name: Pre-install pip requirements
         if: ${{ inputs.pre_install_pip != '' }}
+        env:
+          PRE_INSTALL_PIP: ${{ inputs.pre_install_pip }}
         run: |
           # shellcheck disable=SC2086
-          uv pip install ${{ inputs.pre_install_pip }}
+          uv pip install $PRE_INSTALL_PIP

       - name: Install Package with Test Extras
+        env:
+          INSTALL_EXTRAS: ${{ inputs.install_extras }}
         run: |
           uv pip install pytest pytest-json-report
           if [ "${{ inputs.pre_release }}" == "true" ]; then
             echo "Installing ovoscope from GitHub dev (pre_release)..."
             uv pip install --force-reinstall \
               "git+https://github.com/TigreGotico/ovoscope@dev"
           else
             uv pip install ovoscope
           fi
-          EXTRAS="${{ inputs.install_extras }}"
+          EXTRAS="${INSTALL_EXTRAS}"
           if [ -n "$EXTRAS" ]; then
             uv pip install ".[$EXTRAS]"
           else
             uv pip install .
           fi
           uv pip install --force-reinstall --no-deps .

       - name: Post-install pip pins
         if: ${{ inputs.post_install_pip != '' }}
+        env:
+          POST_INSTALL_PIP: ${{ inputs.post_install_pip }}
         run: |
           # shellcheck disable=SC2086
-          uv pip install --force-reinstall --no-deps ${{ inputs.post_install_pip }}
+          uv pip install --force-reinstall --no-deps $POST_INSTALL_PIP
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ovoscope.yml around lines 283 - 320, The workflow steps
“Pre-install pip requirements”, “Install Package with Test Extras”, and
“Post-install pip pins” are interpolating caller-provided inputs directly into
shell commands, which treats data as executable shell source. Move
`inputs.pre_install_pip`, `inputs.install_extras`, and `inputs.post_install_pip`
into `env:` for the relevant steps and reference those environment variables
inside the `run` blocks instead of inline `${{ inputs.* }}` expansion. Keep the
existing `uv pip install` behavior, but ensure the `pre_install_pip`,
`install_extras`, and `post_install_pip` values are only consumed as data.

Source: Linters/SAST tools

🧹 Nitpick comments (1)
.github/workflows/_selftest-uv.yml (1)

24-30: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Scope the write permissions to the uses: jobs.

These workflow-level scopes also apply to env-coverage, so its checkout/grep job gets a writable token it never needs. Moving the union onto the individual reusable-workflow call jobs lets env-coverage run with read-only permissions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/_selftest-uv.yml around lines 24 - 30, The workflow-level
write permissions in the selftest workflow are too broad and currently apply to
the env-coverage job as well. Move the union of required permissions onto the
individual reusable-workflow call jobs that use the `uses:` syntax, so
env-coverage can run with read-only token scope. Use the existing job names and
reusable workflow call sites in the workflow file to place contents,
pull-requests, and security-events only where needed.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/_selftest-uv.yml:
- Around line 76-94: Extend the selftest guard in env-coverage to check both
UV_SYSTEM_PYTHON and UV_PRERELEASE for any workflow that uses uv pip. Update the
shell loop in _selftest-uv.yml so the existing grep-based assertion around uv
pip install/freeze also fails when UV_PRERELEASE is missing, and emit an error
that names the workflow file and both required env vars.

In @.github/workflows/build-tests.yml:
- Around line 94-98: The Pre-install pip requirements step in the build-tests
workflow is expanding pre_install_pip directly inside a run shell command, which
allows shell injection. Update that step to treat inputs.pre_install_pip as argv
rather than shell text by passing it through a safe action or by assigning it to
an environment variable and invoking uv pip install without unquoted
interpolation. Keep the change localized to the workflow step named Pre-install
pip requirements and preserve the existing conditional behavior.

In @.github/workflows/coverage-pages.yml:
- Around line 82-83: The coverage-pages workflow currently passes install_extras
directly into a shell command, creating a command-injection risk in the reusable
workflow. Update the install step in the workflow so the input is treated as
data/arguments rather than shell source, using the existing install_extras
handling around the uv pip install invocation and keeping the logic in the same
job step.

In @.github/workflows/downstream-check.yml:
- Around line 79-85: The downstream install step is missing an explicit
guarantee that pipdeptree is available before scripts/check_downstream.py runs
python -m pipdeptree. Update the install logic in the workflow step that
installs the OVOS ecosystem and the target package so pipdeptree is installed
explicitly or otherwise ensured via constraints.txt, and keep the existing
downstream report flow working without depending on an implicit transitive
install.

In @.github/workflows/intent-case-tests.yml:
- Around line 187-199: The Install Package with Test Extras step is
interpolating the caller-provided install_extras input directly into the shell
script, which can allow shell expansion during workflow execution. Update that
step to pass install_extras through env: and read it as a shell variable inside
the script, then use that variable in the uv pip install .[...] branch. Refer to
the Install Package with Test Extras block and the EXTRAS handling in
intent-case-tests.yml.

In @.github/workflows/locale-check.yml:
- Around line 56-62: The build step in the locale check workflow is allowing
`tail` to hide failures from `uv build`, so keep `pipefail` enabled for that
command. Update the “Run build to generate SOURCES.txt” step so the pipeline
preserves the exit status of `uv build` while still trimming output, and make
sure the fix is applied in the build job that runs `uv build
--no-build-isolation --out-dir dist/`.

In @.github/workflows/opm-check.yml:
- Around line 124-135: The Install Built Package step still interpolates the
caller-provided install_extras value directly in the shell, so move that input
into env and reference the environment variable in the install logic instead of
embedding it in the run block. Apply the same fix in both affected workflow
steps, using the existing Install Built Package and later uv pip install step so
the value is no longer shell-injected anywhere.

In @.github/workflows/publish-alpha.yml:
- Around line 126-127: The uv installation is happening in the wrong job, so the
later publish step cannot reuse it on a fresh runner. Move the Install uv step
out of bump_version and into publish_pypi, near the uv build invocation, so the
publish job installs its own toolchain before calling uv. Use the job names
bump_version and publish_pypi and the uv build step to place the change
correctly.

In @.github/workflows/publish-stable.yml:
- Around line 110-111: The `Install uv` step is happening in `bump_version`, but
`publish_pypi` is the job that later runs `uv build`, so the tool may be missing
on that runner. Move the `pip install uv` setup into the `publish_pypi` job (or
add an equivalent install step there) so `uv build` can run reliably in the
publish flow.

In @.github/workflows/tts-intelligibility.yml:
- Around line 121-135: The Install Package with Test Extras step is expanding
the reusable-workflow input directly in the shell, which can allow unintended
shell substitution before the install runs. In the workflow step that uses
EXTRAS and uv pip install, pass inputs.install_extras through env: and reference
the environment variable in the script instead of interpolating the input
inline. Keep the fix localized to the Install Package with Test Extras block so
the shell only consumes a pre-set variable.

In @.github/workflows/type-check.yml:
- Around line 93-106: The type-check workflow is interpolating caller-controlled
inputs directly in the shell, which allows command execution before uv runs.
Move the values used in the install step from inputs.test_extras,
inputs.test_extras_fallback, and inputs.install_extras into env variables on the
job/step, then read those environment variables inside the run script in the
type-check workflow. Keep the existing install logic in the same step, but
replace direct inputs.* expansion with env-backed values in the shell body.

In `@docs/release-flow.md`:
- Around line 90-91: The Alpha release diagram still shows the legacy build
command, so update the step in the release-flow diagram to use uv build instead
of python -m build. Make the change in the diagram content that follows the uv
pip install build step so it matches the workflow migration and the actual
command used in the publish-alpha/publish-stable flow.

In `@docs/workflow-reference.md`:
- Around line 906-907: The workflow docs currently use the wrong `uv build`
option in the build step, so update the `workflow-reference` entry for the `Run
build to generate SOURCES.txt` instruction to use the correct
`--no-build-isolation` flag instead of `--no-isolation`. Keep the rest of the
step intact and ensure the documented command matches the actual `uv build` CLI
used in the migration.

---

Outside diff comments:
In @.github/workflows/ovoscope.yml:
- Around line 283-320: The workflow steps “Pre-install pip requirements”,
“Install Package with Test Extras”, and “Post-install pip pins” are
interpolating caller-provided inputs directly into shell commands, which treats
data as executable shell source. Move `inputs.pre_install_pip`,
`inputs.install_extras`, and `inputs.post_install_pip` into `env:` for the
relevant steps and reference those environment variables inside the `run` blocks
instead of inline `${{ inputs.* }}` expansion. Keep the existing `uv pip
install` behavior, but ensure the `pre_install_pip`, `install_extras`, and
`post_install_pip` values are only consumed as data.

In @.github/workflows/python-support.yml:
- Around line 88-100: The install step in python-support.yml builds INSTALL_CMD
as a single string, but the shell later treats it as one executable name, so the
package install fails for both normal and editable modes. Update the Install
package step to construct the installer as an argv array and invoke it with
proper argument expansion, using the same control flow around
matrix.install-mode and inputs.install_extras so the command is passed to uv pip
install correctly.

In `@docs/release-flow.md`:
- Line 126: The Stable release diagram in release-flow still shows the old
Python packaging command; update the publish_pypi job step from python -m build
to uv build. Make this change in the release-flow documentation where the Stable
release flow is described, so the diagram matches the migrated workflow command.

---

Nitpick comments:
In @.github/workflows/_selftest-uv.yml:
- Around line 24-30: The workflow-level write permissions in the selftest
workflow are too broad and currently apply to the env-coverage job as well. Move
the union of required permissions onto the individual reusable-workflow call
jobs that use the `uses:` syntax, so env-coverage can run with read-only token
scope. Use the existing job names and reusable workflow call sites in the
workflow file to place contents, pull-requests, and security-events only where
needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4f6501f7-d43a-4e00-aa41-712d1629f270

📥 Commits

Reviewing files that changed from the base of the PR and between ec6a29c and 0eb1701.

📒 Files selected for processing (28)
  • .github/workflows/_selftest-uv.yml
  • .github/workflows/build-tests.yml
  • .github/workflows/coverage-pages.yml
  • .github/workflows/coverage.yml
  • .github/workflows/docs-check.yml
  • .github/workflows/downstream-check.yml
  • .github/workflows/intent-case-tests.yml
  • .github/workflows/license-check.yml
  • .github/workflows/lint.yml
  • .github/workflows/locale-check.yml
  • .github/workflows/opm-check.yml
  • .github/workflows/ovoscope.yml
  • .github/workflows/pip-audit.yml
  • .github/workflows/publish-alpha.yml
  • .github/workflows/publish-stable.yml
  • .github/workflows/python-support.yml
  • .github/workflows/spec-lint.yml
  • .github/workflows/test.yml
  • .github/workflows/tts-intelligibility.yml
  • .github/workflows/type-check.yml
  • docs/maintenance.md
  • docs/release-flow.md
  • docs/workflow-reference.md
  • pyproject.toml
  • selftest_pkg/__init__.py
  • selftest_pkg/core.py
  • selftest_pkg/tests/__init__.py
  • selftest_pkg/tests/test_dummy.py
💤 Files with no reviewable changes (1)
  • .github/workflows/docs-check.yml

Comment on lines +76 to +94
# Static guard: every workflow that runs `uv pip` MUST also declare
# UV_SYSTEM_PYTHON, or it will fail at runtime on the setup-python interpreter.
env-coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Assert uv workflows declare UV_SYSTEM_PYTHON
run: |
set -euo pipefail
missing=0
for f in .github/workflows/*.yml; do
[ "$(basename "$f")" = "_selftest-uv.yml" ] && continue
if grep -qE 'uv pip (install|freeze)' "$f" && ! grep -q 'UV_SYSTEM_PYTHON' "$f"; then
echo "::error file=$f::uses 'uv pip' but does not declare UV_SYSTEM_PYTHON"
missing=1
fi
done
[ "$missing" -eq 0 ] && echo "All uv workflows declare UV_SYSTEM_PYTHON."
exit "$missing"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Extend the guard to enforce UV_PRERELEASE too.

Lines 88-89 only assert UV_SYSTEM_PYTHON, so a future uv pip workflow can drop UV_PRERELEASE and still pass this harness even though that is the regression this PR is fixing.

Proposed fix
       - name: Assert uv workflows declare UV_SYSTEM_PYTHON
         run: |
           set -euo pipefail
           missing=0
           for f in .github/workflows/*.yml; do
             [ "$(basename "$f")" = "_selftest-uv.yml" ] && continue
-            if grep -qE 'uv pip (install|freeze)' "$f" && ! grep -q 'UV_SYSTEM_PYTHON' "$f"; then
-              echo "::error file=$f::uses 'uv pip' but does not declare UV_SYSTEM_PYTHON"
-              missing=1
+            if grep -qE 'uv pip (install|freeze)' "$f"; then
+              if ! grep -q 'UV_SYSTEM_PYTHON' "$f"; then
+                echo "::error file=$f::uses 'uv pip' but does not declare UV_SYSTEM_PYTHON"
+                missing=1
+              fi
+              if ! grep -q 'UV_PRERELEASE' "$f"; then
+                echo "::error file=$f::uses 'uv pip' but does not declare UV_PRERELEASE"
+                missing=1
+              fi
             fi
           done
           [ "$missing" -eq 0 ] && echo "All uv workflows declare UV_SYSTEM_PYTHON."
           exit "$missing"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Static guard: every workflow that runs `uv pip` MUST also declare
# UV_SYSTEM_PYTHON, or it will fail at runtime on the setup-python interpreter.
env-coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Assert uv workflows declare UV_SYSTEM_PYTHON
run: |
set -euo pipefail
missing=0
for f in .github/workflows/*.yml; do
[ "$(basename "$f")" = "_selftest-uv.yml" ] && continue
if grep -qE 'uv pip (install|freeze)' "$f" && ! grep -q 'UV_SYSTEM_PYTHON' "$f"; then
echo "::error file=$f::uses 'uv pip' but does not declare UV_SYSTEM_PYTHON"
missing=1
fi
done
[ "$missing" -eq 0 ] && echo "All uv workflows declare UV_SYSTEM_PYTHON."
exit "$missing"
# Static guard: every workflow that runs `uv pip` MUST also declare
# UV_SYSTEM_PYTHON, or it will fail at runtime on the setup-python interpreter.
env-coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Assert uv workflows declare UV_SYSTEM_PYTHON
run: |
set -euo pipefail
missing=0
for f in .github/workflows/*.yml; do
[ "$(basename "$f")" = "_selftest-uv.yml" ] && continue
if grep -qE 'uv pip (install|freeze)' "$f"; then
if ! grep -q 'UV_SYSTEM_PYTHON' "$f"; then
echo "::error file=$f::uses 'uv pip' but does not declare UV_SYSTEM_PYTHON"
missing=1
fi
if ! grep -q 'UV_PRERELEASE' "$f"; then
echo "::error file=$f::uses 'uv pip' but does not declare UV_PRERELEASE"
missing=1
fi
fi
done
[ "$missing" -eq 0 ] && echo "All uv workflows declare UV_SYSTEM_PYTHON."
exit "$missing"
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 81-81: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/_selftest-uv.yml around lines 76 - 94, Extend the selftest
guard in env-coverage to check both UV_SYSTEM_PYTHON and UV_PRERELEASE for any
workflow that uses uv pip. Update the shell loop in _selftest-uv.yml so the
existing grep-based assertion around uv pip install/freeze also fails when
UV_PRERELEASE is missing, and emit an error that names the workflow file and
both required env vars.

Comment on lines 94 to +98
- name: Pre-install pip requirements
if: ${{ inputs.pre_install_pip != '' }}
run: |
# shellcheck disable=SC2086
python -m pip install ${{ inputs.pre_install_pip }}
uv pip install ${{ inputs.pre_install_pip }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Treat pre_install_pip as argv, not shell.

Line 98 expands a reusable-workflow input directly inside run:. If any caller forwards untrusted text here, it becomes arbitrary shell on the runner.

Proposed fix
       - name: Pre-install pip requirements
         if: ${{ inputs.pre_install_pip != '' }}
+        env:
+          PRE_INSTALL_PIP: ${{ inputs.pre_install_pip }}
         run: |
-          # shellcheck disable=SC2086
-          uv pip install ${{ inputs.pre_install_pip }}
+          python - <<'PY'
+          import os, shlex, subprocess
+          reqs = shlex.split(os.environ["PRE_INSTALL_PIP"])
+          subprocess.check_call(["uv", "pip", "install", *reqs])
+          PY
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Pre-install pip requirements
if: ${{ inputs.pre_install_pip != '' }}
run: |
# shellcheck disable=SC2086
python -m pip install ${{ inputs.pre_install_pip }}
uv pip install ${{ inputs.pre_install_pip }}
- name: Pre-install pip requirements
if: ${{ inputs.pre_install_pip != '' }}
env:
PRE_INSTALL_PIP: ${{ inputs.pre_install_pip }}
run: |
python - <<'PY'
import os, shlex, subprocess
reqs = shlex.split(os.environ["PRE_INSTALL_PIP"])
subprocess.check_call(["uv", "pip", "install", *reqs])
PY
🧰 Tools
🪛 zizmor (1.26.1)

[error] 98-98: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build-tests.yml around lines 94 - 98, The Pre-install pip
requirements step in the build-tests workflow is expanding pre_install_pip
directly inside a run shell command, which allows shell injection. Update that
step to treat inputs.pre_install_pip as argv rather than shell text by passing
it through a safe action or by assigning it to an environment variable and
invoking uv pip install without unquoted interpolation. Keep the change
localized to the workflow step named Pre-install pip requirements and preserve
the existing conditional behavior.

Source: Linters/SAST tools

Comment on lines 82 to +83
if [ -n "${{ inputs.install_extras }}" ]; then
python -m pip install ${{ inputs.install_extras }}
uv pip install ${{ inputs.install_extras }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Avoid shell-expanding install_extras.

Line 83 treats the workflow input as shell source instead of arguments. In a reusable workflow, that makes install_extras a command-injection surface.

Proposed fix
-          if [ -n "${{ inputs.install_extras }}" ]; then
-            uv pip install ${{ inputs.install_extras }}
+          if [ -n "${{ inputs.install_extras }}" ]; then
+            INSTALL_EXTRAS="${{ inputs.install_extras }}" python - <<'PY'
+            import os, shlex, subprocess
+            extras = shlex.split(os.environ["INSTALL_EXTRAS"])
+            subprocess.check_call(["uv", "pip", "install", *extras])
+            PY
           fi
🧰 Tools
🪛 zizmor (1.26.1)

[error] 82-82: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[error] 82-82: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/coverage-pages.yml around lines 82 - 83, The
coverage-pages workflow currently passes install_extras directly into a shell
command, creating a command-injection risk in the reusable workflow. Update the
install step in the workflow so the input is treated as data/arguments rather
than shell source, using the existing install_extras handling around the uv pip
install invocation and keeping the logic in the same job step.

Source: Linters/SAST tools

Comment on lines 79 to +85
- name: Install OVOS ecosystem and pipdeptree
run: |
python -m pip install build wheel pipdeptree
curl -fsSL -o constraints.txt "${{ inputs.constraints_url }}"
# Install the full OVOS ecosystem so pipdeptree can find all reverse deps
pip install -r constraints.txt || true
uv pip install -r constraints.txt || true
# Re-install the target package pinned to the constraints version
pip install -c constraints.txt "${{ inputs.package_name }}" || true
uv pip install -c constraints.txt "${{ inputs.package_name }}" || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

script="$(fd -p check_downstream.py action . | head -n1)"
echo "check_downstream.py: ${script:-not found}"

if [ -n "${script:-}" ]; then
  ast-grep outline "$script" --view expanded || true
  echo
  echo "Searching for pipdeptree/process usage..."
  rg -n -C2 'pipdeptree|subprocess\.(run|check_call|check_output)|shutil\.which' "$script"
fi

Repository: OpenVoiceOS/gh-automations

Length of output: 1909


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Repository references to pipdeptree:"
rg -n --hidden --glob '!**/.git/**' 'pipdeptree' .

echo
echo "Workflow section around the install step:"
sed -n '60,100p' .github/workflows/downstream-check.yml

Repository: OpenVoiceOS/gh-automations

Length of output: 3687


Keep pipdeptree available for the downstream report
scripts/check_downstream.py still runs python -m pipdeptree, so this step needs an explicit install for it or another guarantee that constraints.txt provides it.

🧰 Tools
🪛 zizmor (1.26.1)

[error] 81-81: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[error] 85-85: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/downstream-check.yml around lines 79 - 85, The downstream
install step is missing an explicit guarantee that pipdeptree is available
before scripts/check_downstream.py runs python -m pipdeptree. Update the install
logic in the workflow step that installs the OVOS ecosystem and the target
package so pipdeptree is installed explicitly or otherwise ensured via
constraints.txt, and keep the existing downstream report flow working without
depending on an implicit transitive install.

Comment on lines 187 to +199
- name: Install Package with Test Extras
run: |
python -m pip install --upgrade pip
python -m pip install pytest pytest-json-report
uv pip install pytest pytest-json-report
if [ "${{ inputs.pre_release }}" == "true" ]; then
pip install --force-reinstall "git+https://github.com/TigreGotico/ovoscope@dev"
uv pip install --force-reinstall "git+https://github.com/TigreGotico/ovoscope@dev"
else
pip install ovoscope
uv pip install ovoscope
fi
EXTRAS="${{ inputs.install_extras }}"
if [ -n "$EXTRAS" ]; then
pip install ".[$EXTRAS]"
uv pip install ".[$EXTRAS]"
else
pip install .
uv pip install .

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Avoid inline expansion of install_extras.

Line 195 embeds a caller-provided string directly into the shell script. In a reusable workflow that is enough for $(...)/backticks to execute on the runner. Pass the input via env: and read $INSTALL_EXTRAS in the script instead.

Suggested fix
       - name: Install Package with Test Extras
+        env:
+          INSTALL_EXTRAS: ${{ inputs.install_extras }}
         run: |
           uv pip install pytest pytest-json-report
           if [ "${{ inputs.pre_release }}" == "true" ]; then
             uv pip install --force-reinstall "git+https://github.com/TigreGotico/ovoscope@dev"
           else
             uv pip install ovoscope
           fi
-          EXTRAS="${{ inputs.install_extras }}"
+          EXTRAS="${INSTALL_EXTRAS}"
           if [ -n "$EXTRAS" ]; then
             uv pip install ".[$EXTRAS]"
           else
             uv pip install .
           fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Install Package with Test Extras
run: |
python -m pip install --upgrade pip
python -m pip install pytest pytest-json-report
uv pip install pytest pytest-json-report
if [ "${{ inputs.pre_release }}" == "true" ]; then
pip install --force-reinstall "git+https://github.com/TigreGotico/ovoscope@dev"
uv pip install --force-reinstall "git+https://github.com/TigreGotico/ovoscope@dev"
else
pip install ovoscope
uv pip install ovoscope
fi
EXTRAS="${{ inputs.install_extras }}"
if [ -n "$EXTRAS" ]; then
pip install ".[$EXTRAS]"
uv pip install ".[$EXTRAS]"
else
pip install .
uv pip install .
- name: Install Package with Test Extras
env:
INSTALL_EXTRAS: ${{ inputs.install_extras }}
run: |
uv pip install pytest pytest-json-report
if [ "${{ inputs.pre_release }}" == "true" ]; then
uv pip install --force-reinstall "git+https://github.com/TigreGotico/ovoscope@dev"
else
uv pip install ovoscope
fi
EXTRAS="${INSTALL_EXTRAS}"
if [ -n "$EXTRAS" ]; then
uv pip install ".[$EXTRAS]"
else
uv pip install .
🧰 Tools
🪛 zizmor (1.26.1)

[error] 195-195: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/intent-case-tests.yml around lines 187 - 199, The Install
Package with Test Extras step is interpolating the caller-provided
install_extras input directly into the shell script, which can allow shell
expansion during workflow execution. Update that step to pass install_extras
through env: and read it as a shell variable inside the script, then use that
variable in the uv pip install .[...] branch. Refer to the Install Package with
Test Extras block and the EXTRAS handling in intent-case-tests.yml.

Source: Linters/SAST tools

Comment on lines +110 to +111
- name: Install uv
run: pip install uv

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Install uv in the publish job instead.

This step runs in bump_version, but Line 165 invokes uv build from publish_pypi, which gets a different runner. The stable publish flow can therefore fail before upload.

Suggested fix
-      - name: Install uv
-        run: pip install uv
...
       - name: Setup Python
         uses: actions/setup-python@v6
         with:
           python-version: "3.14"
+      - name: Install uv
+        run: pip install uv
       - name: Build Distribution Packages
         run: uv build
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/publish-stable.yml around lines 110 - 111, The `Install
uv` step is happening in `bump_version`, but `publish_pypi` is the job that
later runs `uv build`, so the tool may be missing on that runner. Move the `pip
install uv` setup into the `publish_pypi` job (or add an equivalent install step
there) so `uv build` can run reliably in the publish flow.

Comment on lines 121 to +135
- name: Install Package with Test Extras
run: |
python -m pip install --upgrade pip
python -m pip install pytest pytest-json-report
uv pip install pytest pytest-json-report
if [ "${{ inputs.pre_release }}" == "true" ]; then
echo "Installing ovoscope[tts] from GitHub dev (pre_release)..."
pip install --force-reinstall \
uv pip install --force-reinstall \
"ovoscope[tts] @ git+https://github.com/TigreGotico/ovoscope@dev"
else
pip install "ovoscope[tts]"
uv pip install "ovoscope[tts]"
fi
EXTRAS="${{ inputs.install_extras }}"
if [ -n "$EXTRAS" ]; then
pip install ".[$EXTRAS]"
uv pip install ".[$EXTRAS]"
else
pip install .
uv pip install .

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Pass install_extras through the environment.

Line 131 expands a reusable-workflow string input directly into the generated shell script. That allows shell substitution to run on the runner before uv pip install ".[$EXTRAS]" executes. Move it to env: first.

Suggested fix
       - name: Install Package with Test Extras
+        env:
+          INSTALL_EXTRAS: ${{ inputs.install_extras }}
         run: |
           uv pip install pytest pytest-json-report
           if [ "${{ inputs.pre_release }}" == "true" ]; then
             echo "Installing ovoscope[tts] from GitHub dev (pre_release)..."
             uv pip install --force-reinstall \
               "ovoscope[tts] @ git+https://github.com/TigreGotico/ovoscope@dev"
           else
             uv pip install "ovoscope[tts]"
           fi
-          EXTRAS="${{ inputs.install_extras }}"
+          EXTRAS="${INSTALL_EXTRAS}"
           if [ -n "$EXTRAS" ]; then
             uv pip install ".[$EXTRAS]"
           else
             uv pip install .
           fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Install Package with Test Extras
run: |
python -m pip install --upgrade pip
python -m pip install pytest pytest-json-report
uv pip install pytest pytest-json-report
if [ "${{ inputs.pre_release }}" == "true" ]; then
echo "Installing ovoscope[tts] from GitHub dev (pre_release)..."
pip install --force-reinstall \
uv pip install --force-reinstall \
"ovoscope[tts] @ git+https://github.com/TigreGotico/ovoscope@dev"
else
pip install "ovoscope[tts]"
uv pip install "ovoscope[tts]"
fi
EXTRAS="${{ inputs.install_extras }}"
if [ -n "$EXTRAS" ]; then
pip install ".[$EXTRAS]"
uv pip install ".[$EXTRAS]"
else
pip install .
uv pip install .
- name: Install Package with Test Extras
env:
INSTALL_EXTRAS: ${{ inputs.install_extras }}
run: |
uv pip install pytest pytest-json-report
if [ "${{ inputs.pre_release }}" == "true" ]; then
echo "Installing ovoscope[tts] from GitHub dev (pre_release)..."
uv pip install --force-reinstall \
"ovoscope[tts] @ git+https://github.com/TigreGotico/ovoscope@dev"
else
uv pip install "ovoscope[tts]"
fi
EXTRAS="${INSTALL_EXTRAS}"
if [ -n "$EXTRAS" ]; then
uv pip install ".[$EXTRAS]"
else
uv pip install .
🧰 Tools
🪛 zizmor (1.26.1)

[error] 131-131: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/tts-intelligibility.yml around lines 121 - 135, The
Install Package with Test Extras step is expanding the reusable-workflow input
directly in the shell, which can allow unintended shell substitution before the
install runs. In the workflow step that uses EXTRAS and uv pip install, pass
inputs.install_extras through env: and reference the environment variable in the
script instead of interpolating the input inline. Keep the fix localized to the
Install Package with Test Extras block so the shell only consumes a pre-set
variable.

Source: Linters/SAST tools

Comment on lines +93 to +106
uv pip install mypy
PRIMARY="${{ inputs.test_extras }}"
FALLBACK="${{ inputs.test_extras_fallback }}"
if [ -n "$PRIMARY" ] && python -m pip install -e ".[$PRIMARY]" 2>/dev/null; then
if [ -n "$PRIMARY" ] && uv pip install -e ".[$PRIMARY]" 2>/dev/null; then
echo "Installed package with [$PRIMARY] extras"
elif [ -n "$FALLBACK" ] && python -m pip install -e ".[$FALLBACK]" 2>/dev/null; then
elif [ -n "$FALLBACK" ] && uv pip install -e ".[$FALLBACK]" 2>/dev/null; then
echo "Installed package with [$FALLBACK] extras"
elif python -m pip install -e . 2>/dev/null; then
elif uv pip install -e . 2>/dev/null; then
echo "Installed package (no test extras found)"
else
echo "No installable package found — type-checking source tree directly"
fi
if [ -n "${{ inputs.install_extras }}" ]; then
python -m pip install ${{ inputs.install_extras }}
uv pip install ${{ inputs.install_extras }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Stop splicing workflow inputs directly into the shell.

Lines 94-95 and 105 expand inputs.* inside the script body, so a caller can turn $(...)/backticks into runner-side command execution before uv sees the package spec. Pass these values through env: first and then read the environment variables in run:.

Suggested fix
       - name: Install Dependencies
+        env:
+          PRIMARY: ${{ inputs.test_extras }}
+          FALLBACK: ${{ inputs.test_extras_fallback }}
+          INSTALL_EXTRAS: ${{ inputs.install_extras }}
         run: |
           uv pip install mypy
-          PRIMARY="${{ inputs.test_extras }}"
-          FALLBACK="${{ inputs.test_extras_fallback }}"
           if [ -n "$PRIMARY" ] && uv pip install -e ".[$PRIMARY]" 2>/dev/null; then
             echo "Installed package with [$PRIMARY] extras"
           elif [ -n "$FALLBACK" ] && uv pip install -e ".[$FALLBACK]" 2>/dev/null; then
             echo "Installed package with [$FALLBACK] extras"
           elif uv pip install -e . 2>/dev/null; then
             echo "Installed package (no test extras found)"
           else
             echo "No installable package found — type-checking source tree directly"
           fi
-          if [ -n "${{ inputs.install_extras }}" ]; then
-            uv pip install ${{ inputs.install_extras }}
+          if [ -n "$INSTALL_EXTRAS" ]; then
+            # shellcheck disable=SC2086
+            uv pip install $INSTALL_EXTRAS
           fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
uv pip install mypy
PRIMARY="${{ inputs.test_extras }}"
FALLBACK="${{ inputs.test_extras_fallback }}"
if [ -n "$PRIMARY" ] && python -m pip install -e ".[$PRIMARY]" 2>/dev/null; then
if [ -n "$PRIMARY" ] && uv pip install -e ".[$PRIMARY]" 2>/dev/null; then
echo "Installed package with [$PRIMARY] extras"
elif [ -n "$FALLBACK" ] && python -m pip install -e ".[$FALLBACK]" 2>/dev/null; then
elif [ -n "$FALLBACK" ] && uv pip install -e ".[$FALLBACK]" 2>/dev/null; then
echo "Installed package with [$FALLBACK] extras"
elif python -m pip install -e . 2>/dev/null; then
elif uv pip install -e . 2>/dev/null; then
echo "Installed package (no test extras found)"
else
echo "No installable package found — type-checking source tree directly"
fi
if [ -n "${{ inputs.install_extras }}" ]; then
python -m pip install ${{ inputs.install_extras }}
uv pip install ${{ inputs.install_extras }}
- name: Install Dependencies
env:
PRIMARY: ${{ inputs.test_extras }}
FALLBACK: ${{ inputs.test_extras_fallback }}
INSTALL_EXTRAS: ${{ inputs.install_extras }}
run: |
uv pip install mypy
if [ -n "$PRIMARY" ] && uv pip install -e ".[$PRIMARY]" 2>/dev/null; then
echo "Installed package with [$PRIMARY] extras"
elif [ -n "$FALLBACK" ] && uv pip install -e ".[$FALLBACK]" 2>/dev/null; then
echo "Installed package with [$FALLBACK] extras"
elif uv pip install -e . 2>/dev/null; then
echo "Installed package (no test extras found)"
else
echo "No installable package found — type-checking source tree directly"
fi
if [ -n "$INSTALL_EXTRAS" ]; then
# shellcheck disable=SC2086
uv pip install $INSTALL_EXTRAS
fi
🧰 Tools
🪛 zizmor (1.26.1)

[error] 94-94: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[error] 95-95: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[error] 105-105: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[error] 105-105: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/type-check.yml around lines 93 - 106, The type-check
workflow is interpolating caller-controlled inputs directly in the shell, which
allows command execution before uv runs. Move the values used in the install
step from inputs.test_extras, inputs.test_extras_fallback, and
inputs.install_extras into env variables on the job/step, then read those
environment variables inside the run script in the type-check workflow. Keep the
existing install logic in the same step, but replace direct inputs.* expansion
with env-backed values in the shell body.

Source: Linters/SAST tools

Comment thread docs/release-flow.md
Comment on lines +90 to 91
uv pip install build
│ python -m build

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update python -m build to uv build in the Alpha release diagram.

Line 90 correctly updates to uv pip install build, but Line 91 still shows python -m build. Per the workflow migration (publish-alpha.yml and publish-stable.yml), this should be uv build to match the actual command used.

📝 Proposed fix
-    │       uv pip install build
-    │       python -m build
+    │       uv build
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/release-flow.md` around lines 90 - 91, The Alpha release diagram still
shows the legacy build command, so update the step in the release-flow diagram
to use uv build instead of python -m build. Make the change in the diagram
content that follows the uv pip install build step so it matches the workflow
migration and the actual command used in the publish-alpha/publish-stable flow.

Comment on lines +906 to +907
| Install build dependencies | `uv pip install build setuptools` |
| Run build to generate SOURCES.txt | `uv build --no-isolation`. `continue-on-error: true`. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix uv build flag: --no-isolation should be --no-build-isolation.

The documentation describes uv build --no-isolation, but the correct uv build flag is --no-build-isolation. This matches the actual workflow migration (cohort 5) and standard uv CLI usage. Using --no-isolation would result in an error.

📝 Proposed fix
-| Install build dependencies | `uv pip install build setuptools` |
-| Run build to generate SOURCES.txt | `uv build --no-isolation`. `continue-on-error: true`. |
+| Install build dependencies | `uv pip install build setuptools` |
+| Run build to generate SOURCES.txt | `uv build --no-build-isolation`. `continue-on-error: true`. |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| Install build dependencies | `uv pip install build setuptools` |
| Run build to generate SOURCES.txt | `uv build --no-isolation`. `continue-on-error: true`. |
| Install build dependencies | `uv pip install build setuptools` |
| Run build to generate SOURCES.txt | `uv build --no-build-isolation`. `continue-on-error: true`. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/workflow-reference.md` around lines 906 - 907, The workflow docs
currently use the wrong `uv build` option in the build step, so update the
`workflow-reference` entry for the `Run build to generate SOURCES.txt`
instruction to use the correct `--no-build-isolation` flag instead of
`--no-isolation`. Keep the rest of the step intact and ensure the documented
command matches the actual `uv build` CLI used in the migration.

@JarbasAl
JarbasAl merged commit ca022d4 into dev Jun 28, 2026
1 check was pending
@JarbasAl
JarbasAl deleted the fix/uv-allow-prereleases branch June 28, 2026 17:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant