Skip to content

build: use cibuildwheels for PyPi compatible packages #120

build: use cibuildwheels for PyPi compatible packages

build: use cibuildwheels for PyPi compatible packages #120

# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: Build and Test
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
jobs:
build:
# Use larger machine with more disk space
runs-on: ubuntu-24.04-32core
strategy:
matrix:
python-version: ["3.10"]
env:
PYTHON_FAIL_UNDER: 90
CPP_FAIL_UNDER: 80
permissions:
contents: read # Required for actions/checkout
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # ratchet:actions/checkout@v6
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # ratchet:actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- run: df -h
- name: Install dependencies
run: |
python -m pip install --upgrade pip
# Clean up apt cache to save space
sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/*
df -h
# Install python dependencies (with coverage enabled)
echo -e "\n##### Running pip install #####"
pip install -e '.[dev]' --config-settings=cmake.args="-DENABLE_COVERAGE=ON"
- run: df -h
- name: Test with pytest with coverage enabled
run: |
# Run all tests with coverage (Python and C++)
echo -e "\n##### Running Python tests with coverage #####"
coverage run --source=src/ml_flashpoint --branch -m pytest -v -s
- name: Check Python test coverage
run: |
# Verify python coverage thresholds
echo -e "\n##### Generating Python coverage XML #####"
coverage xml -o python-coverage.xml
echo -e "\n##### Verifying Python coverage thresholds #####"
coverage report --fail-under=${{ env.PYTHON_FAIL_UNDER }}
- name: Python Coverage Summary
uses: irongut/CodeCoverageSummary@51cc3a756ddcd398d447c044c02cb6aa83fdae95 # ratchet:irongut/CodeCoverageSummary@v1.3.0
if: always() # Run even if threshold check above fails
with:
filename: python-coverage.xml
badge: true
fail_below_min: true
format: markdown
hide_branch_rate: false
hide_complexity: true
indicators: true
output: both
thresholds: '${{ env.PYTHON_FAIL_UNDER }} 95'
- name: Add Python Coverage Title
if: always()
run: |
# Only run if the summary was actually generated
if [ -f code-coverage-results.md ]; then
echo '### Python Code Coverage Summary' | cat - code-coverage-results.md > temp && mv temp python-code-coverage-results.md
fi
- name: Add Python Coverage PR Comment
uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # ratchet:marocchino/sticky-pull-request-comment@v2
if: false # TODO remove once new workflow confirmed to work
with:
recreate: true
path: python-code-coverage-results.md
- name: Check C++ test coverage
run: |
# Run C++ coverage check
echo -e "\n##### Running C++ coverage check #####"
mkdir -p htmlcov/cpp
gcovr --root=. \
--filter=src/ml_flashpoint \
--exclude=".*/_deps/.*" \
--exclude="/tmp/.*" \
--exclude=".*pybind11.*" \
--gcov-ignore-errors=source_not_found \
--gcov-executable=gcov \
--txt-metric branch \
--html-details htmlcov/cpp/index.html \
--xml-pretty -o cxx-coverage.xml \
--sort uncovered-number \
--gcov-ignore-parse-errors negative_hits.warn \
--gcov-ignore-parse-errors suspicious_hits.warn \
--gcov-ignore-errors=no_working_dir_found \
--fail-under-line=${{ env.CPP_FAIL_UNDER }}
- name: C++ Coverage Summary
uses: irongut/CodeCoverageSummary@51cc3a756ddcd398d447c044c02cb6aa83fdae95 # ratchet:irongut/CodeCoverageSummary@v1.3.0
if: always() # Run even if threshold check above fails
with:
filename: cxx-coverage.xml
badge: true
fail_below_min: true
format: markdown
hide_branch_rate: false
hide_complexity: true
indicators: true
output: both
thresholds: '${{ env.CPP_FAIL_UNDER }} 40'
- name: Add C++ Coverage Title
if: always()
run: |
if [ -f code-coverage-results.md ]; then
echo '### C++ Code Coverage Summary' | cat - code-coverage-results.md > temp && mv temp cpp-code-coverage-results.md
fi
- name: Add C++ Coverage PR Comment
uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # ratchet:marocchino/sticky-pull-request-comment@v2
if: false # TODO: remove when new workflow confirmed to work
with:
header: cpp-coverage
recreate: true
path: cpp-code-coverage-results.md
- name: Save PR number
# Use always() so this runs even if previous coverage/test steps failed.
if: always() && github.event_name == 'pull_request'
run: |
echo ${{ github.event.number }} > pr_number.txt
- name: Archive coverage reports
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: always()
with:
name: coverage-reports
if-no-files-found: warn # Default, but setting explicitly for awareness as non-PRs won't have pr_number.txt
path: |
htmlcov/
python-coverage.xml
cxx-coverage.xml
python-code-coverage-results.md
cpp-code-coverage-results.md
pr_number.txt
lint-code:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # ratchet:actions/checkout@v6
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # ratchet:actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Lint with ruff
run: |
pip install ruff==0.12.11
ruff check .
ruff format --check .
- name: Lint with clang-format
run: |
# Install and run C++ linter
echo -e "\n##### Installing and running clang-format linter #####"
sudo apt-get update && sudo apt-get install -y clang-format-18
clang-format-18 --version
find src -name '*.cpp' -o -name '*.h' | xargs clang-format-18 --dry-run --Werror
lint-license:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Code'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # ratchet:actions/checkout@v6
- name: 'Set up Go'
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # ratchet:actions/setup-go@v6
with:
go-version: '1.24'
cache: true
- name: 'Validate License Headers'
shell: 'bash'
run: |
go run github.com/google/addlicense@v1.1.1 -check -s=only .