From feac17d5b4bb9b015fd1064d56f6e861ca61bdb3 Mon Sep 17 00:00:00 2001 From: julianadrianheine Date: Thu, 2 Jul 2026 12:10:51 -0300 Subject: [PATCH 1/2] Add wheel generation and CI checks --- .github/workflows/ci.yml | 49 ++++++++++++++++++ requirements-dev.txt | 11 ++++ wheelhouse/.gitignore | 1 + wheelhouse/build_cyclonedds_wheel.sh | 77 ++++++++++++++++++++++++++++ wheelhouse/cyclonedds.README.md | 16 ++++++ 5 files changed, 154 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 requirements-dev.txt create mode 100644 wheelhouse/.gitignore create mode 100755 wheelhouse/build_cyclonedds_wheel.sh create mode 100644 wheelhouse/cyclonedds.README.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..63c10f13 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +name: CI + +on: + push: + branches: + - "releases/tri/0.10.5" + pull_request: + branches: + - "releases/tri/0.10.5" + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - python-tag: py311 + python-version: "3.11" + - python-tag: py312 + python-version: "3.12" + + name: Test (Python ${{ matrix.python-version }}) + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + # Build a manylinux wheel using cibuildwheel inside Docker. This handles + # the full from-source build of the cyclonedds C library so the runner + # does not need it installed system-wide. The resulting wheel bundles + # libddsc and can be installed like any normal Python package. + - name: Build wheel + if: steps.cache-wheel.outputs.cache-hit != 'true' + run: bash wheelhouse/build_cyclonedds_wheel.sh ${{ matrix.python-tag }} wheelhouse/ + + - name: Set up venv and install dependencies + run: | + python3 -m venv .venv + .venv/bin/pip install --quiet --upgrade pip + .venv/bin/pip install --quiet wheelhouse/cyclonedds-*.whl + .venv/bin/pip install --quiet -r requirements-dev.txt + + - name: Run tests + run: .venv/bin/python local-ci.py --no-linter diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 00000000..f40f3ac9 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,11 @@ +# Test dependencies for CI and local development. +# +# These are installed into the venv alongside the pre-built cyclonedds wheel +# (see wheelhouse/build_cyclonedds_wheel.sh and .github/workflows/ci.yml). +# They are kept here as a standalone file so that CI can install them without +# triggering a source build of the package (which requires the cyclonedds C +# library). The same packages are listed under extras_require["dev"] in +# setup.py, but that path is only usable when building from source. +pytest>=6.2 +pytest-cov +pytest-mock diff --git a/wheelhouse/.gitignore b/wheelhouse/.gitignore new file mode 100644 index 00000000..704d3075 --- /dev/null +++ b/wheelhouse/.gitignore @@ -0,0 +1 @@ +*.whl diff --git a/wheelhouse/build_cyclonedds_wheel.sh b/wheelhouse/build_cyclonedds_wheel.sh new file mode 100755 index 00000000..ac8b4054 --- /dev/null +++ b/wheelhouse/build_cyclonedds_wheel.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# Build a cyclonedds==0.10.5 manylinux wheel for a given Python version and +# copy it into this directory. +# +# Usage: +# ./build_cyclonedds_wheel.sh [output-dir] +# +# Arguments: +# python-tag : py311 or py312 +# output-dir : destination for the wheel (default: this directory) +# +# Examples: +# ./build_cyclonedds_wheel.sh py311 +# ./build_cyclonedds_wheel.sh py312 /tmp/out + +set -euo pipefail + +# Re-exec under the docker group if this session predates the docker install +# (usermod -aG docker takes effect on next login; sg avoids that requirement). +if ! id -Gn | grep -qw docker; then + exec sg docker -c "bash '$0' $*" +fi + +# Pinned cibuildwheel version and manylinux image digest for bit-for-bit +# reproducible builds. Update both together when intentionally upgrading. +CIBUILDWHEEL_VERSION="3.4.1" +MANYLINUX_IMAGE="quay.io/pypa/manylinux_2_28_x86_64@sha256:853663dc8253b62be437bb52a5caecffd020792af4442f55d927d22e0ea795ae" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" + +if [[ $# -lt 1 || $# -gt 2 ]]; then + echo "Usage: $0 [output-dir] (e.g. py311 or py312)" >&2 + exit 1 +fi + +PYTHON_TAG="$1" +OUTPUT_DIR="${2:-$SCRIPT_DIR}" +# Convert "py311" -> "cp311" +CP_TAG="cp${PYTHON_TAG#py}" +BUILD_ID="${CP_TAG}-manylinux_x86_64" + +# Fix the umask so git creates files with deterministic permissions (0644/0755) +# regardless of the caller's umask. Without this, Bazel's test runner uses a +# different umask than a regular shell, causing pip to record different Unix +# permission bits in the wheel ZIP and producing a different archive SHA. +umask 0022 + +cd "${REPO_ROOT}" + +# Freeze build timestamps to the source commit time for deterministic output. +SOURCE_DATE_EPOCH="$(git show -s --format=%ct HEAD)" +export SOURCE_DATE_EPOCH + +WORK_DIR="$(mktemp -d)" +trap 'rm -rf "$WORK_DIR"' EXIT + +echo "==> Setting up venv and installing cibuildwheel ${CIBUILDWHEEL_VERSION} ..." +python3 -m venv "${WORK_DIR}/.venv" +"${WORK_DIR}/.venv/bin/pip3" install --quiet "cibuildwheel==${CIBUILDWHEEL_VERSION}" + +echo "==> Building wheel for ${PYTHON_TAG} (${BUILD_ID}) ..." +# These variables pin the build environment (container image, dependency +# versions, timestamps) to produce a bit-for-bit reproducible wheel SHA. +# Changing or removing any of them will change the output wheel and require +# rebuilding and recommitting the wheels in this directory. +CIBW_MANYLINUX_X86_64_IMAGE="${MANYLINUX_IMAGE}" \ +CIBW_ENVIRONMENT_PASS="SOURCE_DATE_EPOCH" \ +CIBW_TEST_COMMAND="" \ +CIBW_DEPENDENCY_VERSIONS="pinned" \ +"${WORK_DIR}/.venv/bin/cibuildwheel" --output-dir "${WORK_DIR}/wheelhouse" --only "${BUILD_ID}" + +WHEEL="$(ls "${WORK_DIR}/wheelhouse"/*.whl)" +WHEEL_BASENAME="$(basename "$WHEEL")" + +echo "==> Copying ${WHEEL_BASENAME} -> ${OUTPUT_DIR}/" +cp "$WHEEL" "${OUTPUT_DIR}/" +echo "==> Done: ${OUTPUT_DIR}/${WHEEL_BASENAME}" diff --git a/wheelhouse/cyclonedds.README.md b/wheelhouse/cyclonedds.README.md new file mode 100644 index 00000000..9e429d1b --- /dev/null +++ b/wheelhouse/cyclonedds.README.md @@ -0,0 +1,16 @@ +To rebuild and commit the wheels, run the build script for each Python version +and commit the results: + +```bash +bash wheelhouse/build_cyclonedds_wheel.sh py311 wheelhouse/ +bash wheelhouse/build_cyclonedds_wheel.sh py312 wheelhouse/ +git add wheelhouse/*.whl +git commit -m "Rebuild cyclonedds wheels" +``` + +Notes: +1. The pinned version (0.10.5) matches the cyclonedds version shipped with + ROS 2 Jazzy: https://index.ros.org/p/cyclonedds/#jazzy +2. This package is a Python binding of the underlying C `cyclonedds` binary. + `cibuildwheel` bundles the necessary shared libraries into the wheel so + consumers do not need to install cyclonedds separately. From b4d64b5012d3a27ccbd0425315b6ec720531880f Mon Sep 17 00:00:00 2001 From: julianadrianheine Date: Thu, 2 Jul 2026 15:33:03 -0300 Subject: [PATCH 2/2] Remove unnecesary docker config in the script --- wheelhouse/build_cyclonedds_wheel.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/wheelhouse/build_cyclonedds_wheel.sh b/wheelhouse/build_cyclonedds_wheel.sh index ac8b4054..2642682a 100755 --- a/wheelhouse/build_cyclonedds_wheel.sh +++ b/wheelhouse/build_cyclonedds_wheel.sh @@ -15,12 +15,6 @@ set -euo pipefail -# Re-exec under the docker group if this session predates the docker install -# (usermod -aG docker takes effect on next login; sg avoids that requirement). -if ! id -Gn | grep -qw docker; then - exec sg docker -c "bash '$0' $*" -fi - # Pinned cibuildwheel version and manylinux image digest for bit-for-bit # reproducible builds. Update both together when intentionally upgrading. CIBUILDWHEEL_VERSION="3.4.1"