memsafe 0.3.2

A Secure cross-platform Rust library for securely wrapping data in memory
Documentation
name: PR Checks & Release (Crates.io & GitHub)

on:
  pull_request:
    branches:
      - main
    types:
      - opened
      - synchronize
      - reopened
      - ready_for_review
  push:
    branches:
      - main

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ ubuntu-latest, macos-latest, windows-latest ]
        arch: [ x86_64, aarch64, i686, armv7, ppc64le, riscv64 ]
        exclude:
          # Exclude Windows on non-x86 architectures
          - os: windows-latest
            arch: aarch64
          - os: windows-latest
            arch: armv7
          - os: windows-latest
            arch: ppc64le
          - os: windows-latest
            arch: riscv64
          # Exclude macOS on 32-bit and non-Apple architectures
          - os: macos-latest
            arch: i686
          - os: macos-latest
            arch: armv7
          - os: macos-latest
            arch: ppc64le
          - os: macos-latest
            arch: riscv64

        include:
          # x86_64 targets (64-bit)
          - os: ubuntu-latest
            arch: x86_64
            target: x86_64-unknown-linux-gnu
          - os: macos-latest
            arch: x86_64
            target: x86_64-apple-darwin
          - os: windows-latest
            arch: x86_64
            target: x86_64-pc-windows-msvc

          # ARM64/AArch64 targets (64-bit)
          - os: ubuntu-latest
            arch: aarch64
            target: aarch64-unknown-linux-gnu
          - os: macos-latest
            arch: aarch64
            target: aarch64-apple-darwin

          # i686 targets (32-bit x86)
          - os: ubuntu-latest
            arch: i686
            target: i686-unknown-linux-gnu
          - os: windows-latest
            arch: i686
            target: i686-pc-windows-msvc

          # ARM32/ARMv7 targets (32-bit)
          - os: ubuntu-latest
            arch: armv7
            target: armv7-unknown-linux-gnueabihf

          # PowerPC 64-bit Little Endian
          - os: ubuntu-latest
            arch: ppc64le
            target: powerpc64le-unknown-linux-gnu

          # RISC-V 64-bit
          - os: ubuntu-latest
            arch: riscv64
            target: riscv64gc-unknown-linux-gnu

      fail-fast: false
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: stable
          targets: ${{ matrix.target }}
          components: clippy

      # Cache dependencies to speed up builds
      - name: Cache cargo registry
        uses: actions/cache@v3
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ matrix.target }}-cargo-

      # Install cross for more efficient cross-compilation
      - name: Install cross
        if: matrix.os == 'ubuntu-latest' && matrix.arch != 'x86_64'
        run: |
          cargo install cross --git https://github.com/cross-rs/cross

      # Run Clippy for the native architectures
      - name: Run Clippy (native)
        if: (matrix.os == 'ubuntu-latest' && matrix.arch == 'x86_64') || (matrix.os == 'macos-latest' && matrix.arch == 'x86_64') || (matrix.os == 'windows-latest' && matrix.arch == 'x86_64')
        run: cargo clippy --target ${{ matrix.target }}

      # Run Clippy for Linux cross-compilation
      - name: Run Clippy (Linux cross-compilation)
        if: matrix.os == 'ubuntu-latest' && matrix.arch != 'x86_64'
        run: cross clippy --target ${{ matrix.target }}

      # Native builds and tests
      - name: Build (native)
        if: (matrix.os == 'ubuntu-latest' && matrix.arch == 'x86_64') || (matrix.os == 'macos-latest') || (matrix.os == 'windows-latest')
        run: cargo build --verbose --target ${{ matrix.target }}

      - name: Test (native)
        if: (matrix.os == 'ubuntu-latest' && matrix.arch == 'x86_64') || (matrix.os == 'macos-latest' && matrix.arch == 'x86_64') || (matrix.os == 'windows-latest' && matrix.arch == 'x86_64')
        run: cargo test --verbose --target ${{ matrix.target }}

      # Cross-compilation for Linux targets using cross
      - name: Build (Linux cross-compilation)
        if: matrix.os == 'ubuntu-latest' && matrix.arch != 'x86_64'
        run: cross build --verbose --target ${{ matrix.target }}

      - name: Test (Linux cross-compilation)
        if: matrix.os == 'ubuntu-latest' && matrix.arch != 'x86_64'
        run: cross test --verbose --target ${{ matrix.target }}

      # Windows i686 cross-compilation
      - name: Build and Test (Windows i686)
        if: matrix.os == 'windows-latest' && matrix.arch == 'i686'
        run: |
          cargo build --verbose --target ${{ matrix.target }}
          cargo test --verbose --target ${{ matrix.target }}

      # macOS aarch64 cross-compilation
      - name: Build and Test (macOS aarch64)
        if: matrix.os == 'macos-latest' && matrix.arch == 'aarch64'
        run: |
          cargo build --verbose --target ${{ matrix.target }}
          cargo test --verbose --target ${{ matrix.target }}
  release:
    name: Release on successful tests and merge
    needs: test
    if: github.event_name == 'push'  # Runs only when merged into main
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          ssh-key: ${{ secrets.DEPLOY_KEY }}
          fetch-depth: 0  # Ensure we fetch all history

      - name: Set up Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: stable

      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y build-essential

      - name: Build
        run: cargo build --release --verbose

      - name: Check package version
        id: check_version
        run: echo "VERSION=$(cargo metadata --format-version 1 --no-deps | jq -r '.packages[0].version')" >> $GITHUB_ENV

      - name: Extract PR Number from Merge Commit
        run: |
          PR_NUMBER=$(git log -1 --pretty=%B | grep -oE 'Merge pull request #[0-9]+' | awk '{print $4}' | tr -d '#')

          if [ -z "$PR_NUMBER" ]; then
            echo "❌ Error: Could not determine PR number!"
            exit 1
          fi

          echo "✅ Extracted PR Number: $PR_NUMBER"
          echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV

      - name: Fetch PR Labels Using GitHub API
        env:
          RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
        run: |
          PR_NUMBER="${{ env.PR_NUMBER }}"
          
          LABELS_JSON=$(curl -s -H "Authorization: token $RELEASE_TOKEN" \
            "https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/labels")
          
          echo "✅ PR Labels JSON: $LABELS_JSON"
          
          # Extract labels into a space-separated string
          LABELS=$(echo "$LABELS_JSON" | jq -r 'map(.name) | join(" ")')
          
          echo "✅ PR Labels: $LABELS"
          
          # Determine version bump priority: major > minor > patch
          VERSION_PART="patch"  # Default to patch
          
          if echo "$LABELS" | grep -iq "major"; then
            VERSION_PART="major"
          elif echo "$LABELS" | grep -iq "minor"; then
            VERSION_PART="minor"
          fi
          
          echo "✅ Selected Version Bump: $VERSION_PART"
          echo "VERSION_PART=$VERSION_PART" >> $GITHUB_ENV
          

      - name: Determine Version Bump
        run: |
          if [[ "${{ env.VERSION_PART }}" == "major" ]]; then
            NEW_VERSION=$(echo "${{ env.VERSION }}" | awk -F. -v OFS=. '{$1 += 1 ; $2=0; $3=0; print}')
          elif [[ "${{ env.VERSION_PART }}" == "minor" ]]; then
            NEW_VERSION=$(echo "${{ env.VERSION }}" | awk -F. -v OFS=. '{$2 += 1 ; $3=0; print}')
          else
            NEW_VERSION=$(echo "${{ env.VERSION }}" | awk -F. -v OFS=. '{$NF += 1 ; print}')
          fi

          echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV

      - name: Update Cargo.toml with new version
        run: sed -i 's/^version = "[0-9]\+\.[0-9]\+\.[0-9]\+"/version = "${{ env.NEW_VERSION }}"/' Cargo.toml

      - name: Commit and push new version (Bypass Branch Protection)
        env:
          RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
        run: |
          git config --global user.name "GitHub Actions"
          git config --global user.email "actions@github.com"
          git add Cargo.toml
          git commit -m "Bumping version to ${{ env.NEW_VERSION }} for release 🚀 [skip ci]"
          git push origin main


      - name: Tag version and push
        env:
          RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
        run: |
          git tag "v${{ env.NEW_VERSION }}"
          git push origin "v${{ env.NEW_VERSION }}"

      - name: Publish to Crates.io
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
        run: cargo publish --token $CARGO_REGISTRY_TOKEN

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2.2.1
        with:
          token: ${{ secrets.RELEASE_TOKEN }}
          tag_name: v${{ env.NEW_VERSION }}
          name: Release v${{ env.NEW_VERSION }}
          body: "🚀 Automated release triggered by successful tests on main.\n\n📦 **[View on Crates.io](https://crates.io/crates/memsafe/${{ env.NEW_VERSION }})**"
          draft: false
          prerelease: false