devclean-cli 0.3.0

Audit and safely remove rebuildable development artifacts
Documentation
name: Release

on:
  push:
    tags: ["v*.*.*"]

permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always

jobs:
  verify:
    name: Verify release gates
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
      - uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
        with:
          components: rustfmt, clippy
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
      - run: cargo fmt --all -- --check
      - run: cargo test --all-features --locked
      - run: cargo clippy --all-targets --all-features --locked -- -D warnings

  build:
    name: Build ${{ matrix.target }}
    needs: verify
    runs-on: ${{ matrix.os }}
    permissions:
      contents: read
      id-token: write
      attestations: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            asset: devclean-linux-x86_64
          - os: macos-latest
            target: aarch64-apple-darwin
            asset: devclean-macos-arm64
          - os: macos-latest
            target: x86_64-apple-darwin
            asset: devclean-macos-x86_64
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            asset: devclean-windows-x86_64
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
      - uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
        with:
          targets: ${{ matrix.target }}
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
        with:
          key: ${{ matrix.target }}
      - run: cargo build --release --locked --target ${{ matrix.target }}

      - name: Package Unix archive
        if: runner.os != 'Windows'
        shell: bash
        run: |
          mkdir package
          cp "target/${{ matrix.target }}/release/devclean" package/
          cp README.md LICENSE package/
          tar -C package -czf "${{ matrix.asset }}.tar.gz" .

      - name: Package Windows archive
        if: runner.os == 'Windows'
        shell: pwsh
        run: |
          New-Item -ItemType Directory -Path package
          Copy-Item "target/${{ matrix.target }}/release/devclean.exe" package/
          Copy-Item README.md,LICENSE package/
          Compress-Archive -Path package/* -DestinationPath "${{ matrix.asset }}.zip"

      - uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3
        with:
          subject-path: ${{ matrix.asset }}.*

      - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
        with:
          name: ${{ matrix.asset }}
          path: ${{ matrix.asset }}.*
          if-no-files-found: error

  macos-app:
    name: Build macOS menu bar app
    needs: [verify, build]
    runs-on: macos-latest
    permissions:
      contents: read
      id-token: write
      attestations: write
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
      - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
        with:
          pattern: devclean-macos-*
          path: cli-artifacts
      - name: Create universal Rust helper
        shell: bash
        run: |
          mkdir -p cli-arm64 cli-x86_64 target/universal-apple-darwin/release
          tar -xzf cli-artifacts/devclean-macos-arm64/devclean-macos-arm64.tar.gz -C cli-arm64
          tar -xzf cli-artifacts/devclean-macos-x86_64/devclean-macos-x86_64.tar.gz -C cli-x86_64
          lipo -create cli-arm64/devclean cli-x86_64/devclean \
            -output target/universal-apple-darwin/release/devclean
          test "$(lipo -archs target/universal-apple-darwin/release/devclean)" = "x86_64 arm64" \
            -o "$(lipo -archs target/universal-apple-darwin/release/devclean)" = "arm64 x86_64"
      - name: Test Swift package
        run: swift test --package-path apps/macos
      - name: Build universal app
        env:
          UNIVERSAL: "1"
          HELPER_EXECUTABLE: ${{ github.workspace }}/target/universal-apple-darwin/release/devclean
        run: apps/macos/scripts/build-app.sh
      - name: Verify universal app
        run: |
          codesign --verify --deep --strict --verbose=2 dist/Devclean.app
          lipo -archs dist/Devclean.app/Contents/MacOS/DevcleanMenuBar | grep arm64
          lipo -archs dist/Devclean.app/Contents/MacOS/DevcleanMenuBar | grep x86_64
          lipo -archs dist/Devclean.app/Contents/Helpers/devclean | grep arm64
          lipo -archs dist/Devclean.app/Contents/Helpers/devclean | grep x86_64
      - name: Package app bundle
        run: ditto -c -k --sequesterRsrc --keepParent dist/Devclean.app devclean-menubar-macos-universal.zip
      - uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3
        with:
          subject-path: devclean-menubar-macos-universal.zip
      - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
        with:
          name: devclean-menubar-macos-universal
          path: devclean-menubar-macos-universal.zip
          if-no-files-found: error

  publish:
    name: Publish GitHub release
    needs: [build, macos-app]
    runs-on: ubuntu-latest
    permissions:
      contents: write
      id-token: write
      attestations: write
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
      - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
        with:
          path: dist
          merge-multiple: true
      - uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0
        with:
          path: .
          format: cyclonedx-json
          output-file: dist/devclean-sbom.cdx.json
          upload-artifact: false
      - uses: actions/attest-sbom@4651f806c01d8637787e274ac3bdf724ef169f34 # v3
        with:
          subject-path: dist/devclean-*.*
          sbom-path: dist/devclean-sbom.cdx.json
      - name: Package skill and checksums
        shell: bash
        run: |
          tar -czf dist/dev-disk-cleaner-skill.tar.gz skills/dev-disk-cleaner
          cd dist
          sha256sum * > SHA256SUMS
      - uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3
        with:
          name: devclean ${{ github.ref_name }}
          body_path: RELEASE_NOTES.md
          make_latest: true
          files: dist/*