Skip to content

chore: release v0.35.1 #240

chore: release v0.35.1

chore: release v0.35.1 #240

Workflow file for this run

name: CI
on:
push:
branches:
- "master"
- "dev"
pull_request:
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
checks:
name: ${{ matrix.task }}
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- task: format
do_sync: true
command: uv run --no-sync ruff format --check --diff src tests
sync_args: --no-install-project
- task: ruff
do_sync: true
command: uv run --no-sync ruff check src tests --output-format=github
sync_args: --no-install-project
- task: ty
do_sync: true
command: uv run --no-sync ty check --warn invalid-argument-type --warn unresolved-attribute --warn invalid-assignment --warn not-subscriptable src tests
sync_args: --no-install-project
allow_failure: true # ty has pre-existing warnings; informational only
- task: lockfile
do_sync: false
command: uv lock --check
sync_args: ""
- task: docs
do_sync: true
command: uv run --no-sync python scripts/docs_prebuild.py && uv run --no-sync zensical build --clean
sync_args: --no-install-project --group docs
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install uv
uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0
with:
python-version: "3.14"
enable-cache: true
- name: Install dependencies
if: matrix.do_sync
run: uv sync --frozen ${{ matrix.sync_args }}
- name: Run check
run: ${{ matrix.command }}
continue-on-error: ${{ matrix.allow_failure || false }}
pytest:
name: pytest (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
python-version: ["3.12", "3.13", "3.14"]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install uv
uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0
with:
python-version: ${{ matrix.python-version }}
enable-cache: true
- name: Install dependencies
run: uv sync --frozen
- name: Run tests
run: uv run --no-sync pytest
- name: Add coverage to summary
if: ${{ always() && matrix.python-version == '3.14' }}
run: |
{
echo "## Coverage"
echo ""
uv run --no-sync python -m coverage report || true
} >> "$GITHUB_STEP_SUMMARY"
build:
name: build
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install uv
uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0
with:
python-version: "3.13"
enable-cache: true
- name: Build (wheel + sdist)
run: uv build
- name: Inspect with twine and check-wheel-contents
run: |
uvx twine check dist/*
uvx check-wheel-contents dist/*.whl
- name: Upload packages
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: Packages
path: dist/
if-no-files-found: error
install-test:
name: install-test
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Download built packages
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: Packages
path: dist/
- name: Install uv
uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0
with:
python-version: "3.14"
- name: Install wheel in clean venv
run: |
uv venv /tmp/clean-env
uv pip install --python /tmp/clean-env/bin/python dist/*.whl
- name: Smoke-test imports
run: |
/tmp/clean-env/bin/python -c "
from untether.telegram.render import render_markdown
from untether.runners.claude import BACKEND as claude_backend
from untether.runners.codex import BACKEND as codex_backend
from untether.runners.opencode import BACKEND as opencode_backend
from untether.runners.pi import BACKEND as pi_backend
from untether.runners.gemini import BACKEND as gemini_backend
from untether.runners.amp import BACKEND as amp_backend
from untether.settings import load_settings
print('All imports OK')
"
testpypi-publish:
name: Publish to TestPyPI
if: github.event_name == 'push' && github.ref == 'refs/heads/dev'
needs: [build, pytest]
runs-on: ubuntu-latest
environment:
name: testpypi
url: https://test.pypi.org/p/untether
permissions:
contents: read
id-token: write # OIDC trusted publishing to TestPyPI
steps:
- name: Download built packages
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: Packages
path: dist/
- name: Publish to TestPyPI
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
with:
repository-url: https://test.pypi.org/legacy/
packages-dir: dist/
skip-existing: true
security:
name: ${{ matrix.task }}
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- task: pip-audit
do_sync: true
command: uv run --no-sync pip-audit --skip-editable --progress-spinner=off --ignore-vuln CVE-2026-4539 # pygments 2.19.2, no fix available
sync_args: ""
- task: bandit
do_sync: true
command: uv run --no-sync bandit -r src/ -c pyproject.toml -q
sync_args: --no-install-project
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install uv
uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0
with:
python-version: "3.14"
enable-cache: true
- name: Install dependencies
if: matrix.do_sync
run: uv sync --frozen ${{ matrix.sync_args }}
- name: Run check
run: ${{ matrix.command }}
release-validation:
name: release-validation
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout PR
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check if version changed
id: version-check
run: |
git fetch origin ${{ github.base_ref }} --depth=1
BASE_VERSION=$(git show origin/${{ github.base_ref }}:pyproject.toml | python3 -c "import sys, tomllib; print(tomllib.loads(sys.stdin.read())['project']['version'])")
PR_VERSION=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
if [ "$BASE_VERSION" != "$PR_VERSION" ]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
echo "Version changed: $BASE_VERSION -> $PR_VERSION"
else
echo "changed=false" >> "$GITHUB_OUTPUT"
echo "Version unchanged: $PR_VERSION"
fi
- name: Validate release metadata
if: steps.version-check.outputs.changed == 'true'
run: python3 scripts/validate_release.py