* fix: add procps to Docker image and smoke test to release workflow The Docker image was failing to start because pg0 uses `kill -0 <pid>` to check if PostgreSQL is running, but the python:3.11-slim base image doesn't include the `kill` command. Adding procps provides it. This has been broken since release 0.1.6 when the fallback URI code was removed to support dynamic ports. Without the kill command, pg0 couldn't detect process status and returned None for the database URI. Also adds smoke testing to the release workflow: - Build image locally (single platform) and test before pushing - Run container and wait for /health endpoint (up to 120s) - Only push multi-platform release images if smoke test passes - Each image (api-only, cp-only, standalone) tested independently This prevents releasing broken Docker images to GHCR. * refactor: extract smoke test into reusable script Add scripts/docker-smoke-test.sh that can be run locally or in CI: - Takes image name and optional target (cp-only vs api) - Handles LLM credentials for API/standalone images - Configurable timeout via SMOKE_TEST_TIMEOUT env var - Colored output and clear error messages - Proper cleanup on exit Update release workflow to use the script instead of inline bash.
363 lines
11 KiB
YAML
363 lines
11 KiB
YAML
name: Release
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
|
|
jobs:
|
|
release-python-packages:
|
|
runs-on: ubuntu-latest
|
|
environment: pypi
|
|
permissions:
|
|
id-token: write
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Install uv
|
|
uses: astral-sh/setup-uv@v5
|
|
with:
|
|
enable-cache: true
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version-file: ".python-version"
|
|
|
|
# Build all packages
|
|
- name: Build hindsight-client
|
|
working-directory: ./hindsight-clients/python
|
|
run: uv build --out-dir dist
|
|
|
|
- name: Build hindsight-api
|
|
working-directory: ./hindsight-api
|
|
run: uv build --out-dir dist
|
|
|
|
- name: Build hindsight-all
|
|
working-directory: ./hindsight
|
|
run: uv build --out-dir dist
|
|
|
|
- name: Build hindsight-litellm
|
|
working-directory: ./hindsight-integrations/litellm
|
|
run: uv build --out-dir dist
|
|
|
|
# Publish in order (client and api first, then hindsight-all which depends on them)
|
|
- name: Publish hindsight-client to PyPI
|
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
with:
|
|
packages-dir: ./hindsight-clients/python/dist
|
|
skip-existing: true
|
|
|
|
- name: Publish hindsight-api to PyPI
|
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
with:
|
|
packages-dir: ./hindsight-api/dist
|
|
skip-existing: true
|
|
|
|
- name: Publish hindsight-all to PyPI
|
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
with:
|
|
packages-dir: ./hindsight/dist
|
|
skip-existing: true
|
|
|
|
- name: Publish hindsight-litellm to PyPI
|
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
with:
|
|
packages-dir: ./hindsight-integrations/litellm/dist
|
|
skip-existing: true
|
|
|
|
# Upload artifacts for GitHub release
|
|
- name: Upload artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: python-packages
|
|
path: |
|
|
hindsight-clients/python/dist/*
|
|
hindsight-api/dist/*
|
|
hindsight/dist/*
|
|
hindsight-integrations/litellm/dist/*
|
|
retention-days: 1
|
|
|
|
release-typescript-client:
|
|
runs-on: ubuntu-latest
|
|
environment: npm
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Set up Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
registry-url: 'https://registry.npmjs.org'
|
|
cache: 'npm'
|
|
cache-dependency-path: package-lock.json
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --workspace=hindsight-clients/typescript
|
|
|
|
- name: Build
|
|
run: npm run build --workspace=hindsight-clients/typescript
|
|
|
|
- name: Publish to npm
|
|
working-directory: ./hindsight-clients/typescript
|
|
run: npm publish --access public
|
|
env:
|
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
|
|
- name: Pack for GitHub release
|
|
working-directory: ./hindsight-clients/typescript
|
|
run: npm pack
|
|
|
|
- name: Upload artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: typescript-client
|
|
path: hindsight-clients/typescript/*.tgz
|
|
retention-days: 1
|
|
|
|
release-rust-cli:
|
|
runs-on: ${{ matrix.os }}
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- os: ubuntu-latest
|
|
target: x86_64-unknown-linux-gnu
|
|
artifact_name: hindsight
|
|
asset_name: hindsight-linux-amd64
|
|
- os: macos-latest
|
|
target: x86_64-apple-darwin
|
|
artifact_name: hindsight
|
|
asset_name: hindsight-darwin-amd64
|
|
- os: macos-latest
|
|
target: aarch64-apple-darwin
|
|
artifact_name: hindsight
|
|
asset_name: hindsight-darwin-arm64
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Install Rust
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
targets: ${{ matrix.target }}
|
|
|
|
- name: Build
|
|
working-directory: hindsight-cli
|
|
run: cargo build --release --target ${{ matrix.target }}
|
|
|
|
- name: Prepare artifact
|
|
run: |
|
|
mkdir -p artifacts
|
|
cp hindsight-cli/target/${{ matrix.target }}/release/${{ matrix.artifact_name }} artifacts/${{ matrix.asset_name }}
|
|
chmod +x artifacts/${{ matrix.asset_name }}
|
|
|
|
- name: Upload artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: rust-cli-${{ matrix.asset_name }}
|
|
path: artifacts/${{ matrix.asset_name }}
|
|
retention-days: 1
|
|
|
|
release-docker-images:
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- target: api-only
|
|
image_name: hindsight-api
|
|
- target: cp-only
|
|
image_name: hindsight-control-plane
|
|
- target: standalone
|
|
image_name: hindsight
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Free Disk Space
|
|
uses: jlumbroso/free-disk-space@main
|
|
with:
|
|
tool-cache: false
|
|
android: true
|
|
dotnet: true
|
|
haskell: true
|
|
large-packages: true
|
|
docker-images: true
|
|
swap-storage: true
|
|
|
|
- name: Set up QEMU
|
|
uses: docker/setup-qemu-action@v3
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Log in to GitHub Container Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Extract version from tag
|
|
id: get_version
|
|
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
|
|
|
- name: Extract metadata for release tags
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}
|
|
tags: |
|
|
type=semver,pattern={{version}},value=${{ steps.get_version.outputs.VERSION }}
|
|
type=semver,pattern={{major}}.{{minor}},value=${{ steps.get_version.outputs.VERSION }}
|
|
type=semver,pattern={{major}},value=${{ steps.get_version.outputs.VERSION }}
|
|
type=raw,value=latest
|
|
|
|
# Step 1: Build for local testing (single platform, no push)
|
|
# This creates an identical image to what will be released, just for one platform
|
|
- name: Build image for testing
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
file: docker/standalone/Dockerfile
|
|
target: ${{ matrix.target }}
|
|
push: false
|
|
load: true
|
|
tags: ${{ matrix.image_name }}:test
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
# Step 2: Test the image before pushing anything
|
|
- name: Smoke test - verify container starts
|
|
env:
|
|
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
|
run: ./scripts/docker-smoke-test.sh "${{ matrix.image_name }}:test" "${{ matrix.target }}"
|
|
|
|
# Step 3: Only if smoke test passed, build multi-platform and push to release tags
|
|
# Build layers are cached, so this is fast - just builds the other platform
|
|
- name: Build and push release images
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
file: docker/standalone/Dockerfile
|
|
target: ${{ matrix.target }}
|
|
push: true
|
|
platforms: linux/amd64,linux/arm64
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
release-helm-chart:
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Install Helm
|
|
uses: azure/setup-helm@v4
|
|
with:
|
|
version: 'latest'
|
|
|
|
- name: Log in to GHCR
|
|
run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io -u ${{ github.actor }} --password-stdin
|
|
|
|
- name: Lint Helm chart
|
|
run: helm lint helm/hindsight
|
|
|
|
- name: Package Helm chart
|
|
run: helm package helm/hindsight --destination ./helm-packages
|
|
|
|
- name: Push to GHCR OCI
|
|
run: helm push helm-packages/*.tgz oci://ghcr.io/${{ github.repository_owner }}/charts
|
|
|
|
- name: Upload artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: helm-chart
|
|
path: helm-packages/*.tgz
|
|
retention-days: 1
|
|
|
|
create-github-release:
|
|
runs-on: ubuntu-latest
|
|
needs: [release-python-packages, release-typescript-client, release-rust-cli, release-docker-images, release-helm-chart]
|
|
permissions:
|
|
contents: write
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Extract version from tag
|
|
id: get_version
|
|
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
|
|
|
- name: Download Python packages
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: python-packages
|
|
path: ./artifacts/python-packages
|
|
|
|
- name: Download TypeScript client
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: typescript-client
|
|
path: ./artifacts/typescript-client
|
|
|
|
- name: Download Rust CLI (Linux)
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: rust-cli-hindsight-linux-amd64
|
|
path: ./artifacts/rust-cli-linux
|
|
|
|
- name: Download Rust CLI (macOS Intel)
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: rust-cli-hindsight-darwin-amd64
|
|
path: ./artifacts/rust-cli-darwin-amd64
|
|
|
|
- name: Download Rust CLI (macOS ARM)
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: rust-cli-hindsight-darwin-arm64
|
|
path: ./artifacts/rust-cli-darwin-arm64
|
|
|
|
- name: Download Helm chart
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: helm-chart
|
|
path: ./artifacts/helm-chart
|
|
|
|
- name: Prepare release assets
|
|
run: |
|
|
mkdir -p release-assets
|
|
# Python packages
|
|
cp artifacts/python-packages/hindsight-clients/python/dist/* release-assets/ || true
|
|
cp artifacts/python-packages/hindsight-api/dist/* release-assets/ || true
|
|
cp artifacts/python-packages/hindsight/dist/* release-assets/ || true
|
|
cp artifacts/python-packages/hindsight-integrations/litellm/dist/* release-assets/ || true
|
|
# TypeScript client
|
|
cp artifacts/typescript-client/*.tgz release-assets/ || true
|
|
# Rust CLI binaries
|
|
cp artifacts/rust-cli-linux/hindsight-linux-amd64 release-assets/ || true
|
|
cp artifacts/rust-cli-darwin-amd64/hindsight-darwin-amd64 release-assets/ || true
|
|
cp artifacts/rust-cli-darwin-arm64/hindsight-darwin-arm64 release-assets/ || true
|
|
# Helm chart
|
|
cp artifacts/helm-chart/*.tgz release-assets/ || true
|
|
ls -la release-assets/
|
|
|
|
- name: Create GitHub Release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
files: release-assets/*
|
|
generate_release_notes: true
|
|
draft: false
|
|
prerelease: false
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|