jj-hooks 0.2.1

Run pre-commit / lefthook / hk hooks against jj bookmark pushes
Documentation
name: CI

"on":
  push:
    branches: ["**"]
  pull_request:

env:
  CARGO_TERM_COLOR: always

jobs:
  lints:
    name: Lints
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5

      - name: Install Rust toolchain
        run: |
          rustup show active-toolchain || rustup toolchain install stable
          rustup component add rustfmt clippy

      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: "lints"
          save-if: "true"

      - name: cargo fmt --check
        run: cargo fmt --all -- --check

      - name: cargo clippy
        run: cargo clippy --all-targets -- -D warnings

      # markdownlint-cli2 ships on npm; actionlint as a prebuilt tarball.
      # We install both directly here rather than reusing `just
      # install-deps` so the lints job stays light (no hook runners
      # needed just to lint the repo).
      - name: Install markdownlint-cli2
        run: npm install -g markdownlint-cli2

      - name: Install actionlint
        run: |
          set -euo pipefail
          mkdir -p "$HOME/.local/bin"
          curl -fsSL https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_amd64.tar.gz \
            | tar -xz -C "$HOME/.local/bin" actionlint
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"

      - name: markdownlint
        run: markdownlint-cli2 "**/*.md" "**/*.markdown"

      - name: actionlint
        run: actionlint .github/workflows/*.yml

  test:
    name: Test (${{ matrix.os }})
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
          - os: macos-latest
    runs-on: ${{ matrix.os }}
    # uv reads these to decide where `uv tool install` puts binaries +
    # data. Pinning them under ~/.local means everything landed by
    # install-deps lives in one cacheable directory tree.
    env:
      XDG_BIN_HOME: ${{ github.workspace }}/.tools-bin
      XDG_DATA_HOME: ${{ github.workspace }}/.tools-data
    steps:
      - uses: actions/checkout@v5

      - name: Install Rust toolchain
        run: rustup show active-toolchain || rustup toolchain install stable

      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: "test-${{ matrix.os }}"
          save-if: "true"

      # Pre-built binaries for cargo-nextest, just, cargo-binstall.
      # install-action pulls them from each tool's GitHub Releases — much
      # faster than `cargo install`. cargo-binstall is then used inside
      # the install-deps recipe to fetch hk's prebuilt binary too.
      - uses: taiki-e/install-action@v2
        with:
          tool: cargo-nextest,just,cargo-binstall

      # Cache every tool that install-deps installs (jj, lefthook,
      # actionlint, pkl, hk, pre-commit, prek, markdownlint-cli2). We key
      # on the Justfile + workflow file hashes so any version bump in
      # either invalidates the cache. Skip install-deps + the prebuilt
      # jj download entirely on a hit.
      - name: Cache hook tools (Linux)
        if: runner.os == 'Linux'
        id: tools-cache
        uses: actions/cache@v4
        with:
          path: |
            ${{ env.XDG_BIN_HOME }}
            ${{ env.XDG_DATA_HOME }}
          key: tools-${{ runner.os }}-${{ hashFiles('Justfile', '.github/workflows/ci.yml') }}

      # jj has no install-action manifest yet, and the `jj` crate on
      # crates.io is a squatter that compile-errors pointing at jj-cli.
      # Just download the prebuilt tarball from the jj-vcs/jj release
      # page directly — ~5s vs multi-minute compile. macOS path always
      # runs (no cache); Linux skips when the cache hit covers it.
      - name: Install jj from prebuilt tarball
        if: runner.os == 'macOS' || steps.tools-cache.outputs.cache-hit != 'true'
        run: |
          set -euo pipefail
          jj_version=v0.41.0
          case "$(uname -s)-$(uname -m)" in
              Linux-x86_64)   triple=x86_64-unknown-linux-musl ;;
              Linux-aarch64)  triple=aarch64-unknown-linux-musl ;;
              Darwin-arm64)   triple=aarch64-apple-darwin ;;
              Darwin-x86_64)  triple=x86_64-apple-darwin ;;
              *)
                  echo "unsupported host: $(uname -s)-$(uname -m)" >&2
                  exit 1
                  ;;
          esac
          url="https://github.com/jj-vcs/jj/releases/download/${jj_version}/jj-${jj_version}-${triple}.tar.gz"
          # On Linux send to the cached XDG_BIN_HOME; on macOS use ~/.local/bin
          # since brew owns macOS install paths and we don't cache there.
          dest="${XDG_BIN_HOME:-$HOME/.local/bin}"
          mkdir -p "$dest"
          curl -fsSL "$url" | tar -xz --strip-components=1 -C "$dest" ./jj
          "$dest/jj" --version

      - name: Install Python (for uv on Linux)
        if: runner.os == 'Linux' && steps.tools-cache.outputs.cache-hit != 'true'
        uses: actions/setup-python@v5
        with:
          python-version: "3.x"

      - name: Install uv (Linux only — macOS uses brew)
        if: runner.os == 'Linux' && steps.tools-cache.outputs.cache-hit != 'true'
        uses: astral-sh/setup-uv@v6

      - name: Install hook runners
        if: runner.os == 'macOS' || steps.tools-cache.outputs.cache-hit != 'true'
        run: just install-deps

      - name: Add tool dirs to PATH
        run: echo "$XDG_BIN_HOME" >> "$GITHUB_PATH"

      - name: cargo nextest run
        run: cargo nextest run --no-fail-fast