0.1.3 #12
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This workflow will upload a Python Package to PyPI when a release is created | |
| # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries | |
| # This workflow uses actions that are not certified by GitHub. | |
| # They are provided by a third-party and are governed by | |
| # separate terms of service, privacy policy, and support | |
| # documentation. | |
| name: Upload PyPI package | |
| on: | |
| release: | |
| types: [published, edited] | |
| workflow_dispatch: | |
| inputs: | |
| test_pypi: | |
| description: "Publish to Test PyPI instead of PyPI" | |
| required: false | |
| default: false | |
| type: boolean | |
| permissions: | |
| contents: read | |
| 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@v5 | |
| - 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@v5 | |
| - 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@v5 | |
| - 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@v5 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.10" # Use minimum version for consistency | |
| - name: Install security tools | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install "safety>=3.0.0" "typer<0.12.0" "marshmallow<4.0.0" | |
| - name: Run safety security scan | |
| run: safety check --output json > safety-report.json | |
| - name: Upload security reports | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: security-reports | |
| path: | | |
| safety-report.json | |
| if: always() | |
| release-build: | |
| name: Build release distributions | |
| runs-on: ubuntu-latest | |
| needs: [test-with-ros2] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - 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 | |
| python -m pip install build twine | |
| - name: Verify version consistency | |
| if: github.event_name == 'release' && (github.event.action == 'published' || (github.event.action == 'edited' && !github.event.release.prerelease)) | |
| run: | | |
| # Install package first | |
| pip install -e . | |
| # Get package version (fail fast if not available) | |
| VERSION=$(python -c "import msgcenterpy; print(msgcenterpy.__version__)") | |
| # Handle both v0.0.3 and 0.0.3 tag formats | |
| RAW_TAG="${GITHUB_REF#refs/tags/}" | |
| if [[ "$RAW_TAG" == v* ]]; then | |
| TAG_VERSION="${RAW_TAG#v}" | |
| else | |
| TAG_VERSION="$RAW_TAG" | |
| fi | |
| echo "Package version: $VERSION" | |
| echo "Tag version: $TAG_VERSION" | |
| if [ "$VERSION" != "$TAG_VERSION" ]; then | |
| echo "❌ Version mismatch: package=$VERSION, tag=$TAG_VERSION" | |
| echo "Please ensure the package version matches the git tag" | |
| exit 1 | |
| fi | |
| echo "✅ Version verification passed: $VERSION" | |
| - name: Build release distributions | |
| run: | | |
| python -m build | |
| - name: Check package | |
| run: | | |
| twine check dist/* | |
| - name: Upload distributions | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-dists | |
| path: dist/ | |
| pypi-publish: | |
| name: Publish to PyPI | |
| runs-on: ubuntu-latest | |
| needs: | |
| - release-build | |
| if: github.event_name == 'release' && !github.event.release.prerelease && github.event.inputs.test_pypi != 'true' && (github.event.action == 'published' || github.event.action == 'edited') | |
| permissions: | |
| # IMPORTANT: this permission is mandatory for trusted publishing | |
| id-token: write | |
| # Note: For enhanced security, consider configuring deployment environments | |
| # in your GitHub repository settings with protection rules | |
| steps: | |
| - name: Retrieve release distributions | |
| uses: actions/download-artifact@v5 | |
| with: | |
| name: release-dists | |
| path: dist/ | |
| - name: Publish release distributions to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| test-pypi-publish: | |
| name: Publish to Test PyPI | |
| runs-on: ubuntu-latest | |
| needs: | |
| - release-build | |
| if: github.event.inputs.test_pypi == 'true' || (github.event_name == 'release' && github.event.release.prerelease && (github.event.action == 'published' || github.event.action == 'edited')) | |
| permissions: | |
| # IMPORTANT: this permission is mandatory for trusted publishing | |
| id-token: write | |
| # Note: For enhanced security, consider configuring deployment environments | |
| # in your GitHub repository settings with protection rules | |
| steps: | |
| - name: Retrieve release distributions | |
| uses: actions/download-artifact@v5 | |
| with: | |
| name: release-dists | |
| path: dist/ | |
| - name: Publish release distributions to Test PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| repository-url: https://test.pypi.org/legacy/ | |
| create-github-release-assets: | |
| name: Add assets to GitHub release | |
| runs-on: ubuntu-latest | |
| needs: release-build | |
| if: github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'edited') | |
| permissions: | |
| contents: write # Need write access to upload release assets | |
| steps: | |
| - name: Retrieve release distributions | |
| uses: actions/download-artifact@v5 | |
| with: | |
| name: release-dists | |
| path: dist/ | |
| - name: Upload release assets | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: dist/* | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| post-publish: | |
| name: Post-publish tasks | |
| runs-on: ubuntu-latest | |
| needs: [pypi-publish, test-pypi-publish] | |
| if: always() && (needs.pypi-publish.result == 'success' || needs.test-pypi-publish.result == 'success') | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Create deployment summary | |
| run: | | |
| echo "## Deployment Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "| Item | Status |" >> $GITHUB_STEP_SUMMARY | |
| echo "|------|--------|" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ needs.pypi-publish.result }}" = "success" ]; then | |
| echo "| PyPI | Published |" >> $GITHUB_STEP_SUMMARY | |
| elif [ "${{ needs.test-pypi-publish.result }}" = "success" ]; then | |
| echo "| Test PyPI | Published |" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "| GitHub Release | Assets uploaded |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Version | ${{ github.event.release.tag_name || 'test' }} |" >> $GITHUB_STEP_SUMMARY |