hbsx 0.2.1-patch.4

A easy-to-use file encryption tool with compression support
Documentation
name: Release

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: write

jobs:
  create-release:
    name: Create Release
    runs-on: ubuntu-latest
    outputs:
      upload_url: ${{ steps.create_release.outputs.upload_url }}
      version: ${{ steps.get_version.outputs.version }}
    steps:
      - name: Get version from tag
        id: get_version
        run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT

      - name: Create Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: Release ${{ github.ref }}
          draft: false
          prerelease: false

  build:
    name: Build for ${{ matrix.os }} (${{ matrix.target }})
    needs: create-release
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          # Windows
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            artifact_name: hbsx.exe
            asset_name: hbsx-windows-x86_64.exe
          - os: windows-latest
            target: aarch64-pc-windows-msvc
            artifact_name: hbsx.exe
            asset_name: hbsx-windows-aarch64.exe

          # Linux
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            artifact_name: hbsx
            asset_name: hbsx-linux-x86_64
          - os: ubuntu-24.04-arm
            target: aarch64-unknown-linux-gnu
            artifact_name: hbsx
            asset_name: hbsx-linux-aarch64
          - os: ubuntu-latest
            target: x86_64-unknown-linux-musl
            artifact_name: hbsx
            asset_name: hbsx-linux-x86_64-musl

          # macOS
          - os: macos-latest
            target: x86_64-apple-darwin
            artifact_name: hbsx
            asset_name: hbsx-macos-x86_64
          - os: macos-latest
            target: aarch64-apple-darwin
            artifact_name: hbsx
            asset_name: hbsx-macos-aarch64

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

      - name: Update Cargo.toml version
        shell: python
        run: |
          import re
          version = "${{ needs.create-release.outputs.version }}"
          print(f"Updating Cargo.toml to version {version}")
          
          with open('Cargo.toml', 'r', encoding='utf-8') as f:
              content = f.read()
          
          # 更新 version 字段(在 [package] 部分)
          content = re.sub(
              r'^version\s*=\s*"[^"]*"',
              f'version = "{version}"',
              content,
              count=1,
              flags=re.MULTILINE
          )
          
          with open('Cargo.toml', 'w', encoding='utf-8') as f:
              f.write(content)
          
          # 验证更新
          with open('Cargo.toml', 'r', encoding='utf-8') as f:
              for line in f:
                  if line.startswith('version ='):
                      print(f"Updated: {line.strip()}")
                      break

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Install musl tools (Linux musl)
        if: matrix.target == 'x86_64-unknown-linux-musl'
        run: |
          sudo apt-get update
          sudo apt-get install -y musl-tools

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: ~/.cargo/registry
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}

      - name: Cache cargo index
        uses: actions/cache@v4
        with:
          path: ~/.cargo/git
          key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }}

      - name: Cache target directory
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-${{ matrix.target }}-cargo-target-${{ hashFiles('**/Cargo.lock') }}

      - name: Show build environment
        run: |
          echo "Target: ${{ matrix.target }}"
          echo "OS: ${{ matrix.os }}"
          echo "Architecture: $(uname -m)"
          echo "Rust version:"
          rustc --version
          cargo --version

      - name: Build
        run: cargo build --release --target ${{ matrix.target }} --verbose

      - name: Strip binary (Linux and macOS)
        if: matrix.os != 'windows-latest'
        run: strip target/${{ matrix.target }}/release/${{ matrix.artifact_name }}

      - name: Compress binary (Linux and macOS)
        if: matrix.os != 'windows-latest'
        run: |
          cd target/${{ matrix.target }}/release
          tar czf ${{ matrix.asset_name }}.tar.gz ${{ matrix.artifact_name }}
          mv ${{ matrix.asset_name }}.tar.gz ../../../

      - name: Compress binary (Windows)
        if: matrix.os == 'windows-latest'
        shell: pwsh
        run: |
          cd target/${{ matrix.target }}/release
          Compress-Archive -Path ${{ matrix.artifact_name }} -DestinationPath ../../../${{ matrix.asset_name }}.zip

      - name: Upload Release Asset (Linux and macOS)
        if: matrix.os != 'windows-latest'
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ needs.create-release.outputs.upload_url }}
          asset_path: ./${{ matrix.asset_name }}.tar.gz
          asset_name: ${{ matrix.asset_name }}.tar.gz
          asset_content_type: application/gzip

      - name: Upload Release Asset (Windows)
        if: matrix.os == 'windows-latest'
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ needs.create-release.outputs.upload_url }}
          asset_path: ./${{ matrix.asset_name }}.zip
          asset_name: ${{ matrix.asset_name }}.zip
          asset_content_type: application/zip

      - name: Generate SHA256 checksums (Linux and macOS)
        if: matrix.os != 'windows-latest'
        run: |
          sha256sum ${{ matrix.asset_name }}.tar.gz > ${{ matrix.asset_name }}.tar.gz.sha256

      - name: Generate SHA256 checksums (Windows)
        if: matrix.os == 'windows-latest'
        shell: pwsh
        run: |
          $hash = (Get-FileHash -Path ${{ matrix.asset_name }}.zip -Algorithm SHA256).Hash.ToLower()
          "$hash  ${{ matrix.asset_name }}.zip" | Out-File -FilePath ${{ matrix.asset_name }}.zip.sha256 -Encoding utf8 -NoNewline

      - name: Upload SHA256 checksum (Linux and macOS)
        if: matrix.os != 'windows-latest'
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ needs.create-release.outputs.upload_url }}
          asset_path: ./${{ matrix.asset_name }}.tar.gz.sha256
          asset_name: ${{ matrix.asset_name }}.tar.gz.sha256
          asset_content_type: text/plain

      - name: Upload SHA256 checksum (Windows)
        if: matrix.os == 'windows-latest'
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ needs.create-release.outputs.upload_url }}
          asset_path: ./${{ matrix.asset_name }}.zip.sha256
          asset_name: ${{ matrix.asset_name }}.zip.sha256
          asset_content_type: text/plain

      # 保存构建产物用于 npm 发布
      - name: Upload artifact for npm publishing
        uses: actions/upload-artifact@v4
        with:
          name: binary-${{ matrix.target }}
          path: target/${{ matrix.target }}/release/${{ matrix.artifact_name }}
          retention-days: 1

  publish-npm:
    name: Publish to npm
    needs: [create-release, build]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          registry-url: 'https://registry.npmjs.org'

      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          path: artifacts

      - name: List downloaded artifacts
        run: |
          echo "Downloaded artifacts:"
          ls -R artifacts/

      - name: Copy binaries to platform packages
        run: |
          # 创建 bin 目录
          mkdir -p package/npm/platform-packages/win32-x64/bin
          mkdir -p package/npm/platform-packages/win32-arm64/bin
          mkdir -p package/npm/platform-packages/linux-x64/bin
          mkdir -p package/npm/platform-packages/linux-arm64/bin
          mkdir -p package/npm/platform-packages/darwin-x64/bin
          mkdir -p package/npm/platform-packages/darwin-arm64/bin

          # 复制 Windows 二进制
          cp artifacts/binary-x86_64-pc-windows-msvc/hbsx.exe package/npm/platform-packages/win32-x64/bin/
          cp artifacts/binary-aarch64-pc-windows-msvc/hbsx.exe package/npm/platform-packages/win32-arm64/bin/

          # 复制 Linux 二进制 (使用 musl 版本作为主要版本)
          cp artifacts/binary-x86_64-unknown-linux-musl/hbsx package/npm/platform-packages/linux-x64/bin/
          cp artifacts/binary-aarch64-unknown-linux-gnu/hbsx package/npm/platform-packages/linux-arm64/bin/

          # 复制 macOS 二进制
          cp artifacts/binary-x86_64-apple-darwin/hbsx package/npm/platform-packages/darwin-x64/bin/
          cp artifacts/binary-aarch64-apple-darwin/hbsx package/npm/platform-packages/darwin-arm64/bin/

          # 设置执行权限
          chmod +x package/npm/platform-packages/*/bin/hbsx

      - name: Update package versions
        run: |
          VERSION="${{ needs.create-release.outputs.version }}"
          echo "Updating packages to version $VERSION"
          
          # 使用 Node.js 脚本直接修改 JSON 文件,避免 npm version 的问题
          cd package/npm
          
          # 更新主包版本
          node -e "
            const fs = require('fs');
            const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
            const version = process.env.VERSION;
            pkg.version = version;
            for (const dep in pkg.optionalDependencies) {
              pkg.optionalDependencies[dep] = version;
            }
            fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
            console.log('✓ Main package updated to', version);
          " VERSION="$VERSION"
          
          # 更新平台包版本
          for platform in win32-x64 win32-arm64 linux-x64 linux-arm64 darwin-x64 darwin-arm64; do
            node -e "
              const fs = require('fs');
              const pkg = JSON.parse(fs.readFileSync('platform-packages/$platform/package.json', 'utf8'));
              pkg.version = process.env.VERSION;
              fs.writeFileSync('platform-packages/$platform/package.json', JSON.stringify(pkg, null, 2) + '\n');
              console.log('✓ Platform package $platform updated to', process.env.VERSION);
            " VERSION="$VERSION" platform="$platform"
          done
          
          echo "✓ All package versions updated to $VERSION"

      - name: Setup npm authentication
        run: |
          echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
          echo "registry=https://registry.npmjs.org/" >> ~/.npmrc
          echo "always-auth=true" >> ~/.npmrc

      - name: Publish platform packages
        run: |
          cd package/npm
          
          # 发布平台包
          for platform in win32-x64 win32-arm64 linux-x64 linux-arm64 darwin-x64 darwin-arm64; do
            echo "Publishing @jihuayu/hbsx-$platform..."
            cd platform-packages/$platform
            npm publish --access public
            cd ../..
          done

      - name: Publish main package
        run: |
          cd package/npm
          echo "Publishing @jihuayu/hbsx..."
          npm publish --access public

      - name: Summary
        run: |
          echo "✓ All npm packages published successfully!"
          echo "Version: ${{ needs.create-release.outputs.version }}"
          echo ""
          echo "Install with:"
          echo "  npm install -g @jihuayu/hbsx@${{ needs.create-release.outputs.version }}"

  publish-crates:
    name: Publish to crates.io
    needs: [create-release, build]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Update Cargo.toml version
        shell: python
        run: |
          import re
          version = "${{ needs.create-release.outputs.version }}"
          print(f"Updating Cargo.toml to version {version}")
          
          with open('Cargo.toml', 'r', encoding='utf-8') as f:
              content = f.read()
          
          # 更新 version 字段
          content = re.sub(
              r'^version\s*=\s*"[^"]*"',
              f'version = "{version}"',
              content,
              count=1,
              flags=re.MULTILINE
          )
          
          with open('Cargo.toml', 'w', encoding='utf-8') as f:
              f.write(content)
          
          print(f"✓ Cargo.toml updated to version {version}")

      - name: Verify package
        run: cargo package --allow-dirty

      - name: Publish to crates.io
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: |
          echo "Publishing hbsx to crates.io..."
          cargo publish --allow-dirty --token "$CARGO_REGISTRY_TOKEN"
          echo "✓ Published to crates.io"

      - name: Summary
        run: |
          echo "✓ Package published to crates.io successfully!"
          echo "Version: ${{ needs.create-release.outputs.version }}"
          echo ""
          echo "Install with:"
          echo "  cargo install hbsx"