From 31a12e984eca7a9d93febbdd5b31e8452fa4b253 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Sun, 28 Jun 2026 17:00:36 +0100 Subject: [PATCH 01/12] Replace pip with uv across all workflows and docs - 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. --- .github/workflows/build-tests.yml | 19 +++++++------- .github/workflows/coverage-pages.yml | 12 +++++---- .github/workflows/coverage.yml | 17 +++++++------ .github/workflows/downstream-check.yml | 7 +++--- .github/workflows/intent-case-tests.yml | 18 ++++++++------ .github/workflows/license-check.yml | 9 ++++--- .github/workflows/lint.yml | 7 ++++-- .github/workflows/locale-check.yml | 7 ++++-- .github/workflows/opm-check.yml | 18 ++++++++------ .github/workflows/ovoscope.yml | 30 ++++++++++++----------- .github/workflows/pip-audit.yml | 7 ++++-- .github/workflows/publish-alpha.yml | 6 ++--- .github/workflows/publish-stable.yml | 7 +++--- .github/workflows/python-support.yml | 10 +++++--- .github/workflows/spec-lint.yml | 6 +++-- .github/workflows/test.yml | 4 ++- .github/workflows/tts-intelligibility.yml | 14 ++++++----- .github/workflows/type-check.yml | 13 ++++++---- docs/maintenance.md | 2 +- docs/release-flow.md | 2 +- docs/workflow-reference.md | 12 ++++----- 21 files changed, 131 insertions(+), 96 deletions(-) diff --git a/.github/workflows/build-tests.yml b/.github/workflows/build-tests.yml index 86d70e9..488796e 100644 --- a/.github/workflows/build-tests.yml +++ b/.github/workflows/build-tests.yml @@ -63,6 +63,9 @@ jobs: with: python-version: ${{ matrix.python-version }} + - name: Install uv + run: pip install uv + - name: Checkout gh-automations scripts uses: actions/checkout@v6 with: @@ -76,20 +79,18 @@ jobs: sudo apt-get install -yq python3-dev libssl-dev ${{ inputs.system_deps }} - name: Install Build Tools - run: | - python -m pip install --upgrade pip - python -m pip install build wheel + run: uv pip install build wheel - 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: Build Distribution Packages id: build run: | - python -m build + uv build - name: Install Built Package id: install @@ -98,19 +99,19 @@ jobs: EXTRAS="${{ inputs.install_extras }}" if [ -n "$WHEEL" ]; then if [ -n "$EXTRAS" ]; then - pip install "${WHEEL}[${EXTRAS}]" + uv pip install "${WHEEL}[${EXTRAS}]" else - pip install "$WHEEL" + uv pip install "$WHEEL" fi else - pip install dist/*.tar.gz 2>/dev/null || { echo "No dist files found"; exit 1; } + uv pip install dist/*.tar.gz 2>/dev/null || { echo "No dist files found"; exit 1; } fi - name: Run Tests id: tests if: ${{ inputs.test_path != '' }} run: | - python -m pip install pytest + uv pip install pytest python -m pytest ${{ inputs.test_path }} -v - name: Save result diff --git a/.github/workflows/coverage-pages.yml b/.github/workflows/coverage-pages.yml index f5df9cd..4f7f389 100644 --- a/.github/workflows/coverage-pages.yml +++ b/.github/workflows/coverage-pages.yml @@ -55,6 +55,9 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv + - name: Install System Dependencies if: ${{ inputs.system_deps != '' }} run: | @@ -63,17 +66,16 @@ jobs: - name: Install Dependencies run: | - python -m pip install --upgrade pip - python -m pip install pytest pytest-cov coverage[toml] ovoscope - if python -m pip install -e ".[dev]" 2>/dev/null; then + uv pip install pytest pytest-cov coverage[toml] ovoscope + if uv pip install -e ".[dev]" 2>/dev/null; then echo "Installed package with [dev] extras" - elif python -m pip install -e . 2>/dev/null; then + elif uv pip install -e . 2>/dev/null; then echo "Installed package (no [dev] extras)" else echo "No installable package found at repo root — continuing without install" fi if [ -n "${{ inputs.install_extras }}" ]; then - python -m pip install ${{ inputs.install_extras }} + uv pip install ${{ inputs.install_extras }} fi - name: Run Tests with Coverage diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 08b2f77..1abbddd 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -107,6 +107,9 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv + - name: Install System Dependencies if: ${{ inputs.system_deps != '' }} run: | @@ -114,31 +117,29 @@ jobs: sudo apt-get install -yq ${{ inputs.system_deps }} - name: Install Dependencies - run: | - python -m pip install --upgrade pip - python -m pip install pytest pytest-cov coverage[toml] + run: uv pip install pytest pytest-cov coverage[toml] - 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: Install Package run: | 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 at repo root — continuing without install" fi if [ -n "${{ inputs.install_extras }}" ]; then - python -m pip install ${{ inputs.install_extras }} + uv pip install ${{ inputs.install_extras }} fi - name: Run Tests with Coverage diff --git a/.github/workflows/downstream-check.yml b/.github/workflows/downstream-check.yml index b1ab50d..b5b4fe0 100644 --- a/.github/workflows/downstream-check.yml +++ b/.github/workflows/downstream-check.yml @@ -55,6 +55,8 @@ jobs: uses: actions/setup-python@v6 with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv - name: Install System Dependencies run: | sudo apt-get update -q @@ -71,12 +73,11 @@ jobs: ${{ inputs.system_deps }} - 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 - name: Generate downstream report run: | python action/github/scripts/check_downstream.py \ diff --git a/.github/workflows/intent-case-tests.yml b/.github/workflows/intent-case-tests.yml index d614464..bd37a68 100644 --- a/.github/workflows/intent-case-tests.yml +++ b/.github/workflows/intent-case-tests.yml @@ -134,6 +134,9 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv + - name: Install System Dependencies if: ${{ inputs.system_deps != '' || inputs.require_padatious }} run: | @@ -152,10 +155,10 @@ jobs: install_plugin() { local name="$1" pypi="$2" gh="$3" if [ "$PRE_RELEASE" == "true" ]; then - pip install --force-reinstall "git+https://github.com/${gh}@dev" || { + uv pip install --force-reinstall "git+https://github.com/${gh}@dev" || { echo "::error::Failed to install $name from GitHub dev"; exit 1; } else - pip install "$pypi" || { + uv pip install "$pypi" || { echo "::error::Failed to install $name from PyPI"; exit 1; } fi } @@ -178,18 +181,17 @@ jobs: - 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 . fi python -c "import ovoscope; print('ovoscope path:', ovoscope.__file__)" diff --git a/.github/workflows/license-check.yml b/.github/workflows/license-check.yml index 2c6bbd3..827b2b1 100644 --- a/.github/workflows/license-check.yml +++ b/.github/workflows/license-check.yml @@ -89,8 +89,11 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv + - name: Install Build Tools - run: python -m pip install build wheel pip-licenses + run: uv pip install build wheel pip-licenses - name: Install System Dependencies run: | @@ -98,10 +101,10 @@ jobs: sudo apt-get install -yq python3-dev libssl-dev ${{ inputs.system_deps }} - name: Install package - run: pip install ".${{ inputs.install_extras }}" + run: uv pip install ".${{ inputs.install_extras }}" - name: Collect transitive dependencies - run: pip freeze > requirements-all.txt + run: uv pip freeze > requirements-all.txt - name: Build exclude regex id: exclude diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 117f9a6..2175826 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -56,9 +56,12 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv + - name: Install ruff if: ${{ inputs.ruff }} - run: python -m pip install ruff + run: uv pip install ruff - name: Run ruff if: ${{ inputs.ruff }} @@ -68,7 +71,7 @@ jobs: - name: Install pre-commit if: ${{ inputs.pre_commit }} - run: python -m pip install pre-commit + run: uv pip install pre-commit - name: Run pre-commit if: ${{ inputs.pre_commit }} diff --git a/.github/workflows/locale-check.yml b/.github/workflows/locale-check.yml index 21419a8..e1a9c32 100644 --- a/.github/workflows/locale-check.yml +++ b/.github/workflows/locale-check.yml @@ -45,13 +45,16 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv + - name: Install build dependencies run: | - python -m pip install build setuptools + uv pip install build setuptools - name: Run build to generate SOURCES.txt run: | - python -m build --no-isolation --outdir dist/ 2>&1 | tail -20 + uv build --no-isolation --outdir dist/ 2>&1 | tail -20 continue-on-error: true - name: Run locale build check diff --git a/.github/workflows/opm-check.yml b/.github/workflows/opm-check.yml index 5942238..6820ae0 100644 --- a/.github/workflows/opm-check.yml +++ b/.github/workflows/opm-check.yml @@ -85,6 +85,9 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv + - name: Checkout gh-automations scripts uses: actions/checkout@v6 with: @@ -100,7 +103,6 @@ jobs: - name: Install Build Tools run: | - python -m pip install --upgrade pip OPM_SPEC="ovos-plugin-manager" MIN="${{ inputs.opm_min_version }}" MAX="${{ inputs.opm_max_version }}" @@ -108,11 +110,11 @@ jobs: if [ -n "$MAX" ]; then OPM_SPEC="${OPM_SPEC},<${MAX}"; fi PIP_FLAGS="" if [ -n "$MIN" ] && echo "$MIN" | grep -qE '[a-zA-Z]'; then PIP_FLAGS="--pre"; fi - python -m pip install build wheel "${OPM_SPEC}" $PIP_FLAGS + uv pip install build wheel "${OPM_SPEC}" $PIP_FLAGS - name: Build Distribution Packages run: | - python -m build + uv build - name: Install Built Package run: | @@ -120,12 +122,12 @@ jobs: EXTRAS="${{ inputs.install_extras }}" if [ -n "$WHEEL" ]; then if [ -n "$EXTRAS" ]; then - pip install "${WHEEL}[${EXTRAS}]" + uv pip install "${WHEEL}[${EXTRAS}]" else - pip install "$WHEEL" + uv pip install "$WHEEL" fi else - pip install dist/*.tar.gz + uv pip install dist/*.tar.gz fi - name: Verify OPM Detection (wheel install) @@ -212,9 +214,9 @@ jobs: EXTRAS="${{ inputs.install_extras }}" if [ -n "$EXTRAS" ]; then - pip install -e ".[$EXTRAS]" + uv pip install -e ".[$EXTRAS]" else - pip install -e . + uv pip install -e . fi python3 _gh_automations/scripts/check_opm.py \ diff --git a/.github/workflows/ovoscope.yml b/.github/workflows/ovoscope.yml index 3082af6..fe0edf3 100644 --- a/.github/workflows/ovoscope.yml +++ b/.github/workflows/ovoscope.yml @@ -154,6 +154,9 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv + - name: Install System Dependencies if: ${{ inputs.system_deps != '' || inputs.require_padatious }} run: | @@ -191,7 +194,7 @@ jobs: SRC="ovos-adapt-parser>=1.3.3a1" EXTRA="" fi - pip install $EXTRA "$SRC" || { + uv pip install $EXTRA "$SRC" || { echo "::error::Failed to install ovos-adapt-parser from $SRC" echo "::error::Note: Entry point is 'ovos-adapt-pipeline-plugin'" echo "::error::Add 'ovos-adapt-parser' to your [test] extras in pyproject.toml" @@ -212,7 +215,7 @@ jobs: SRC="ovos-padatious>=1.6.2a1" EXTRA="" fi - pip install $EXTRA "$SRC" || { + uv pip install $EXTRA "$SRC" || { echo "::error::Failed to install ovos-padatious from $SRC" echo "::error::Note: Entry point is 'ovos-padatious-pipeline-plugin'" echo "::error::Add 'ovos-padatious' to your [test] extras in pyproject.toml" @@ -229,7 +232,7 @@ jobs: SRC="ovos-m2v-pipeline" EXTRA="" fi - pip install $EXTRA "$SRC" || { + uv pip install $EXTRA "$SRC" || { echo "::error::Failed to install ovos-m2v-pipeline from $SRC" echo "::error::Add 'ovos-m2v-pipeline' to your [test] extras in pyproject.toml" exit 1 @@ -245,7 +248,7 @@ jobs: SRC="nebulento" EXTRA="" fi - pip install $EXTRA "$SRC" || { + uv pip install $EXTRA "$SRC" || { echo "::error::Failed to install nebulento from $SRC" echo "::error::Note: Entry point is 'ovos-nebulento-pipeline-plugin'" echo "::error::Add 'nebulento' to your [test] extras in pyproject.toml" @@ -262,7 +265,7 @@ jobs: SRC="palavreado" EXTRA="" fi - pip install $EXTRA "$SRC" || { + uv pip install $EXTRA "$SRC" || { echo "::error::Failed to install palavreado from $SRC" echo "::error::Note: Entry point is 'palavreado'" echo "::error::Add 'palavreado' to your [test] extras in pyproject.toml" @@ -276,31 +279,30 @@ jobs: 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: 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 from GitHub dev (pre_release)..." - pip install --force-reinstall \ + 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 . fi # The checked-out source MUST be what gets tested. When the local # version equals a published release (e.g. dev is at the same alpha # already on PyPI), the prior installs can leave pip resolving the # package back to the PyPI wheel, silently discarding the PR's source. # Force the local checkout to win, without disturbing resolved deps. - pip install --force-reinstall --no-deps . + uv pip install --force-reinstall --no-deps . python -c "import ovoscope; print('ovoscope path:', ovoscope.__file__)" - name: Post-install pip pins @@ -310,7 +312,7 @@ jobs: # --no-deps keeps these exact builds without re-resolving (which would # pull a same-version published wheel that carries a stricter cap). # shellcheck disable=SC2086 - python -m pip install --force-reinstall --no-deps ${{ inputs.post_install_pip }} + uv pip install --force-reinstall --no-deps ${{ inputs.post_install_pip }} - name: Check required pipeline availability run: | diff --git a/.github/workflows/pip-audit.yml b/.github/workflows/pip-audit.yml index 9b2af23..7378d43 100644 --- a/.github/workflows/pip-audit.yml +++ b/.github/workflows/pip-audit.yml @@ -73,8 +73,11 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv + - name: Install Build Tools - run: python -m pip install build wheel pip-audit + run: uv pip install build wheel pip-audit - name: Install System Dependencies run: | @@ -82,7 +85,7 @@ jobs: sudo apt-get install -yq python3-dev ${{ inputs.system_deps }} - name: Install package - run: pip install ".${{ inputs.install_extras }}" + run: uv pip install ".${{ inputs.install_extras }}" - name: Run pip-audit id: pip_audit_check diff --git a/.github/workflows/publish-alpha.yml b/.github/workflows/publish-alpha.yml index 9dbd72e..cff11e1 100644 --- a/.github/workflows/publish-alpha.yml +++ b/.github/workflows/publish-alpha.yml @@ -123,6 +123,8 @@ jobs: uses: actions/setup-python@v6 with: python-version: "3.14" + - name: Install uv + run: pip install uv - name: Determine version bump id: version_bump run: | @@ -293,10 +295,8 @@ jobs: uses: actions/setup-python@v6 with: python-version: "3.14" - - name: Install Build Tools - run: python -m pip install build - name: Build Distribution Packages - run: python -m build + run: uv build - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: diff --git a/.github/workflows/publish-stable.yml b/.github/workflows/publish-stable.yml index 5fdb615..0d3bb41 100644 --- a/.github/workflows/publish-stable.yml +++ b/.github/workflows/publish-stable.yml @@ -107,6 +107,9 @@ jobs: with: python-version: "3.14" + - name: Install uv + run: pip install uv + - name: Declare Alpha stable id: version working-directory: action/github/scripts @@ -158,10 +161,8 @@ jobs: uses: actions/setup-python@v6 with: python-version: "3.14" - - name: Install Build Tools - run: python -m pip install build - name: Build Distribution Packages - run: python -m build + run: uv build - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: diff --git a/.github/workflows/python-support.yml b/.github/workflows/python-support.yml index cbb2a71..d85e008 100644 --- a/.github/workflows/python-support.yml +++ b/.github/workflows/python-support.yml @@ -65,6 +65,9 @@ jobs: with: python-version: ${{ matrix.python-version }} + - name: Install uv + run: pip install uv + - name: Checkout gh-automations scripts uses: actions/checkout@v6 with: @@ -81,12 +84,11 @@ jobs: id: install continue-on-error: true run: | - python -m pip install --upgrade pip - python -m pip install ovos-plugin-manager + uv pip install ovos-plugin-manager - INSTALL_CMD="pip install" + INSTALL_CMD="uv pip install" if [ "${{ matrix.install-mode }}" == "editable" ]; then - INSTALL_CMD="pip install -e" + INSTALL_CMD="uv pip install -e" fi if [ -f setup.py ] || [ -f pyproject.toml ]; then diff --git a/.github/workflows/spec-lint.yml b/.github/workflows/spec-lint.yml index a6a1497..1a6340c 100644 --- a/.github/workflows/spec-lint.yml +++ b/.github/workflows/spec-lint.yml @@ -73,6 +73,9 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv + - name: Resolve locale path id: resolve env: @@ -98,8 +101,7 @@ jobs: env: OVOS_SPEC_TOOLS_SPEC: ${{ inputs.ovos_spec_tools_spec }} run: | - python -m pip install --upgrade pip - python -m pip install "$OVOS_SPEC_TOOLS_SPEC" + uv pip install "$OVOS_SPEC_TOOLS_SPEC" - name: Run ovos-spec-lint id: lint diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 96938f5..5b1a83c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,7 +25,9 @@ jobs: - uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} + - name: Install uv + run: pip install uv - name: Install test dependencies - run: pip install pytest ovos-plugin-manager + run: uv pip install pytest ovos-plugin-manager - name: Run script tests run: pytest test/test_scripts.py -v diff --git a/.github/workflows/tts-intelligibility.yml b/.github/workflows/tts-intelligibility.yml index 5449b61..5278fa3 100644 --- a/.github/workflows/tts-intelligibility.yml +++ b/.github/workflows/tts-intelligibility.yml @@ -94,6 +94,9 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv + - name: Install System Dependencies if: ${{ inputs.system_deps != '' }} run: | @@ -112,20 +115,19 @@ jobs: - 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 . fi python -c "import ovoscope; print('ovoscope path:', ovoscope.__file__)" diff --git a/.github/workflows/type-check.yml b/.github/workflows/type-check.yml index 71337c9..e7e1867 100644 --- a/.github/workflows/type-check.yml +++ b/.github/workflows/type-check.yml @@ -74,6 +74,9 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Install uv + run: pip install uv + - name: Install System Dependencies if: ${{ inputs.system_deps != '' }} run: | @@ -82,20 +85,20 @@ jobs: - name: Install Dependencies run: | - python -m pip install --upgrade pip mypy + 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 }} fi - name: Run mypy diff --git a/docs/maintenance.md b/docs/maintenance.md index 352a7a6..3383464 100644 --- a/docs/maintenance.md +++ b/docs/maintenance.md @@ -7,7 +7,7 @@ Tracker for open technical debt and opportunistic improvements in `gh-automation ### Deprecated workflows pending removal **Files:** `.github/workflows/coverage-pages.yml`, `.github/workflows/python-support.yml` -Both carry a `REMOVE AFTER: 2027-01-01` banner. Before removal, confirm zero active callers via `docs/repos.md`. Both still use `python -m pip install` directly (rather than `uv`) — frozen for back-compat until removal. +Both carry a `REMOVE AFTER: 2027-01-01` banner. Before removal, confirm zero active callers via `docs/repos.md`. Both still use `uv pip install` — frozen for back-compat until removal. ### `continue-on-error: true` requires discipline **Files:** `skill-check.yml`, `pip-audit.yml`, `coverage.yml`, `opm-check.yml`, `spec-lint.yml` diff --git a/docs/release-flow.md b/docs/release-flow.md index 354652e..ec03abd 100644 --- a/docs/release-flow.md +++ b/docs/release-flow.md @@ -87,7 +87,7 @@ release_workflow.yml (per-repo) │ curl → open PR to master │ ├─► publish_pypi job (per-repo, inline) - │ python -m pip install build + │ uv pip install build │ python -m build │ pypa/gh-action-pypi-publish → PyPI (alpha) │ diff --git a/docs/workflow-reference.md b/docs/workflow-reference.md index 343b8ea..885173d 100644 --- a/docs/workflow-reference.md +++ b/docs/workflow-reference.md @@ -363,7 +363,7 @@ Tests that use a missing pipeline are **skipped** (via `is_pipeline_available()` | Checkout gh-automations scripts | Checks out `OpenVoiceOS/gh-automations@dev` into `_gh_automations/` (PR events only) | | Setup Python | `actions/setup-python@v5` | | Install System Dependencies | `apt-get install` the `system_deps` list (skipped if empty) | -| Install Package with Test Extras | `pip install ".[test]"` (or the configured extras) plus `pytest pytest-json-report ovoscope` | +| Install Package with Test Extras | `uv pip install ".[test]"` (or the configured extras) plus `pytest pytest-json-report ovoscope` | | Check required pipeline availability | Inline Python reads `opm.pipeline` entry points and exits 1 if any `require_*` pipeline is absent | | Run ovoscope tests | `pytest --json-report` with `continue-on-error: true` so the PR comment step always runs | | Format ovoscope section for PR comment | Inline Python reads the JSON report and generates `ovoscope-section.md` grouped by test class | @@ -442,9 +442,9 @@ For deploying HTML coverage reports to GitHub Pages, see [`coverage-pages.yml`]( | `runner` | string | `ubuntu-latest` | Runner label | | `python_version` | string | `3.11` | Python version to run tests under | | `system_deps` | string | `""` | Extra apt packages to install before testing (space-separated) | -| `test_extras` | string | `dev` | Pyproject extras key declaring test deps. Tried first via `pip install -e .[]` | +| `test_extras` | string | `dev` | Pyproject extras key declaring test deps. Tried first via `uv pip install -e .[]` | | `test_extras_fallback` | string | `test` | Extras key tried if `test_extras` is not declared. Empty to skip | -| `install_extras` | string | `""` | Extra pip install arguments run AFTER the package install (e.g. `-r requirements/test.txt`, a git URL override) | +| `install_extras` | string | `""` | Extra uv install arguments run AFTER the package install (e.g. `-r requirements/test.txt`, a git URL override) | | `test_path` | string | `test/` | Path passed to pytest | | `coverage_source` | string | `.` | `--cov=` — set to your package directory (e.g. `ovos_core`) to measure only your own code | | `min_coverage` | number | `0` | Minimum total coverage %. Job fails if below threshold. `0` = disabled. | @@ -515,7 +515,7 @@ Runs `pytest --cov` and deploys the HTML coverage report to GitHub Pages. Design | `runner` | string | `ubuntu-latest` | Runner label | | `python_version` | string | `3.11` | Python version to run tests under | | `system_deps` | string | `""` | Extra apt packages to install before testing (space-separated) | -| `install_extras` | string | `""` | Extra pip install arguments run before tests | +| `install_extras` | string | `""` | Extra uv install arguments run before tests | | `test_path` | string | `test/` | Path passed to pytest | | `coverage_source` | string | `.` | `--cov=` — set to your package directory | | `gh_pages_subdir` | string | `coverage` | Sub-directory within the Pages site, e.g. `coverage` → `https://org.github.io/repo/coverage/`. Empty string = deploy at root. | @@ -903,8 +903,8 @@ Follows the canonical 3-phase pattern (`continue-on-error` → format → post |------|-------------| | Checkout + scripts checkout | Checks out the calling repo and (on PR events) the gh-automations scripts | | Setup Python | `actions/setup-python@v5` | -| Install build dependencies | `pip install build setuptools` | -| Run build to generate SOURCES.txt | `python -m build --no-isolation`. `continue-on-error: true`. | +| Install build dependencies | `uv pip install build setuptools` | +| Run build to generate SOURCES.txt | `uv build --no-isolation`. `continue-on-error: true`. | | Run locale build check | `check_locale_build.py --repo-root . --locale-path … --output-json /tmp/locale-report.json --verbose`. `continue-on-error: true`. | | Format locale section | Inline Python reads `locale-report.json` → `locale-section.md` | | Post locale section to PR comment | Calls `update_pr_comment.py` with `--section-id locale` | From 308c06143cf61157f22b22659c8cea26a0137c24 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Sun, 28 Jun 2026 17:12:39 +0100 Subject: [PATCH 02/12] fix: set UV_SYSTEM_PYTHON so uv installs into the setup-python interpreter 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) --- .github/workflows/build-tests.yml | 4 ++++ .github/workflows/coverage-pages.yml | 4 ++++ .github/workflows/coverage.yml | 4 ++++ .github/workflows/downstream-check.yml | 4 ++++ .github/workflows/intent-case-tests.yml | 4 ++++ .github/workflows/license-check.yml | 4 ++++ .github/workflows/lint.yml | 4 ++++ .github/workflows/locale-check.yml | 6 +++++- .github/workflows/opm-check.yml | 4 ++++ .github/workflows/ovoscope.yml | 4 ++++ .github/workflows/pip-audit.yml | 4 ++++ .github/workflows/python-support.yml | 4 ++++ .github/workflows/spec-lint.yml | 4 ++++ .github/workflows/test.yml | 4 ++++ .github/workflows/tts-intelligibility.yml | 4 ++++ .github/workflows/type-check.yml | 4 ++++ 16 files changed, 65 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-tests.yml b/.github/workflows/build-tests.yml index 488796e..b7bbc02 100644 --- a/.github/workflows/build-tests.yml +++ b/.github/workflows/build-tests.yml @@ -47,6 +47,10 @@ on: description: > Post a '🔨 Build Tests' section in the OVOS PR Checks comment. Only runs on pull_request events. +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: build_tests: strategy: diff --git a/.github/workflows/coverage-pages.yml b/.github/workflows/coverage-pages.yml index 4f7f389..a0d09ad 100644 --- a/.github/workflows/coverage-pages.yml +++ b/.github/workflows/coverage-pages.yml @@ -40,6 +40,10 @@ on: default: "gh-pages" description: "Branch to push the HTML coverage report to." +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: coverage_pages: runs-on: ${{ inputs.runner }} diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 1abbddd..8c672d5 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -83,6 +83,10 @@ on: default: 14 description: "Days to retain the coverage XML artifact" +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: coverage: runs-on: ${{ inputs.runner }} diff --git a/.github/workflows/downstream-check.yml b/.github/workflows/downstream-check.yml index b5b4fe0..58864cf 100644 --- a/.github/workflows/downstream-check.yml +++ b/.github/workflows/downstream-check.yml @@ -35,6 +35,10 @@ on: default: "dev" description: "Deprecated — ignored. Report is now uploaded as an artifact instead of committed." +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: check_downstream: runs-on: ${{ inputs.runner }} diff --git a/.github/workflows/intent-case-tests.yml b/.github/workflows/intent-case-tests.yml index bd37a68..438c2bc 100644 --- a/.github/workflows/intent-case-tests.yml +++ b/.github/workflows/intent-case-tests.yml @@ -107,6 +107,10 @@ on: Minimum overall pass rate (0.0-1.0). Fails the shard when the observed rate is below this value. +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: intent_case_tests: runs-on: ${{ inputs.runner }} diff --git a/.github/workflows/license-check.yml b/.github/workflows/license-check.yml index 827b2b1..97cb03d 100644 --- a/.github/workflows/license-check.yml +++ b/.github/workflows/license-check.yml @@ -66,6 +66,10 @@ on: Post a section in the shared 'OVOS PR Checks' comment on the PR. Only runs when the workflow is triggered by a pull_request event. +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: license_tests: runs-on: ${{ inputs.runner }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 2175826..3b2eb22 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -32,6 +32,10 @@ on: default: true description: "Post a section in the OVOS PR Checks comment on pull_request events" +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: lint: runs-on: ${{ inputs.runner }} diff --git a/.github/workflows/locale-check.yml b/.github/workflows/locale-check.yml index e1a9c32..ab3cc41 100644 --- a/.github/workflows/locale-check.yml +++ b/.github/workflows/locale-check.yml @@ -22,6 +22,10 @@ on: Post sections in the shared 'OVOS PR Checks' comment. Only runs when triggered by a pull_request event. +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: locale_check: runs-on: ${{ inputs.runner }} @@ -54,7 +58,7 @@ jobs: - name: Run build to generate SOURCES.txt run: | - uv build --no-isolation --outdir dist/ 2>&1 | tail -20 + uv build --no-build-isolation --out-dir dist/ 2>&1 | tail -20 continue-on-error: true - name: Run locale build check diff --git a/.github/workflows/opm-check.yml b/.github/workflows/opm-check.yml index 6820ae0..832333b 100644 --- a/.github/workflows/opm-check.yml +++ b/.github/workflows/opm-check.yml @@ -73,6 +73,10 @@ on: default: "" description: "Maximum ovos-plugin-manager version (exclusive upper bound), e.g. '3.0.0'. Leave empty for no upper bound." +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: opm_check: runs-on: ${{ inputs.runner }} diff --git a/.github/workflows/ovoscope.yml b/.github/workflows/ovoscope.yml index fe0edf3..ca28d67 100644 --- a/.github/workflows/ovoscope.yml +++ b/.github/workflows/ovoscope.yml @@ -131,6 +131,10 @@ on: # sibling `intent-case-tests.yml` reusable workflow. Use both # workflows in tandem (or only one) depending on what the skill ships. +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: ovoscope: runs-on: ${{ inputs.runner }} diff --git a/.github/workflows/pip-audit.yml b/.github/workflows/pip-audit.yml index 7378d43..c628890 100644 --- a/.github/workflows/pip-audit.yml +++ b/.github/workflows/pip-audit.yml @@ -49,6 +49,10 @@ on: Upload a SARIF report to GitHub's Security tab (Code scanning alerts). Requires the repo to have GitHub Advanced Security enabled, or be public. +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: pip_audit: runs-on: ${{ inputs.runner }} diff --git a/.github/workflows/python-support.yml b/.github/workflows/python-support.yml index d85e008..fda6ca4 100644 --- a/.github/workflows/python-support.yml +++ b/.github/workflows/python-support.yml @@ -49,6 +49,10 @@ on: default: true description: "Post/update the '🐍 Python Support' section in the PR comment" +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: check_compatibility: strategy: diff --git a/.github/workflows/spec-lint.yml b/.github/workflows/spec-lint.yml index 1a6340c..0833e32 100644 --- a/.github/workflows/spec-lint.yml +++ b/.github/workflows/spec-lint.yml @@ -47,6 +47,10 @@ on: Post a '🧪 Spec Lint' section in the shared 'OVOS PR Checks' comment. Only runs when the workflow is triggered by a pull_request event. +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: spec_lint: runs-on: ${{ inputs.runner }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5b1a83c..de6c8ab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,6 +13,10 @@ on: - 'test/**' workflow_dispatch: +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: test: strategy: diff --git a/.github/workflows/tts-intelligibility.yml b/.github/workflows/tts-intelligibility.yml index 5278fa3..35ede2f 100644 --- a/.github/workflows/tts-intelligibility.yml +++ b/.github/workflows/tts-intelligibility.yml @@ -72,6 +72,10 @@ on: downgrade to report-only — the score is still posted to the PR comment but the check never fails — for engines/langs still being tuned. +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: tts-intelligibility: runs-on: ${{ inputs.runner }} diff --git a/.github/workflows/type-check.yml b/.github/workflows/type-check.yml index e7e1867..b833a89 100644 --- a/.github/workflows/type-check.yml +++ b/.github/workflows/type-check.yml @@ -50,6 +50,10 @@ on: Post a 🔎 Type Check section in the shared OVOS PR Checks comment. Only runs when the workflow is triggered by a pull_request event. +# uv installs into the setup-python interpreter (no venv on the runner) +env: + UV_SYSTEM_PYTHON: "1" + jobs: type_check: runs-on: ${{ inputs.runner }} From f2ebb847947287331523a71e0fc21f9051b7fbae Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Sun, 28 Jun 2026 17:12:40 +0100 Subject: [PATCH 03/12] test: add temporary uv-migration self-test harness 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) --- .github/workflows/_selftest-uv.yml | 106 +++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 .github/workflows/_selftest-uv.yml diff --git a/.github/workflows/_selftest-uv.yml b/.github/workflows/_selftest-uv.yml new file mode 100644 index 0000000..fa6538a --- /dev/null +++ b/.github/workflows/_selftest-uv.yml @@ -0,0 +1,106 @@ +# TEMPORARY — validation harness for the pip→uv migration (PR #60). +# Delete this file before merging to dev; it is not a reusable workflow and +# has no downstream consumers. +# +# Why this exists: `actions/setup-python` provides a bare interpreter with no +# active virtualenv. `uv pip install` refuses to touch a non-venv interpreter +# unless `--system` / `UV_SYSTEM_PYTHON=1` is set. The migration relies on the +# workflow-level `env: UV_SYSTEM_PYTHON: "1"` block added to every uv workflow. +# These jobs prove that (a) the uv command surface works on real runners under +# that env, and (b) no uv workflow is missing the env block. +name: "[selftest] uv migration" + +on: + push: + branches: [migrate-to-uv] + workflow_dispatch: + +permissions: + contents: read + +jobs: + # Exercise every uv verb the migration introduces (install, install -e, + # build, freeze) against a throwaway package generated at runtime — no + # fixture files committed, nothing downstream touched. + uv-runtime: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] + steps: + - uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + + - name: Install uv + run: pip install uv + + - name: Create throwaway package + run: | + PKG="${RUNNER_TEMP}/uv_selftest_pkg" + mkdir -p "$PKG/src/uv_selftest" + echo "__version__ = '0.0.0'" > "$PKG/src/uv_selftest/__init__.py" + cat > "$PKG/pyproject.toml" <<'EOF' + [build-system] + requires = ["setuptools>=61"] + build-backend = "setuptools.build_meta" + + [project] + name = "uv-selftest" + version = "0.0.0" + requires-python = ">=3.10" + + [project.optional-dependencies] + test = ["pytest"] + + [tool.setuptools.packages.find] + where = ["src"] + EOF + mkdir -p "$PKG/test" + echo "def test_ok(): assert True" > "$PKG/test/test_smoke.py" + echo "PKG=$PKG" >> "$GITHUB_ENV" + + - name: Document the failure mode (without UV_SYSTEM_PYTHON) + # Informational only: shows that uv refuses a non-venv install by + # default, which is exactly what the workflow-level env block fixes. + # Not a hard assertion, so it stays robust across uv versions. + run: | + if env -u UV_SYSTEM_PYTHON uv pip install --quiet pytest 2>err.log; then + echo "::notice::uv allowed a system install without UV_SYSTEM_PYTHON (uv default may have changed)" + else + echo "::notice::Confirmed: uv refuses system install without UV_SYSTEM_PYTHON —" + sed 's/^/ /' err.log || true + fi + + - name: uv command surface (with UV_SYSTEM_PYTHON, as the workflows set it) + env: + UV_SYSTEM_PYTHON: "1" + run: | + set -euxo pipefail + uv pip install pytest build wheel + uv build --out-dir "${PKG}/dist" "${PKG}" + uv pip install "${PKG}"[test] + uv pip install -e "${PKG}"[test] + uv pip freeze | grep -i uv-selftest + python -m pytest "${PKG}/test" -v + + # 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" From 5f9089e82d8e1cbfc812f6070d5ffd4534338b90 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Sun, 28 Jun 2026 17:16:38 +0100 Subject: [PATCH 04/12] test: drive real reusable workflows with an in-repo dummy package 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) --- .github/workflows/_selftest-uv.yml | 123 +++++++++++++---------------- pyproject.toml | 21 +++++ selftest_pkg/__init__.py | 3 + selftest_pkg/core.py | 9 +++ selftest_pkg/tests/__init__.py | 0 selftest_pkg/tests/test_dummy.py | 9 +++ 6 files changed, 95 insertions(+), 70 deletions(-) create mode 100644 pyproject.toml create mode 100644 selftest_pkg/__init__.py create mode 100644 selftest_pkg/core.py create mode 100644 selftest_pkg/tests/__init__.py create mode 100644 selftest_pkg/tests/test_dummy.py diff --git a/.github/workflows/_selftest-uv.yml b/.github/workflows/_selftest-uv.yml index fa6538a..0dcf0c3 100644 --- a/.github/workflows/_selftest-uv.yml +++ b/.github/workflows/_selftest-uv.yml @@ -1,13 +1,19 @@ -# TEMPORARY — validation harness for the pip→uv migration (PR #60). -# Delete this file before merging to dev; it is not a reusable workflow and -# has no downstream consumers. +# TEMPORARY — validation harness for the pip->uv migration (PR #60). +# Delete this file (plus the root pyproject.toml and selftest_pkg/) before +# merging to dev. It is not a reusable workflow and has no downstream consumers. # -# Why this exists: `actions/setup-python` provides a bare interpreter with no -# active virtualenv. `uv pip install` refuses to touch a non-venv interpreter -# unless `--system` / `UV_SYSTEM_PYTHON=1` is set. The migration relies on the -# workflow-level `env: UV_SYSTEM_PYTHON: "1"` block added to every uv workflow. -# These jobs prove that (a) the uv command surface works on real runners under -# that env, and (b) no uv workflow is missing the env block. +# It drives the REAL reusable workflows via local `uses:` against the in-repo +# dummy package (root pyproject.toml + selftest_pkg/), so the actual build / +# install / coverage / audit / type-check plumbing runs under uv on real +# runners — not just isolated uv commands. +# +# Why the fix under test matters: actions/setup-python gives a bare interpreter +# with no active virtualenv, and `uv pip install` refuses a non-venv install +# unless UV_SYSTEM_PYTHON=1 / --system is set. Every uv workflow now declares +# that env at workflow level; these jobs prove it works end to end. +# +# Triggered on push to this branch only, with pr_comment:false everywhere, so +# nothing is posted to PR #60. name: "[selftest] uv migration" on: @@ -19,71 +25,48 @@ permissions: contents: read jobs: - # Exercise every uv verb the migration introduces (install, install -e, - # build, freeze) against a throwaway package generated at runtime — no - # fixture files committed, nothing downstream touched. - uv-runtime: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] - steps: - - uses: actions/setup-python@v6 - with: - python-version: ${{ matrix.python-version }} - - - name: Install uv - run: pip install uv + # Build sdist+wheel under `uv build`, install the wheel with extras under + # `uv pip install`, run pytest — across every supported Python. + build-tests: + uses: ./.github/workflows/build-tests.yml + with: + python_versions: '["3.10", "3.11", "3.12", "3.13", "3.14"]' + install_extras: test + test_path: selftest_pkg/tests + pr_comment: false - - name: Create throwaway package - run: | - PKG="${RUNNER_TEMP}/uv_selftest_pkg" - mkdir -p "$PKG/src/uv_selftest" - echo "__version__ = '0.0.0'" > "$PKG/src/uv_selftest/__init__.py" - cat > "$PKG/pyproject.toml" <<'EOF' - [build-system] - requires = ["setuptools>=61"] - build-backend = "setuptools.build_meta" - - [project] - name = "uv-selftest" - version = "0.0.0" - requires-python = ">=3.10" + # Editable install with extras under `uv pip install -e .[dev]` + pytest-cov. + coverage: + uses: ./.github/workflows/coverage.yml + with: + test_extras: dev + test_path: selftest_pkg/tests + coverage_source: selftest_pkg + pr_comment: false - [project.optional-dependencies] - test = ["pytest"] + # Editable install under uv, then mypy against the dummy package. + type-check: + uses: ./.github/workflows/type-check.yml + with: + test_extras: dev + mypy_args: selftest_pkg + pr_comment: false - [tool.setuptools.packages.find] - where = ["src"] - EOF - mkdir -p "$PKG/test" - echo "def test_ok(): assert True" > "$PKG/test/test_smoke.py" - echo "PKG=$PKG" >> "$GITHUB_ENV" + # `uv pip install ".[test]"` then `uv pip freeze` -> pip-licenses. + license-check: + uses: ./.github/workflows/license-check.yml + with: + install_extras: "[test]" + warn_only: true + pr_comment: false - - name: Document the failure mode (without UV_SYSTEM_PYTHON) - # Informational only: shows that uv refuses a non-venv install by - # default, which is exactly what the workflow-level env block fixes. - # Not a hard assertion, so it stays robust across uv versions. - run: | - if env -u UV_SYSTEM_PYTHON uv pip install --quiet pytest 2>err.log; then - echo "::notice::uv allowed a system install without UV_SYSTEM_PYTHON (uv default may have changed)" - else - echo "::notice::Confirmed: uv refuses system install without UV_SYSTEM_PYTHON —" - sed 's/^/ /' err.log || true - fi - - - name: uv command surface (with UV_SYSTEM_PYTHON, as the workflows set it) - env: - UV_SYSTEM_PYTHON: "1" - run: | - set -euxo pipefail - uv pip install pytest build wheel - uv build --out-dir "${PKG}/dist" "${PKG}" - uv pip install "${PKG}"[test] - uv pip install -e "${PKG}"[test] - uv pip freeze | grep -i uv-selftest - python -m pytest "${PKG}/test" -v + # `uv pip install ".[test]"` then pip-audit over the resolved deps. + pip-audit: + uses: ./.github/workflows/pip-audit.yml + with: + install_extras: "[test]" + warn_only: true + pr_comment: false # 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. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b66859c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,21 @@ +# TEMPORARY — dummy package for the uv-migration self-test (PR #60). +# Gives `_selftest-uv.yml` an installable target so it can drive the REAL +# reusable workflows (build / install / coverage / audit / type-check) under +# uv, instead of only raw uv commands. Delete this file together with the +# `selftest_pkg/` directory and `_selftest-uv.yml` before merging to dev. +[build-system] +requires = ["setuptools>=61"] +build-backend = "setuptools.build_meta" + +[project] +name = "uv-selftest-dummy" +version = "0.0.0" +description = "Throwaway package exercising gh-automations workflows under uv" +requires-python = ">=3.10" + +[project.optional-dependencies] +test = ["pytest"] +dev = ["pytest", "pytest-cov"] + +[tool.setuptools.packages.find] +include = ["selftest_pkg*"] diff --git a/selftest_pkg/__init__.py b/selftest_pkg/__init__.py new file mode 100644 index 0000000..ff6b23a --- /dev/null +++ b/selftest_pkg/__init__.py @@ -0,0 +1,3 @@ +"""Throwaway package for the uv-migration self-test (PR #60). Safe to delete.""" + +__version__ = "0.0.0" diff --git a/selftest_pkg/core.py b/selftest_pkg/core.py new file mode 100644 index 0000000..85118f0 --- /dev/null +++ b/selftest_pkg/core.py @@ -0,0 +1,9 @@ +"""Trivial, fully typed module so mypy/type-check has a real target.""" + + +def add(a: int, b: int) -> int: + return a + b + + +def greet(name: str) -> str: + return f"hello {name}" diff --git a/selftest_pkg/tests/__init__.py b/selftest_pkg/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/selftest_pkg/tests/test_dummy.py b/selftest_pkg/tests/test_dummy.py new file mode 100644 index 0000000..90fd0c7 --- /dev/null +++ b/selftest_pkg/tests/test_dummy.py @@ -0,0 +1,9 @@ +from selftest_pkg.core import add, greet + + +def test_add() -> None: + assert add(2, 3) == 5 + + +def test_greet() -> None: + assert greet("ovos") == "hello ovos" From 4807c9bd2305288581af258d048d94ffe88706f2 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Sun, 28 Jun 2026 17:23:29 +0100 Subject: [PATCH 05/12] test: grant caller the union of reusable-workflow permissions 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). --- .github/workflows/_selftest-uv.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/_selftest-uv.yml b/.github/workflows/_selftest-uv.yml index 0dcf0c3..cc8bb97 100644 --- a/.github/workflows/_selftest-uv.yml +++ b/.github/workflows/_selftest-uv.yml @@ -21,8 +21,13 @@ on: branches: [migrate-to-uv] workflow_dispatch: +# Must cover the union of permissions the called reusable workflows declare, +# or GitHub rejects the call at compile time (startup failure) — even though +# the features needing them are disabled here (pr_comment/deploy_pages/sarif). permissions: - contents: read + contents: write # coverage.yml job declares contents: write (deploy_pages) + pull-requests: write # PR-comment jobs + security-events: write # pip-audit.yml SARIF upload jobs: # Build sdist+wheel under `uv build`, install the wheel with extras under From 9213aebd48467786e0cd62748f02a8f9fbaee6c0 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Sun, 28 Jun 2026 17:27:07 +0100 Subject: [PATCH 06/12] =?UTF-8?q?test:=20bisect=20=E2=80=94=20call=20only?= =?UTF-8?q?=20build-tests=20to=20isolate=20startup=20failure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/_selftest-uv.yml | 33 +----------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/.github/workflows/_selftest-uv.yml b/.github/workflows/_selftest-uv.yml index cc8bb97..aa8ab5a 100644 --- a/.github/workflows/_selftest-uv.yml +++ b/.github/workflows/_selftest-uv.yml @@ -40,38 +40,7 @@ jobs: test_path: selftest_pkg/tests pr_comment: false - # Editable install with extras under `uv pip install -e .[dev]` + pytest-cov. - coverage: - uses: ./.github/workflows/coverage.yml - with: - test_extras: dev - test_path: selftest_pkg/tests - coverage_source: selftest_pkg - pr_comment: false - - # Editable install under uv, then mypy against the dummy package. - type-check: - uses: ./.github/workflows/type-check.yml - with: - test_extras: dev - mypy_args: selftest_pkg - pr_comment: false - - # `uv pip install ".[test]"` then `uv pip freeze` -> pip-licenses. - license-check: - uses: ./.github/workflows/license-check.yml - with: - install_extras: "[test]" - warn_only: true - pr_comment: false - - # `uv pip install ".[test]"` then pip-audit over the resolved deps. - pip-audit: - uses: ./.github/workflows/pip-audit.yml - with: - install_extras: "[test]" - warn_only: true - pr_comment: false + # BISECT: other reusable calls temporarily removed to isolate the startup failure. # 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. From f35c9371387fec2c76ac34c8878c9b97036a92ad Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Sun, 28 Jun 2026 17:28:13 +0100 Subject: [PATCH 07/12] =?UTF-8?q?test:=20bisect=20step=202=20=E2=80=94=20a?= =?UTF-8?q?dd=20type-check=20+=20license-check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/_selftest-uv.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/_selftest-uv.yml b/.github/workflows/_selftest-uv.yml index aa8ab5a..7818119 100644 --- a/.github/workflows/_selftest-uv.yml +++ b/.github/workflows/_selftest-uv.yml @@ -40,7 +40,20 @@ jobs: test_path: selftest_pkg/tests pr_comment: false - # BISECT: other reusable calls temporarily removed to isolate the startup failure. + # BISECT step 2: add the two standard-permission calls. + type-check: + uses: ./.github/workflows/type-check.yml + with: + test_extras: dev + mypy_args: selftest_pkg + pr_comment: false + + license-check: + uses: ./.github/workflows/license-check.yml + with: + install_extras: "[test]" + warn_only: true + pr_comment: false # 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. From f6b9c547071e4a16381360b838b8e36a8696eead Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Sun, 28 Jun 2026 17:28:57 +0100 Subject: [PATCH 08/12] =?UTF-8?q?test:=20bisect=20=E2=80=94=20type-check?= =?UTF-8?q?=20only=20(drop=20license-check)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/_selftest-uv.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/_selftest-uv.yml b/.github/workflows/_selftest-uv.yml index 7818119..afd1cc6 100644 --- a/.github/workflows/_selftest-uv.yml +++ b/.github/workflows/_selftest-uv.yml @@ -48,13 +48,6 @@ jobs: mypy_args: selftest_pkg pr_comment: false - license-check: - uses: ./.github/workflows/license-check.yml - with: - install_extras: "[test]" - warn_only: true - pr_comment: false - # 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: From 63a603ae729057f701ccd847624d6e58b92b9fee Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Sun, 28 Jun 2026 17:34:53 +0100 Subject: [PATCH 09/12] fix: remove duplicate continue-on-error key in type-check/docs-check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .github/workflows/docs-check.yml | 1 - .github/workflows/type-check.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/docs-check.yml b/.github/workflows/docs-check.yml index bb975dd..a5dfcf0 100644 --- a/.github/workflows/docs-check.yml +++ b/.github/workflows/docs-check.yml @@ -114,7 +114,6 @@ jobs: 2>&1 | tee /tmp/markdownlint-output.txt || true fi markdownlint-cli2 "**/*.md" 2>&1 - continue-on-error: true - name: Format docs check section for PR comment if: ${{ inputs.pr_comment && github.event_name == 'pull_request' }} diff --git a/.github/workflows/type-check.yml b/.github/workflows/type-check.yml index b833a89..1f48f60 100644 --- a/.github/workflows/type-check.yml +++ b/.github/workflows/type-check.yml @@ -123,7 +123,6 @@ jobs: | tee /tmp/mypy-human.txt || true # Exit code from human-readable run (not tee) mypy ${{ inputs.mypy_args }} --show-column-numbers --no-error-summary 2>&1 - continue-on-error: true - name: Format type check section for PR comment if: ${{ inputs.pr_comment && github.event_name == 'pull_request' }} From 4a1dbd5718861ac18f494caebab794712389f746 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Sun, 28 Jun 2026 17:34:53 +0100 Subject: [PATCH 10/12] test: restore full self-test (all 5 reusable calls) after dup-key fix --- .github/workflows/_selftest-uv.yml | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/.github/workflows/_selftest-uv.yml b/.github/workflows/_selftest-uv.yml index afd1cc6..cc8bb97 100644 --- a/.github/workflows/_selftest-uv.yml +++ b/.github/workflows/_selftest-uv.yml @@ -40,7 +40,16 @@ jobs: test_path: selftest_pkg/tests pr_comment: false - # BISECT step 2: add the two standard-permission calls. + # Editable install with extras under `uv pip install -e .[dev]` + pytest-cov. + coverage: + uses: ./.github/workflows/coverage.yml + with: + test_extras: dev + test_path: selftest_pkg/tests + coverage_source: selftest_pkg + pr_comment: false + + # Editable install under uv, then mypy against the dummy package. type-check: uses: ./.github/workflows/type-check.yml with: @@ -48,6 +57,22 @@ jobs: mypy_args: selftest_pkg pr_comment: false + # `uv pip install ".[test]"` then `uv pip freeze` -> pip-licenses. + license-check: + uses: ./.github/workflows/license-check.yml + with: + install_extras: "[test]" + warn_only: true + pr_comment: false + + # `uv pip install ".[test]"` then pip-audit over the resolved deps. + pip-audit: + uses: ./.github/workflows/pip-audit.yml + with: + install_extras: "[test]" + warn_only: true + pr_comment: false + # 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: From 0eb1701723db8e381c4f3f2a1795892d48197d64 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Sun, 28 Jun 2026 17:50:00 +0100 Subject: [PATCH 11/12] fix(uv): allow prereleases so OVOS alpha floor-pins resolve MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 ( --- .github/workflows/build-tests.yml | 6 ++++++ .github/workflows/coverage-pages.yml | 1 + .github/workflows/coverage.yml | 1 + .github/workflows/downstream-check.yml | 1 + .github/workflows/intent-case-tests.yml | 1 + .github/workflows/license-check.yml | 1 + .github/workflows/lint.yml | 1 + .github/workflows/locale-check.yml | 1 + .github/workflows/opm-check.yml | 1 + .github/workflows/ovoscope.yml | 1 + .github/workflows/pip-audit.yml | 1 + .github/workflows/python-support.yml | 1 + .github/workflows/spec-lint.yml | 1 + .github/workflows/test.yml | 1 + .github/workflows/tts-intelligibility.yml | 1 + .github/workflows/type-check.yml | 1 + 16 files changed, 21 insertions(+) diff --git a/.github/workflows/build-tests.yml b/.github/workflows/build-tests.yml index b7bbc02..75b29a0 100644 --- a/.github/workflows/build-tests.yml +++ b/.github/workflows/build-tests.yml @@ -50,6 +50,12 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + # The OVOS ecosystem ships pre-1.0 alphas and relies on prerelease floor-pins + # (pkg>=X.Ya1). pip honoured those transitively; uv's default mode does not when + # a package also has stable releases (e.g. ovos-PHAL's ovos-phal-plugin-ipgeo + # >=0.1.9a1, which has a coexisting stable 0.1.7). Allow prereleases so the + # floor-pins resolve as they did under pip — version caps still bound them. + UV_PRERELEASE: "allow" jobs: build_tests: diff --git a/.github/workflows/coverage-pages.yml b/.github/workflows/coverage-pages.yml index a0d09ad..ef9bf4c 100644 --- a/.github/workflows/coverage-pages.yml +++ b/.github/workflows/coverage-pages.yml @@ -43,6 +43,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: coverage_pages: diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 8c672d5..fc7dad0 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -86,6 +86,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: coverage: diff --git a/.github/workflows/downstream-check.yml b/.github/workflows/downstream-check.yml index 58864cf..55e0804 100644 --- a/.github/workflows/downstream-check.yml +++ b/.github/workflows/downstream-check.yml @@ -38,6 +38,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: check_downstream: diff --git a/.github/workflows/intent-case-tests.yml b/.github/workflows/intent-case-tests.yml index 438c2bc..cb34e08 100644 --- a/.github/workflows/intent-case-tests.yml +++ b/.github/workflows/intent-case-tests.yml @@ -110,6 +110,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: intent_case_tests: diff --git a/.github/workflows/license-check.yml b/.github/workflows/license-check.yml index 97cb03d..7658b98 100644 --- a/.github/workflows/license-check.yml +++ b/.github/workflows/license-check.yml @@ -69,6 +69,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: license_tests: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 3b2eb22..f0927ae 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -35,6 +35,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: lint: diff --git a/.github/workflows/locale-check.yml b/.github/workflows/locale-check.yml index ab3cc41..de4c512 100644 --- a/.github/workflows/locale-check.yml +++ b/.github/workflows/locale-check.yml @@ -25,6 +25,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: locale_check: diff --git a/.github/workflows/opm-check.yml b/.github/workflows/opm-check.yml index 832333b..e1a577a 100644 --- a/.github/workflows/opm-check.yml +++ b/.github/workflows/opm-check.yml @@ -76,6 +76,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: opm_check: diff --git a/.github/workflows/ovoscope.yml b/.github/workflows/ovoscope.yml index ca28d67..425e5f8 100644 --- a/.github/workflows/ovoscope.yml +++ b/.github/workflows/ovoscope.yml @@ -134,6 +134,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: ovoscope: diff --git a/.github/workflows/pip-audit.yml b/.github/workflows/pip-audit.yml index c628890..3caf22f 100644 --- a/.github/workflows/pip-audit.yml +++ b/.github/workflows/pip-audit.yml @@ -52,6 +52,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: pip_audit: diff --git a/.github/workflows/python-support.yml b/.github/workflows/python-support.yml index fda6ca4..9ba2607 100644 --- a/.github/workflows/python-support.yml +++ b/.github/workflows/python-support.yml @@ -52,6 +52,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: check_compatibility: diff --git a/.github/workflows/spec-lint.yml b/.github/workflows/spec-lint.yml index 0833e32..262a376 100644 --- a/.github/workflows/spec-lint.yml +++ b/.github/workflows/spec-lint.yml @@ -50,6 +50,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: spec_lint: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index de6c8ab..4ff5fac 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,6 +16,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: test: diff --git a/.github/workflows/tts-intelligibility.yml b/.github/workflows/tts-intelligibility.yml index 35ede2f..74ebd8e 100644 --- a/.github/workflows/tts-intelligibility.yml +++ b/.github/workflows/tts-intelligibility.yml @@ -75,6 +75,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: tts-intelligibility: diff --git a/.github/workflows/type-check.yml b/.github/workflows/type-check.yml index 1f48f60..d0fa7d7 100644 --- a/.github/workflows/type-check.yml +++ b/.github/workflows/type-check.yml @@ -53,6 +53,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" + UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did jobs: type_check: From 960b6c7d848ce89fcbcc1fe5bb968dd780a453ee Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Sun, 28 Jun 2026 17:52:11 +0100 Subject: [PATCH 12/12] feat(uv): make prerelease mode a workflow_call input (uv_prerelease) 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 --- .github/workflows/build-tests.yml | 9 ++++++++- .github/workflows/coverage-pages.yml | 9 ++++++++- .github/workflows/coverage.yml | 9 ++++++++- .github/workflows/downstream-check.yml | 9 ++++++++- .github/workflows/intent-case-tests.yml | 9 ++++++++- .github/workflows/license-check.yml | 9 ++++++++- .github/workflows/lint.yml | 9 ++++++++- .github/workflows/locale-check.yml | 9 ++++++++- .github/workflows/opm-check.yml | 9 ++++++++- .github/workflows/ovoscope.yml | 9 ++++++++- .github/workflows/pip-audit.yml | 9 ++++++++- .github/workflows/python-support.yml | 9 ++++++++- .github/workflows/spec-lint.yml | 9 ++++++++- .github/workflows/tts-intelligibility.yml | 9 ++++++++- .github/workflows/type-check.yml | 9 ++++++++- 15 files changed, 120 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build-tests.yml b/.github/workflows/build-tests.yml index 75b29a0..bbf4ae4 100644 --- a/.github/workflows/build-tests.yml +++ b/.github/workflows/build-tests.yml @@ -8,6 +8,13 @@ name: Build Tests on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -55,7 +62,7 @@ env: # a package also has stable releases (e.g. ovos-PHAL's ovos-phal-plugin-ipgeo # >=0.1.9a1, which has a coexisting stable 0.1.7). Allow prereleases so the # floor-pins resolve as they did under pip — version caps still bound them. - UV_PRERELEASE: "allow" + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: build_tests: diff --git a/.github/workflows/coverage-pages.yml b/.github/workflows/coverage-pages.yml index ef9bf4c..810fbf6 100644 --- a/.github/workflows/coverage-pages.yml +++ b/.github/workflows/coverage-pages.yml @@ -8,6 +8,13 @@ name: Coverage Pages on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -43,7 +50,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: coverage_pages: diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index fc7dad0..356466e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -2,6 +2,13 @@ name: Coverage Report on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -86,7 +93,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: coverage: diff --git a/.github/workflows/downstream-check.yml b/.github/workflows/downstream-check.yml index 55e0804..c6be69f 100644 --- a/.github/workflows/downstream-check.yml +++ b/.github/workflows/downstream-check.yml @@ -2,6 +2,13 @@ name: Downstream Dependency Check on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. package_name: type: string required: true @@ -38,7 +45,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: check_downstream: diff --git a/.github/workflows/intent-case-tests.yml b/.github/workflows/intent-case-tests.yml index cb34e08..e4109df 100644 --- a/.github/workflows/intent-case-tests.yml +++ b/.github/workflows/intent-case-tests.yml @@ -21,6 +21,13 @@ name: Intent-Case Tests on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -110,7 +117,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: intent_case_tests: diff --git a/.github/workflows/license-check.yml b/.github/workflows/license-check.yml index 7658b98..98d98cf 100644 --- a/.github/workflows/license-check.yml +++ b/.github/workflows/license-check.yml @@ -19,6 +19,13 @@ name: License Check on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -69,7 +76,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: license_tests: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f0927ae..c7ca7b1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -4,6 +4,13 @@ name: Lint on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -35,7 +42,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: lint: diff --git a/.github/workflows/locale-check.yml b/.github/workflows/locale-check.yml index de4c512..fc7fd61 100644 --- a/.github/workflows/locale-check.yml +++ b/.github/workflows/locale-check.yml @@ -5,6 +5,13 @@ name: Locale Build Check on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -25,7 +32,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: locale_check: diff --git a/.github/workflows/opm-check.yml b/.github/workflows/opm-check.yml index e1a577a..c475b86 100644 --- a/.github/workflows/opm-check.yml +++ b/.github/workflows/opm-check.yml @@ -9,6 +9,13 @@ name: OPM Plugin Check on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -76,7 +83,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: opm_check: diff --git a/.github/workflows/ovoscope.yml b/.github/workflows/ovoscope.yml index 425e5f8..3f0d3fa 100644 --- a/.github/workflows/ovoscope.yml +++ b/.github/workflows/ovoscope.yml @@ -28,6 +28,13 @@ name: Ovoscope End-to-End Tests on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -134,7 +141,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: ovoscope: diff --git a/.github/workflows/pip-audit.yml b/.github/workflows/pip-audit.yml index 3caf22f..9c41583 100644 --- a/.github/workflows/pip-audit.yml +++ b/.github/workflows/pip-audit.yml @@ -8,6 +8,13 @@ name: Pip Audit on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -52,7 +59,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: pip_audit: diff --git a/.github/workflows/python-support.yml b/.github/workflows/python-support.yml index 9ba2607..3bb7ce4 100644 --- a/.github/workflows/python-support.yml +++ b/.github/workflows/python-support.yml @@ -12,6 +12,13 @@ name: Python Support on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -52,7 +59,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: check_compatibility: diff --git a/.github/workflows/spec-lint.yml b/.github/workflows/spec-lint.yml index 262a376..b76cb90 100644 --- a/.github/workflows/spec-lint.yml +++ b/.github/workflows/spec-lint.yml @@ -8,6 +8,13 @@ name: Spec Lint on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -50,7 +57,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: spec_lint: diff --git a/.github/workflows/tts-intelligibility.yml b/.github/workflows/tts-intelligibility.yml index 74ebd8e..25a0909 100644 --- a/.github/workflows/tts-intelligibility.yml +++ b/.github/workflows/tts-intelligibility.yml @@ -18,6 +18,13 @@ name: TTS Intelligibility on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -75,7 +82,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: tts-intelligibility: diff --git a/.github/workflows/type-check.yml b/.github/workflows/type-check.yml index d0fa7d7..fd5de6f 100644 --- a/.github/workflows/type-check.yml +++ b/.github/workflows/type-check.yml @@ -7,6 +7,13 @@ name: Type Check on: workflow_call: inputs: + uv_prerelease: + type: string + default: "allow" + description: > + uv prerelease resolution mode (allow | if-necessary | explicit | + disallow). Defaults to "allow": the OVOS ecosystem ships pre-1.0 alphas + and relies on prerelease floor-pins resolving the way pip did. runner: type: string default: "ubuntu-latest" @@ -53,7 +60,7 @@ on: # uv installs into the setup-python interpreter (no venv on the runner) env: UV_SYSTEM_PYTHON: "1" - UV_PRERELEASE: "allow" # OVOS ships pre-1.0 alphas; resolve prerelease floor-pins like pip did + UV_PRERELEASE: ${{ inputs.uv_prerelease }} jobs: type_check: