Support bounded digital I/O for named signal skills #170
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: tests | |
| on: | |
| workflow_dispatch: | |
| # Scope push to main only — PR branches are covered by pull_request, so this | |
| # avoids a redundant second run (and the "re-ran one, the twin still red" trap) | |
| # on every push to a PR branch. | |
| push: | |
| branches: [main] | |
| pull_request: | |
| jobs: | |
| lint: | |
| name: Lint (pre-commit) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install dependencies | |
| shell: bash | |
| run: | | |
| python -m pip install --upgrade pip | |
| # ruckig 0.17.3 sdist doesn't build under scikit-build-core 1.0; | |
| # pre-install the fixed commit until a release lands (pantor/ruckig#262). | |
| pip install "ruckig @ git+https://github.com/pantor/ruckig@2249d57ffaa19ecdadeaab62daf97857813629ff" | |
| # Resolve the shared contract branch before the package: the new | |
| # release tag is created only after its companion PR merges. | |
| BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}" | |
| if [ "$BRANCH" != "main" ] && git ls-remote --heads https://github.com/Jepson2k/waldoctl.git "$BRANCH" 2>/dev/null | grep -q .; then | |
| sed -i.bak "s#waldoctl.git@v[0-9.]*#waldoctl.git@${BRANCH}#" pyproject.toml | |
| fi | |
| pip install -e ".[dev]" | |
| if [ -f pyproject.toml.bak ]; then | |
| mv pyproject.toml.bak pyproject.toml | |
| fi | |
| - name: Run pre-commit | |
| uses: pre-commit/action@v3.0.1 | |
| test: | |
| name: ${{ matrix.os }} / Python ${{ matrix.python-version }} | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, windows-latest, macos-latest] | |
| python-version: ['3.11', '3.12', '3.13', '3.14'] | |
| defaults: | |
| run: | |
| shell: bash -l {0} | |
| steps: | |
| - name: Checkout repository (with submodules) | |
| uses: actions/checkout@v4 | |
| - name: Detect matching pinokin branch | |
| id: pinokin | |
| shell: bash | |
| run: | | |
| BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}" | |
| if git ls-remote --heads https://github.com/Jepson2k/pinokin.git "$BRANCH" 2>/dev/null | grep -q .; then | |
| echo "matching=true" >> "$GITHUB_OUTPUT" | |
| echo "branch=$BRANCH" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "matching=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| # ---------------------------------------------------------------------- | |
| # Path A: matching pinokin branch -> conda env (provides libpinocchio + | |
| # libcoal headers/libs) so pinokin can be built from source. We install | |
| # PAROL6 first (which pulls in the pinned pinokin v0.1.6 wheel) and | |
| # then override pinokin with the source-built wheel from the matching | |
| # branch. This is the only way to exercise unreleased pinokin features | |
| # before a release lands. | |
| # ---------------------------------------------------------------------- | |
| - name: Setup Miniforge (matching pinokin branch) | |
| if: steps.pinokin.outputs.matching == 'true' | |
| uses: conda-incubator/setup-miniconda@v3 | |
| with: | |
| miniforge-version: latest | |
| python-version: ${{ matrix.python-version }} | |
| conda-remove-defaults: true | |
| activate-environment: parol6-test | |
| - name: Clone matching pinokin branch | |
| if: steps.pinokin.outputs.matching == 'true' | |
| run: | | |
| git clone --depth=1 --branch="${{ steps.pinokin.outputs.branch }}" https://github.com/Jepson2k/pinokin.git pinokin-src | |
| conda env update -n parol6-test -f pinokin-src/environment.yml | |
| # ---------------------------------------------------------------------- | |
| # Path B: no matching pinokin branch -> plain pip with the pinned | |
| # release wheel. Anything in PAROL6 that requires a newer pinokin | |
| # feature will fail loudly here (intended). | |
| # ---------------------------------------------------------------------- | |
| - name: Setup Python (pinned pinokin) | |
| if: steps.pinokin.outputs.matching != 'true' | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| cache: pip | |
| cache-dependency-path: pyproject.toml | |
| - name: Install package | |
| run: | | |
| python -m pip install --upgrade pip | |
| # ruckig 0.17.3 sdist doesn't build under scikit-build-core 1.0; | |
| # pre-install the fixed commit until a release lands (pantor/ruckig#262). | |
| pip install "ruckig @ git+https://github.com/pantor/ruckig@2249d57ffaa19ecdadeaab62daf97857813629ff" | |
| # Resolve the shared contract branch before the package: the new | |
| # release tag is created only after its companion PR merges. | |
| BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}" | |
| if [ "$BRANCH" != "main" ] && git ls-remote --heads https://github.com/Jepson2k/waldoctl.git "$BRANCH" 2>/dev/null | grep -q .; then | |
| sed -i.bak "s#waldoctl.git@v[0-9.]*#waldoctl.git@${BRANCH}#" pyproject.toml | |
| fi | |
| pip install -e ".[dev]" pytest-timeout | |
| if [ -f pyproject.toml.bak ]; then | |
| mv pyproject.toml.bak pyproject.toml | |
| fi | |
| # Override the pinned pinokin v0.1.6 wheel with the matching-branch | |
| # source build. --force-reinstall + --no-deps swaps just pinokin | |
| # without disturbing other resolved dependencies. | |
| - name: Override pinokin with matching-branch source build | |
| if: steps.pinokin.outputs.matching == 'true' | |
| run: | | |
| cd pinokin-src | |
| pip install . --no-build-isolation --force-reinstall --no-deps | |
| python -c "from pinokin import CollisionChecker; print('CollisionChecker available')" | |
| - name: Show environment | |
| run: | | |
| python -V | |
| pip list | |
| - name: Run tests | |
| env: | |
| PYTHONUNBUFFERED: '1' | |
| PYTHONUTF8: '1' | |
| run: | | |
| pytest | |
| # The examples are the scripts a user copies, and `--examples` is opt-in, | |
| # so nothing was running them: four had rotted into refusals on their | |
| # own happy path. They run each script as a subprocess against the | |
| # simulator, so they belong after the suite rather than inside it. | |
| - name: Run examples | |
| env: | |
| PYTHONUNBUFFERED: '1' | |
| PYTHONUTF8: '1' | |
| run: pytest tests/test_examples.py --examples |