Modernize tooling: uv, ruff, ty, Python 3.13+ and full typing #86
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: | |
| - master | |
| tags: | |
| - "v*" | |
| pull_request: | |
| branches: | |
| - master | |
| # Cancel in-flight runs when newer commits are pushed to the same | |
| # branch/PR, but never cancel a tag run mid-publish. | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }} | |
| jobs: | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "pyproject.toml" | |
| - name: Install only ruff | |
| run: uv sync --only-group ruff | |
| - name: Lint | |
| run: uv run --no-sync ruff check --output-format=github . | |
| - name: Format | |
| run: uv run --no-sync ruff format --check . | |
| typecheck: | |
| name: Typecheck | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "pyproject.toml" | |
| # ty needs the runtime dependencies installed to resolve their | |
| # imports, so this installs the project itself, unlike the lint job | |
| - name: Install ty and runtime dependencies | |
| run: uv sync --no-default-groups --group ty | |
| - name: Typecheck | |
| run: uv run --no-sync ty check --output-format=github --error-on-warning | |
| test: | |
| name: Test on ${{ matrix.name }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # the test suite exercises a real OS keyring, which is only | |
| # available unattended on Windows runners | |
| - name: Windows py313 | |
| os: windows-latest | |
| pyversion: "3.13" | |
| - name: Windows py314 | |
| os: windows-latest | |
| pyversion: "3.14" | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install uv and Python ${{ matrix.pyversion }} | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | |
| with: | |
| python-version: ${{ matrix.pyversion }} | |
| enable-cache: true | |
| cache-dependency-glob: "pyproject.toml" | |
| cache-suffix: py${{ matrix.pyversion }} | |
| - name: Install dependencies | |
| run: uv sync | |
| - name: Test | |
| run: uv run --no-sync pytest -v --cov=keycmd --cov-report=term-missing tests | |
| build: | |
| name: Build and test wheel | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | |
| - name: Build sdist and wheel | |
| run: uv build | |
| - name: Twine check | |
| run: uvx twine check dist/* | |
| - name: Upload wheel artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| path: dist | |
| name: dist | |
| publish: | |
| name: Publish to Github and Pypi | |
| runs-on: ubuntu-latest | |
| needs: [lint, typecheck, test, build] | |
| if: success() && startsWith(github.ref, 'refs/tags/v') | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download wheel artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: dist | |
| path: dist | |
| - name: Release to GitHub | |
| uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| files: | | |
| dist/*.tar.gz | |
| dist/*.whl | |
| draft: true | |
| prerelease: false | |
| - name: Publish to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| user: __token__ | |
| password: ${{ secrets.PYPI_PASSWORD }} |