feat: add Rust implementation and reorganize codebase #6
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
| name: Rust Checks and Release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - 'rust/**' | |
| - '.github/workflows/rust.yml' | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| paths: | |
| - 'rust/**' | |
| - '.github/workflows/rust.yml' | |
| workflow_dispatch: | |
| inputs: | |
| release_mode: | |
| description: 'Manual release mode' | |
| required: true | |
| type: choice | |
| default: 'instant' | |
| options: | |
| - instant | |
| bump_type: | |
| description: 'Manual release type' | |
| required: true | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| description: | |
| description: 'Manual release description (optional)' | |
| required: false | |
| type: string | |
| concurrency: ${{ github.workflow }}-${{ github.ref }} | |
| defaults: | |
| run: | |
| working-directory: rust | |
| jobs: | |
| # Linting and formatting | |
| lint: | |
| name: Rust - Lint and Format Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt, clippy | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| rust/target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }} | |
| - name: Check formatting | |
| run: cargo fmt --all -- --check | |
| - name: Run Clippy | |
| run: cargo clippy --all-targets --all-features -- -D warnings | |
| # Test matrix: Rust on multiple OS | |
| test: | |
| name: Rust - Test (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| rust/target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }} | |
| - name: Run tests | |
| run: cargo test --all-features | |
| # Build check | |
| build: | |
| name: Rust - Build | |
| runs-on: ubuntu-latest | |
| needs: [lint, test] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| rust/target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }} | |
| - name: Build release | |
| run: cargo build --release | |
| - name: Build Docker image | |
| run: docker build -t web-capture-rust . | |
| # Release - only runs on main after tests pass (for push events) | |
| release: | |
| name: Rust - Release | |
| needs: [lint, test, build] | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| rust/target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }} | |
| - name: Check if version changed | |
| id: version_check | |
| run: | | |
| # Get current version from Cargo.toml | |
| CURRENT_VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)".*/\1/') | |
| echo "Current version: $CURRENT_VERSION" | |
| # Check if tag exists | |
| if git rev-parse "rust-v$CURRENT_VERSION" >/dev/null 2>&1; then | |
| echo "Tag rust-v$CURRENT_VERSION already exists" | |
| echo "should_release=false" >> $GITHUB_OUTPUT | |
| else | |
| echo "Tag rust-v$CURRENT_VERSION does not exist, will release" | |
| echo "should_release=true" >> $GITHUB_OUTPUT | |
| echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Publish to crates.io | |
| if: steps.version_check.outputs.should_release == 'true' | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| run: | | |
| cargo publish --allow-dirty || echo "Publish failed or already published" | |
| - name: Create GitHub Release | |
| if: steps.version_check.outputs.should_release == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| VERSION="${{ steps.version_check.outputs.version }}" | |
| gh release create "rust-v$VERSION" \ | |
| --title "Rust v$VERSION" \ | |
| --notes "Rust web-capture version $VERSION" \ | |
| --target ${{ github.sha }} | |
| # Manual Instant Release | |
| instant-release: | |
| name: Rust - Instant Release | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.release_mode == 'instant' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| rust/target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }} | |
| - name: Configure Git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Bump version | |
| id: bump | |
| run: | | |
| # Get current version | |
| CURRENT=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)".*/\1/') | |
| IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" | |
| # Bump based on type | |
| case "${{ github.event.inputs.bump_type }}" in | |
| major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;; | |
| minor) MINOR=$((MINOR + 1)); PATCH=0 ;; | |
| patch) PATCH=$((PATCH + 1)) ;; | |
| esac | |
| NEW_VERSION="$MAJOR.$MINOR.$PATCH" | |
| echo "New version: $NEW_VERSION" | |
| # Update Cargo.toml | |
| sed -i "s/^version = \"$CURRENT\"/version = \"$NEW_VERSION\"/" Cargo.toml | |
| echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT | |
| - name: Commit version bump | |
| run: | | |
| git add Cargo.toml | |
| git commit -m "chore(rust): bump version to ${{ steps.bump.outputs.version }}" | |
| git push | |
| - name: Publish to crates.io | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| run: | | |
| cargo publish --allow-dirty || echo "Publish failed or already published" | |
| - name: Create GitHub Release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| VERSION="${{ steps.bump.outputs.version }}" | |
| DESCRIPTION="${{ github.event.inputs.description || 'Manual release' }}" | |
| gh release create "rust-v$VERSION" \ | |
| --title "Rust v$VERSION" \ | |
| --notes "$DESCRIPTION" \ | |
| --target ${{ github.sha }} |