klvmr 0.3.2

Implementation of `klvm` for Chik Network's cryptocurrency
Documentation
name: Build Mac, Linux, and Windows wheels

on:
  push:
    branches:
      #- main
      - dev
    tags:
        - '**'
  pull_request:
    branches:
      - '**'

permissions:
  contents: read
  id-token: write

jobs:
  build_wheels:
    name: Wheel on ${{ matrix.os }} py-${{ matrix.python }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [macos-latest, ubuntu-latest, windows-latest]
        python: [3.7]

    steps:
    - uses: actions/checkout@v3
      with:
        fetch-depth: 0

    - uses: chik-network/actions/setup-python@main
      name: Install Python ${{ matrix.python }}
      with:
        python-version: ${{ matrix.python }}

    - name: Update pip
      run: |
          python -m pip install --upgrade pip

    - name: Set up rust
      uses: actions-rs/toolchain@v1
      with:
        toolchain: stable

    - name: Install dependencies
      run: |
          python -m pip install maturin

    - name: Build MacOs with maturin on Python ${{ matrix.python }}
      if: startsWith(matrix.os, 'macos')
      env:
        MACOSX_DEPLOYMENT_TARGET: '10.14'
      run: |
        python -m venv venv
        ln -s venv/bin/activate
        . ./activate
        maturin build -m wheel/Cargo.toml --sdist -i python --release --strip --features=openssl

    - name: Build Linux in manylinux2014 with maturin on Python ${{ matrix.python }}
      if: startsWith(matrix.os, 'ubuntu')
      run: |
        docker run --rm \
          -v ${{ github.workspace }}:/ws --workdir=/ws \
          quay.io/pypa/manylinux2014_x86_64 \
          bash -exc '\
            curl -L https://sh.rustup.rs > rustup-init.sh && \
            sh rustup-init.sh -y && \
            yum -y --disablerepo=epel install openssl-devel && \
            source $HOME/.cargo/env && \
            rustup target add x86_64-unknown-linux-musl && \
            PY_VERSION=${{ matrix.python }}
            PY_VERSION=${PY_VERSION/.} && \
            echo "Python version with dot removed is $PY_VERSION" && \
            if [ "$PY_VERSION" = "37" ]; \
            then export SCND_VERSION="${PY_VERSION}m"; \
            else export SCND_VERSION="$PY_VERSION"; fi && \
            echo "Exporting path /opt/python/cp$PY_VERSION-cp$SCND_VERSION/bin" && \
            export PATH=/opt/python/cp$PY_VERSION-cp$SCND_VERSION/bin/:$PATH && \
            /opt/python/cp38-cp38/bin/python -m venv /venv && \
            . /venv/bin/activate && \
            pip install --upgrade pip && \
            pip install maturin && \
            CC=gcc maturin build -m wheel/Cargo.toml --release --strip --manylinux 2014 --features=openssl \
          '
        python -m venv venv
        ln -s venv/bin/activate

    - name: Build Windows with maturin on Python ${{ matrix.python }}
      if: startsWith(matrix.os, 'windows')
      run: |
        python -m venv venv
        . .\venv\Scripts\Activate.ps1
        ln -s venv\Scripts\Activate.ps1 activate
        maturin build -m wheel/Cargo.toml -i python --release --strip
        # this will install into the venv
        # it'd be better to use the wheel, but I can't figure out how to do that
        # TODO: figure this out
        # this does NOT work: pip install target/wheels/klvm_rs-*.whl
        maturin develop --release -m wheel/Cargo.toml
        # the line above also doesn't seem to work

    - name: Install klvm_rs wheel
      if: ${{ !startsWith(matrix.os, 'windows') }}
      run: |
        . ./activate
        ls target/wheels/
        # this mess puts the name of the `.whl` file into `$WHEEL_PATH`
        # remove the dot, use the `glob` lib to grab the file from the directory
        WHEEL_PATH=$(echo ${{ matrix.python }} | python -c 'DOTLESS=input().replace(".", ""); import glob; print(" ".join(glob.glob("target/wheels/klvm_rs-*-cp%s-abi3-*.whl" % DOTLESS)))' )
        echo ${WHEEL_PATH}
        pip install ${WHEEL_PATH}

    - name: Install other wheels
      run: |
        . ./activate
        python -m pip install pytest
        python -m pip install blspy

    - name: Run tests from wheel
      run: |
        . ./activate
        cd wheel/python
        pytest --import-mode append tests
        # we use `append` because otherwise the `klvm_rs` source is added
        # to `sys.path` and it uses that instead of the wheel (and so
        # ignoring `klvm_rs.so`, which is pretty important)

    - name: Upload artifacts
      uses: actions/upload-artifact@v3
      with:
        name: wheels
        path: ./target/wheels/

  upload:
    name: Upload to PyPI
    runs-on: ubuntu-latest
    needs: build_wheels
    steps:
    - name: Checkout code
      uses: actions/checkout@v3
      with:
        fetch-depth: 0

    - name: Install python
      uses: Chik-Network/actions/setup-python@main
      with:
        python-version: "3.10"

    - name: Download artifacts
      uses: actions/download-artifact@v3
      with:
        name: wheels
        path: ./target/wheels/

    - name: publish (PyPi)
      if: startsWith(github.event.ref, 'refs/tags')
      uses: pypa/gh-action-pypi-publish@release/v1
      with:
        packages-dir: target/wheels/
        skip-existing: true

  checks:
    runs-on: ubuntu-20.04
    name: Checks
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 1
      - name: Install rust
        uses: actions-rs/toolchain@v1
        with:
            toolchain: stable
            override: true
            components: rustfmt, clippy
      - name: Clippy
        run: cargo clippy --all-targets --workspace -- -D warnings
      - name: fmt
        run: cargo fmt --all -- --files-with-diff --check

  # leaving out Windows fuzzing for now though it seems supported
  # https://llvm.org/docs/LibFuzzer.html#q-does-libfuzzer-support-windows
  fuzz_targets:
    name: Run fuzz targets
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [macos-latest, ubuntu-latest]
        python: [3.7]
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 1
      - name: Install rust
        uses: actions-rs/toolchain@v1
        with:
            toolchain: nightly
            override: true
            components: rustfmt, clippy
      - name: fmt
        run: |
          cd fuzz
          cargo fmt -- --files-with-diff --check
      - name: clippy
        run: |
          cd fuzz
          cargo clippy
      - name: cargo-fuzz
        run: cargo +nightly install cargo-fuzz
      # TODO: it would be nice to save and restore the corpus between runs
      - name: build corpus
        run: |
          cd tools
          cargo run --bin generate-fuzz-corpus
      - name: build
        run: cargo fuzz list | xargs -I "%" sh -c "cargo +nightly fuzz run % -- -max_total_time=30 || exit 255"

  unit_tests:
    name: Unit tests
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [macos-latest, ubuntu-latest, windows-latest]
        python: [3.7]
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 1
      - name: Install rust
        uses: actions-rs/toolchain@v1
        with:
            toolchain: stable
            components: rustfmt, clippy

      - name: build
        run: cargo build --workspace --exclude klvm_rs-fuzz

      - name: cargo test (default)
        run: cargo test && cargo test --release

      - name: cargo test (counters)
        run: cargo test --features=counters && cargo test --features=counters --release

      - name: cargo test (pre-eval)
        run: cargo test --features=pre-eval && cargo test --features=pre-eval --release

      - name: cargo test (pre-eval and counters)
        run: cargo test --features=pre-eval,counters && cargo test --features=pre-eval,counters --release

  coverage:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions-rs/toolchain@v1
        with:
            toolchain: stable
      - name: Run for coverage
        run: |
          sudo apt-get update
          sudo apt-get install lcov -y
          rustup component add llvm-tools-preview
          export CARGOFLAGS="-j $(nproc)"
          cargo install grcov
          export RUSTFLAGS="-Cinstrument-coverage"
          export LLVM_PROFILE_FILE=$(pwd)/target/klvm_rs-%p-%m.profraw
          export CARGO_TARGET_DIR=$(pwd)/target
          export RUST_TEST_THREADS=$(nproc)
          cargo test --release --workspace
          python -m venv venv
          source venv/bin/activate
          pip install colorama maturin pytest pytest-cov
          maturin develop --release -m wheel/Cargo.toml --features=openssl
          (cd tests && python generate-programs.py && python run-programs.py) || true
          pytest wheel/python/tests --cov=klvm_rs --cov-report lcov:py_cov.info --cov-branch
          grcov . --binary-path target -s . --branch --ignore-not-existing --ignore='*/.cargo/*' --ignore='target/*' -o pre_rust_cov.info
          python -c 'with open("pre_rust_cov.info") as f: lines = [l for l in f if not (l.startswith("DA:") and int(l.split(",")[1].strip()) >= 2**63)]; open("rust_cov.info", "w").writelines(lines)'
          lcov --add-tracefile rust_cov.info -a py_cov.info -o lcov.info
      - name: Upload to Coveralls
        uses: coverallsapp/github-action@v2
        if: always()
        env:
          COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
        with:
          path-to-lcov: './lcov.info'