Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Normalize tracked text files to LF for stable diffs across platforms.
* text=auto eol=lf

# Keep markdown readable in diffs and consistently normalized.
*.md text eol=lf diff=markdown

# Keep Python and shell automation normalized for reliable review and execution.
*.py text eol=lf
*.sh text eol=lf
*.ps1 text eol=lf

# Keep structured config normalized so tooling behaves consistently.
*.yml text eol=lf
*.yaml text eol=lf
*.toml text eol=lf
*.json text eol=lf
*.jsonc text eol=lf

# Keep ignore and attribute files themselves normalized for portability.
.gitignore text eol=lf
.gitattributes text eol=lf

# Add project-specific binary types below.
# *.png binary
# *.pdf binary
# *.docx binary
49 changes: 49 additions & 0 deletions .github/actions/setup-python/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Setup Python environment
description: >
Install a Python interpreter, create a venv via scripts/setup.sh or
scripts/setup.ps1, and add the venv to PATH so every subsequent step
uses the same isolated environment that local development does.

inputs:
python-version:
description: Python version to install
required: false
default: "3.12"

runs:
using: composite
steps:
- name: Install Python ${{ inputs.python-version }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.1.0
with:
python-version: ${{ inputs.python-version }}
cache: pip
cache-dependency-path: pyproject.toml

- name: Install uv when uv.lock is present
if: ${{ hashFiles('uv.lock') != '' }}
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7

- name: Create venv and install package (Linux/macOS)
if: runner.os != 'Windows'
shell: bash
run: bash scripts/setup.sh

- name: Create venv and install package (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: .\scripts\setup.ps1

- name: Activate venv for subsequent steps (Linux/macOS)
if: runner.os != 'Windows'
shell: bash
run: |
echo "${GITHUB_WORKSPACE}/.venv/bin" >> "$GITHUB_PATH"
echo "VIRTUAL_ENV=${GITHUB_WORKSPACE}/.venv" >> "$GITHUB_ENV"

- name: Activate venv for subsequent steps (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
"$env:GITHUB_WORKSPACE\.venv\Scripts" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
"VIRTUAL_ENV=$env:GITHUB_WORKSPACE\.venv" | Out-File -Append -FilePath $env:GITHUB_ENV -Encoding utf8
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly

- package-ecosystem: pip
directory: /
schedule:
interval: weekly
211 changes: 211 additions & 0 deletions .github/workflows/python-qa.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
name: Python QA

on:
workflow_call:
inputs:
python-min:
description: Minimum Python version
type: string
default: "3.11"
python-max:
description: Maximum Python version
type: string
default: "3.14"
full-os-matrix:
description: Run full 3-OS matrix or Ubuntu-only
type: boolean
default: true
run-package-check:
description: Run the packaging gate
type: boolean
default: true

permissions:
contents: read

jobs:
lint:
strategy:
fail-fast: false
matrix:
os: ${{ fromJSON(inputs.full-os-matrix && '["ubuntu-latest","windows-latest","macos-latest"]' || '["ubuntu-latest"]') }}
python: ["${{ inputs.python-min }}", "${{ inputs.python-max }}"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.1.0
with:
python-version: ${{ matrix.python }}
- name: Install uv when uv.lock is present
if: ${{ hashFiles('uv.lock') != '' }}
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- name: Setup environment
shell: bash
if: runner.os != 'Windows'
run: bash scripts/setup.sh
- name: Setup environment (Windows)
shell: pwsh
if: runner.os == 'Windows'
run: .\scripts\setup.ps1
- name: Activate venv
shell: bash
if: runner.os != 'Windows'
run: echo "${{ github.workspace }}/.venv/bin" >> "$GITHUB_PATH"
- name: Activate venv (Windows)
shell: pwsh
if: runner.os == 'Windows'
run: echo "${{ github.workspace }}\.venv\Scripts" | Out-File -FilePath $env:GITHUB_PATH -Append
- name: Run lint check
run: python scripts/check_lint.py

types:
strategy:
fail-fast: false
matrix:
os: ${{ fromJSON(inputs.full-os-matrix && '["ubuntu-latest","windows-latest","macos-latest"]' || '["ubuntu-latest"]') }}
python: ["${{ inputs.python-min }}", "${{ inputs.python-max }}"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.1.0
with:
python-version: ${{ matrix.python }}
- name: Install uv when uv.lock is present
if: ${{ hashFiles('uv.lock') != '' }}
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- name: Setup environment
shell: bash
if: runner.os != 'Windows'
run: bash scripts/setup.sh
- name: Setup environment (Windows)
shell: pwsh
if: runner.os == 'Windows'
run: .\scripts\setup.ps1
- name: Activate venv
shell: bash
if: runner.os != 'Windows'
run: echo "${{ github.workspace }}/.venv/bin" >> "$GITHUB_PATH"
- name: Activate venv (Windows)
shell: pwsh
if: runner.os == 'Windows'
run: echo "${{ github.workspace }}\.venv\Scripts" | Out-File -FilePath $env:GITHUB_PATH -Append
- name: Run type check
run: python scripts/check_types.py

tests:
strategy:
fail-fast: false
matrix:
os: ${{ fromJSON(inputs.full-os-matrix && '["ubuntu-latest","windows-latest","macos-latest"]' || '["ubuntu-latest"]') }}
python: ["${{ inputs.python-min }}", "${{ inputs.python-max }}"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.1.0
with:
python-version: ${{ matrix.python }}
- name: Install uv when uv.lock is present
if: ${{ hashFiles('uv.lock') != '' }}
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- name: Setup environment
shell: bash
if: runner.os != 'Windows'
run: bash scripts/setup.sh
- name: Setup environment (Windows)
shell: pwsh
if: runner.os == 'Windows'
run: .\scripts\setup.ps1
- name: Activate venv
shell: bash
if: runner.os != 'Windows'
run: echo "${{ github.workspace }}/.venv/bin" >> "$GITHUB_PATH"
- name: Activate venv (Windows)
shell: pwsh
if: runner.os == 'Windows'
run: echo "${{ github.workspace }}\.venv\Scripts" | Out-File -FilePath $env:GITHUB_PATH -Append
- name: Run tests
run: python scripts/check_tests.py

security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.1.0
with:
python-version: ${{ inputs.python-min }}
- name: Install uv when uv.lock is present
if: ${{ hashFiles('uv.lock') != '' }}
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- name: Setup environment
shell: bash
run: bash scripts/setup.sh
- name: Activate venv
shell: bash
run: echo "${{ github.workspace }}/.venv/bin" >> "$GITHUB_PATH"
- name: Run security check
run: python scripts/check_security.py

spelling:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.1.0
with:
python-version: ${{ inputs.python-min }}
- name: Install uv when uv.lock is present
if: ${{ hashFiles('uv.lock') != '' }}
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- name: Setup environment
shell: bash
run: bash scripts/setup.sh
- name: Activate venv
shell: bash
run: echo "${{ github.workspace }}/.venv/bin" >> "$GITHUB_PATH"
- name: Run spelling check
run: python scripts/check_spelling.py

package:
if: inputs.run-package-check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.1.0
with:
python-version: ${{ inputs.python-min }}
- name: Install uv when uv.lock is present
if: ${{ hashFiles('uv.lock') != '' }}
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- name: Setup environment
shell: bash
run: bash scripts/setup.sh
- name: Activate venv
shell: bash
run: echo "${{ github.workspace }}/.venv/bin" >> "$GITHUB_PATH"
- name: Run package check
run: python scripts/check_package.py

ci-passed:
if: always()
needs: [lint, types, tests, security, spelling, package]
runs-on: ubuntu-latest
steps:
- name: Verify all checks passed
shell: bash
run: |
echo "Lint: ${{ needs.lint.result }}"
echo "Types: ${{ needs.types.result }}"
echo "Tests: ${{ needs.tests.result }}"
echo "Security: ${{ needs.security.result }}"
echo "Spelling: ${{ needs.spelling.result }}"
echo "Package: ${{ needs.package.result }}"

if [[ "${{ needs.lint.result }}" != "success" ]] || \
[[ "${{ needs.types.result }}" != "success" ]] || \
[[ "${{ needs.tests.result }}" != "success" ]] || \
[[ "${{ needs.security.result }}" != "success" ]] || \
[[ "${{ needs.spelling.result }}" != "success" ]] || \
[[ "${{ needs.package.result }}" != "success" && "${{ needs.package.result }}" != "skipped" ]]; then
echo "::error::One or more quality checks failed"
exit 1
fi
echo "All quality checks passed"
Loading
Loading