tli 0.1.2

Fast file-backed task tracker for humans, hooks, and AI agents.
Documentation
name: Release

on:
  push:
    tags:
      - "v*"

permissions:
  contents: write

jobs:
  verify:
    name: verify
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Cache Rust build
        uses: Swatinem/rust-cache@v2

      - name: Run tests
        run: cargo test --locked

      - name: Check formatting
        run: cargo fmt -- --check

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

  build-release:
    name: build-release
    needs: verify
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            artifact_name: tli
            asset_name: tli-linux-x64.zip
          - os: macos-latest
            target: aarch64-apple-darwin
            artifact_name: tli
            asset_name: tli-macos-arm64.zip
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            artifact_name: tli.exe
            asset_name: tli-windows-x64.zip

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

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

      - name: Cache Rust build
        uses: Swatinem/rust-cache@v2

      - name: Set version from tag
        env:
          VERSION: ${{ github.ref_name }}
        shell: pwsh
        run: |
          $version = $env:VERSION -replace '^v', ''
          $cargoToml = 'Cargo.toml'
          $content = Get-Content $cargoToml -Raw
          $updated = [regex]::Replace($content, '(?m)^version = "[^"]+"', "version = `"$version`"", 1)

          if ($updated -eq $content) {
            throw "Failed to update Cargo.toml version from tag $version"
          }

          Set-Content $cargoToml $updated -NoNewline

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

      - name: Package binary
        shell: pwsh
        run: |
          Compress-Archive -Path "target/${{ matrix.target }}/release/${{ matrix.artifact_name }}" -DestinationPath "target/${{ matrix.target }}/release/${{ matrix.asset_name }}" -Force

      - name: Upload workflow artifact
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.asset_name }}
          path: target/${{ matrix.target }}/release/${{ matrix.asset_name }}

      - name: Upload binary to GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          files: target/${{ matrix.target }}/release/${{ matrix.asset_name }}
          generate_release_notes: true

  publish-crates:
    name: publish-crates
    needs: build-release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Cache Rust build
        uses: Swatinem/rust-cache@v2

      - name: Set version from tag
        env:
          VERSION: ${{ github.ref_name }}
        run: |
          VERSION="${VERSION#v}"
          sed -i -E "0,/^version = \"[^\"]+\"/s//version = \"$VERSION\"/" Cargo.toml

      - name: Publish to crates.io
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: cargo publish --allow-dirty

  publish-npm:
    name: publish-npm
    needs: build-release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Install Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 22
          registry-url: "https://registry.npmjs.org"

      - name: Set version from tag
        run: |
          VERSION="${GITHUB_REF_NAME#v}"
          npm version "$VERSION" --no-git-tag-version
        working-directory: npm

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

      - name: Bundle release binaries into npm package
        run: |
          TMP_DIR="$(mktemp -d)"
          trap 'rm -rf "$TMP_DIR"' EXIT

          LINUX_ZIP="$(find dist -type f -name 'tli-linux-x64.zip' -print -quit)"
          MACOS_ZIP="$(find dist -type f -name 'tli-macos-arm64.zip' -print -quit)"
          WINDOWS_ZIP="$(find dist -type f -name 'tli-windows-x64.zip' -print -quit)"

          test -n "$LINUX_ZIP"
          test -n "$MACOS_ZIP"
          test -n "$WINDOWS_ZIP"

          unzip -j "$LINUX_ZIP" tli -d "$TMP_DIR"
          mv "$TMP_DIR/tli" npm/bin/tli-linux-x64
          unzip -j "$MACOS_ZIP" tli -d "$TMP_DIR"
          mv "$TMP_DIR/tli" npm/bin/tli-darwin-arm64
          unzip -j "$WINDOWS_ZIP" tli.exe -d "$TMP_DIR"
          mv "$TMP_DIR/tli.exe" npm/bin/tli-win32-x64.exe
          chmod +x npm/bin/tli-linux-x64 npm/bin/tli-darwin-arm64

          test -f npm/bin/tli.js
          test -f npm/bin/tli-linux-x64
          test -f npm/bin/tli-darwin-arm64
          test -f npm/bin/tli-win32-x64.exe

      - name: Copy README and LICENSE to npm package
        run: |
          cp README.md npm/README.md
          cp LICENSE npm/LICENSE

      - name: Publish to npm
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npm publish --access public
        working-directory: npm