diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9a00031 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,78 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +permissions: + contents: read + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + python: + name: Python ${{ matrix.python }} + runs-on: ubuntu-latest + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + python: ["3.11", "3.12"] + steps: + - uses: actions/checkout@v7.0.1 + + - uses: astral-sh/setup-uv@v10.3.3 + with: + version: "0.13.6" + python-version: ${{ matrix.python }} + + - name: Check the lockfile matches pyproject.toml + run: uv lock --check + + # The locked Linux torch pulls about 3 GB of CUDA packages that a CI runner cannot use. + # Install the CPU build of torch, with every other package pinned to the version in uv.lock. + - name: Install locked versions (CPU torch) + run: | + uv export --frozen --no-hashes --no-emit-project -o "$RUNNER_TEMP/constraints.txt" + uv venv + uv pip install --torch-backend cpu -c "$RUNNER_TEMP/constraints.txt" -e . --group dev + + # The rotation test writes rotation metadata with the ffmpeg CLI. + - name: Install ffmpeg + run: sudo apt-get update -q && sudo apt-get install -y -q ffmpeg + + - name: Lint + run: | + uv run --no-sync ruff check src tests + uv run --no-sync ruff format --check src tests + + - name: Test + run: uv run --no-sync pytest -q -rs + + viewer-and-wheel: + name: Viewer and wheel + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v7.0.1 + + - uses: actions/setup-node@v7.1.0 + with: + node-version: 24 + cache: npm + cache-dependency-path: web/package-lock.json + + - uses: astral-sh/setup-uv@v10.3.3 + with: + version: "0.13.6" + + # Installs and type-checks the viewer, builds it and the wheel, and fails if the wheel lacks it. + - name: Build + run: ./scripts/build.sh + + - name: Lint viewer + working-directory: web + run: npx oxlint src diff --git a/README.md b/README.md index eb9d42b..9f3e0ae 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # jepa-scope +[![CI](https://github.com/ryangswe/jepa-scope/actions/workflows/ci.yml/badge.svg)](https://github.com/ryangswe/jepa-scope/actions/workflows/ci.yml) + jepa-scope shows you what a JEPA video encoder sees. Point it at a video and it opens a local viewer with the model's patch features drawn over the picture, plus a timeline of how surprised the model was by each moment. It runs Meta's pre-trained V-JEPA 2 on a laptop, so you need no training run, no