pond-db 0.2.2

Lossless storage and hybrid search for AI agent sessions, across every agentic client.
Documentation
name: CI

on:
  push:
    branches: [main]
  pull_request:
  # Recovery path: re-run packaging (binaries + Homebrew + NUR + GitHub release
  # assets) for an already-tagged release, e.g. when goreleaser failed after
  # release-plz already published to crates.io. Runs only `publish-release`
  # against the given tag.
  workflow_dispatch:
    inputs:
      tag:
        description: "Existing tag to (re)package, e.g. v0.2.1"
        required: true

permissions:
  contents: write
  pull-requests: write

# Newer push or PR update on the same ref supersedes the older in-flight run.
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  CARGO_TERM_COLOR: always
  BAZEL_REMOTE_AUTH: ${{ secrets.BAZEL_REMOTE_AUTH }}

jobs:
  build-and-test:
    name: build-and-test
    # Skip on the recovery dispatch - it only re-runs publish-release for a tag.
    if: github.event_name != 'workflow_dispatch'
    runs-on: [self-hosted, linux, x64]
    steps:
      - uses: actions/checkout@v6.0.2
        with:
          fetch-depth: 0

      - uses: arduino/setup-protoc@v3

      - uses: kunobi-ninja/kache-action@v1
        with:
          s3-bucket: ttq
          s3-endpoint: https://nbg1.your-objectstorage.com
          s3-region: nbg1
          s3-prefix: kache/pond
          s3-access-key-id: ${{ secrets.KACHE_S3_ACCESS_KEY }}
          s3-secret-access-key: ${{ secrets.KACHE_S3_SECRET_KEY }}

      - uses: moonrepo/setup-toolchain@v0
      - uses: moonrepo/setup-rust@v1
      - run: moon run pond:format pond:lint pond:test

  release-plz:
    name: release-plz
    needs: build-and-test
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    outputs:
      releases_created: ${{ steps.release-plz.outputs.releases_created }}
    steps:
      - uses: actions/checkout@v6.0.2
        with:
          fetch-depth: 0   # release-plz needs full git history for changelog

      - id: release-plz
        uses: release-plz/action@v0.5
        # No `dry_run` input on purpose: the action adds `--dry-run` whenever the
        # input is non-empty (it tests `-n`, so even `dry_run: false` enables it).
        # Omitting it is the only way to actually publish. Default command runs
        # both `release-pr` (opens the release PR) and `release` (cuts the tag +
        # crates.io publish + GitHub release once a release-plz-* branch merges).
        env:
          GITHUB_TOKEN: ${{ secrets.GH_RELEASE_TOKEN }}
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

  publish-release:
    name: publish-release
    needs: release-plz
    # Runs after release-plz cuts a release, OR on a manual recovery dispatch.
    # always()+!cancelled() lets it run on workflow_dispatch even though
    # release-plz is skipped there (its `if` is push-only).
    if: ${{ always() && !cancelled() && (needs.release-plz.outputs.releases_created == 'true' || github.event_name == 'workflow_dispatch') }}
    # Self-hosted: provides the allowlisted network path to the cluster API.
    # Cluster *config* (kubeconfig, buildx builder, S3 creds) is bootstrapped
    # from secrets below, so the runner needs no pre-provisioned pond setup -
    # only docker+buildx, kubectl, and moon installed.
    runs-on: [self-hosted, linux, x64]
    steps:
      - uses: actions/checkout@v6.0.2
        with:
          fetch-depth: 0
          clean: false
          # On recovery dispatch, check out the tag so goreleaser releases it;
          # empty ref (push flow) checks out the triggering commit.
          ref: ${{ inputs.tag }}

      # nix-hash, required by goreleaser's `nix` block to compute the NUR sha256.
      - uses: cachix/install-nix-action@v31

      - name: Bootstrap cluster access + buildx builder
        env:
          KUBECONFIG_DATA: ${{ secrets.KUBECONFIG_CASCADE }}
        run: |
          # Keep the kubeconfig OUT of the repo checkout: goreleaser aborts on a
          # dirty tree, and a kubeconfig in the workspace is an untracked file.
          # ($RUNNER_TEMP is only available in steps, not at job-level env.)
          # export (not just assign) so subprocesses in this step - e.g.
          # `docker buildx create --driver kubernetes` - inherit it; GITHUB_ENV
          # carries it to later steps (build-dist's kubectl).
          export KUBECONFIG="$RUNNER_TEMP/.kube-cascade"
          echo "KUBECONFIG=$KUBECONFIG" >> "$GITHUB_ENV"
          # Remove any kubeconfig a prior run left in the workspace (clean:false
          # preserves untracked files) so it can't dirty the tree.
          rm -f "${{ github.workspace }}/.kube-cascade"
          printf '%s' "$KUBECONFIG_DATA" | base64 -d > "$KUBECONFIG"
          chmod 600 "$KUBECONFIG"
          # buildx builder state is client-side; on a fresh runner re-register it.
          # Drop any stale in-cluster deployment first so create is idempotent.
          docker buildx rm pond-hetzner 2>/dev/null || true
          docker buildx create --name pond-hetzner --driver kubernetes \
            --driver-opt namespace=pond-buildkit,replicas=1,nodeselector=workload=buildkit,timeout=10m \
            --driver-opt requests.cpu=6,requests.memory=12Gi,limits.memory=14Gi \
            --platform linux/amd64

      # Cross-compiles all 4 targets on the Hetzner buildkit pool (kache S3 +
      # bazel-remote), exactly as local; drops binaries in target/dist/.
      - name: Build dist binaries
        run: moon run pond:build-dist
        env:
          KACHE_S3_ACCESS_KEY: ${{ secrets.KACHE_S3_ACCESS_KEY }}
          KACHE_S3_SECRET_KEY: ${{ secrets.KACHE_S3_SECRET_KEY }}
          KACHE_S3_REGION: nbg1
          # Bucket-virtual-host form; build-dist strips the bucket subdomain to
          # derive the buildx S3 cache endpoint.
          KACHE_S3_ENDPOINT: https://ttq.nbg1.your-objectstorage.com

      # builder: prebuilt - packages target/dist/ into archives + brew/nix/release.
      - uses: goreleaser/goreleaser-action@v7
        with:
          distribution: goreleaser-pro   # `builder: prebuilt` is a Pro feature
          version: '~> v2'
          args: release --clean
        env:
          GITHUB_TOKEN: ${{ secrets.GH_RELEASE_TOKEN }}
          GH_RELEASE_TOKEN: ${{ secrets.GH_RELEASE_TOKEN }}
          GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}