Skip to content

Allow pasting images in the web app (#46) #202

Allow pasting images in the web app (#46)

Allow pasting images in the web app (#46) #202

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
# ─────────────────────────────────────────────────────────────────────────────
# Detect which paths changed
# ─────────────────────────────────────────────────────────────────────────────
changes:
name: Detect Changes
runs-on: ubuntu-latest
permissions:
pull-requests: read
outputs:
rust: ${{ steps.filter.outputs.rust }}
frontend: ${{ steps.filter.outputs.frontend }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
rust:
- 'src/**'
- 'Cargo.toml'
- 'Cargo.lock'
- 'tests/**'
- 'benches/**'
- '.cargo/**'
frontend:
- 'web/**'
# ─────────────────────────────────────────────────────────────────────────────
# Rust: Format, Lint, Test
# ─────────────────────────────────────────────────────────────────────────────
rust:
name: Rust
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.rust == 'true'
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Cache Cargo
uses: swatinem/rust-cache@v2
with:
shared-key: rust-ci
- name: Check formatting
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Run tests
run: cargo test --all-features
# ─────────────────────────────────────────────────────────────────────────────
# WASM: Build wasm32 binary and upload artifact
# ─────────────────────────────────────────────────────────────────────────────
wasm:
name: Build WASM
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.rust == 'true'
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
- name: Cache Cargo
uses: swatinem/rust-cache@v2
with:
shared-key: wasm-build
- name: Install wasm-bindgen-cli
uses: taiki-e/install-action@v2
with:
tool: wasm-bindgen-cli
- name: Build WASM
run: cargo build --target wasm32-unknown-unknown --release --no-default-features --features wasm,simd
- name: Generate JS bindings
run: |
wasm-bindgen \
--target web \
--out-dir ./web/src/lib/pixo-wasm \
--out-name pixo \
target/wasm32-unknown-unknown/release/pixo.wasm
rm -f ./web/src/lib/pixo-wasm/.gitignore
- name: Install binaryen (wasm-opt)
run: |
sudo apt-get update
sudo apt-get install -y binaryen
- name: Optimize WASM
run: |
wasm-opt -Oz --strip-debug --strip-dwarf --strip-producers --strip-target-features \
--enable-bulk-memory --enable-sign-ext --enable-nontrapping-float-to-int \
-o ./web/src/lib/pixo-wasm/pixo_bg.wasm \
./web/src/lib/pixo-wasm/pixo_bg.wasm
- name: Report WASM size
run: |
ls -lh ./web/src/lib/pixo-wasm/pixo_bg.wasm
echo "::notice::WASM size: $(stat -c%s ./web/src/lib/pixo-wasm/pixo_bg.wasm) bytes"
- name: Upload WASM artifact
uses: actions/upload-artifact@v4
with:
name: pixo-wasm
path: web/src/lib/pixo-wasm/
retention-days: 1
# ─────────────────────────────────────────────────────────────────────────────
# Frontend: Type check, Build, E2E tests
# ─────────────────────────────────────────────────────────────────────────────
frontend:
name: Frontend
runs-on: ubuntu-latest
needs: [changes, wasm]
# Run if frontend changed, OR if rust changed (to test new WASM)
# Skip only if neither changed
if: always() && (needs.changes.outputs.frontend == 'true' || needs.changes.outputs.rust == 'true')
defaults:
run:
working-directory: web
steps:
- uses: actions/checkout@v4
# Download fresh WASM artifact if Rust changed
- name: Download WASM artifact
if: needs.changes.outputs.rust == 'true'
uses: actions/download-artifact@v4
with:
name: pixo-wasm
path: web/src/lib/pixo-wasm/
# Use committed WASM if only frontend changed
- name: Use committed WASM
if: needs.changes.outputs.rust != 'true'
run: echo "Using committed WASM (no Rust changes)"
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: web/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Type check
run: pnpm check
- name: Build
run: pnpm build
- name: Cache Playwright browsers
uses: actions/cache@v4
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('web/pnpm-lock.yaml') }}
- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: pnpm exec playwright install chromium --with-deps
- name: Install Playwright system deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: pnpm exec playwright install-deps chromium
- name: Run E2E tests
run: pnpm e2e
- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: web/playwright-report/
retention-days: 7
- name: Upload test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-results
path: web/test-results/
retention-days: 7
# ─────────────────────────────────────────────────────────────────────────────
# Cross-platform: Test on macOS (ARM64/NEON)
# ─────────────────────────────────────────────────────────────────────────────
macos:
name: macOS (ARM64)
runs-on: macos-latest
needs: changes
# Only run on main branch to save CI minutes
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.changes.outputs.rust == 'true'
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache Cargo
uses: swatinem/rust-cache@v2
with:
shared-key: macos-ci
- name: Run tests
run: cargo test --all-features
- name: Verify NEON SIMD works
run: |
# Run a quick benchmark to verify SIMD acceleration
cargo bench --bench components -- --noplot "adler32" 2>&1 | head -30