Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "fenv"]
path = fenv
url = https://github.com/janderland/fenv.git
16 changes: 10 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ FQL is a query language and alternative client API for FoundationDB written in G
- **Run FQL interactively**: `./build.sh --run [args]`

### Docker-based Development
The build system uses Docker Compose for consistent builds and testing with FoundationDB integration. Always use `./build.sh --verify` instead of running Go commands directly to ensure proper environment setup.
The build system uses fenv (https://github.com/janderland/fenv), a Docker-based FoundationDB development environment, for consistent builds and testing with FoundationDB integration. Always use `./build.sh --verify` instead of running Go commands directly to ensure proper environment setup.

## Architecture

Expand Down Expand Up @@ -78,9 +78,13 @@ Query syntax uses directories (`/path/to/dir`), tuples `("elem1", 2, 0xFF)`, and

## Docker Environment

The build system uses Docker Compose for consistent builds:
- `build.sh` script provides unified interface
The build system uses fenv for consistent builds:
- `build.sh` script provides unified interface wrapping `fenv/fenv.sh`
- `docker/Dockerfile` is a multi-stage build:
- `fenv-builder` stage extends fenv base image with project-specific build tools
- `gobuild` stage compiles the FQL binary
- Final stage creates minimal runtime image
- `bake.hcl` defines Docker build configuration
- `compose.yaml` defines runtime services (build, fql, fdb containers)
- Use `--latest` flag for offline development
- FDB container automatically managed for tests
- `compose.yaml` defines runtime service for running fql image
- fenv automatically manages FDB container for integration testing
- Use `--latest` flag for offline development
7 changes: 6 additions & 1 deletion bake.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ variable "FDB_LIB_URL" {
default = "https://github.com/apple/foundationdb/releases/download/6.2.30/foundationdb-clients_6.2.30-1_amd64.deb"
}

variable "FENV_DOCKER_TAG" {
default = "6.2.30"
}

variable "GO_URL" {
default = "https://go.dev/dl/go1.19.1.linux-amd64.tar.gz"
}
Expand Down Expand Up @@ -45,6 +49,7 @@ function "build_args" {
result = {
FQL_VER = DOCKER_TAG
FDB_LIB_URL = FDB_LIB_URL
FENV_DOCKER_TAG = FENV_DOCKER_TAG
GO_URL = GO_URL
GOLANGCI_LINT_VER = GOLANGCI_LINT_VER
SHELLCHECK_URL = SHELLCHECK_URL
Expand All @@ -61,7 +66,7 @@ group "default" {
target "build" {
context = "./docker"
dockerfile = "Dockerfile"
target = "builder"
target = "fenv-builder"
tags = ["docker.io/janderland/fql-build:${DOCKER_TAG}"]
platforms = ["linux/amd64"]
args = build_args()
Expand Down
83 changes: 45 additions & 38 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ set -eo pipefail

function print_help {
cat << END
build.sh is a facade for docker compose. It runs a set of
optional tasks in the order specified below. This is the same
script used by CI/CD to build, test, and package FQL.
build.sh is a facade for fenv (FoundationDB development environment).
It runs a set of optional tasks in the order specified below. This is
the same script used by CI/CD to build, test, and package FQL.

If the '--image build' flag is set then the script starts off by
running 'docker build' for the 'fql-build' docker image. The tag
building the extended fenv image with all build tools. The tag
is determined by the git tag/hash and the FDB version. This image
is used to run the 'generate' and 'verify' tasks below.

Expand All @@ -18,7 +18,7 @@ code generated by 'go generate ./...' is up to date.

If the '--verify' flag is set then the script builds, lints, and
tests the codebase. This task interacts with an FDB docker
container which is automatically started.
container which is automatically started by fenv.

If the --docs' flag is set then the documentation HTML will be
generated under the /docs directory.
Expand All @@ -44,9 +44,8 @@ separating them with commas.

./build.sh --image build,fql

When building Docker images, the dependencies of the Dockerfile
are specified in 'bake.hcl'. When this file is changed, you'll
need to rebuild the docker images for the changes to take effect.
This script now uses fenv to provide a consistent build environment
with FoundationDB integration.
END
}

Expand Down Expand Up @@ -139,54 +138,62 @@ while [[ $# -gt 0 ]]; do
done


# Build variables required by the docker compose command.

BUILD_TASKS=()

if [[ -n "$VERIFY_GENERATION" ]]; then
BUILD_TASKS+=('./scripts/verify_generation.sh')
fi

if [[ -n "$VERIFY_CODEBASE" ]]; then
BUILD_TASKS+=('./scripts/setup_database.sh')
BUILD_TASKS+=("./scripts/verify_codebase.sh")
fi

if [[ -n "$GENERATE_DOCS" ]]; then
BUILD_TASKS+=('./scripts/generate_docs.sh')
fi

BUILD_COMMAND="$(join_array ' && ' "${BUILD_TASKS[@]}")"
echo "BUILD_COMMAND=${BUILD_COMMAND}"
export BUILD_COMMAND

FQL_COMMAND=${FQL_ARGS[*]}
echo "FQL_COMMAND=${FQL_COMMAND}"
export FQL_COMMAND
# Build variables for fenv and docker commands.

DOCKER_TAG="$(./scripts/docker_tag.sh)"
echo "DOCKER_TAG=${DOCKER_TAG}"
export DOCKER_TAG

FDB_DOCKER_IMAGE="foundationdb/foundationdb:${FDB_VER:-6.2.30}"
echo "FDB_DOCKER_IMAGE=${FDB_DOCKER_IMAGE}"
export FDB_DOCKER_IMAGE
# Set fenv environment variables
export FENV_FDB_VER="${FDB_VER:-6.2.30}"
export FENV_PROJECT_NAME="fql"

# fenv.sh script location
FENV_SCRIPT="./fenv/fenv.sh"

# Common fenv flags
FENV_FLAGS=()
FENV_FLAGS+=(--docker ./docker/Dockerfile)
FENV_FLAGS+=(--target fenv-builder)


# Run the requested commands.

# Build the extended fenv image if requested
if [[ -n "$IMAGE_BUILD" ]]; then
(set -x; docker buildx bake -f bake.hcl --load build)
echo "Building extended fenv image..."
(set -x; "$FENV_SCRIPT" "${FENV_FLAGS[@]}" --build)
fi

# Execute build tasks (generate, verify, docs) using fenv
if [[ -n "$VERIFY_GENERATION" ]]; then
echo "Verifying code generation..."
(set -x; "$FENV_SCRIPT" "${FENV_FLAGS[@]}" --exec ./scripts/verify_generation.sh)
fi

if [[ -n "$BUILD_COMMAND" ]]; then
(set -x; docker compose run --rm build /bin/sh -c "$BUILD_COMMAND")
if [[ -n "$VERIFY_CODEBASE" ]]; then
echo "Setting up database and verifying codebase..."
(set -x; "$FENV_SCRIPT" "${FENV_FLAGS[@]}" --exec ./scripts/setup_database.sh --exec ./scripts/verify_codebase.sh)
fi

if [[ -n "$GENERATE_DOCS" ]]; then
echo "Generating documentation..."
(set -x; "$FENV_SCRIPT" "${FENV_FLAGS[@]}" --exec ./scripts/generate_docs.sh)
fi

# Build the final fql image if requested
if [[ -n "$IMAGE_FQL" ]]; then
echo "Building fql runtime image..."
FDB_DOCKER_IMAGE="foundationdb/foundationdb:${FENV_FDB_VER}"
export FDB_DOCKER_IMAGE
(set -x; docker buildx bake -f bake.hcl --load fql)
fi

# Run fql interactively if requested
if [[ -n "$RUN_FQL" ]]; then
echo "Running fql with args: ${FQL_ARGS[*]}"
FDB_DOCKER_IMAGE="foundationdb/foundationdb:${FENV_FDB_VER}"
FQL_COMMAND="${FQL_ARGS[*]}"
export FDB_DOCKER_IMAGE FQL_COMMAND
(set -x; docker compose run --rm fql 'docker:docker@{fdb}:4500' "${FQL_ARGS[@]}")
fi
95 changes: 52 additions & 43 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,65 +1,62 @@
# 'builder' includes all build & testing dependencies.
FROM debian:12 AS builder
# 'fenv-builder' extends the fenv base image with FQL build & testing dependencies.
# This stage is used by fenv for local development and CI/CD verification tasks.
ARG FENV_DOCKER_TAG
FROM fenv:${FENV_DOCKER_TAG} AS fenv-builder

RUN apt-get update &&\
# Install additional system packages needed for build
RUN apt-get update && \
apt-get install --no-install-recommends -y \
build-essential=12.9 \
ca-certificates=20* \
git=1:2.39.* \
curl=7.88.* &&\
apt-get clean &&\
curl=7.88.* && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

# The FDB installer is not deleted so it can be used to
# install the library in the final stage at the end of
# this file.
ARG FDB_LIB_URL
RUN curl -Lo /fdb.deb $FDB_LIB_URL &&\
dpkg -i /fdb.deb

ARG GO_URL
RUN curl -Lo /go.tar.gz $GO_URL &&\
tar -C /usr/local -xzf /go.tar.gz &&\
rm /go.tar.gz
# Install Go
ARG GO_URL="https://go.dev/dl/go1.19.1.linux-amd64.tar.gz"
RUN curl -fsSL ${GO_URL} | tar -C /usr/local -xz
ENV PATH="/root/go/bin:/usr/local/go/bin:${PATH}"
ENV GOCACHE="/cache/gocache"
ENV GOMODCACHE="/cache/gomod"

# Install golangci-lint
ARG GOLANGCI_LINT_URL="https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh"
ARG GOLANGCI_LINT_VER
RUN curl -Lo /golint.sh $GOLANGCI_LINT_URL &&\
sh /golint.sh -b "$(go env GOPATH)/bin" $GOLANGCI_LINT_VER &&\
rm /golint.sh
ARG GOLANGCI_LINT_VER="v1.49.0"
RUN curl -fsSL ${GOLANGCI_LINT_URL} | sh -s -- -b "$(go env GOPATH)/bin" ${GOLANGCI_LINT_VER}
ENV GOLANGCI_LINT_CACHE="/cache/golangci-lint"

ARG SHELLCHECK_URL
RUN curl -Lo /shellcheck.tar.xz $SHELLCHECK_URL &&\
tar -xf /shellcheck.tar.xz &&\
mv /shellcheck-*/shellcheck /usr/local/bin &&\
rm -r /shellcheck.tar.xz /shellcheck-*
# Install shellcheck
ARG SHELLCHECK_URL="https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.x86_64.tar.xz"
RUN curl -fsSL ${SHELLCHECK_URL} -o /tmp/shellcheck.tar.xz && \
tar -xf /tmp/shellcheck.tar.xz -C /tmp && \
mv /tmp/shellcheck-*/shellcheck /usr/local/bin && \
rm -rf /tmp/shellcheck*

ARG HADOLINT_URL
RUN curl -Lo /usr/local/bin/hadolint $HADOLINT_URL &&\
# Install hadolint
ARG HADOLINT_URL="https://github.com/hadolint/hadolint/releases/download/v2.7.0/hadolint-Linux-x86_64"
RUN curl -fsSL ${HADOLINT_URL} -o /usr/local/bin/hadolint && \
chmod +x /usr/local/bin/hadolint

ARG JQ_URL
RUN curl -Lo /usr/local/bin/jq $JQ_URL &&\
# Install jq
ARG JQ_URL="https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64"
RUN curl -fsSL ${JQ_URL} -o /usr/local/bin/jq && \
chmod +x /usr/local/bin/jq

ARG PANDOC_URL
RUN curl -Lo /pandoc.deb $PANDOC_URL &&\
dpkg -i /pandoc.deb &&\
rm /pandoc.deb
# Install pandoc
ARG PANDOC_URL="https://github.com/jgm/pandoc/releases/download/3.3/pandoc-3.3-1-amd64.deb"
RUN curl -fsSL ${PANDOC_URL} -o /tmp/pandoc.deb && \
dpkg -i /tmp/pandoc.deb && \
rm /tmp/pandoc.deb

# Configure git so it allows any user to run git commands
# on the /fql directory. This allows the user which runs
# CI to be different from the user which built the Docker
# image.
RUN git config --global --add safe.directory /fql
# Configure git to allow any user to run git commands on /src
# This allows the user which runs CI to be different from the
# user which built the Docker image.
RUN git config --global --add safe.directory /src


# 'gobuild' executes 'go build'.
FROM builder AS gobuild
# 'gobuild' stage compiles the FQL binary.
FROM fenv-builder AS gobuild

COPY . /src
WORKDIR /src
Expand All @@ -68,11 +65,23 @@ ARG FQL_VER
RUN go build -o /fql -ldflags="-X 'github.com/janderland/fql/internal/app.Version=${FQL_VER}'"


# The final stage builds the 'fql' image.
# 'fdb-installer' stage downloads the FDB client .deb for the final stage.
FROM debian:12 AS fdb-installer

RUN apt-get update && \
apt-get install --no-install-recommends -y curl=7.88.* && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

ARG FDB_LIB_URL
RUN curl -fsSL ${FDB_LIB_URL} -o /fdb.deb


# The final stage builds the minimal 'fql' runtime image.
FROM debian:12

COPY --from=gobuild /fdb.deb /fdb.deb
RUN dpkg -i ./fdb.deb &&\
COPY --from=fdb-installer /fdb.deb /fdb.deb
RUN dpkg -i ./fdb.deb && \
rm /fdb.deb

ENV TERM="xterm-256color"
Expand Down
1 change: 1 addition & 0 deletions fenv
Submodule fenv added at 387b62
Loading