diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml
index e2cf9334a..6189fe6f7 100644
--- a/.github/workflows/docker.yaml
+++ b/.github/workflows/docker.yaml
@@ -20,7 +20,7 @@ on:
workflow_dispatch:
inputs:
process:
- description: 'Process to build (pgvector | node-sqitch | postgis)'
+ description: 'Process to build (pgvector | node-sqitch | postgis | pgvector-postgis | launchql)'
type: choice
required: true
options:
@@ -28,6 +28,7 @@ on:
- node-sqitch
- postgis
- pgvector-postgis
+ - launchql
default: pgvector
version:
description: 'Specific version to build (must exist in version.yaml)'
@@ -95,3 +96,55 @@ jobs:
REPO_NAME=$REPO \
PLATFORMS="$PLATFORMS" \
build-push-process
+
+ build-launchql:
+ if: github.event_name != 'pull_request' || !github.event.pull_request.draft
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+ packages: write
+
+ defaults:
+ run:
+ working-directory: docker
+
+ env:
+ REPO: ghcr.io/${{ github.repository_owner }}
+ PLATFORMS: linux/amd64,linux/arm64
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Login to GHCR
+ if: github.event_name != 'pull_request'
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build LaunchQL (no push)
+ if: github.event_name == 'pull_request'
+ run: |
+ make \
+ PROCESS=launchql \
+ REPO_NAME=$REPO \
+ PLATFORMS="$PLATFORMS" \
+ build-process
+
+ - name: Build and push LaunchQL (all versions)
+ if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
+ run: |
+ make \
+ PROCESS=launchql \
+ REPO_NAME=$REPO \
+ PLATFORMS="$PLATFORMS" \
+ build-push-process
diff --git a/docker/Makefile b/docker/Makefile
index 5964b5090..4e251f212 100644
--- a/docker/Makefile
+++ b/docker/Makefile
@@ -8,7 +8,7 @@ PLATFORMS?=linux/arm64
PROCESS?=pgvector
# Convenience: list of known processes
-PROCESSES:=pgvector node-sqitch postgis pgvector-postgis
+PROCESSES:=pgvector node-sqitch postgis pgvector-postgis launchql
CONTAINER_NAME?=$(PROCESS)
@@ -54,12 +54,20 @@ build-process-version:
@test -n "$(BASE)" || { echo "Error: BASE is required"; exit 1; }
@test -n "$(VERSION)" || { echo "Error: VERSION is required"; exit 1; }
@echo " -> $(BASE):$(VERSION) => $(REPO_NAME)/$(PROCESS):$(VERSION) (build)"
- @docker buildx build \
+ @DOCKERFILE_PATH="$(PROCESS)/Dockerfile"; \
+ CONTEXT=$$( \
+ if [ "$(PROCESS)" = "launchql" ]; then \
+ echo ".."; \
+ else \
+ echo "$(PROCESS)"; \
+ fi ); \
+ docker buildx build \
--platform $(PLATFORMS) \
--build-arg BASE=$(BASE) \
--build-arg BASE_VERSION=$(VERSION) \
+ --file $$DOCKERFILE_PATH \
-t $(REPO_NAME)/$(PROCESS):$(VERSION) \
- $(PROCESS)
+ $$CONTEXT
# Build+push only a specific VERSION for $(PROCESS). Intended for internal use by build-push-process.
# Usage (internal): $(MAKE) BASE= VERSION= build-push-process-version
@@ -67,13 +75,21 @@ build-push-process-version:
@test -n "$(BASE)" || { echo "Error: BASE is required"; exit 1; }
@test -n "$(VERSION)" || { echo "Error: VERSION is required"; exit 1; }
@echo " -> $(BASE):$(VERSION) => $(REPO_NAME)/$(PROCESS):$(VERSION) (push)"
- @docker buildx build \
+ @DOCKERFILE_PATH="$(PROCESS)/Dockerfile"; \
+ CONTEXT=$$( \
+ if [ "$(PROCESS)" = "launchql" ]; then \
+ echo ".."; \
+ else \
+ echo "$(PROCESS)"; \
+ fi ); \
+ docker buildx build \
--platform $(PLATFORMS) \
--build-arg BASE=$(BASE) \
--build-arg BASE_VERSION=$(VERSION) \
+ --file $$DOCKERFILE_PATH \
-t $(REPO_NAME)/$(PROCESS):$(VERSION) \
--push \
- $(PROCESS)
+ $$CONTEXT
# Aliases
all: build-all
@@ -91,3 +107,6 @@ postgis:
pgvector-postgis:
$(MAKE) PROCESS=pgvector-postgis build-process
+
+launchql:
+ $(MAKE) PROCESS=launchql build-process
diff --git a/docker/launchql/Dockerfile b/docker/launchql/Dockerfile
new file mode 100644
index 000000000..f45fce538
--- /dev/null
+++ b/docker/launchql/Dockerfile
@@ -0,0 +1,56 @@
+ARG BASE=node
+ARG BASE_VERSION=20-bookworm
+FROM ${BASE}:${BASE_VERSION} AS build
+
+LABEL org.opencontainers.image.source="https://github.com/launchql/launchql"
+ARG BASE
+ARG BASE_VERSION
+ENV BASE_VERSION=${BASE_VERSION}
+
+WORKDIR /app
+
+# System deps for building native modules and tools used by the monorepo
+RUN set -eux; \
+ apt-get update; \
+ apt-get install -y --no-install-recommends \
+ ca-certificates curl git python3 make g++; \
+ update-ca-certificates || true; \
+ corepack enable; \
+ corepack prepare yarn@1.22.22 --activate; \
+ rm -rf /var/lib/apt/lists/*
+
+# Copy full repo (build context must be repo root when building this image)
+COPY . .
+
+# Install and build all workspaces
+RUN set -eux; \
+ yarn install --frozen-lockfile; \
+ yarn build
+
+################################################################################
+FROM ${BASE}:${BASE_VERSION} AS launchql
+
+LABEL org.opencontainers.image.source="https://github.com/launchql/launchql"
+WORKDIR /app
+
+# Runtime deps (psql optional but handy for debugging)
+RUN set -eux; \
+ apt-get update; \
+ apt-get install -y --no-install-recommends ca-certificates postgresql-client; \
+ update-ca-certificates || true; \
+ corepack enable; \
+ corepack prepare yarn@1.22.22 --activate; \
+ rm -rf /var/lib/apt/lists/*
+
+# Copy built repo from builder
+COPY --from=build /app /app
+
+# Lightweight shims to expose CLI on PATH
+RUN set -eux; \
+ install -d /usr/local/bin; \
+ printf '#!/usr/bin/env bash\nnode /app/packages/cli/dist/index.js "$@"\n' > /usr/local/bin/lql; \
+ printf '#!/usr/bin/env bash\nnode /app/packages/cli/dist/index.js "$@"\n' > /usr/local/bin/launchql; \
+ chmod +x /usr/local/bin/lql /usr/local/bin/launchql
+
+ENTRYPOINT ["/usr/local/bin/lql"]
+CMD ["--help"]
diff --git a/docker/launchql/version.yaml b/docker/launchql/version.yaml
new file mode 100644
index 000000000..ed9cabf40
--- /dev/null
+++ b/docker/launchql/version.yaml
@@ -0,0 +1,4 @@
+base: node
+versions:
+ - 20-bookworm
+