Files
MsgCenterPy/.github/workflows/ci.yml
2025-11-25 13:21:55 +08:00

204 lines
5.8 KiB
YAML

# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Python package
on:
push:
branches: ["main", "dev"]
pull_request:
branches: ["main", "dev"]
jobs:
# Step 1: Code formatting and pre-commit validation (fast failure)
code-format:
name: Code formatting and pre-commit validation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.10" # Use minimum version for consistency
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .[dev]
- name: Run pre-commit hooks
uses: pre-commit/action@v3.0.1
with:
extra_args: --all-files
# Step 2: Basic build and test with minimum Python version (3.10)
basic-build:
name: Basic build (Python 3.10, Ubuntu)
runs-on: ubuntu-latest
needs: [code-format] # Only run after code formatting passes
steps:
- uses: actions/checkout@v6
- name: Set up Python 3.10
uses: actions/setup-python@v6
with:
python-version: "3.10"
- name: Cache pip dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ubuntu-pip-3.10-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
ubuntu-pip-3.10-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install pytest
pip install -e .[dev]
- name: Test with pytest
run: |
pytest -v
# Step 3: ROS2 integration test
test-with-ros2:
name: ROS2 integration test
runs-on: ubuntu-latest
needs: [basic-build] # Only run after basic build passes
steps:
- uses: actions/checkout@v6
- name: Setup Miniconda
uses: conda-incubator/setup-miniconda@v3
with:
miniconda-version: "latest"
channels: conda-forge,robostack-staging,defaults
channel-priority: strict
activate-environment: ros2-test-env
python-version: "3.11.11"
auto-activate-base: false
auto-update-conda: false
show-channel-urls: true
- name: Install ROS2 and dependencies
shell: bash -l {0}
run: |
# Install ROS2 core packages
conda install -y \
ros-humble-ros-core \
ros-humble-std-msgs \
ros-humble-geometry-msgs
- name: Install package and run tests
shell: bash -l {0}
run: |
# Install our package with basic dependencies (not ros2 extra to avoid conflicts)
pip install -e .[dev]
# Run all tests with verbose output (ROS2 tests will be automatically included)
python -c "import rclpy, rosidl_runtime_py; print('All ROS2 dependencies available')"
pytest -v
# Step 4: Security scan
security:
name: Security scan
runs-on: ubuntu-latest
needs: [basic-build] # Run in parallel with ROS2 test after basic build
steps:
- uses: actions/checkout@v6
- name: Run Safety CLI to check for vulnerabilities
uses: pyupio/safety-action@v1
with:
api-key: ${{ secrets.SAFETY_CHECK }}
output-format: json
args: --detailed-output --output-format json
- name: Upload security reports
uses: actions/upload-artifact@v5
with:
name: security-reports
path: |
safety-report.json
if: always()
# Step 5: Package build check
package-build:
name: Package build check
runs-on: ubuntu-latest
needs: [basic-build] # Run in parallel with other checks
steps:
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.10" # Use minimum version for consistency
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build package
run: python -m build
- name: Check package
run: twine check dist/*
- name: Upload build artifacts
uses: actions/upload-artifact@v5
with:
name: dist
path: dist/
# Step 6: Full matrix build (only after all basic checks pass)
full-matrix-build:
name: Test Python ${{ matrix.python-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
needs: [test-with-ros2, security, package-build] # Wait for all prerequisite checks
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.10", "3.11", "3.12", "3.13"]
exclude:
# Skip the combination we already tested in basic-build
- os: ubuntu-latest
python-version: "3.10"
steps:
- uses: actions/checkout@v6
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-${{ matrix.python-version }}-
${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install pytest
pip install -e .[dev]
- name: Test with pytest
run: |
pytest