Release #144
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| platforms: | |
| description: "Comma-separated platforms (like --platforms). Ignored if all_platforms=true" | |
| required: false | |
| default: "linux-x86_64,macos-aarch64,linux-aarch64" | |
| all_platforms: | |
| description: "Build all platforms (like --all-platforms)" | |
| type: boolean | |
| required: false | |
| default: false | |
| github_release: | |
| description: "Publish GitHub Release" | |
| type: boolean | |
| required: false | |
| default: true | |
| pre_release: | |
| description: "Mark GitHub release as pre-release" | |
| type: boolean | |
| required: false | |
| default: true | |
| docker_push: | |
| description: "Push Docker image to Docker Hub" | |
| type: boolean | |
| required: false | |
| default: true | |
| docker_repo: | |
| description: "Docker Hub repo (owner/name)" | |
| required: false | |
| default: "jamals86/kalamdb" | |
| permissions: | |
| contents: write | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_VERSION: "1.92.0" | |
| WASM_PACK_VERSION: "0.14.0" | |
| PG_EXTENSION_MAJOR: "16" | |
| PG_EXTENSION_FLAVOR: "pg16" | |
| PGRX_VERSION: "0.17.0" | |
| DEFAULT_PLATFORMS: "linux-x86_64,macos-aarch64,linux-aarch64" | |
| RUSTC_WRAPPER: "" | |
| CARGO_BUILD_RUSTC_WRAPPER: "" | |
| jobs: | |
| read_version: | |
| name: Read Version from Cargo.toml | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| tag: ${{ steps.version.outputs.tag }} | |
| pre_release: ${{ steps.version.outputs.pre_release }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Read version and set outputs | |
| id: version | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="$(sed -n '/^\[workspace.package\]/,/^\[/{s/^version[[:space:]]*=[[:space:]]*"\([^"]*\)".*/\1/p}' Cargo.toml | head -n1)" | |
| if [[ -z "$VERSION" ]]; then | |
| echo "Failed to read [workspace.package].version from Cargo.toml" >&2 | |
| exit 1 | |
| fi | |
| TAG="v${VERSION}" | |
| PRE_RELEASE="${{ github.event.inputs.pre_release }}" | |
| if [[ -z "$PRE_RELEASE" ]]; then | |
| PRE_RELEASE="true" | |
| fi | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | |
| echo "pre_release=$PRE_RELEASE" >> "$GITHUB_OUTPUT" | |
| echo "✅ Version: $VERSION, Tag: $TAG, Pre-release: $PRE_RELEASE" | |
| license_compliance: | |
| name: License Compliance | |
| runs-on: ubuntu-latest | |
| needs: read_version | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| - name: Setup Node 22 | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| - name: Install cargo-license | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cargo install cargo-license --locked | |
| - name: Generate Rust runtime license report | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p target/license | |
| cargo license -j --avoid-dev-deps --avoid-build-deps -o target/license/rust-runtime-licenses.json | |
| - name: Install UI dependencies | |
| shell: bash | |
| working-directory: ui | |
| run: | | |
| set -euo pipefail | |
| npm install --no-audit --no-fund | |
| - name: Generate UI production license report | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cd ui | |
| npx --yes license-checker --production --excludePrivatePackages --json > ../target/license/ui-licenses.json | |
| - name: Install SDK dependencies | |
| shell: bash | |
| working-directory: link/sdks/typescript/client | |
| run: | | |
| set -euo pipefail | |
| npm install --no-audit --no-fund | |
| - name: Generate SDK production license report | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cd link/sdks/typescript/client | |
| npx --yes license-checker --production --json > "$GITHUB_WORKSPACE/target/license/sdk-licenses.json" | |
| - name: Validate and generate third-party report | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| python3 scripts/license_compliance.py \ | |
| --policy cargo-license-check.toml \ | |
| --rust-report target/license/rust-runtime-licenses.json \ | |
| --ui-report target/license/ui-licenses.json \ | |
| --sdk-report target/license/sdk-licenses.json \ | |
| --output target/license/THIRD_PARTY_LICENSES.md | |
| - name: Build release license bundle | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| mkdir -p "dist/$VERSION" | |
| cp LICENSE.txt "dist/$VERSION/LICENSE.txt" | |
| cp NOTICE "dist/$VERSION/NOTICE" | |
| cp target/license/THIRD_PARTY_LICENSES.md "dist/$VERSION/THIRD_PARTY_LICENSES.md" | |
| - name: Upload license artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: dist-licenses | |
| path: | | |
| dist/${{ needs.read_version.outputs.version }}/LICENSE.txt | |
| dist/${{ needs.read_version.outputs.version }}/NOTICE | |
| dist/${{ needs.read_version.outputs.version }}/THIRD_PARTY_LICENSES.md | |
| if-no-files-found: error | |
| build_ui: | |
| name: Build Admin UI | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| targets: wasm32-unknown-unknown | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: wasm-build | |
| cache-on-failure: true | |
| - name: Setup Node 22 | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| - name: Install wasm-pack | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cargo install wasm-pack --version "$WASM_PACK_VERSION" --locked | |
| wasm-pack --version | |
| - name: Build SDK (@kalamdb/client) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cd link/sdks/typescript/client | |
| npm install | |
| npm run build | |
| - name: Build Admin UI | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cd ui | |
| npm install | |
| npm run build | |
| - name: Upload UI dist | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: ui-dist | |
| path: ui/dist/ | |
| if-no-files-found: error | |
| build_cli_linux_x86_64: | |
| name: Build CLI Linux x86_64 | |
| runs-on: ubuntu-24.04 | |
| needs: read_version | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| targets: x86_64-unknown-linux-gnu | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: cli-linux-x86_64-ubuntu-24-04 | |
| cache-on-failure: true | |
| - name: Install system deps | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| clang \ | |
| libclang-dev \ | |
| pkg-config \ | |
| libssl-dev | |
| - name: Build CLI linux-x86_64 | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cargo build \ | |
| --profile release-dist \ | |
| --target x86_64-unknown-linux-gnu \ | |
| --bin kalam | |
| - name: Package CLI artifact | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| mkdir -p dist/$VERSION | |
| CLI_OUT="kalamcli-${VERSION}-linux-x86_64" | |
| cp "target/x86_64-unknown-linux-gnu/release-dist/kalam" "dist/$VERSION/$CLI_OUT" | |
| chmod +x "dist/$VERSION/$CLI_OUT" | |
| (cd "dist/$VERSION" && tar -czf "$CLI_OUT.tar.gz" "$CLI_OUT") | |
| - name: Upload CLI artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: dist-cli-linux-x86_64 | |
| path: dist/${{ needs.read_version.outputs.version }}/*.tar.gz | |
| if-no-files-found: error | |
| build_cli_windows_x86_64: | |
| name: Build CLI Windows x86_64 | |
| runs-on: ubuntu-latest | |
| needs: read_version | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| targets: x86_64-pc-windows-gnu | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: cli-windows-x86_64 | |
| cache-on-failure: true | |
| - name: Install system deps | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends zip mingw-w64 | |
| - name: Install cross | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cargo install cross --locked | |
| - name: Build CLI windows-x86_64 | |
| shell: bash | |
| env: | |
| CROSS_CONTAINER_ENGINE_NO_BUILDKIT: "0" | |
| run: | | |
| set -euo pipefail | |
| cross build \ | |
| --profile release-dist \ | |
| --target x86_64-pc-windows-gnu \ | |
| --bin kalam | |
| - name: Package CLI artifact | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| mkdir -p dist/$VERSION | |
| CLI_OUT="kalamcli-${VERSION}-windows-x86_64.exe" | |
| cp "target/x86_64-pc-windows-gnu/release-dist/kalam.exe" "dist/$VERSION/$CLI_OUT" | |
| CROSS_IMAGE="ghcr.io/cross-rs/x86_64-pc-windows-gnu:latest" | |
| docker run --rm -v "$PWD":/work "$CROSS_IMAGE" bash -lc '\ | |
| set -euo pipefail; \ | |
| DLL_DIR=/usr/x86_64-w64-mingw32/bin; \ | |
| for dll in libstdc++-6.dll libgcc_s_seh-1.dll libwinpthread-1.dll; do \ | |
| if [[ ! -f "${DLL_DIR}/${dll}" ]]; then \ | |
| echo "WARNING: Missing ${dll} in ${DLL_DIR}" >&2; \ | |
| continue; \ | |
| fi; \ | |
| cp "${DLL_DIR}/${dll}" "/work/dist/'"$VERSION"'/"; \ | |
| done' || echo "WARNING: Failed to copy Windows runtime DLLs from cross image" | |
| (cd "dist/$VERSION" && zip -q "${CLI_OUT%.exe}.zip" "$CLI_OUT" *.dll 2>/dev/null || zip -q "${CLI_OUT%.exe}.zip" "$CLI_OUT") | |
| - name: Upload CLI artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: dist-cli-windows-x86_64 | |
| path: dist/${{ needs.read_version.outputs.version }}/*.zip | |
| if-no-files-found: error | |
| build_cli_macos_arm: | |
| name: Build CLI macOS ARM | |
| runs-on: macos-14 | |
| needs: read_version | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| targets: aarch64-apple-darwin | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: cli-macos-aarch64 | |
| cache-on-failure: true | |
| - name: Install LLVM (fix libclang.dylib) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| brew install llvm@16 | |
| echo "LIBCLANG_PATH=$(brew --prefix llvm@16)/lib" >> "$GITHUB_ENV" | |
| echo "LLVM_CONFIG_PATH=$(brew --prefix llvm@16)/bin/llvm-config" >> "$GITHUB_ENV" | |
| - name: Build CLI macos-aarch64 | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cargo build \ | |
| --profile release-dist \ | |
| --target aarch64-apple-darwin \ | |
| --bin kalam | |
| - name: Package CLI artifact | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| mkdir -p dist/$VERSION | |
| CLI_OUT="kalamcli-${VERSION}-macos-aarch64" | |
| cp "target/aarch64-apple-darwin/release-dist/kalam" "dist/$VERSION/$CLI_OUT" | |
| chmod +x "dist/$VERSION/$CLI_OUT" | |
| (cd "dist/$VERSION" && tar -czf "$CLI_OUT.tar.gz" "$CLI_OUT") | |
| - name: Upload CLI artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: dist-cli-macos-arm | |
| path: dist/${{ needs.read_version.outputs.version }}/*.tar.gz | |
| if-no-files-found: error | |
| build_linux_x86_64: | |
| name: Build Server Linux x86_64 | |
| runs-on: ubuntu-24.04 | |
| needs: [build_ui, read_version] | |
| env: | |
| PLATFORMS_INPUT: ${{ github.event.inputs.platforms }} | |
| ALL_PLATFORMS_INPUT: ${{ github.event.inputs.all_platforms }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Determine platforms | |
| id: vars | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # Determine requested platforms for this run | |
| PLATFORMS_INPUT="${PLATFORMS_INPUT:-}" | |
| if [[ -z "${PLATFORMS_INPUT}" ]]; then | |
| PLATFORMS_INPUT="${{ env.DEFAULT_PLATFORMS }}" | |
| fi | |
| if [[ "${{ github.event_name }}" == "push" ]]; then | |
| PLATFORMS_INPUT="${{ env.DEFAULT_PLATFORMS }}" | |
| fi | |
| if [[ "${ALL_PLATFORMS_INPUT:-}" == "true" ]]; then | |
| PLATFORMS_INPUT="linux-x86_64,linux-aarch64,macos-x86_64,macos-aarch64,windows-x86_64" | |
| fi | |
| BUILD_LINUX=false | |
| if [[ "$PLATFORMS_INPUT" == *"linux-x86_64"* ]]; then BUILD_LINUX=true; fi | |
| { | |
| echo "platforms=$PLATFORMS_INPUT" | |
| echo "build_linux=$BUILD_LINUX" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Download UI dist | |
| if: ${{ steps.vars.outputs.build_linux == 'true' }} | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: ui-dist | |
| path: ui/dist | |
| - name: Setup Rust | |
| if: ${{ steps.vars.outputs.build_linux == 'true' }} | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| targets: x86_64-unknown-linux-gnu | |
| - name: Cache Rust | |
| if: ${{ steps.vars.outputs.build_linux == 'true' }} | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: server-linux-x86_64-ubuntu-24-04 | |
| cache-on-failure: true | |
| - name: Install system deps | |
| if: ${{ steps.vars.outputs.build_linux == 'true' }} | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| clang \ | |
| libclang-dev \ | |
| pkg-config \ | |
| libssl-dev | |
| - name: Build linux-x86_64 (release-dist) | |
| if: ${{ steps.vars.outputs.build_linux == 'true' }} | |
| shell: bash | |
| env: | |
| SKIP_UI_BUILD: "1" | |
| run: | | |
| set -euo pipefail | |
| cargo build \ | |
| --profile release-dist \ | |
| --target x86_64-unknown-linux-gnu \ | |
| --bin kalamdb-server | |
| - name: Package linux artifacts | |
| if: ${{ steps.vars.outputs.build_linux == 'true' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| mkdir -p dist/$VERSION | |
| SRV_OUT="kalamdb-server-${VERSION}-linux-x86_64" | |
| cp "target/x86_64-unknown-linux-gnu/release-dist/kalamdb-server" "dist/$VERSION/$SRV_OUT" | |
| chmod +x "dist/$VERSION/$SRV_OUT" | |
| (cd "dist/$VERSION" && tar -czf "$SRV_OUT.tar.gz" "$SRV_OUT") | |
| - name: Upload artifacts | |
| if: ${{ steps.vars.outputs.build_linux == 'true' }} | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: dist-linux-x86_64 | |
| path: dist/${{ needs.read_version.outputs.version }}/* | |
| if-no-files-found: error | |
| build_linux_aarch64: | |
| name: Build Server Linux ARM64 | |
| runs-on: ubuntu-latest | |
| needs: [build_ui, read_version] | |
| env: | |
| PLATFORMS_INPUT: ${{ github.event.inputs.platforms }} | |
| ALL_PLATFORMS_INPUT: ${{ github.event.inputs.all_platforms }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Set build flags | |
| id: vars | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # Always build linux-aarch64 for Docker multi-arch support | |
| BUILD_LINUX_ARM=true | |
| { | |
| echo "build_linux_arm=$BUILD_LINUX_ARM" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Download UI dist | |
| if: ${{ steps.vars.outputs.build_linux_arm == 'true' }} | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: ui-dist | |
| path: ui/dist | |
| - name: Setup Rust | |
| if: ${{ steps.vars.outputs.build_linux_arm == 'true' }} | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| targets: aarch64-unknown-linux-gnu | |
| - name: Cache Rust | |
| if: ${{ steps.vars.outputs.build_linux_arm == 'true' }} | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: server-linux-aarch64 | |
| cache-on-failure: true | |
| - name: Install cross | |
| if: ${{ steps.vars.outputs.build_linux_arm == 'true' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cargo install cross --locked | |
| - name: Build linux-aarch64 (cross, docker profile) | |
| if: ${{ steps.vars.outputs.build_linux_arm == 'true' }} | |
| shell: bash | |
| env: | |
| CROSS_CONTAINER_ENGINE_NO_BUILDKIT: "0" | |
| SKIP_UI_BUILD: "1" | |
| run: | | |
| set -euo pipefail | |
| cross build \ | |
| --profile docker \ | |
| --target aarch64-unknown-linux-gnu \ | |
| --bin kalamdb-server | |
| - name: Package linux-aarch64 artifacts | |
| if: ${{ steps.vars.outputs.build_linux_arm == 'true' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| mkdir -p dist/$VERSION | |
| SRV_OUT="kalamdb-server-${VERSION}-linux-aarch64" | |
| cp "target/aarch64-unknown-linux-gnu/docker/kalamdb-server" "dist/$VERSION/$SRV_OUT" | |
| chmod +x "dist/$VERSION/$SRV_OUT" | |
| (cd "dist/$VERSION" && tar -czf "$SRV_OUT.tar.gz" "$SRV_OUT") | |
| - name: Upload artifacts | |
| if: ${{ steps.vars.outputs.build_linux_arm == 'true' }} | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: dist-linux-aarch64 | |
| path: dist/${{ needs.read_version.outputs.version }}/* | |
| if-no-files-found: error | |
| build_cli_linux_aarch64: | |
| name: Build CLI Linux ARM64 | |
| runs-on: ubuntu-latest | |
| needs: read_version | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| targets: aarch64-unknown-linux-gnu | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: cli-linux-aarch64 | |
| cache-on-failure: true | |
| - name: Install cross | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cargo install cross --locked | |
| - name: Build CLI linux-aarch64 | |
| shell: bash | |
| env: | |
| CROSS_CONTAINER_ENGINE_NO_BUILDKIT: "0" | |
| run: | | |
| set -euo pipefail | |
| cross build \ | |
| --profile docker \ | |
| --target aarch64-unknown-linux-gnu \ | |
| --bin kalam | |
| - name: Package CLI artifact | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| mkdir -p dist/$VERSION | |
| CLI_OUT="kalamcli-${VERSION}-linux-aarch64" | |
| cp "target/aarch64-unknown-linux-gnu/docker/kalam" "dist/$VERSION/$CLI_OUT" | |
| chmod +x "dist/$VERSION/$CLI_OUT" | |
| (cd "dist/$VERSION" && tar -czf "$CLI_OUT.tar.gz" "$CLI_OUT") | |
| - name: Upload CLI artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: dist-cli-linux-aarch64 | |
| path: dist/${{ needs.read_version.outputs.version }}/*.tar.gz | |
| if-no-files-found: error | |
| build_windows_x86_64: | |
| name: Build Windows x86_64 | |
| runs-on: ubuntu-latest | |
| needs: [build_ui, read_version] | |
| env: | |
| PLATFORMS_INPUT: ${{ github.event.inputs.platforms }} | |
| ALL_PLATFORMS_INPUT: ${{ github.event.inputs.all_platforms }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Determine platforms | |
| id: vars | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| PLATFORMS_INPUT="${PLATFORMS_INPUT:-}" | |
| if [[ -z "${PLATFORMS_INPUT}" ]]; then | |
| PLATFORMS_INPUT="${{ env.DEFAULT_PLATFORMS }}" | |
| fi | |
| if [[ "${{ github.event_name }}" == "push" ]]; then | |
| PLATFORMS_INPUT="${{ env.DEFAULT_PLATFORMS }}" | |
| fi | |
| if [[ "${ALL_PLATFORMS_INPUT:-}" == "true" ]]; then | |
| PLATFORMS_INPUT="linux-x86_64,linux-aarch64,macos-x86_64,macos-aarch64,windows-x86_64" | |
| fi | |
| BUILD_WINDOWS=false | |
| if [[ "$PLATFORMS_INPUT" == *"windows-x86_64"* ]]; then BUILD_WINDOWS=true; fi | |
| { | |
| echo "platforms=$PLATFORMS_INPUT" | |
| echo "build_windows=$BUILD_WINDOWS" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Download UI dist | |
| if: ${{ steps.vars.outputs.build_windows == 'true' }} | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: ui-dist | |
| path: ui/dist | |
| - name: Setup Rust | |
| if: ${{ steps.vars.outputs.build_windows == 'true' }} | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| targets: x86_64-pc-windows-gnu | |
| - name: Cache Rust | |
| if: ${{ steps.vars.outputs.build_windows == 'true' }} | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: server-windows-x86_64 | |
| cache-on-failure: true | |
| - name: Install system deps | |
| if: ${{ steps.vars.outputs.build_windows == 'true' }} | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends zip mingw-w64 | |
| - name: Install cross | |
| if: ${{ steps.vars.outputs.build_windows == 'true' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cargo install cross --locked | |
| - name: Build windows-x86_64 (cross, release-dist profile) | |
| if: ${{ steps.vars.outputs.build_windows == 'true' }} | |
| shell: bash | |
| env: | |
| CROSS_CONTAINER_ENGINE_NO_BUILDKIT: "0" | |
| SKIP_UI_BUILD: "1" | |
| run: | | |
| set -euo pipefail | |
| cross build \ | |
| --profile release-dist \ | |
| --target x86_64-pc-windows-gnu \ | |
| --bin kalamdb-server | |
| - name: Package windows artifacts | |
| if: ${{ steps.vars.outputs.build_windows == 'true' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| mkdir -p dist/$VERSION | |
| SRV_OUT="kalamdb-server-${VERSION}-windows-x86_64.exe" | |
| cp "target/x86_64-pc-windows-gnu/release-dist/kalamdb-server.exe" "dist/$VERSION/$SRV_OUT" | |
| for dll in libstdc++-6.dll libgcc_s_seh-1.dll libwinpthread-1.dll; do | |
| dll_path="$(x86_64-w64-mingw32-gcc -print-file-name="$dll" 2>/dev/null || true)" | |
| if [[ -z "$dll_path" || "$dll_path" == "$dll" || ! -f "$dll_path" ]]; then | |
| dll_path="$(find /usr /opt -path "*x86_64-w64-mingw32*" -type f -name "$dll" -print -quit 2>/dev/null || true)" | |
| fi | |
| if [[ -z "$dll_path" || ! -f "$dll_path" ]]; then | |
| echo "Missing $dll (searched via x86_64-w64-mingw32-gcc and /usr,/opt)" >&2 | |
| exit 1 | |
| fi | |
| cp "$dll_path" "dist/$VERSION/" | |
| done | |
| (cd "dist/$VERSION" && zip -q "${SRV_OUT%.exe}.zip" "$SRV_OUT" libstdc++-6.dll libgcc_s_seh-1.dll libwinpthread-1.dll) | |
| - name: Upload artifacts | |
| if: ${{ steps.vars.outputs.build_windows == 'true' }} | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: dist-windows-x86_64 | |
| path: dist/${{ needs.read_version.outputs.version }}/* | |
| if-no-files-found: error | |
| build_macos_arm: | |
| name: Build macOS ARM | |
| runs-on: macos-14 | |
| needs: [build_ui, read_version] | |
| env: | |
| PLATFORMS_INPUT: ${{ github.event.inputs.platforms }} | |
| ALL_PLATFORMS_INPUT: ${{ github.event.inputs.all_platforms }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Determine platforms | |
| id: vars | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| PLATFORMS_INPUT="${PLATFORMS_INPUT:-}" | |
| if [[ -z "${PLATFORMS_INPUT}" ]]; then | |
| PLATFORMS_INPUT="${{ env.DEFAULT_PLATFORMS }}" | |
| fi | |
| if [[ "${{ github.event_name }}" == "push" ]]; then | |
| PLATFORMS_INPUT="${{ env.DEFAULT_PLATFORMS }}" | |
| fi | |
| if [[ "${ALL_PLATFORMS_INPUT:-}" == "true" ]]; then | |
| PLATFORMS_INPUT="linux-x86_64,linux-aarch64,macos-x86_64,macos-aarch64,windows-x86_64" | |
| fi | |
| BUILD_MACOS=false | |
| if [[ "$PLATFORMS_INPUT" == *"macos-aarch64"* ]]; then BUILD_MACOS=true; fi | |
| { | |
| echo "platforms=$PLATFORMS_INPUT" | |
| echo "build_macos=$BUILD_MACOS" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Download UI dist | |
| if: ${{ steps.vars.outputs.build_macos == 'true' }} | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: ui-dist | |
| path: ui/dist | |
| - name: Setup Rust | |
| if: ${{ steps.vars.outputs.build_macos == 'true' }} | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| targets: aarch64-apple-darwin | |
| - name: Cache Rust | |
| if: ${{ steps.vars.outputs.build_macos == 'true' }} | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: server-macos-aarch64 | |
| cache-on-failure: true | |
| - name: Install LLVM (fix libclang.dylib) | |
| if: ${{ steps.vars.outputs.build_macos == 'true' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| brew install llvm@16 | |
| echo "LIBCLANG_PATH=$(brew --prefix llvm@16)/lib" >> "$GITHUB_ENV" | |
| echo "LLVM_CONFIG_PATH=$(brew --prefix llvm@16)/bin/llvm-config" >> "$GITHUB_ENV" | |
| - name: Build macos-aarch64 (release-dist) | |
| if: ${{ steps.vars.outputs.build_macos == 'true' }} | |
| shell: bash | |
| env: | |
| SKIP_UI_BUILD: "1" | |
| run: | | |
| set -euo pipefail | |
| cargo build \ | |
| --profile release-dist \ | |
| --target aarch64-apple-darwin \ | |
| --bin kalamdb-server | |
| - name: Smoke test macOS ARM server | |
| if: ${{ steps.vars.outputs.build_macos == 'true' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cp backend/server.example.toml server.toml | |
| sed -i '' 's|rocksdb_path = "./data/rocksdb"|rocksdb_path = "./test-data/rocksdb"|g' server.toml | |
| sed -i '' 's|default_storage_path = "./data/storage"|default_storage_path = "./test-data/storage"|g' server.toml | |
| sed -i '' 's|logs_path = "./logs"|logs_path = "./test-data/logs"|g' server.toml | |
| sed -i '' 's|jwt_secret = ".*"|jwt_secret = "smoke-test-secret-key-minimum-32-characters-long-for-ci"|g' server.toml | |
| mkdir -p test-data/rocksdb test-data/storage test-data/logs | |
| ./target/aarch64-apple-darwin/release-dist/kalamdb-server & | |
| SERVER_PID=$! | |
| echo "Waiting for server to start..." | |
| for i in {1..60}; do | |
| if curl -s http://localhost:8080/v1/api/healthcheck > /dev/null 2>&1; then | |
| echo "Server is ready!" | |
| break | |
| fi | |
| if ! kill -0 $SERVER_PID 2>/dev/null; then | |
| echo "Server process died" | |
| exit 1 | |
| fi | |
| echo "Waiting... ($i/60)" | |
| sleep 1 | |
| done | |
| if ! curl -s http://localhost:8080/v1/api/healthcheck > /dev/null 2>&1; then | |
| echo "Server failed to start within 60 seconds" | |
| kill $SERVER_PID 2>/dev/null || true | |
| exit 1 | |
| fi | |
| kill $SERVER_PID 2>/dev/null || true | |
| - name: Package macOS artifacts | |
| if: ${{ steps.vars.outputs.build_macos == 'true' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| mkdir -p dist/$VERSION | |
| SRV_OUT="kalamdb-server-${VERSION}-macos-aarch64" | |
| cp "target/aarch64-apple-darwin/release-dist/kalamdb-server" "dist/$VERSION/$SRV_OUT" | |
| chmod +x "dist/$VERSION/$SRV_OUT" | |
| (cd "dist/$VERSION" && tar -czf "$SRV_OUT.tar.gz" "$SRV_OUT") | |
| - name: Upload artifacts (macos arm) | |
| if: ${{ steps.vars.outputs.build_macos == 'true' }} | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: dist-macos-arm | |
| path: dist/${{ needs.read_version.outputs.version }}/* | |
| if-no-files-found: error | |
| # ═══════════════════════════════════════════════════════════════════════════ | |
| # PG EXTENSION - Build pg_kalam PostgreSQL extension for Linux | |
| # ═══════════════════════════════════════════════════════════════════════════ | |
| build_pg_extension_x86_64: | |
| name: Build PG Extension Linux x86_64 | |
| runs-on: ubuntu-latest | |
| needs: read_version | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Build extension in Docker (x86_64 Bookworm) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # Build the builder image for the selected PostgreSQL major. | |
| docker build \ | |
| --build-arg PG_MAJOR="$PG_EXTENSION_MAJOR" \ | |
| --build-arg PGRX_VERSION="$PGRX_VERSION" \ | |
| -f pg/docker/Dockerfile.builder-base \ | |
| -t pg-kalam-builder-x86 \ | |
| . | |
| # Compile extension inside the Bookworm container | |
| mkdir -p artifacts .cargo/pg-extension-x86/registry .cargo/pg-extension-x86/git .cargo/pg-extension-x86/target | |
| docker run --rm \ | |
| -v "$PWD:/src:ro" \ | |
| -v "$PWD/artifacts:/artifacts" \ | |
| -v "$PWD/.cargo/pg-extension-x86/registry:/usr/local/cargo/registry" \ | |
| -v "$PWD/.cargo/pg-extension-x86/git:/usr/local/cargo/git" \ | |
| -v "$PWD/.cargo/pg-extension-x86/target:/target-cache" \ | |
| -e CARGO_INCREMENTAL=0 \ | |
| -e CARGO_TARGET_DIR=/target-cache \ | |
| -e RUSTFLAGS="-Cdebuginfo=0" \ | |
| -e PG_EXTENSION_MAJOR \ | |
| -e PG_EXTENSION_FLAVOR \ | |
| pg-kalam-builder-x86 \ | |
| bash -c ' | |
| cd /src && \ | |
| cargo pgrx install \ | |
| -p kalam-pg-extension \ | |
| -c "/usr/lib/postgresql/${PG_EXTENSION_MAJOR}/bin/pg_config" \ | |
| --no-default-features \ | |
| --profile release-pg \ | |
| -F ${PG_EXTENSION_FLAVOR} && \ | |
| LIBDIR="$(/usr/lib/postgresql/${PG_EXTENSION_MAJOR}/bin/pg_config --pkglibdir)" && \ | |
| SQLDIR="$(/usr/lib/postgresql/${PG_EXTENSION_MAJOR}/bin/pg_config --sharedir)/extension" && \ | |
| cp "$LIBDIR/pg_kalam.so" /artifacts/ && \ | |
| cp "$SQLDIR/pg_kalam.control" /artifacts/ && \ | |
| cp "$SQLDIR"/pg_kalam--*.sql /artifacts/ | |
| ' | |
| - name: Package extension artifacts | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| PKG="pg_kalam-${VERSION}-${PG_EXTENSION_FLAVOR}-linux-x86_64" | |
| mkdir -p "dist/${VERSION}/${PKG}" | |
| cp artifacts/pg_kalam.so "dist/${VERSION}/${PKG}/" | |
| cp artifacts/pg_kalam.control "dist/${VERSION}/${PKG}/" | |
| cp artifacts/pg_kalam--*.sql "dist/${VERSION}/${PKG}/" | |
| cat > "dist/${VERSION}/${PKG}/install.sh" << 'INSTALL_EOF' | |
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | |
| PG_CONFIG="${1:-pg_config}" | |
| LIBDIR="$("$PG_CONFIG" --pkglibdir)" | |
| SHAREDIR="$("$PG_CONFIG" --sharedir)/extension" | |
| echo "Installing pg_kalam to $LIBDIR and $SHAREDIR ..." | |
| install -m 755 "$SCRIPT_DIR/pg_kalam.so" "$LIBDIR/" | |
| install -m 644 "$SCRIPT_DIR/pg_kalam.control" "$SHAREDIR/" | |
| install -m 644 "$SCRIPT_DIR"/pg_kalam--*.sql "$SHAREDIR/" | |
| echo "Done. Run: CREATE EXTENSION pg_kalam;" | |
| INSTALL_EOF | |
| chmod +x "dist/${VERSION}/${PKG}/install.sh" | |
| (cd "dist/${VERSION}" && tar -czf "${PKG}.tar.gz" "${PKG}") | |
| rm -rf "dist/${VERSION}/${PKG}" | |
| ls -lh "dist/${VERSION}/" | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: dist-pg-extension-linux-x86_64 | |
| path: dist/${{ needs.read_version.outputs.version }}/* | |
| if-no-files-found: error | |
| # ═══════════════════════════════════════════════════════════════════════════ | |
| # SMOKE TESTS - Run against the pre-built Linux x86_64 binary | |
| # ═══════════════════════════════════════════════════════════════════════════ | |
| smoke_tests: | |
| name: Smoke Tests (Linux x86_64) | |
| runs-on: ubuntu-latest | |
| needs: | |
| - build_linux_x86_64 | |
| - build_cli_linux_x86_64 | |
| - read_version | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download server binary | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: dist-linux-x86_64 | |
| path: dist/ | |
| - name: Download CLI binary | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: dist-cli-linux-x86_64 | |
| path: dist/ | |
| - name: Install system dependencies | |
| shell: bash | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| clang \ | |
| libclang-dev \ | |
| llvm-dev \ | |
| pkg-config \ | |
| libssl-dev | |
| - name: Setup Rust (for running tests) | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: smoke-tests | |
| cache-on-failure: true | |
| - name: Install cargo-nextest | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin | |
| cargo nextest --version | |
| - name: Prepare binaries | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| find dist -name "*.tar.gz" -type f -exec tar -xzf {} -C dist/ \; | |
| SERVER_BIN=$(find dist -name "kalamdb-server-*-linux-x86_64" -type f ! -name "*.tar.gz" | head -1) | |
| [[ -z "$SERVER_BIN" ]] && { echo "Server binary not found"; exit 1; } | |
| chmod +x "$SERVER_BIN" && cp "$SERVER_BIN" ./kalamdb-server | |
| CLI_BIN=$(find dist -name "kalamcli-*-linux-x86_64" -type f ! -name "*.tar.gz" | head -1) | |
| [[ -z "$CLI_BIN" ]] && { echo "CLI binary not found"; exit 1; } | |
| chmod +x "$CLI_BIN" && cp "$CLI_BIN" ./kalamcli | |
| ls -la ./kalamdb-server ./kalamcli | |
| - name: Create server config | |
| shell: bash | |
| run: | | |
| cp backend/server.example.toml server.toml | |
| sed -i 's|rocksdb_path = "./data/rocksdb"|rocksdb_path = "./test-data/rocksdb"|g' server.toml | |
| sed -i 's|default_storage_path = "./data/storage"|default_storage_path = "./test-data/storage"|g' server.toml | |
| sed -i 's|logs_path = "./logs"|logs_path = "./test-data/logs"|g' server.toml | |
| sed -i 's|jwt_secret = ".*"|jwt_secret = "smoke-test-secret-key-minimum-32-characters-long-for-ci"|g' server.toml | |
| sed -i 's|max_queries_per_sec = 1000|max_queries_per_sec = 10000|g' server.toml | |
| sed -i 's|max_messages_per_sec = 500|max_messages_per_sec = 1000|g' server.toml | |
| - name: Start server | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p test-data/rocksdb test-data/storage test-data/logs | |
| ./kalamdb-server > server.log 2>&1 & | |
| SERVER_PID=$! | |
| echo "SERVER_PID=$SERVER_PID" >> "$GITHUB_ENV" | |
| for i in {1..60}; do | |
| if curl -sf http://localhost:8080/health > /dev/null 2>&1; then | |
| echo "✅ Server is ready (${i}s)" | |
| exit 0 | |
| fi | |
| if ! kill -0 "$SERVER_PID" 2>/dev/null; then | |
| echo "❌ Server process died" | |
| cat server.log || true | |
| exit 1 | |
| fi | |
| echo " Waiting... ($i/60)" | |
| sleep 1 | |
| done | |
| echo "❌ Timed out waiting for server" | |
| cat server.log || true | |
| exit 1 | |
| - name: Run smoke tests | |
| id: smoke_tests | |
| continue-on-error: true | |
| shell: bash | |
| env: | |
| KALAMDB_SERVER_URL: "http://localhost:8080" | |
| KALAMDB_ROOT_PASSWORD: "kalamdb123" | |
| run: | | |
| set -euo pipefail | |
| cd cli | |
| if cargo nextest run --features e2e-tests --test smoke 2>&1 | tee ../smoke-test-output.txt; then | |
| echo "smoke_tests_passed=true" >> "$GITHUB_OUTPUT" | |
| echo "✅ All smoke tests passed!" | |
| else | |
| echo "smoke_tests_passed=false" >> "$GITHUB_OUTPUT" | |
| echo "⚠️ Some smoke tests failed" | |
| fi | |
| - name: Validate packaged CLI binary | |
| shell: bash | |
| env: | |
| KALAMDB_SERVER_URL: "http://localhost:8080" | |
| run: | | |
| set -euo pipefail | |
| ./kalamcli \ | |
| -u "$KALAMDB_SERVER_URL" \ | |
| --username root \ | |
| --password kalamdb123 \ | |
| --json \ | |
| --command "SELECT 1 AS packaged_cli_release_check" \ | |
| | tee packaged-cli-smoke-output.txt | |
| grep -q 'packaged_cli_release_check' packaged-cli-smoke-output.txt | |
| - name: Stop server | |
| if: always() | |
| shell: bash | |
| run: | | |
| [[ -n "${SERVER_PID:-}" ]] && kill "$SERVER_PID" 2>/dev/null || true | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: smoke-test-results | |
| path: | | |
| smoke-test-output.txt | |
| packaged-cli-smoke-output.txt | |
| server.log | |
| if-no-files-found: ignore | |
| - name: Report test status | |
| if: always() | |
| shell: bash | |
| run: | | |
| if [[ "${{ steps.smoke_tests.outputs.smoke_tests_passed }}" == "true" ]]; then | |
| echo "::notice::✅ Smoke tests passed successfully" | |
| else | |
| echo "::error::Smoke tests failed - review smoke-test-results artifact for details" | |
| fi | |
| - name: Fail if smoke tests failed | |
| if: always() && steps.smoke_tests.outputs.smoke_tests_passed != 'true' | |
| shell: bash | |
| run: | | |
| echo "Smoke tests failed" >&2 | |
| exit 1 | |
| # ═══════════════════════════════════════════════════════════════════════════ | |
| # PG EXTENSION TESTS - Native e2e suite against live KalamDB + pgrx PostgreSQL | |
| # ═══════════════════════════════════════════════════════════════════════════ | |
| pg_extension_tests_native: | |
| name: PG Extension Tests (native) | |
| runs-on: ubuntu-latest | |
| needs: | |
| - build_linux_x86_64 | |
| - read_version | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download server binary | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: dist-linux-x86_64 | |
| path: dist/ | |
| - name: Install system dependencies | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| clang \ | |
| libclang-dev \ | |
| llvm-dev \ | |
| pkg-config \ | |
| libssl-dev \ | |
| libreadline-dev | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: pg-extension-tests-native | |
| cache-on-failure: true | |
| - name: Cache pgrx PostgreSQL install | |
| id: cache-pgrx-install | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.pgrx/${{ env.PG_EXTENSION_MAJOR }}.* | |
| ~/.pgrx/config.toml | |
| key: ${{ runner.os }}-pgrx-install-${{ env.PGRX_VERSION }}-pg${{ env.PG_EXTENSION_MAJOR }} | |
| - name: Install cargo-nextest and cargo-pgrx | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin | |
| if ! command -v cargo-pgrx >/dev/null 2>&1 || ! cargo pgrx --version | grep -q "cargo-pgrx ${PGRX_VERSION}$"; then | |
| cargo install cargo-pgrx --version "${PGRX_VERSION}" --locked | |
| fi | |
| cargo nextest --version | |
| cargo pgrx --version | |
| - name: Initialize pgrx PostgreSQL | |
| if: steps.cache-pgrx-install.outputs.cache-hit != 'true' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cargo pgrx init "--pg${PG_EXTENSION_MAJOR}" download | |
| - name: Prepare server binary | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| find dist -name "*.tar.gz" -type f -exec tar -xzf {} -C dist/ \; | |
| SERVER_BIN=$(find dist -name "kalamdb-server-*-linux-x86_64" -type f ! -name "*.tar.gz" | head -1) | |
| [[ -z "$SERVER_BIN" ]] && { echo "Server binary not found"; exit 1; } | |
| chmod +x "$SERVER_BIN" | |
| cp "$SERVER_BIN" ./kalamdb-server | |
| ls -la ./kalamdb-server | |
| - name: Create server config | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cp backend/server.example.toml server.toml | |
| sed -i 's|rocksdb_path = "./data/rocksdb"|rocksdb_path = "./test-data/rocksdb"|g' server.toml | |
| sed -i 's|default_storage_path = "./data/storage"|default_storage_path = "./test-data/storage"|g' server.toml | |
| sed -i 's|logs_path = "./logs"|logs_path = "./test-data/logs"|g' server.toml | |
| sed -i 's|jwt_secret = ".*"|jwt_secret = "pg-native-test-secret-key-minimum-32-characters-long"|g' server.toml | |
| - name: Start server | |
| shell: bash | |
| env: | |
| KALAMDB_SERVER_HOST: "0.0.0.0" | |
| KALAMDB_ROOT_PASSWORD: "kalamdb123" | |
| KALAMDB_JWT_SECRET: "pg-native-test-secret-key-minimum-32-characters-long" | |
| KALAMDB_NODE_ID: "1" | |
| KALAMDB_CLUSTER_RPC_ADDR: "0.0.0.0:9188" | |
| KALAMDB_CLUSTER_API_ADDR: "http://127.0.0.1:8080" | |
| run: | | |
| set -euo pipefail | |
| mkdir -p test-data/rocksdb test-data/storage test-data/logs | |
| ./kalamdb-server > pg-server.log 2>&1 & | |
| SERVER_PID=$! | |
| echo "SERVER_PID=$SERVER_PID" >> "$GITHUB_ENV" | |
| for i in {1..60}; do | |
| if curl -sf http://127.0.0.1:8080/health >/dev/null 2>&1; then | |
| echo "✅ Server is ready (${i}s)" | |
| exit 0 | |
| fi | |
| if ! kill -0 "$SERVER_PID" 2>/dev/null; then | |
| echo "❌ Server process died" | |
| cat pg-server.log || true | |
| exit 1 | |
| fi | |
| echo " Waiting... ($i/60)" | |
| sleep 1 | |
| done | |
| echo "❌ Timed out waiting for server" | |
| cat pg-server.log || true | |
| exit 1 | |
| - name: Setup pgrx PostgreSQL and install extension | |
| shell: bash | |
| env: | |
| PG_MAJOR: ${{ env.PG_EXTENSION_MAJOR }} | |
| PG_EXTENSION_FLAVOR: ${{ env.PG_EXTENSION_FLAVOR }} | |
| run: | | |
| set -euo pipefail | |
| ./pg/scripts/pgrx-test-setup.sh 2>&1 | tee pg-pgrx-setup-output.txt | |
| - name: Run native PG extension perf tests first | |
| shell: bash | |
| env: | |
| KALAMDB_SERVER_URL: "http://127.0.0.1:8080" | |
| KALAMDB_ROOT_PASSWORD: "kalamdb123" | |
| run: | | |
| set -euo pipefail | |
| : > pg-native-test-output.txt | |
| cargo nextest run \ | |
| -p kalam-pg-extension \ | |
| --features e2e \ | |
| --test e2e_perf \ | |
| --test-threads 1 \ | |
| 2>&1 | tee pg-native-test-output.txt | |
| - name: Run remaining native PG extension e2e tests | |
| shell: bash | |
| env: | |
| KALAMDB_SERVER_URL: "http://127.0.0.1:8080" | |
| KALAMDB_ROOT_PASSWORD: "kalamdb123" | |
| run: | | |
| set -euo pipefail | |
| cargo nextest run \ | |
| -p kalam-pg-extension \ | |
| --features e2e \ | |
| --test e2e_ddl \ | |
| --test e2e_dml \ | |
| --test e2e_scenarios \ | |
| --test extension_metadata \ | |
| --test session_settings \ | |
| --test-threads 1 \ | |
| 2>&1 | tee -a pg-native-test-output.txt | |
| - name: Stop pgrx PostgreSQL | |
| if: always() | |
| shell: bash | |
| env: | |
| PG_MAJOR: ${{ env.PG_EXTENSION_MAJOR }} | |
| PG_EXTENSION_FLAVOR: ${{ env.PG_EXTENSION_FLAVOR }} | |
| run: | | |
| ./pg/scripts/pgrx-test-setup.sh --stop || true | |
| - name: Stop server | |
| if: always() | |
| shell: bash | |
| run: | | |
| [[ -n "${SERVER_PID:-}" ]] && kill "$SERVER_PID" 2>/dev/null || true | |
| - name: Collect PG native test logs | |
| if: always() | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p pg-native-test-results | |
| cp pg-server.log pg-native-test-results/ 2>/dev/null || true | |
| cp pg-pgrx-setup-output.txt pg-native-test-results/ 2>/dev/null || true | |
| cp pg-native-test-output.txt pg-native-test-results/ 2>/dev/null || true | |
| cp "$HOME/.pgrx/data-${PG_EXTENSION_MAJOR}/pgrx.log" pg-native-test-results/pgrx.log 2>/dev/null || true | |
| - name: Upload PG native test results | |
| if: always() | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: pg-native-test-results | |
| path: pg-native-test-results/* | |
| if-no-files-found: ignore | |
| release: | |
| name: Publish GitHub Release | |
| runs-on: ubuntu-latest | |
| needs: | |
| - license_compliance | |
| - build_cli_linux_x86_64 | |
| - build_cli_linux_aarch64 | |
| - build_cli_windows_x86_64 | |
| - build_cli_macos_arm | |
| - build_linux_x86_64 | |
| - build_linux_aarch64 | |
| - build_windows_x86_64 | |
| - build_macos_arm | |
| - build_pg_extension_x86_64 | |
| - read_version | |
| - smoke_tests | |
| - pg_extension_tests_native | |
| - docker | |
| - docker_pg | |
| if: ${{ github.event_name == 'push' || github.event.inputs.github_release == 'true' }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Update README release metadata | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| TAG="${{ needs.read_version.outputs.tag }}" | |
| git fetch origin main | |
| git checkout main | |
| sed -i "s/^\*\*Latest release:\*\* .*/**Latest release:** ${TAG}/" README.md | |
| if git diff --quiet -- README.md; then | |
| echo "README already up to date" | |
| exit 0 | |
| fi | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add README.md | |
| git commit -m "docs: update release metadata" | |
| git push origin main | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v6 | |
| with: | |
| path: release-assets | |
| pattern: 'dist-*' | |
| - name: Generate SHA256SUMS | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| mkdir -p "dist/$VERSION" | |
| # Flatten artifacts into dist/<version>/ | |
| find release-assets -type f -maxdepth 4 -print0 | while IFS= read -r -d '' f; do | |
| cp "$f" "dist/$VERSION/" | |
| done | |
| cd "dist/$VERSION" | |
| if ! ls -1 ./*.tar.gz ./*.zip >/dev/null 2>&1; then | |
| echo "No release artifacts found. Check workflow inputs.platforms / all_platforms." >&2 | |
| exit 1 | |
| fi | |
| PG_EXTENSION_ASSET="pg_kalam-${VERSION}-${PG_EXTENSION_FLAVOR}-linux-x86_64.tar.gz" | |
| if [[ ! -f "$PG_EXTENSION_ASSET" ]]; then | |
| echo "Missing PostgreSQL extension release asset: $PG_EXTENSION_ASSET" >&2 | |
| exit 1 | |
| fi | |
| sha256sum ./*.tar.gz ./*.zip > SHA256SUMS | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ needs.read_version.outputs.tag }} | |
| prerelease: ${{ needs.read_version.outputs.pre_release == 'true' }} | |
| generate_release_notes: true | |
| files: | | |
| dist/${{ needs.read_version.outputs.version }}/*.tar.gz | |
| dist/${{ needs.read_version.outputs.version }}/*.zip | |
| dist/${{ needs.read_version.outputs.version }}/SHA256SUMS | |
| dist/${{ needs.read_version.outputs.version }}/LICENSE.txt | |
| dist/${{ needs.read_version.outputs.version }}/NOTICE | |
| dist/${{ needs.read_version.outputs.version }}/THIRD_PARTY_LICENSES.md | |
| docker: | |
| name: Push Docker image (Docker Hub) | |
| runs-on: ubuntu-latest | |
| needs: | |
| - build_cli_linux_x86_64 | |
| - build_cli_linux_aarch64 | |
| - build_linux_x86_64 | |
| - build_linux_aarch64 | |
| - read_version | |
| if: ${{ github.event_name == 'push' || github.event.inputs.docker_push == 'true' }} | |
| env: | |
| DOCKER_REPO_INPUT: ${{ github.event.inputs.docker_repo }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Set Docker repo | |
| id: vars | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| DOCKER_REPO="${DOCKER_REPO_INPUT:-}" | |
| DOCKER_IMAGE_SOURCE="https://github.com/${{ github.repository }}" | |
| DOCKER_IMAGE_CREATED="$(date -u +%Y-%m-%dT%H:%M:%SZ)" | |
| if [[ -z "$DOCKER_REPO" ]]; then | |
| DOCKER_REPO="jamals86/kalamdb" | |
| fi | |
| SHORT_SHA="${GITHUB_SHA:-}" | |
| if [[ -n "$SHORT_SHA" ]]; then | |
| SHORT_SHA="${SHORT_SHA:0:7}" | |
| else | |
| SHORT_SHA="$(git rev-parse --short=7 HEAD)" | |
| fi | |
| DOCKER_VERSION_COMMIT_TAG="${VERSION}-h${SHORT_SHA}" | |
| DOCKER_VALIDATE_TAG_AMD64="${VERSION}-ci-${SHORT_SHA}-amd64" | |
| DOCKER_VALIDATE_TAG_ARM64="${VERSION}-ci-${SHORT_SHA}-arm64" | |
| echo "docker_repo=$DOCKER_REPO" >> "$GITHUB_OUTPUT" | |
| echo "docker_version_commit_tag=$DOCKER_VERSION_COMMIT_TAG" >> "$GITHUB_OUTPUT" | |
| echo "docker_validate_tag_amd64=$DOCKER_VALIDATE_TAG_AMD64" >> "$GITHUB_OUTPUT" | |
| echo "docker_validate_tag_arm64=$DOCKER_VALIDATE_TAG_ARM64" >> "$GITHUB_OUTPUT" | |
| echo "docker_image_source=$DOCKER_IMAGE_SOURCE" >> "$GITHUB_OUTPUT" | |
| echo "docker_image_created=$DOCKER_IMAGE_CREATED" >> "$GITHUB_OUTPUT" | |
| - name: Download pre-built artifacts (x86_64) | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: dist-linux-x86_64 | |
| path: artifacts/server-amd64 | |
| - name: Download pre-built CLI artifact (x86_64) | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: dist-cli-linux-x86_64 | |
| path: artifacts/cli-amd64 | |
| - name: Download pre-built artifacts (aarch64) | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: dist-linux-aarch64 | |
| path: artifacts/server-arm64 | |
| - name: Download pre-built CLI artifact (aarch64) | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: dist-cli-linux-aarch64 | |
| path: artifacts/cli-arm64 | |
| - name: Extract and prepare binaries (amd64) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| mkdir -p binaries-amd64 | |
| # Extract server binary | |
| tar -xzf "artifacts/server-amd64/kalamdb-server-${VERSION}-linux-x86_64.tar.gz" -C binaries-amd64 | |
| mv "binaries-amd64/kalamdb-server-${VERSION}-linux-x86_64" binaries-amd64/kalamdb-server | |
| # Extract CLI binary | |
| tar -xzf "artifacts/cli-amd64/kalamcli-${VERSION}-linux-x86_64.tar.gz" -C binaries-amd64 | |
| mv "binaries-amd64/kalamcli-${VERSION}-linux-x86_64" binaries-amd64/kalam | |
| chmod +x binaries-amd64/kalamdb-server binaries-amd64/kalam | |
| ls -la binaries-amd64/ | |
| - name: Extract and prepare binaries (arm64) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| mkdir -p binaries-arm64 | |
| # Extract server binary | |
| tar -xzf "artifacts/server-arm64/kalamdb-server-${VERSION}-linux-aarch64.tar.gz" -C binaries-arm64 | |
| mv "binaries-arm64/kalamdb-server-${VERSION}-linux-aarch64" binaries-arm64/kalamdb-server | |
| # Extract CLI binary | |
| tar -xzf "artifacts/cli-arm64/kalamcli-${VERSION}-linux-aarch64.tar.gz" -C binaries-arm64 | |
| mv "binaries-arm64/kalamcli-${VERSION}-linux-aarch64" binaries-arm64/kalam | |
| chmod +x binaries-arm64/kalamdb-server binaries-arm64/kalam | |
| ls -la binaries-arm64/ | |
| - name: Setup QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Setup Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Build and push Docker image candidate (linux/amd64) | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: docker/build/Dockerfile.prebuilt | |
| push: true | |
| platforms: linux/amd64 | |
| build-contexts: | | |
| binaries=binaries-amd64 | |
| build-args: | | |
| OCI_IMAGE_VERSION=${{ needs.read_version.outputs.version }} | |
| OCI_IMAGE_REVISION=${{ github.sha }} | |
| OCI_IMAGE_CREATED=${{ steps.vars.outputs.docker_image_created }} | |
| OCI_IMAGE_SOURCE=${{ steps.vars.outputs.docker_image_source }} | |
| OCI_IMAGE_URL=https://kalamdb.org | |
| OCI_IMAGE_DOCUMENTATION=https://kalamdb.org/docs | |
| OCI_IMAGE_AUTHORS=Jamal Saad | |
| OCI_IMAGE_VENDOR=KalamDB | |
| OCI_IMAGE_LICENSES=Apache-2.0 | |
| tags: | | |
| ${{ steps.vars.outputs.docker_repo }}:${{ steps.vars.outputs.docker_validate_tag_amd64 }} | |
| - name: Build and push Docker image candidate (linux/arm64) | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: docker/build/Dockerfile.prebuilt | |
| push: true | |
| platforms: linux/arm64 | |
| build-contexts: | | |
| binaries=binaries-arm64 | |
| build-args: | | |
| OCI_IMAGE_VERSION=${{ needs.read_version.outputs.version }} | |
| OCI_IMAGE_REVISION=${{ github.sha }} | |
| OCI_IMAGE_CREATED=${{ steps.vars.outputs.docker_image_created }} | |
| OCI_IMAGE_SOURCE=${{ steps.vars.outputs.docker_image_source }} | |
| OCI_IMAGE_URL=https://kalamdb.org | |
| OCI_IMAGE_DOCUMENTATION=https://kalamdb.org/docs | |
| OCI_IMAGE_AUTHORS=Jamal Saad | |
| OCI_IMAGE_VENDOR=KalamDB | |
| OCI_IMAGE_LICENSES=Apache-2.0 | |
| tags: | | |
| ${{ steps.vars.outputs.docker_repo }}:${{ steps.vars.outputs.docker_validate_tag_arm64 }} | |
| - name: Validate Docker image candidate (linux/amd64) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| export KALAMDB_JWT_SECRET="$(openssl rand -base64 32)" | |
| export TEST_PORT=18081 | |
| export TIMEOUT=45 | |
| export MAX_IMAGE_SIZE_BYTES=300000000 | |
| export EXPECTED_OCI_VERSION="${{ needs.read_version.outputs.version }}" | |
| export EXPECTED_OCI_SOURCE="${{ steps.vars.outputs.docker_image_source }}" | |
| IMAGE="${{ steps.vars.outputs.docker_repo }}:${{ steps.vars.outputs.docker_validate_tag_amd64 }}" | |
| docker pull "$IMAGE" | |
| chmod +x docker/build/test-docker-image.sh | |
| ./docker/build/test-docker-image.sh "$IMAGE" 2>&1 | tee docker-image-amd64-verification.txt | |
| - name: Validate Docker image candidate (linux/arm64) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| export KALAMDB_JWT_SECRET="$(openssl rand -base64 32)" | |
| export DOCKER_PLATFORM="linux/arm64" | |
| export TEST_PORT=18082 | |
| export TIMEOUT=75 | |
| export MAX_IMAGE_SIZE_BYTES=300000000 | |
| export EXPECTED_OCI_VERSION="${{ needs.read_version.outputs.version }}" | |
| export EXPECTED_OCI_SOURCE="${{ steps.vars.outputs.docker_image_source }}" | |
| IMAGE="${{ steps.vars.outputs.docker_repo }}:${{ steps.vars.outputs.docker_validate_tag_arm64 }}" | |
| docker pull --platform linux/arm64 "$IMAGE" | |
| chmod +x docker/build/test-docker-image.sh | |
| ./docker/build/test-docker-image.sh "$IMAGE" 2>&1 | tee docker-image-arm64-verification.txt | |
| - name: Inspect validated Docker image candidates | |
| if: always() | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| { | |
| echo "Docker image candidate inspection" | |
| echo "================================" | |
| for image in \ | |
| "${{ steps.vars.outputs.docker_repo }}:${{ steps.vars.outputs.docker_validate_tag_amd64 }}" \ | |
| "${{ steps.vars.outputs.docker_repo }}:${{ steps.vars.outputs.docker_validate_tag_arm64 }}"; do | |
| echo | |
| echo "IMAGE: $image" | |
| if docker image inspect "$image" >/dev/null 2>&1; then | |
| docker image inspect "$image" --format 'user={{.Config.User}} size={{.Size}} bytes created={{.Created}}' | |
| docker image inspect "$image" --format 'version={{ index .Config.Labels "org.opencontainers.image.version" }} source={{ index .Config.Labels "org.opencontainers.image.source" }} revision={{ index .Config.Labels "org.opencontainers.image.revision" }}' | |
| else | |
| echo "image not present locally" | |
| fi | |
| done | |
| } > docker-image-inspection.txt | |
| - name: Upload Docker verification artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: docker-image-verification | |
| path: | | |
| docker-image-amd64-verification.txt | |
| docker-image-arm64-verification.txt | |
| docker-image-inspection.txt | |
| if-no-files-found: ignore | |
| - name: Promote validated Docker image (linux/amd64) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| REPO="${{ steps.vars.outputs.docker_repo }}" | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| CANDIDATE_TAG="${{ steps.vars.outputs.docker_validate_tag_amd64 }}" | |
| docker buildx imagetools create -t "${REPO}:${VERSION}-amd64" "${REPO}:${CANDIDATE_TAG}" | |
| - name: Promote validated Docker image (linux/arm64) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| REPO="${{ steps.vars.outputs.docker_repo }}" | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| CANDIDATE_TAG="${{ steps.vars.outputs.docker_validate_tag_arm64 }}" | |
| docker buildx imagetools create -t "${REPO}:${VERSION}-arm64" "${REPO}:${CANDIDATE_TAG}" | |
| - name: Create and push multi-arch manifest | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| REPO="${{ steps.vars.outputs.docker_repo }}" | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| VERSION_COMMIT_TAG="${{ steps.vars.outputs.docker_version_commit_tag }}" | |
| # Create manifest for versioned tag | |
| docker buildx imagetools create -t "${REPO}:${VERSION}" \ | |
| "${REPO}:${VERSION}-amd64" \ | |
| "${REPO}:${VERSION}-arm64" | |
| # Create manifest for version + commit tag | |
| docker buildx imagetools create -t "${REPO}:${VERSION_COMMIT_TAG}" \ | |
| "${REPO}:${VERSION}-amd64" \ | |
| "${REPO}:${VERSION}-arm64" | |
| # Create manifest for latest tag | |
| docker buildx imagetools create -t "${REPO}:latest" \ | |
| "${REPO}:${VERSION}-amd64" \ | |
| "${REPO}:${VERSION}-arm64" | |
| echo "✅ Multi-arch manifest created for ${REPO}:${VERSION}, ${REPO}:${VERSION_COMMIT_TAG}, and ${REPO}:latest" | |
| - name: Update Docker Hub repository README | |
| id: dockerhub_readme | |
| continue-on-error: true | |
| uses: peter-evans/dockerhub-description@v4 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| repository: ${{ steps.vars.outputs.docker_repo }} | |
| readme-filepath: ./docker/REPO-README.md | |
| - name: Warn if Docker Hub README update failed | |
| if: steps.dockerhub_readme.outcome == 'failure' | |
| shell: bash | |
| run: | | |
| echo "::warning::Docker image publish succeeded, but Docker Hub README update failed. Ensure DOCKERHUB_USERNAME is a repo admin and DOCKERHUB_TOKEN has read/write/delete scope." | |
| # ═══════════════════════════════════════════════════════════════════════════ | |
| # DOCKER PG - Push PostgreSQL + pg_kalam extension image to Docker Hub | |
| # ═══════════════════════════════════════════════════════════════════════════ | |
| docker_pg: | |
| name: Push PG Extension Docker image | |
| runs-on: ubuntu-latest | |
| needs: | |
| - build_pg_extension_x86_64 | |
| - docker | |
| - smoke_tests | |
| - pg_extension_tests_native | |
| - read_version | |
| if: ${{ github.event_name == 'push' || github.event.inputs.docker_push == 'true' }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Set PG candidate tag | |
| id: pg_vars | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| SHORT_SHA="${GITHUB_SHA:-}" | |
| if [[ -n "$SHORT_SHA" ]]; then | |
| SHORT_SHA="${SHORT_SHA:0:7}" | |
| else | |
| SHORT_SHA="$(git rev-parse --short=7 HEAD)" | |
| fi | |
| PG_REPO="jamals86/pg-kalam" | |
| PG_CANDIDATE_TAG="${VERSION}-${PG_EXTENSION_FLAVOR}-ci-${SHORT_SHA}" | |
| echo "pg_repo=$PG_REPO" >> "$GITHUB_OUTPUT" | |
| echo "pg_candidate_tag=$PG_CANDIDATE_TAG" >> "$GITHUB_OUTPUT" | |
| - name: Read PG image description | |
| id: pg_image_description | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| DESCRIPTION="$(tr '\n' ' ' < pg/docker/image-description.txt | sed 's/[[:space:]]\+/ /g; s/^ //; s/ $//')" | |
| echo "value=$DESCRIPTION" >> "$GITHUB_OUTPUT" | |
| - name: Download PG extension artifact (x86_64) | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: dist-pg-extension-linux-x86_64 | |
| path: pg-artifacts-amd64/ | |
| - name: Prepare extension files | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| # Extract x86_64 tarball | |
| mkdir -p pg-ext-amd64 | |
| tar -xzf "pg-artifacts-amd64/pg_kalam-${VERSION}-${PG_EXTENSION_FLAVOR}-linux-x86_64.tar.gz" -C pg-ext-amd64 --strip-components=1 | |
| echo "=== x86_64 ===" | |
| ls -lh pg-ext-amd64/ | |
| - name: Setup Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Build and push PG image candidate (amd64) | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: pg-ext-amd64 | |
| file: pg/docker/Dockerfile.release-pg | |
| push: true | |
| platforms: linux/amd64 | |
| build-args: | | |
| PG_MAJOR=${{ env.PG_EXTENSION_MAJOR }} | |
| POSTGRES_BASE_IMAGE=public.ecr.aws/docker/library/postgres:${{ env.PG_EXTENSION_MAJOR }}-bookworm | |
| OCI_IMAGE_DESCRIPTION=${{ steps.pg_image_description.outputs.value }} | |
| labels: | | |
| org.opencontainers.image.title=pg-kalam | |
| org.opencontainers.image.description=${{ steps.pg_image_description.outputs.value }} | |
| tags: | | |
| ${{ steps.pg_vars.outputs.pg_repo }}:${{ steps.pg_vars.outputs.pg_candidate_tag }} | |
| - name: Install PostgreSQL client tools | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends postgresql-client | |
| - name: Run PG Docker compose smoke suite | |
| id: pg_docker_tests | |
| continue-on-error: true | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| SERVER_REPO="${{ github.event.inputs.docker_repo }}" | |
| if [[ -z "$SERVER_REPO" ]]; then | |
| SERVER_REPO="jamals86/kalamdb" | |
| fi | |
| SERVER_IMAGE="${SERVER_REPO}:${VERSION}" | |
| PG_IMAGE="${{ steps.pg_vars.outputs.pg_repo }}:${{ steps.pg_vars.outputs.pg_candidate_tag }}" | |
| COMPOSE_FILE="pg/docker/docker-compose.test.yml" | |
| COMPOSE_PROJECT="pg-kalam-release" | |
| export KALAMDB_IMAGE="$SERVER_IMAGE" | |
| export KALAMDB_PG_IMAGE="$PG_IMAGE" | |
| export KALAMDB_TEST_HTTP_PORT=18088 | |
| export KALAMDB_TEST_RPC_PORT=19188 | |
| export KALAMDB_TEST_PG_PORT=15433 | |
| export RUST_LOG=info | |
| docker pull "$SERVER_IMAGE" | |
| docker pull "$PG_IMAGE" | |
| docker compose -f "$COMPOSE_FILE" -p "$COMPOSE_PROJECT" down -v --remove-orphans 2>/dev/null || true | |
| docker compose -f "$COMPOSE_FILE" -p "$COMPOSE_PROJECT" up -d kalamdb | |
| KALAMDB_CONTAINER_ID="$(docker compose -f "$COMPOSE_FILE" -p "$COMPOSE_PROJECT" ps -q kalamdb)" | |
| if [[ -z "$KALAMDB_CONTAINER_ID" ]]; then | |
| echo "Failed to resolve kalamdb container id" >&2 | |
| docker compose -f "$COMPOSE_FILE" -p "$COMPOSE_PROJECT" ps || true | |
| echo "pg_docker_tests_passed=false" >> "$GITHUB_OUTPUT" | |
| exit 1 | |
| fi | |
| KALAMDB_READY=false | |
| for i in {1..90}; do | |
| if docker exec "$KALAMDB_CONTAINER_ID" /usr/local/bin/busybox wget -q -O /dev/null http://127.0.0.1:8080/health >/dev/null 2>&1; then | |
| KALAMDB_READY=true | |
| break | |
| fi | |
| if [[ "$(docker inspect --format '{{.State.Status}}' "$KALAMDB_CONTAINER_ID")" != "running" ]]; then | |
| echo "KalamDB container stopped before becoming ready" >&2 | |
| docker logs "$KALAMDB_CONTAINER_ID" || true | |
| break | |
| fi | |
| sleep 1 | |
| done | |
| if [[ "$KALAMDB_READY" != "true" ]]; then | |
| echo "KalamDB container did not become ready in time" >&2 | |
| docker logs "$KALAMDB_CONTAINER_ID" || true | |
| echo "pg_docker_tests_passed=false" >> "$GITHUB_OUTPUT" | |
| exit 1 | |
| fi | |
| docker compose -f "$COMPOSE_FILE" -p "$COMPOSE_PROJECT" up -d postgres | |
| if PGHOST=127.0.0.1 \ | |
| PGPORT="$KALAMDB_TEST_PG_PORT" \ | |
| PGUSER=kalamdb \ | |
| PGPASSWORD=kalamdb123 \ | |
| PGDATABASE=kalamdb \ | |
| KALAMDB_API_URL="http://127.0.0.1:${KALAMDB_TEST_HTTP_PORT}" \ | |
| KALAMDB_PASSWORD=kalamdb123 \ | |
| ./pg/docker/test.sh 2>&1 | tee pg-docker-test-output.txt; then | |
| echo "pg_docker_tests_passed=true" >> "$GITHUB_OUTPUT" | |
| echo "✅ PG Docker image verified with compose-based smoke suite: ${PG_IMAGE}" | |
| else | |
| echo "pg_docker_tests_passed=false" >> "$GITHUB_OUTPUT" | |
| echo "⚠️ PG Docker compose smoke suite failed" | |
| fi | |
| - name: Inspect validated PG Docker image candidate | |
| if: always() | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| IMAGE="${{ steps.pg_vars.outputs.pg_repo }}:${{ steps.pg_vars.outputs.pg_candidate_tag }}" | |
| if docker image inspect "$IMAGE" >/dev/null 2>&1; then | |
| docker image inspect "$IMAGE" --format 'user={{.Config.User}} size={{.Size}} bytes created={{.Created}}' > pg-docker-image-inspection.txt | |
| docker image inspect "$IMAGE" --format 'version={{ index .Config.Labels "org.opencontainers.image.version" }} description={{ index .Config.Labels "org.opencontainers.image.description" }}' >> pg-docker-image-inspection.txt | |
| else | |
| echo "image not present locally" > pg-docker-image-inspection.txt | |
| fi | |
| - name: Capture PG Docker logs | |
| if: always() | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| docker compose -f pg/docker/docker-compose.test.yml -p pg-kalam-release logs --no-color > pg-docker-compose.log 2>&1 || true | |
| - name: Upload PG Docker test artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: pg-docker-test-results | |
| path: | | |
| pg-docker-test-output.txt | |
| pg-docker-compose.log | |
| pg-docker-image-inspection.txt | |
| if-no-files-found: ignore | |
| - name: Stop PG Docker compose stack | |
| if: always() | |
| shell: bash | |
| run: | | |
| docker compose -f pg/docker/docker-compose.test.yml -p pg-kalam-release down -v --remove-orphans 2>/dev/null || true | |
| - name: Report PG Docker test status | |
| if: always() | |
| shell: bash | |
| run: | | |
| if [[ "${{ steps.pg_docker_tests.outputs.pg_docker_tests_passed }}" == "true" ]]; then | |
| echo "::notice::✅ PG Docker compose smoke suite passed" | |
| else | |
| echo "::error::PG Docker compose smoke suite failed - review pg-docker-test-results artifact for details" | |
| fi | |
| - name: Fail if PG Docker tests failed | |
| if: always() && steps.pg_docker_tests.outputs.pg_docker_tests_passed != 'true' | |
| shell: bash | |
| run: | | |
| echo "PG Docker compose smoke suite failed" >&2 | |
| exit 1 | |
| - name: Promote validated PG Docker image | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| REPO="${{ steps.pg_vars.outputs.pg_repo }}" | |
| VERSION="${{ needs.read_version.outputs.version }}" | |
| CANDIDATE_TAG="${{ steps.pg_vars.outputs.pg_candidate_tag }}" | |
| docker buildx imagetools create -t "${REPO}:${VERSION}-${PG_EXTENSION_FLAVOR}" "${REPO}:${CANDIDATE_TAG}" | |
| docker buildx imagetools create -t "${REPO}:latest-${PG_EXTENSION_FLAVOR}" "${REPO}:${CANDIDATE_TAG}" | |