enprot 0.5.13

Engyon Protected Text (EPT) — confidentiality processor and capability ledger
name: bindings

on:
  push:
    branches: [main]
    paths:
      - "bindings/**"
      - "tools/**"
      - "hooks/**"
      - "include/enprot.h"
      - "src/ffi.rs"
      - "enprot-ffi/**"
      - ".github/workflows/bindings.yml"
  pull_request:
    paths:
      - "bindings/**"
      - "tools/**"
      - "hooks/**"
      - "include/enprot.h"
      - "src/ffi.rs"
      - "enprot-ffi/**"
      - ".github/workflows/bindings.yml"
  workflow_dispatch:

jobs:
  python:
    name: pyenprot (${{ matrix.os }} / Python ${{ matrix.python }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]
        python: ["3.9", "3.12"]
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - name: Install Botan + librnp (linux)
        if: runner.os == 'Linux'
        env:
          BOTAN_VERSION: "3.7.0"
          PREFIX: /usr
        run: ./ci/install.sh

      - name: Install Botan + librnp (macos)
        if: runner.os == 'macOS'
        run: |
          brew install botan rnp
          brew link --overwrite rnp || true

      - name: Build libenprot
        env:
          PKG_CONFIG_PATH: ${{ runner.os == 'Linux' && '/usr/lib/pkgconfig' || '' }}
        shell: bash
        run: cargo build --release --lib

      - name: Locate libenprot
        id: lib
        shell: bash
        run: |
          if [ "$RUNNER_OS" = "macOS" ]; then
            lib="$(pwd)/target/release/libenprot.dylib"
          else
            lib="$(pwd)/target/release/libenprot.so"
          fi
          echo "path=$lib" >> "$GITHUB_OUTPUT"

      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python }}

      - name: Install pytest + pyenprot
        working-directory: bindings/python
        run: |
          python -m pip install --upgrade pip
          python -m pip install pytest
          python -m pip install -e .

      - name: Run pytest
        working-directory: bindings/python
        env:
          ENPROT_LIB: ${{ steps.lib.outputs.path }}
          DYLD_LIBRARY_PATH: ${{ runner.os == 'macOS' && '/usr/local/lib:/opt/homebrew/lib' || '' }}
        run: python -m pytest tests/ -v

  nodejs:
    name: enprot-nodejs (${{ matrix.os }} / Node ${{ matrix.node }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]
        node: [18, 20, 22]
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - name: Install Botan + librnp (linux)
        if: runner.os == 'Linux'
        env:
          BOTAN_VERSION: "3.7.0"
          PREFIX: /usr
        run: ./ci/install.sh

      - name: Install Botan + librnp (macos)
        if: runner.os == 'macOS'
        run: |
          brew install botan rnp
          brew link --overwrite rnp || true

      - name: Build libenprot
        env:
          PKG_CONFIG_PATH: ${{ runner.os == 'Linux' && '/usr/lib/pkgconfig' || '' }}
        shell: bash
        run: cargo build --release --lib

      - name: Locate libenprot
        id: lib
        shell: bash
        run: |
          if [ "$RUNNER_OS" = "macOS" ]; then
            lib="$(pwd)/target/release/libenprot.dylib"
          else
            lib="$(pwd)/target/release/libenprot.so"
          fi
          echo "path=$lib" >> "$GITHUB_OUTPUT"

      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}

      - name: Install deps
        working-directory: bindings/nodejs
        run: npm install

      - name: Run tests
        working-directory: bindings/nodejs
        env:
          ENPROT_LIB: ${{ steps.lib.outputs.path }}
          DYLD_LIBRARY_PATH: ${{ runner.os == 'macOS' && '/usr/local/lib:/opt/homebrew/lib' || '' }}
        run: node --test test/test_bindings.js

  tools:
    name: SOPS importer + pre-commit hook
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install pytest + PyYAML
        run: python -m pip install pytest pyyaml

      - name: Run SOPS importer tests
        run: python -m pytest tools/test_import_sops.py -v

      - name: Run hook on samples (expect failure)
        run: |
          set +e
          out=$(python3 hooks/pre-commit/enprot_pre_commit.py sample/simple.ept sample/test.ept 2>&1)
          rc=$?
          echo "$out"
          if [ $rc -ne 1 ]; then
            echo "EXPECTED rc=1 (plaintext detected), got $rc"
            exit 1
          fi

      - name: Run hook on clean file (expect success)
        run: |
          mkdir -p /tmp/hooktest
          cat > /tmp/hooktest/clean.ept <<'EOF'
          hello
          # <( ENCRYPTED SECRET )>
          # <( DATA abc123 )>
          # <( END SECRET )>
          EOF
          python3 hooks/pre-commit/enprot_pre_commit.py /tmp/hooktest/clean.ept